39 "mem-intrinsic-expand-size",
45struct PreISelIntrinsicLowering {
52 const bool UseMemIntrinsicLibFunc;
54 explicit PreISelIntrinsicLowering(
57 bool UseMemIntrinsicLibFunc_ =
true)
58 :
TM(TM_), LookupTTI(LookupTTI_),
59 UseMemIntrinsicLibFunc(UseMemIntrinsicLibFunc_) {}
61 static bool shouldExpandMemIntrinsicWithSize(
Value *
Size,
63 bool expandMemIntrinsicUses(
Function &
F)
const;
78 auto CI = dyn_cast<CallInst>(U.getUser());
79 if (!CI || CI->getCalledOperand() != &
F)
84 B.CreateGEP(Int8Ty, CI->getArgOperand(0), CI->getArgOperand(1));
87 Value *ResultPtr =
B.CreateGEP(Int8Ty, CI->getArgOperand(0), OffsetI32);
89 CI->replaceAllUsesWith(ResultPtr);
90 CI->eraseFromParent();
111 "Pre-ISel intrinsics do lower into regular function calls");
118 FunctionCallee FCache = M->getOrInsertFunction(NewFn,
F.getFunctionType());
121 Fn->setLinkage(
F.getLinkage());
125 Fn->addFnAttr(Attribute::NonLazyBind);
132 auto *CB = cast<CallBase>(U.getUser());
134 if (CB->getCalledFunction() != &
F) {
137 assert((Kind == objcarc::ARCInstKind::RetainRV ||
138 Kind == objcarc::ARCInstKind::UnsafeClaimRV) &&
139 "use expected to be the argument of operand bundle "
140 "\"clang.arc.attachedcall\"");
145 auto *CI = cast<CallInst>(CB);
146 assert(CI->getCalledFunction() &&
"Cannot lower an indirect call!");
151 CI->getOperandBundlesAsDefs(BundleList);
170 if (
F.getAttributes().hasAttrSomewhere(Attribute::Returned, &
Index) &&
173 Attribute::Returned);
175 if (!CI->use_empty())
176 CI->replaceAllUsesWith(NewCI);
177 CI->eraseFromParent();
185bool PreISelIntrinsicLowering::shouldExpandMemIntrinsicWithSize(
197 return SizeVal > Threshold || Threshold == 0;
209bool PreISelIntrinsicLowering::expandMemIntrinsicUses(
Function &
F)
const {
211 bool Changed =
false;
217 case Intrinsic::memcpy: {
218 auto *Memcpy = cast<MemCpyInst>(Inst);
221 if (shouldExpandMemIntrinsicWithSize(Memcpy->getLength(),
TTI)) {
222 if (UseMemIntrinsicLibFunc &&
229 Memcpy->eraseFromParent();
234 case Intrinsic::memmove: {
235 auto *Memmove = cast<MemMoveInst>(Inst);
238 if (shouldExpandMemIntrinsicWithSize(Memmove->getLength(),
TTI)) {
239 if (UseMemIntrinsicLibFunc &&
245 Memmove->eraseFromParent();
251 case Intrinsic::memset: {
252 auto *Memset = cast<MemSetInst>(Inst);
255 if (shouldExpandMemIntrinsicWithSize(Memset->getLength(),
TTI)) {
256 if (UseMemIntrinsicLibFunc &&
262 Memset->eraseFromParent();
275bool PreISelIntrinsicLowering::lowerIntrinsics(
Module &M)
const {
276 bool Changed =
false;
278 switch (
F.getIntrinsicID()) {
281 case Intrinsic::memcpy:
282 case Intrinsic::memmove:
283 case Intrinsic::memset:
284 Changed |= expandMemIntrinsicUses(
F);
286 case Intrinsic::load_relative:
289 case Intrinsic::objc_autorelease:
292 case Intrinsic::objc_autoreleasePoolPop:
295 case Intrinsic::objc_autoreleasePoolPush:
298 case Intrinsic::objc_autoreleaseReturnValue:
301 case Intrinsic::objc_copyWeak:
304 case Intrinsic::objc_destroyWeak:
307 case Intrinsic::objc_initWeak:
310 case Intrinsic::objc_loadWeak:
313 case Intrinsic::objc_loadWeakRetained:
316 case Intrinsic::objc_moveWeak:
319 case Intrinsic::objc_release:
322 case Intrinsic::objc_retain:
325 case Intrinsic::objc_retainAutorelease:
328 case Intrinsic::objc_retainAutoreleaseReturnValue:
331 case Intrinsic::objc_retainAutoreleasedReturnValue:
332 Changed |=
lowerObjCCall(
F,
"objc_retainAutoreleasedReturnValue");
334 case Intrinsic::objc_retainBlock:
337 case Intrinsic::objc_storeStrong:
340 case Intrinsic::objc_storeWeak:
343 case Intrinsic::objc_unsafeClaimAutoreleasedReturnValue:
344 Changed |=
lowerObjCCall(
F,
"objc_unsafeClaimAutoreleasedReturnValue");
346 case Intrinsic::objc_retainedObject:
349 case Intrinsic::objc_unretainedObject:
352 case Intrinsic::objc_unretainedPointer:
355 case Intrinsic::objc_retain_autorelease:
358 case Intrinsic::objc_sync_enter:
361 case Intrinsic::objc_sync_exit:
371class PreISelIntrinsicLoweringLegacyPass :
public ModulePass {
375 PreISelIntrinsicLoweringLegacyPass() :
ModulePass(
ID) {}
384 return this->getAnalysis<TargetTransformInfoWrapperPass>().getTTI(
F);
387 const auto &
TM = getAnalysis<TargetPassConfig>().getTM<
TargetMachine>();
388 PreISelIntrinsicLowering
Lowering(
TM, LookupTTI);
395char PreISelIntrinsicLoweringLegacyPass::ID;
398 "pre-isel-intrinsic-lowering",
399 "Pre-ISel Intrinsic Lowering",
false,
false)
407 return new PreISelIntrinsicLoweringLegacyPass();
418 PreISelIntrinsicLowering
Lowering(
TM, LookupTTI);
static bool setNonLazyBind(Function &F)
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static bool lowerIntrinsics(Module &M)
Module.h This file contains the declarations for the Module class.
This file defines ARC utility functions which are used by various parts of the compiler.
FunctionAnalysisManager FAM
const char LLVMTargetMachineRef TM
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
static cl::opt< int64_t > MemIntrinsicExpandSizeThresholdOpt("mem-intrinsic-expand-size", cl::desc("Set minimum mem intrinsic size to expand in IR"), cl::init(-1), cl::Hidden)
Threshold to leave statically sized memory intrinsic calls.
pre isel intrinsic lowering
pre isel intrinsic Pre ISel Intrinsic Lowering
static bool lowerObjCCall(Function &F, const char *NewFn, bool setNonLazyBind=false)
static CallInst::TailCallKind getOverridingTailCallKind(const Function &F)
static bool lowerLoadRelative(Function &F)
static bool canEmitLibcall(const TargetMachine &TM, Function *F, RTLIB::Libcall LC)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file describes how to lower LLVM code to machine code.
Target-Independent Code Generator Pass Configuration Options pass.
A container for analyses that lazily runs them and caches their results.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
void addParamAttr(unsigned ArgNo, Attribute::AttrKind Kind)
Adds the attribute to the indicated argument.
This class represents a function call, abstracting a target machine's calling convention.
void setTailCallKind(TailCallKind TCK)
This is the shared class of boolean and integer constants.
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
A handy container for a FunctionType+Callee-pointer pair, which can be passed around as a single enti...
const Function & getFunction() const
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
An analysis over an "outer" IR unit that provides access to an analysis manager over an "inner" IR un...
static bool mayLowerToFunctionCall(Intrinsic::ID IID)
Check if the intrinsic might lower into a regular function call in the course of IR transformations.
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
virtual bool runOnModule(Module &M)=0
runOnModule - Virtual method overriden by subclasses to process the module being operated on.
A Module instance is used to store all the information related to an LLVM module.
virtual void getAnalysisUsage(AnalysisUsage &) const
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Analysis pass providing the TargetTransformInfo.
const char * getLibcallName(RTLIB::Libcall Call) const
Get the libcall routine name for the specified libcall.
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
Primary interface to the complete machine description for the target machine.
Target-Independent Code Generator Pass Configuration Options.
The instances of the Type class are immutable: once they are created, they are never changed.
static IntegerType * getInt8Ty(LLVMContext &C)
static IntegerType * getInt32Ty(LLVMContext &C)
A Use represents the edge between a Value definition and its users.
LLVM Value Representation.
void setName(const Twine &Name)
Change the name of the value.
An efficient, type-erasing, non-owning reference to a callable.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Libcall
RTLIB::Libcall enum - This enum defines all of the runtime library calls the backend can emit.
initializer< Ty > init(const Ty &Val)
ARCInstKind getAttachedARCFunctionKind(const CallBase *CB)
This function returns the ARCInstKind of the function attached to operand bundle clang_arc_attachedca...
bool IsNeverTail(ARCInstKind Class)
Test if the given class represents instructions which are never safe to mark with the "tail" keyword.
bool IsAlwaysTail(ARCInstKind Class)
Test if the given class represents instructions which are always safe to mark with the "tail" keyword...
ARCInstKind
Equivalence classes of instructions in the ARC Model.
ARCInstKind GetFunctionClass(const Function *F)
Determine if F is one of the special known Functions.
This is an optimization pass for GlobalISel generic memory operations.
bool expandMemMoveAsLoop(MemMoveInst *MemMove, const TargetTransformInfo &TTI)
Expand MemMove as a loop.
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...
ModulePass * createPreISelIntrinsicLoweringPass()
This pass lowers the @llvm.load.relative and @llvm.objc.
void expandMemCpyAsLoop(MemCpyInst *MemCpy, const TargetTransformInfo &TTI, ScalarEvolution *SE=nullptr)
Expand MemCpy as a loop. MemCpy is not deleted.
void expandMemSetAsLoop(MemSetInst *MemSet)
Expand MemSet as a loop. MemSet is not deleted.
This struct is a compact representation of a valid (non-zero power of two) alignment.
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)