LLVM  14.0.0git
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 
17 #include "llvm/CodeGen/Passes.h"
18 #include "llvm/IR/Function.h"
19 #include "llvm/IR/IRBuilder.h"
20 #include "llvm/IR/Instructions.h"
21 #include "llvm/IR/Intrinsics.h"
22 #include "llvm/IR/Module.h"
23 #include "llvm/IR/Type.h"
24 #include "llvm/IR/User.h"
25 #include "llvm/InitializePasses.h"
26 #include "llvm/Pass.h"
27 #include "llvm/Support/Casting.h"
28 
29 using namespace llvm;
30 
31 static bool lowerLoadRelative(Function &F) {
32  if (F.use_empty())
33  return false;
34 
35  bool Changed = false;
36  Type *Int32Ty = Type::getInt32Ty(F.getContext());
37  Type *Int32PtrTy = Int32Ty->getPointerTo();
38  Type *Int8Ty = Type::getInt8Ty(F.getContext());
39 
40  for (Use &U : llvm::make_early_inc_range(F.uses())) {
41  auto CI = dyn_cast<CallInst>(U.getUser());
42  if (!CI || CI->getCalledOperand() != &F)
43  continue;
44 
45  IRBuilder<> B(CI);
46  Value *OffsetPtr =
47  B.CreateGEP(Int8Ty, CI->getArgOperand(0), CI->getArgOperand(1));
48  Value *OffsetPtrI32 = B.CreateBitCast(OffsetPtr, Int32PtrTy);
49  Value *OffsetI32 = B.CreateAlignedLoad(Int32Ty, OffsetPtrI32, Align(4));
50 
51  Value *ResultPtr = B.CreateGEP(Int8Ty, CI->getArgOperand(0), OffsetI32);
52 
53  CI->replaceAllUsesWith(ResultPtr);
54  CI->eraseFromParent();
55  Changed = true;
56  }
57 
58  return Changed;
59 }
60 
61 // ObjCARC has knowledge about whether an obj-c runtime function needs to be
62 // always tail-called or never tail-called.
66  return CallInst::TCK_Tail;
67  else if (objcarc::IsNeverTail(Kind))
68  return CallInst::TCK_NoTail;
69  return CallInst::TCK_None;
70 }
71 
72 static bool lowerObjCCall(Function &F, const char *NewFn,
73  bool setNonLazyBind = false) {
74  if (F.use_empty())
75  return false;
76 
77  // If we haven't already looked up this function, check to see if the
78  // program already contains a function with this name.
79  Module *M = F.getParent();
80  FunctionCallee FCache = M->getOrInsertFunction(NewFn, F.getFunctionType());
81 
82  if (Function *Fn = dyn_cast<Function>(FCache.getCallee())) {
83  Fn->setLinkage(F.getLinkage());
84  if (setNonLazyBind && !Fn->isWeakForLinker()) {
85  // If we have Native ARC, set nonlazybind attribute for these APIs for
86  // performance.
87  Fn->addFnAttr(Attribute::NonLazyBind);
88  }
89  }
90 
92 
93  for (Use &U : llvm::make_early_inc_range(F.uses())) {
94  auto *CB = cast<CallBase>(U.getUser());
95 
96  if (CB->getCalledFunction() != &F) {
98  (void)Kind;
101  "use expected to be the argument of operand bundle "
102  "\"clang.arc.attachedcall\"");
103  U.set(FCache.getCallee());
104  continue;
105  }
106 
107  auto *CI = cast<CallInst>(CB);
108  assert(CI->getCalledFunction() && "Cannot lower an indirect call!");
109 
110  IRBuilder<> Builder(CI->getParent(), CI->getIterator());
111  SmallVector<Value *, 8> Args(CI->args());
112  CallInst *NewCI = Builder.CreateCall(FCache, Args);
113  NewCI->setName(CI->getName());
114 
115  // Try to set the most appropriate TailCallKind based on both the current
116  // attributes and the ones that we could get from ObjCARC's special
117  // knowledge of the runtime functions.
118  //
119  // std::max respects both requirements of notail and tail here:
120  // * notail on either the call or from ObjCARC becomes notail
121  // * tail on either side is stronger than none, but not notail
122  CallInst::TailCallKind TCK = CI->getTailCallKind();
123  NewCI->setTailCallKind(std::max(TCK, OverridingTCK));
124 
125  if (!CI->use_empty())
126  CI->replaceAllUsesWith(NewCI);
127  CI->eraseFromParent();
128  }
129 
130  return true;
131 }
132 
133 static bool lowerIntrinsics(Module &M) {
134  bool Changed = false;
135  for (Function &F : M) {
136  if (F.getName().startswith("llvm.load.relative.")) {
137  Changed |= lowerLoadRelative(F);
138  continue;
139  }
140  switch (F.getIntrinsicID()) {
141  default:
142  break;
143  case Intrinsic::objc_autorelease:
144  Changed |= lowerObjCCall(F, "objc_autorelease");
145  break;
146  case Intrinsic::objc_autoreleasePoolPop:
147  Changed |= lowerObjCCall(F, "objc_autoreleasePoolPop");
148  break;
149  case Intrinsic::objc_autoreleasePoolPush:
150  Changed |= lowerObjCCall(F, "objc_autoreleasePoolPush");
151  break;
152  case Intrinsic::objc_autoreleaseReturnValue:
153  Changed |= lowerObjCCall(F, "objc_autoreleaseReturnValue");
154  break;
155  case Intrinsic::objc_copyWeak:
156  Changed |= lowerObjCCall(F, "objc_copyWeak");
157  break;
158  case Intrinsic::objc_destroyWeak:
159  Changed |= lowerObjCCall(F, "objc_destroyWeak");
160  break;
161  case Intrinsic::objc_initWeak:
162  Changed |= lowerObjCCall(F, "objc_initWeak");
163  break;
164  case Intrinsic::objc_loadWeak:
165  Changed |= lowerObjCCall(F, "objc_loadWeak");
166  break;
167  case Intrinsic::objc_loadWeakRetained:
168  Changed |= lowerObjCCall(F, "objc_loadWeakRetained");
169  break;
170  case Intrinsic::objc_moveWeak:
171  Changed |= lowerObjCCall(F, "objc_moveWeak");
172  break;
173  case Intrinsic::objc_release:
174  Changed |= lowerObjCCall(F, "objc_release", true);
175  break;
176  case Intrinsic::objc_retain:
177  Changed |= lowerObjCCall(F, "objc_retain", true);
178  break;
179  case Intrinsic::objc_retainAutorelease:
180  Changed |= lowerObjCCall(F, "objc_retainAutorelease");
181  break;
182  case Intrinsic::objc_retainAutoreleaseReturnValue:
183  Changed |= lowerObjCCall(F, "objc_retainAutoreleaseReturnValue");
184  break;
185  case Intrinsic::objc_retainAutoreleasedReturnValue:
186  Changed |= lowerObjCCall(F, "objc_retainAutoreleasedReturnValue");
187  break;
188  case Intrinsic::objc_retainBlock:
189  Changed |= lowerObjCCall(F, "objc_retainBlock");
190  break;
191  case Intrinsic::objc_storeStrong:
192  Changed |= lowerObjCCall(F, "objc_storeStrong");
193  break;
194  case Intrinsic::objc_storeWeak:
195  Changed |= lowerObjCCall(F, "objc_storeWeak");
196  break;
197  case Intrinsic::objc_unsafeClaimAutoreleasedReturnValue:
198  Changed |= lowerObjCCall(F, "objc_unsafeClaimAutoreleasedReturnValue");
199  break;
200  case Intrinsic::objc_retainedObject:
201  Changed |= lowerObjCCall(F, "objc_retainedObject");
202  break;
203  case Intrinsic::objc_unretainedObject:
204  Changed |= lowerObjCCall(F, "objc_unretainedObject");
205  break;
206  case Intrinsic::objc_unretainedPointer:
207  Changed |= lowerObjCCall(F, "objc_unretainedPointer");
208  break;
209  case Intrinsic::objc_retain_autorelease:
210  Changed |= lowerObjCCall(F, "objc_retain_autorelease");
211  break;
212  case Intrinsic::objc_sync_enter:
213  Changed |= lowerObjCCall(F, "objc_sync_enter");
214  break;
215  case Intrinsic::objc_sync_exit:
216  Changed |= lowerObjCCall(F, "objc_sync_exit");
217  break;
218  }
219  }
220  return Changed;
221 }
222 
223 namespace {
224 
225 class PreISelIntrinsicLoweringLegacyPass : public ModulePass {
226 public:
227  static char ID;
228 
229  PreISelIntrinsicLoweringLegacyPass() : ModulePass(ID) {}
230 
231  bool runOnModule(Module &M) override { return lowerIntrinsics(M); }
232 };
233 
234 } // end anonymous namespace
235 
237 
238 INITIALIZE_PASS(PreISelIntrinsicLoweringLegacyPass,
239  "pre-isel-intrinsic-lowering", "Pre-ISel Intrinsic Lowering",
240  false, false)
241 
243  return new PreISelIntrinsicLoweringLegacyPass;
244 }
245 
247  ModuleAnalysisManager &AM) {
248  if (!lowerIntrinsics(M))
249  return PreservedAnalyses::all();
250  else
251  return PreservedAnalyses::none();
252 }
llvm::PreservedAnalyses
A set of analyses that are preserved following a run of a transformation pass.
Definition: PassManager.h:155
lowerLoadRelative
static bool lowerLoadRelative(Function &F)
Definition: PreISelIntrinsicLowering.cpp:31
Int32Ty
IntegerType * Int32Ty
Definition: NVVMIntrRange.cpp:67
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AllocatorList.h:23
M
We currently emits eax Perhaps this is what we really should generate is Is imull three or four cycles eax eax The current instruction priority is based on pattern complexity The former is more complex because it folds a load so the latter will not be emitted Perhaps we should use AddedComplexity to give LEA32r a higher priority We should always try to match LEA first since the LEA matching code does some estimate to determine whether the match is profitable if we care more about code then imull is better It s two bytes shorter than movl leal On a Pentium M
Definition: README.txt:252
llvm::ModulePass
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
Definition: Pass.h:238
lowerIntrinsics
static bool lowerIntrinsics(Module &M)
Definition: PreISelIntrinsicLowering.cpp:133
llvm::Function
Definition: Function.h:62
Pass.h
llvm::SmallVector< Value *, 8 >
llvm::CallInst::setTailCallKind
void setTailCallKind(TailCallKind TCK)
Definition: Instructions.h:1681
llvm::objcarc::GetFunctionClass
ARCInstKind GetFunctionClass(const Function *F)
Determine if F is one of the special known Functions.
Definition: ObjCARCInstKind.cpp:85
llvm::IRBuilder<>
llvm::PreservedAnalyses::none
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
Definition: PassManager.h:158
llvm::Type
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
Module.h
llvm::objcarc::IsNeverTail
bool IsNeverTail(ARCInstKind Class)
Test if the given class represents instructions which are never safe to mark with the "tail" keyword.
Definition: ObjCARCInstKind.cpp:556
llvm::CallInst::TCK_None
@ TCK_None
Definition: Instructions.h:1656
llvm::Type::getInt8Ty
static IntegerType * getInt8Ty(LLVMContext &C)
Definition: Type.cpp:239
llvm::Type::getInt32Ty
static IntegerType * getInt32Ty(LLVMContext &C)
Definition: Type.cpp:241
F
#define F(x, y, z)
Definition: MD5.cpp:55
llvm::createPreISelIntrinsicLoweringPass
ModulePass * createPreISelIntrinsicLoweringPass()
This pass lowers the @llvm.load.relative and @llvm.objc.
getOverridingTailCallKind
static CallInst::TailCallKind getOverridingTailCallKind(const Function &F)
Definition: PreISelIntrinsicLowering.cpp:63
Intrinsics.h
llvm::objcarc::ARCInstKind::RetainRV
@ RetainRV
objc_retainAutoreleasedReturnValue
B
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
llvm::Value::setName
void setName(const Twine &Name)
Change the name of the value.
Definition: Value.cpp:376
Align
uint64_t Align
Definition: ELFObjHandler.cpp:82
llvm::lltok::Kind
Kind
Definition: LLToken.h:18
llvm::objcarc::ARCInstKind
ARCInstKind
Definition: ObjCARCInstKind.h:28
Type.h
llvm::objcarc::IsAlwaysTail
bool IsAlwaysTail(ARCInstKind Class)
Test if the given class represents instructions which are always safe to mark with the "tail" keyword...
Definition: ObjCARCInstKind.cpp:520
Passes.h
llvm::PreISelIntrinsicLoweringPass::run
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
Definition: PreISelIntrinsicLowering.cpp:246
llvm::CallInst::TailCallKind
TailCallKind
Definition: Instructions.h:1655
llvm::make_early_inc_range
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
Definition: STLExtras.h:642
ObjCARCInstKind.h
IRBuilder.h
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::Module
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:65
Builder
assume Assume Builder
Definition: AssumeBundleBuilder.cpp:650
INITIALIZE_PASS
INITIALIZE_PASS(PreISelIntrinsicLoweringLegacyPass, "pre-isel-intrinsic-lowering", "Pre-ISel Intrinsic Lowering", false, false) ModulePass *llvm
Definition: PreISelIntrinsicLowering.cpp:238
llvm::CallInst::TCK_Tail
@ TCK_Tail
Definition: Instructions.h:1657
llvm::objcarc::getAttachedARCFunctionKind
ARCInstKind getAttachedARCFunctionKind(const CallBase *CB)
This function returns the ARCInstKind of the function attached to operand bundle clang_arc_attachedca...
Definition: ObjCARCUtil.h:60
lowerObjCCall
static bool lowerObjCCall(Function &F, const char *NewFn, bool setNonLazyBind=false)
Definition: PreISelIntrinsicLowering.cpp:72
llvm::FunctionCallee::getCallee
Value * getCallee()
Definition: DerivedTypes.h:184
ObjCARCUtil.h
llvm::PreservedAnalyses::all
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition: PassManager.h:161
Casting.h
Function.h
llvm::Type::getPointerTo
PointerType * getPointerTo(unsigned AddrSpace=0) const
Return a pointer to the current type.
Definition: Type.cpp:776
llvm::objcarc::ARCInstKind::ClaimRV
@ ClaimRV
objc_unsafeClaimAutoreleasedReturnValue
Instructions.h
User.h
llvm::max
Align max(MaybeAlign Lhs, Align Rhs)
Definition: Alignment.h:340
llvm::FunctionCallee
A handy container for a FunctionType+Callee-pointer pair, which can be passed around as a single enti...
Definition: DerivedTypes.h:165
llvm::AnalysisManager
A container for analyses that lazily runs them and caches their results.
Definition: InstructionSimplify.h:44
llvm::CallInst
This class represents a function call, abstracting a target machine's calling convention.
Definition: Instructions.h:1478
llvm::AMDGPU::HSAMD::Kernel::Key::Args
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
Definition: AMDGPUMetadata.h:389
setNonLazyBind
static bool setNonLazyBind(Function &F)
Definition: BuildLibCalls.cpp:205
llvm::CallInst::TCK_NoTail
@ TCK_NoTail
Definition: Instructions.h:1659
InitializePasses.h
llvm::Value
LLVM Value Representation.
Definition: Value.h:74
PreISelIntrinsicLowering.h
llvm::Use
A Use represents the edge between a Value definition and its users.
Definition: Use.h:44
llvm::Intrinsic::ID
unsigned ID
Definition: TargetTransformInfo.h:38