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/Passes.h" 15 #include "llvm/IR/Function.h" 16 #include "llvm/IR/IRBuilder.h" 17 #include "llvm/IR/Instructions.h" 18 #include "llvm/IR/Intrinsics.h" 19 #include "llvm/IR/Module.h" 20 #include "llvm/Pass.h" 21 22 using namespace llvm; 23 24 namespace { 25 26 bool lowerLoadRelative(Function &F) { 27 if (F.use_empty()) 28 return false; 29 30 bool Changed = false; 31 Type *Int32Ty = Type::getInt32Ty(F.getContext()); 32 Type *Int32PtrTy = Int32Ty->getPointerTo(); 33 Type *Int8Ty = Type::getInt8Ty(F.getContext()); 34 35 for (auto I = F.use_begin(), E = F.use_end(); I != E;) { 36 auto CI = dyn_cast<CallInst>(I->getUser()); 37 ++I; 38 if (!CI || CI->getCalledValue() != &F) 39 continue; 40 41 IRBuilder<> B(CI); 42 Value *OffsetPtr = 43 B.CreateGEP(Int8Ty, CI->getArgOperand(0), CI->getArgOperand(1)); 44 Value *OffsetPtrI32 = B.CreateBitCast(OffsetPtr, Int32PtrTy); 45 Value *OffsetI32 = B.CreateAlignedLoad(OffsetPtrI32, 4); 46 47 Value *ResultPtr = B.CreateGEP(Int8Ty, CI->getArgOperand(0), OffsetI32); 48 49 CI->replaceAllUsesWith(ResultPtr); 50 CI->eraseFromParent(); 51 Changed = true; 52 } 53 54 return Changed; 55 } 56 57 bool lowerIntrinsics(Module &M) { 58 bool Changed = false; 59 for (Function &F : M) { 60 if (F.getName().startswith("llvm.load.relative.")) 61 Changed |= lowerLoadRelative(F); 62 } 63 return Changed; 64 } 65 66 class PreISelIntrinsicLowering : public ModulePass { 67 public: 68 static char ID; 69 PreISelIntrinsicLowering() : ModulePass(ID) {} 70 71 bool runOnModule(Module &M) { 72 return lowerIntrinsics(M); 73 } 74 }; 75 76 char PreISelIntrinsicLowering::ID; 77 78 } 79 80 INITIALIZE_PASS(PreISelIntrinsicLowering, "pre-isel-intrinsic-lowering", 81 "Pre-ISel Intrinsic Lowering", false, false) 82 83 ModulePass *llvm::createPreISelIntrinsicLoweringPass() { 84 return new PreISelIntrinsicLowering; 85 } 86