1 //===- SPIRVLowerConstExpr.cpp - Regularize LLVM for SPIR-V ------- C++ -*-===// 2 // 3 // The LLVM/SPIRV Translator 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 // Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved. 9 // 10 // Permission is hereby granted, free of charge, to any person obtaining a 11 // copy of this software and associated documentation files (the "Software"), 12 // to deal with the Software without restriction, including without limitation 13 // the rights to use, copy, modify, merge, publish, distribute, sublicense, 14 // and/or sell copies of the Software, and to permit persons to whom the 15 // Software is furnished to do so, subject to the following conditions: 16 // 17 // Redistributions of source code must retain the above copyright notice, 18 // this list of conditions and the following disclaimers. 19 // Redistributions in binary form must reproduce the above copyright notice, 20 // this list of conditions and the following disclaimers in the documentation 21 // and/or other materials provided with the distribution. 22 // Neither the names of Advanced Micro Devices, Inc., nor the names of its 23 // contributors may be used to endorse or promote products derived from this 24 // Software without specific prior written permission. 25 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 26 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 27 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 28 // CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 29 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 30 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH 31 // THE SOFTWARE. 32 // 33 //===----------------------------------------------------------------------===// 34 // 35 // This file implements regularization of LLVM moduel for SPIR-V. 36 // 37 //===----------------------------------------------------------------------===// 38 #define DEBUG_TYPE "spv-lower-const-expr" 39 40 #include "SPIRVInternal.h" 41 #include "OCLUtil.h" 42 #include "SPIRVMDBuilder.h" 43 #include "SPIRVMDWalker.h" 44 45 #include "llvm/ADT/StringSwitch.h" 46 #include "llvm/ADT/Triple.h" 47 #include "llvm/IR/InstVisitor.h" 48 #include "llvm/IR/Instructions.h" 49 #include "llvm/IR/IRBuilder.h" 50 #include "llvm/IR/Verifier.h" 51 #include "llvm/Pass.h" 52 #include "llvm/PassSupport.h" 53 #include "llvm/Support/CommandLine.h" 54 #include "llvm/Support/Debug.h" 55 #include "llvm/Support/raw_ostream.h" 56 57 #include <list> 58 #include <set> 59 60 using namespace llvm; 61 using namespace SPIRV; 62 using namespace OCLUtil; 63 64 namespace SPIRV { 65 66 cl::opt<bool> SPIRVLowerConst("spirv-lower-const-expr", cl::init(true), 67 cl::desc("LLVM/SPIR-V translation enalbe lowering constant expression")); 68 69 class SPIRVLowerConstExpr: public ModulePass { 70 public: 71 SPIRVLowerConstExpr():ModulePass(ID), M(nullptr), Ctx(nullptr) { 72 initializeSPIRVLowerConstExprPass(*PassRegistry::getPassRegistry()); 73 } 74 75 virtual bool runOnModule(Module &M); 76 void visit(Module *M); 77 78 static char ID; 79 private: 80 Module *M; 81 LLVMContext *Ctx; 82 }; 83 84 char SPIRVLowerConstExpr::ID = 0; 85 86 bool 87 SPIRVLowerConstExpr::runOnModule(Module& Module) { 88 if (!SPIRVLowerConst) 89 return false; 90 91 M = &Module; 92 Ctx = &M->getContext(); 93 94 DEBUG(dbgs() << "Enter SPIRVLowerConstExpr:\n"); 95 visit(M); 96 97 DEBUG(dbgs() << "After SPIRVLowerConstExpr:\n" << *M); 98 std::string Err; 99 raw_string_ostream ErrorOS(Err); 100 if (verifyModule(*M, &ErrorOS)){ 101 DEBUG(errs() << "Fails to verify module: " << ErrorOS.str()); 102 } 103 return true; 104 } 105 106 /// Since SPIR-V cannot represent constant expression, constant expressions 107 /// in LLVM needs to be lowered to instructions. 108 /// For each function, the constant expressions used by instructions of the 109 /// function are replaced by instructions placed in the entry block since it 110 /// dominates all other BB's. Each constant expression only needs to be lowered 111 /// once in each function and all uses of it by instructions in that function 112 /// is replaced by one instruction. 113 /// ToDo: remove redundant instructions for common subexpression 114 115 void 116 SPIRVLowerConstExpr::visit(Module *M) { 117 for (auto I = M->begin(), E = M->end(); I != E; ++I) { 118 std::map<ConstantExpr*, Instruction *> CMap; 119 std::list<Instruction *> WorkList; 120 auto FBegin = I->begin(); 121 for (auto BI = FBegin, BE = I->end(); BI != BE; ++BI) { 122 for (auto II = BI->begin(), IE = BI->end(); II != IE; ++II) { 123 WorkList.push_back(static_cast<Instruction*>(II)); 124 } 125 } 126 while (!WorkList.empty()) { 127 auto II = WorkList.front(); 128 WorkList.pop_front(); 129 for (unsigned OI = 0, OE = II->getNumOperands(); OI != OE; ++OI) { 130 auto Op = II->getOperand(OI); 131 132 if (auto CE = dyn_cast<ConstantExpr>(Op)) { 133 SPIRVDBG(dbgs() << "[lowerConstantExpressions] " << *CE;) 134 auto ReplInst = CE->getAsInstruction(); 135 ReplInst->insertBefore(static_cast<Instruction*>(FBegin->begin())); 136 SPIRVDBG(dbgs() << " -> " << *ReplInst << '\n';) 137 WorkList.push_front(ReplInst); 138 std::vector<Instruction *> Users; 139 // Do not replace use during iteration of use. Do it in another loop. 140 for (auto U:CE->users()){ 141 SPIRVDBG(dbgs() << "[lowerConstantExpressions] Use: " << 142 *U << '\n';) 143 if (auto InstUser = dyn_cast<Instruction>(U)) { 144 if (InstUser->getParent()->getParent() != &(*I)) 145 continue; 146 Users.push_back(InstUser); 147 } 148 } 149 for (auto &User:Users) 150 User->replaceUsesOfWith(CE, ReplInst); 151 } 152 } 153 } 154 } 155 } 156 157 } 158 159 INITIALIZE_PASS(SPIRVLowerConstExpr, "spv-lower-const-expr", 160 "Regularize LLVM for SPIR-V", false, false) 161 162 ModulePass *llvm::createSPIRVLowerConstExpr() { 163 return new SPIRVLowerConstExpr(); 164 } 165