1 //===-- PreISelIntrinsicLowering.cpp - Pre-ISel intrinsic lowering pass ---===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This pass implements IR lowering for the llvm.load.relative intrinsic. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "llvm/CodeGen/PreISelIntrinsicLowering.h" 15 #include "llvm/CodeGen/Passes.h" 16 #include "llvm/IR/Function.h" 17 #include "llvm/IR/IRBuilder.h" 18 #include "llvm/IR/Instructions.h" 19 #include "llvm/IR/Intrinsics.h" 20 #include "llvm/IR/Module.h" 21 #include "llvm/Pass.h" 22 23 using namespace llvm; 24 25 namespace { 26 27 bool lowerLoadRelative(Function &F) { 28 if (F.use_empty()) 29 return false; 30 31 bool Changed = false; 32 Type *Int32Ty = Type::getInt32Ty(F.getContext()); 33 Type *Int32PtrTy = Int32Ty->getPointerTo(); 34 Type *Int8Ty = Type::getInt8Ty(F.getContext()); 35 36 for (auto I = F.use_begin(), E = F.use_end(); I != E;) { 37 auto CI = dyn_cast<CallInst>(I->getUser()); 38 ++I; 39 if (!CI || CI->getCalledValue() != &F) 40 continue; 41 42 IRBuilder<> B(CI); 43 Value *OffsetPtr = 44 B.CreateGEP(Int8Ty, CI->getArgOperand(0), CI->getArgOperand(1)); 45 Value *OffsetPtrI32 = B.CreateBitCast(OffsetPtr, Int32PtrTy); 46 Value *OffsetI32 = B.CreateAlignedLoad(OffsetPtrI32, 4); 47 48 Value *ResultPtr = B.CreateGEP(Int8Ty, CI->getArgOperand(0), OffsetI32); 49 50 CI->replaceAllUsesWith(ResultPtr); 51 CI->eraseFromParent(); 52 Changed = true; 53 } 54 55 return Changed; 56 } 57 58 bool lowerIntrinsics(Module &M) { 59 bool Changed = false; 60 for (Function &F : M) { 61 if (F.getName().startswith("llvm.load.relative.")) 62 Changed |= lowerLoadRelative(F); 63 } 64 return Changed; 65 } 66 67 class PreISelIntrinsicLoweringLegacyPass : public ModulePass { 68 public: 69 static char ID; 70 PreISelIntrinsicLoweringLegacyPass() : ModulePass(ID) {} 71 72 bool runOnModule(Module &M) { return lowerIntrinsics(M); } 73 }; 74 75 char PreISelIntrinsicLoweringLegacyPass::ID; 76 } 77 78 INITIALIZE_PASS(PreISelIntrinsicLoweringLegacyPass, 79 "pre-isel-intrinsic-lowering", "Pre-ISel Intrinsic Lowering", 80 false, false) 81 82 namespace llvm { 83 ModulePass *createPreISelIntrinsicLoweringPass() { 84 return new PreISelIntrinsicLoweringLegacyPass; 85 } 86 87 PreservedAnalyses PreISelIntrinsicLoweringPass::run(Module &M, 88 ModuleAnalysisManager &AM) { 89 if (!lowerIntrinsics(M)) 90 return PreservedAnalyses::all(); 91 else 92 return PreservedAnalyses::none(); 93 } 94 } // End llvm namespace 95