//===- PreISelIntrinsicLowering.cpp - Pre-ISel intrinsic lowering pass ----===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This pass implements IR lowering for the llvm.load.relative intrinsic. // //===----------------------------------------------------------------------===// #include "llvm/CodeGen/PreISelIntrinsicLowering.h" #include "llvm/CodeGen/Passes.h" #include "llvm/IR/Function.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/Module.h" #include "llvm/IR/Type.h" #include "llvm/IR/User.h" #include "llvm/Pass.h" #include "llvm/Support/Casting.h" using namespace llvm; static bool lowerLoadRelative(Function &F) { if (F.use_empty()) return false; bool Changed = false; Type *Int32Ty = Type::getInt32Ty(F.getContext()); Type *Int32PtrTy = Int32Ty->getPointerTo(); Type *Int8Ty = Type::getInt8Ty(F.getContext()); for (auto I = F.use_begin(), E = F.use_end(); I != E;) { auto CI = dyn_cast<CallInst>(I->getUser()); ++I; if (!CI || CI->getCalledValue() != &F) continue; IRBuilder<> B(CI); Value *OffsetPtr = B.CreateGEP(Int8Ty, CI->getArgOperand(0), CI->getArgOperand(1)); Value *OffsetPtrI32 = B.CreateBitCast(OffsetPtr, Int32PtrTy); Value *OffsetI32 = B.CreateAlignedLoad(OffsetPtrI32, 4); Value *ResultPtr = B.CreateGEP(Int8Ty, CI->getArgOperand(0), OffsetI32); CI->replaceAllUsesWith(ResultPtr); CI->eraseFromParent(); Changed = true; } return Changed; } static bool lowerIntrinsics(Module &M) { bool Changed = false; for (Function &F : M) { if (F.getName().startswith("llvm.load.relative.")) Changed |= lowerLoadRelative(F); } return Changed; } namespace { class PreISelIntrinsicLoweringLegacyPass : public ModulePass { public: static char ID; PreISelIntrinsicLoweringLegacyPass() : ModulePass(ID) {} bool runOnModule(Module &M) override { return lowerIntrinsics(M); } }; } // end anonymous namespace char PreISelIntrinsicLoweringLegacyPass::ID; INITIALIZE_PASS(PreISelIntrinsicLoweringLegacyPass, "pre-isel-intrinsic-lowering", "Pre-ISel Intrinsic Lowering", false, false) ModulePass *llvm::createPreISelIntrinsicLoweringPass() { return new PreISelIntrinsicLoweringLegacyPass; } PreservedAnalyses PreISelIntrinsicLoweringPass::run(Module &M, ModuleAnalysisManager &AM) { if (!lowerIntrinsics(M)) return PreservedAnalyses::all(); else return PreservedAnalyses::none(); }