LLVM  8.0.1
PreISelIntrinsicLowering.cpp
Go to the documentation of this file.
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 and llvm.objc.*
11 // intrinsics.
12 //
13 //===----------------------------------------------------------------------===//
14 
16 #include "llvm/CodeGen/Passes.h"
17 #include "llvm/IR/Function.h"
18 #include "llvm/IR/Intrinsics.h"
19 #include "llvm/IR/IRBuilder.h"
20 #include "llvm/IR/Instructions.h"
21 #include "llvm/IR/Module.h"
22 #include "llvm/IR/Type.h"
23 #include "llvm/IR/User.h"
24 #include "llvm/Pass.h"
25 #include "llvm/Support/Casting.h"
26 
27 using namespace llvm;
28 
29 static bool lowerLoadRelative(Function &F) {
30  if (F.use_empty())
31  return false;
32 
33  bool Changed = false;
35  Type *Int32PtrTy = Int32Ty->getPointerTo();
36  Type *Int8Ty = Type::getInt8Ty(F.getContext());
37 
38  for (auto I = F.use_begin(), E = F.use_end(); I != E;) {
39  auto CI = dyn_cast<CallInst>(I->getUser());
40  ++I;
41  if (!CI || CI->getCalledValue() != &F)
42  continue;
43 
44  IRBuilder<> B(CI);
45  Value *OffsetPtr =
46  B.CreateGEP(Int8Ty, CI->getArgOperand(0), CI->getArgOperand(1));
47  Value *OffsetPtrI32 = B.CreateBitCast(OffsetPtr, Int32PtrTy);
48  Value *OffsetI32 = B.CreateAlignedLoad(OffsetPtrI32, 4);
49 
50  Value *ResultPtr = B.CreateGEP(Int8Ty, CI->getArgOperand(0), OffsetI32);
51 
52  CI->replaceAllUsesWith(ResultPtr);
53  CI->eraseFromParent();
54  Changed = true;
55  }
56 
57  return Changed;
58 }
59 
60 static bool lowerObjCCall(Function &F, const char *NewFn,
61  bool setNonLazyBind = false) {
62  if (F.use_empty())
63  return false;
64 
65  // If we haven't already looked up this function, check to see if the
66  // program already contains a function with this name.
67  Module *M = F.getParent();
68  Constant* FCache = M->getOrInsertFunction(NewFn, F.getFunctionType());
69 
70  if (Function* Fn = dyn_cast<Function>(FCache)) {
71  Fn->setLinkage(F.getLinkage());
72  if (setNonLazyBind && !Fn->isWeakForLinker()) {
73  // If we have Native ARC, set nonlazybind attribute for these APIs for
74  // performance.
75  Fn->addFnAttr(Attribute::NonLazyBind);
76  }
77  }
78 
79  for (auto I = F.use_begin(), E = F.use_end(); I != E;) {
80  auto *CI = dyn_cast<CallInst>(I->getUser());
81  assert(CI->getCalledFunction() && "Cannot lower an indirect call!");
82  ++I;
83 
84  IRBuilder<> Builder(CI->getParent(), CI->getIterator());
85  SmallVector<Value *, 8> Args(CI->arg_begin(), CI->arg_end());
86  CallInst *NewCI = Builder.CreateCall(FCache, Args);
87  NewCI->setName(CI->getName());
88  NewCI->setTailCallKind(CI->getTailCallKind());
89  if (!CI->use_empty())
90  CI->replaceAllUsesWith(NewCI);
91  CI->eraseFromParent();
92  }
93 
94  return true;
95 }
96 
97 static bool lowerIntrinsics(Module &M) {
98  bool Changed = false;
99  for (Function &F : M) {
100  if (F.getName().startswith("llvm.load.relative.")) {
101  Changed |= lowerLoadRelative(F);
102  continue;
103  }
104  switch (F.getIntrinsicID()) {
105  default:
106  break;
108  Changed |= lowerObjCCall(F, "objc_autorelease");
109  break;
111  Changed |= lowerObjCCall(F, "objc_autoreleasePoolPop");
112  break;
114  Changed |= lowerObjCCall(F, "objc_autoreleasePoolPush");
115  break;
117  Changed |= lowerObjCCall(F, "objc_autoreleaseReturnValue");
118  break;
120  Changed |= lowerObjCCall(F, "objc_copyWeak");
121  break;
123  Changed |= lowerObjCCall(F, "objc_destroyWeak");
124  break;
126  Changed |= lowerObjCCall(F, "objc_initWeak");
127  break;
129  Changed |= lowerObjCCall(F, "objc_loadWeak");
130  break;
132  Changed |= lowerObjCCall(F, "objc_loadWeakRetained");
133  break;
135  Changed |= lowerObjCCall(F, "objc_moveWeak");
136  break;
138  Changed |= lowerObjCCall(F, "objc_release", true);
139  break;
141  Changed |= lowerObjCCall(F, "objc_retain", true);
142  break;
144  Changed |= lowerObjCCall(F, "objc_retainAutorelease");
145  break;
147  Changed |= lowerObjCCall(F, "objc_retainAutoreleaseReturnValue");
148  break;
150  Changed |= lowerObjCCall(F, "objc_retainAutoreleasedReturnValue");
151  break;
153  Changed |= lowerObjCCall(F, "objc_retainBlock");
154  break;
156  Changed |= lowerObjCCall(F, "objc_storeStrong");
157  break;
159  Changed |= lowerObjCCall(F, "objc_storeWeak");
160  break;
162  Changed |= lowerObjCCall(F, "objc_unsafeClaimAutoreleasedReturnValue");
163  break;
165  Changed |= lowerObjCCall(F, "objc_retainedObject");
166  break;
168  Changed |= lowerObjCCall(F, "objc_unretainedObject");
169  break;
171  Changed |= lowerObjCCall(F, "objc_unretainedPointer");
172  break;
174  Changed |= lowerObjCCall(F, "objc_retain_autorelease");
175  break;
177  Changed |= lowerObjCCall(F, "objc_sync_enter");
178  break;
180  Changed |= lowerObjCCall(F, "objc_sync_exit");
181  break;
182  }
183  }
184  return Changed;
185 }
186 
187 namespace {
188 
189 class PreISelIntrinsicLoweringLegacyPass : public ModulePass {
190 public:
191  static char ID;
192 
193  PreISelIntrinsicLoweringLegacyPass() : ModulePass(ID) {}
194 
195  bool runOnModule(Module &M) override { return lowerIntrinsics(M); }
196 };
197 
198 } // end anonymous namespace
199 
201 
202 INITIALIZE_PASS(PreISelIntrinsicLoweringLegacyPass,
203  "pre-isel-intrinsic-lowering", "Pre-ISel Intrinsic Lowering",
204  false, false)
205 
207  return new PreISelIntrinsicLoweringLegacyPass;
208 }
209 
211  ModuleAnalysisManager &AM) {
212  if (!lowerIntrinsics(M))
213  return PreservedAnalyses::all();
214  else
215  return PreservedAnalyses::none();
216 }
use_iterator use_end()
Definition: Value.h:347
This class represents lattice values for constants.
Definition: AllocatorList.h:24
Constant * getOrInsertFunction(StringRef Name, FunctionType *T, AttributeList AttributeList)
Look up the specified function in the module symbol table.
Definition: Module.cpp:144
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:1393
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:652
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition: IRBuilder.h:743
Value * CreateBitCast(Value *V, Type *DestTy, const Twine &Name="")
Definition: IRBuilder.h:1732
LinkageTypes getLinkage() const
Definition: GlobalValue.h:451
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:157
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:154
The instances of the Type class are immutable: once they are created, they are never changed...
Definition: Type.h:46
INITIALIZE_PASS(PreISelIntrinsicLoweringLegacyPass, "pre-isel-intrinsic-lowering", "Pre-ISel Intrinsic Lowering", false, false) ModulePass *llvm
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This is an important base class in LLVM.
Definition: Constant.h:42
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:193
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition: PassManager.h:160
Value * CreateGEP(Value *Ptr, ArrayRef< Value *> IdxList, const Twine &Name="")
Definition: IRBuilder.h:1458
Module.h This file contains the declarations for the Module class.
FunctionType * getFunctionType() const
Returns the FunctionType for me.
Definition: Function.h:164
use_iterator use_begin()
Definition: Value.h:339
static IntegerType * getInt32Ty(LLVMContext &C)
Definition: Type.cpp:176
#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:225
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:323
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Module * getParent()
Get the module that this global value is contained inside of...
Definition: GlobalValue.h:566
LLVM Value Representation.
Definition: Value.h:73
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:174
bool use_empty() const
Definition: Value.h:323
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
IntegerType * Int32Ty