LLVM  9.0.0svn
PreISelIntrinsicLowering.cpp
Go to the documentation of this file.
1 //===- PreISelIntrinsicLowering.cpp - Pre-ISel intrinsic lowering pass ----===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This pass implements IR lowering for the llvm.load.relative and llvm.objc.*
10 // intrinsics.
11 //
12 //===----------------------------------------------------------------------===//
13 
15 #include "llvm/CodeGen/Passes.h"
16 #include "llvm/IR/Function.h"
17 #include "llvm/IR/Intrinsics.h"
18 #include "llvm/IR/IRBuilder.h"
19 #include "llvm/IR/Instructions.h"
20 #include "llvm/IR/Module.h"
21 #include "llvm/IR/Type.h"
22 #include "llvm/IR/User.h"
23 #include "llvm/Pass.h"
24 #include "llvm/Support/Casting.h"
25 
26 using namespace llvm;
27 
28 static bool lowerLoadRelative(Function &F) {
29  if (F.use_empty())
30  return false;
31 
32  bool Changed = false;
34  Type *Int32PtrTy = Int32Ty->getPointerTo();
35  Type *Int8Ty = Type::getInt8Ty(F.getContext());
36 
37  for (auto I = F.use_begin(), E = F.use_end(); I != E;) {
38  auto CI = dyn_cast<CallInst>(I->getUser());
39  ++I;
40  if (!CI || CI->getCalledValue() != &F)
41  continue;
42 
43  IRBuilder<> B(CI);
44  Value *OffsetPtr =
45  B.CreateGEP(Int8Ty, CI->getArgOperand(0), CI->getArgOperand(1));
46  Value *OffsetPtrI32 = B.CreateBitCast(OffsetPtr, Int32PtrTy);
47  Value *OffsetI32 = B.CreateAlignedLoad(Int32Ty, OffsetPtrI32, 4);
48 
49  Value *ResultPtr = B.CreateGEP(Int8Ty, CI->getArgOperand(0), OffsetI32);
50 
51  CI->replaceAllUsesWith(ResultPtr);
52  CI->eraseFromParent();
53  Changed = true;
54  }
55 
56  return Changed;
57 }
58 
59 static bool lowerObjCCall(Function &F, const char *NewFn,
60  bool setNonLazyBind = false) {
61  if (F.use_empty())
62  return false;
63 
64  // If we haven't already looked up this function, check to see if the
65  // program already contains a function with this name.
66  Module *M = F.getParent();
67  FunctionCallee FCache = M->getOrInsertFunction(NewFn, F.getFunctionType());
68 
69  if (Function *Fn = dyn_cast<Function>(FCache.getCallee())) {
70  Fn->setLinkage(F.getLinkage());
71  if (setNonLazyBind && !Fn->isWeakForLinker()) {
72  // If we have Native ARC, set nonlazybind attribute for these APIs for
73  // performance.
74  Fn->addFnAttr(Attribute::NonLazyBind);
75  }
76  }
77 
78  for (auto I = F.use_begin(), E = F.use_end(); I != E;) {
79  auto *CI = dyn_cast<CallInst>(I->getUser());
80  assert(CI->getCalledFunction() && "Cannot lower an indirect call!");
81  ++I;
82 
83  IRBuilder<> Builder(CI->getParent(), CI->getIterator());
84  SmallVector<Value *, 8> Args(CI->arg_begin(), CI->arg_end());
85  CallInst *NewCI = Builder.CreateCall(FCache, Args);
86  NewCI->setName(CI->getName());
87  NewCI->setTailCallKind(CI->getTailCallKind());
88  if (!CI->use_empty())
89  CI->replaceAllUsesWith(NewCI);
90  CI->eraseFromParent();
91  }
92 
93  return true;
94 }
95 
96 static bool lowerIntrinsics(Module &M) {
97  bool Changed = false;
98  for (Function &F : M) {
99  if (F.getName().startswith("llvm.load.relative.")) {
100  Changed |= lowerLoadRelative(F);
101  continue;
102  }
103  switch (F.getIntrinsicID()) {
104  default:
105  break;
106  case Intrinsic::objc_autorelease:
107  Changed |= lowerObjCCall(F, "objc_autorelease");
108  break;
109  case Intrinsic::objc_autoreleasePoolPop:
110  Changed |= lowerObjCCall(F, "objc_autoreleasePoolPop");
111  break;
112  case Intrinsic::objc_autoreleasePoolPush:
113  Changed |= lowerObjCCall(F, "objc_autoreleasePoolPush");
114  break;
115  case Intrinsic::objc_autoreleaseReturnValue:
116  Changed |= lowerObjCCall(F, "objc_autoreleaseReturnValue");
117  break;
118  case Intrinsic::objc_copyWeak:
119  Changed |= lowerObjCCall(F, "objc_copyWeak");
120  break;
121  case Intrinsic::objc_destroyWeak:
122  Changed |= lowerObjCCall(F, "objc_destroyWeak");
123  break;
124  case Intrinsic::objc_initWeak:
125  Changed |= lowerObjCCall(F, "objc_initWeak");
126  break;
127  case Intrinsic::objc_loadWeak:
128  Changed |= lowerObjCCall(F, "objc_loadWeak");
129  break;
130  case Intrinsic::objc_loadWeakRetained:
131  Changed |= lowerObjCCall(F, "objc_loadWeakRetained");
132  break;
133  case Intrinsic::objc_moveWeak:
134  Changed |= lowerObjCCall(F, "objc_moveWeak");
135  break;
136  case Intrinsic::objc_release:
137  Changed |= lowerObjCCall(F, "objc_release", true);
138  break;
139  case Intrinsic::objc_retain:
140  Changed |= lowerObjCCall(F, "objc_retain", true);
141  break;
142  case Intrinsic::objc_retainAutorelease:
143  Changed |= lowerObjCCall(F, "objc_retainAutorelease");
144  break;
145  case Intrinsic::objc_retainAutoreleaseReturnValue:
146  Changed |= lowerObjCCall(F, "objc_retainAutoreleaseReturnValue");
147  break;
148  case Intrinsic::objc_retainAutoreleasedReturnValue:
149  Changed |= lowerObjCCall(F, "objc_retainAutoreleasedReturnValue");
150  break;
151  case Intrinsic::objc_retainBlock:
152  Changed |= lowerObjCCall(F, "objc_retainBlock");
153  break;
154  case Intrinsic::objc_storeStrong:
155  Changed |= lowerObjCCall(F, "objc_storeStrong");
156  break;
157  case Intrinsic::objc_storeWeak:
158  Changed |= lowerObjCCall(F, "objc_storeWeak");
159  break;
160  case Intrinsic::objc_unsafeClaimAutoreleasedReturnValue:
161  Changed |= lowerObjCCall(F, "objc_unsafeClaimAutoreleasedReturnValue");
162  break;
163  case Intrinsic::objc_retainedObject:
164  Changed |= lowerObjCCall(F, "objc_retainedObject");
165  break;
166  case Intrinsic::objc_unretainedObject:
167  Changed |= lowerObjCCall(F, "objc_unretainedObject");
168  break;
169  case Intrinsic::objc_unretainedPointer:
170  Changed |= lowerObjCCall(F, "objc_unretainedPointer");
171  break;
172  case Intrinsic::objc_retain_autorelease:
173  Changed |= lowerObjCCall(F, "objc_retain_autorelease");
174  break;
175  case Intrinsic::objc_sync_enter:
176  Changed |= lowerObjCCall(F, "objc_sync_enter");
177  break;
178  case Intrinsic::objc_sync_exit:
179  Changed |= lowerObjCCall(F, "objc_sync_exit");
180  break;
181  }
182  }
183  return Changed;
184 }
185 
186 namespace {
187 
188 class PreISelIntrinsicLoweringLegacyPass : public ModulePass {
189 public:
190  static char ID;
191 
192  PreISelIntrinsicLoweringLegacyPass() : ModulePass(ID) {}
193 
194  bool runOnModule(Module &M) override { return lowerIntrinsics(M); }
195 };
196 
197 } // end anonymous namespace
198 
200 
201 INITIALIZE_PASS(PreISelIntrinsicLoweringLegacyPass,
202  "pre-isel-intrinsic-lowering", "Pre-ISel Intrinsic Lowering",
203  false, false)
204 
206  return new PreISelIntrinsicLoweringLegacyPass;
207 }
208 
210  ModuleAnalysisManager &AM) {
211  if (!lowerIntrinsics(M))
212  return PreservedAnalyses::all();
213  else
214  return PreservedAnalyses::none();
215 }
use_iterator use_end()
Definition: Value.h:346
This class represents lattice values for constants.
Definition: AllocatorList.h:23
A Module instance is used to store all the information related to an LLVM module. ...
Definition: Module.h:65
LoadInst * CreateAlignedLoad(Type *Ty, Value *Ptr, unsigned Align, const char *Name)
Provided to resolve &#39;CreateAlignedLoad(Ptr, Align, "...")&#39; correctly, instead of converting the strin...
Definition: IRBuilder.h:1428
A handy container for a FunctionType+Callee-pointer pair, which can be passed around as a single enti...
Definition: DerivedTypes.h:164
This class represents a function call, abstracting a target machine&#39;s calling convention.
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
F(f)
static bool setNonLazyBind(Function &F)
PointerType * getPointerTo(unsigned AddrSpace=0) const
Return a pointer to the current type.
Definition: Type.cpp:651
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition: IRBuilder.h:742
Value * CreateBitCast(Value *V, Type *DestTy, const Twine &Name="")
Definition: IRBuilder.h:1767
LinkageTypes getLinkage() const
Definition: GlobalValue.h:450
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Definition: Value.cpp:429
static bool lowerLoadRelative(Function &F)
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
Definition: PassManager.h:156
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
A set of analyses that are preserved following a run of a transformation pass.
Definition: PassManager.h:153
The instances of the Type class are immutable: once they are created, they are never changed...
Definition: Type.h:45
INITIALIZE_PASS(PreISelIntrinsicLoweringLegacyPass, "pre-isel-intrinsic-lowering", "Pre-ISel Intrinsic Lowering", false, false) ModulePass *llvm
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static bool lowerObjCCall(Function &F, const char *NewFn, bool setNonLazyBind=false)
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function. ...
Definition: Function.cpp:192
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition: PassManager.h:159
Value * CreateGEP(Value *Ptr, ArrayRef< Value *> IdxList, const Twine &Name="")
Definition: IRBuilder.h:1493
Module.h This file contains the declarations for the Module class.
FunctionCallee getOrInsertFunction(StringRef Name, FunctionType *T, AttributeList AttributeList)
Look up the specified function in the module symbol table.
Definition: Module.cpp:143
FunctionType * getFunctionType() const
Returns the FunctionType for me.
Definition: Function.h:163
use_iterator use_begin()
Definition: Value.h:338
static IntegerType * getInt32Ty(LLVMContext &C)
Definition: Type.cpp:175
#define I(x, y, z)
Definition: MD5.cpp:58
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
Definition: Pass.h:224
LLVM_NODISCARD std::enable_if<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
Definition: Casting.h:332
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Module * getParent()
Get the module that this global value is contained inside of...
Definition: GlobalValue.h:565
LLVM Value Representation.
Definition: Value.h:72
ModulePass * createPreISelIntrinsicLoweringPass()
This pass lowers the @llvm.load.relative and @llvm.objc.
A container for analyses that lazily runs them and caches their results.
static bool lowerIntrinsics(Module &M)
static IntegerType * getInt8Ty(LLVMContext &C)
Definition: Type.cpp:173
bool use_empty() const
Definition: Value.h:322
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
IntegerType * Int32Ty