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 23using namespace llvm; 24 25namespace { 26 27bool 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 58bool 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 67class PreISelIntrinsicLoweringLegacyPass : public ModulePass { 68public: 69 static char ID; 70 PreISelIntrinsicLoweringLegacyPass() : ModulePass(ID) {} 71 72 bool runOnModule(Module &M) { return lowerIntrinsics(M); } 73}; 74 75char PreISelIntrinsicLoweringLegacyPass::ID; 76} 77 78INITIALIZE_PASS(PreISelIntrinsicLoweringLegacyPass, 79 "pre-isel-intrinsic-lowering", "Pre-ISel Intrinsic Lowering", 80 false, false) 81 82namespace llvm { 83ModulePass *createPreISelIntrinsicLoweringPass() { 84 return new PreISelIntrinsicLoweringLegacyPass; 85} 86 87PreservedAnalyses 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