forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			97 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			97 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			C++
		
	
	
	
| //===- 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();
 | |
| }
 |