blob: a1ff231412d8098b885870de50c40ffa38258769 [file] [log] [blame]
Peter Collingbourne7dd8dbf2016-04-22 21:18:02 +00001//===-- 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
22using namespace llvm;
23
24namespace {
25
26bool 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
57bool 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
66class PreISelIntrinsicLowering : public ModulePass {
67public:
68 static char ID;
69 PreISelIntrinsicLowering() : ModulePass(ID) {}
70
71 bool runOnModule(Module &M) {
72 return lowerIntrinsics(M);
73 }
74};
75
76char PreISelIntrinsicLowering::ID;
77
78}
79
80INITIALIZE_PASS(PreISelIntrinsicLowering, "pre-isel-intrinsic-lowering",
81 "Pre-ISel Intrinsic Lowering", false, false)
82
83ModulePass *llvm::createPreISelIntrinsicLoweringPass() {
84 return new PreISelIntrinsicLowering;
85}