Home | History | Annotate | Download | only in CodeGen
      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