46 "mem-intrinsic-expand-size",
52struct PreISelIntrinsicLowering {
60 const bool UseMemIntrinsicLibFunc;
62 explicit PreISelIntrinsicLowering(
66 bool UseMemIntrinsicLibFunc_ =
true)
67 : TM(TM_), LookupTTI(LookupTTI_), LookupTLI(LookupTLI_),
68 UseMemIntrinsicLibFunc(UseMemIntrinsicLibFunc_) {}
70 static bool shouldExpandMemIntrinsicWithSize(
Value *
Size,
71 const TargetTransformInfo &
TTI);
73 expandMemIntrinsicUses(Function &
F,
74 DenseMap<Constant *, GlobalVariable *> &CMap)
const;
75 bool lowerIntrinsics(
Module &M)
const;
86 Use *LastUse =
nullptr;
88 while (!Intrin.
use_empty() && (!LastUse || LastUse->getNext())) {
89 Use *U = LastUse ? LastUse->getNext() : &*Intrin.
use_begin();
94 Changed |= Removed = Callback(CI);
110 if (!CI || CI->getCalledOperand() != &
F)
115 B.CreatePtrAdd(CI->getArgOperand(0), CI->getArgOperand(1));
118 Value *ResultPtr =
B.CreatePtrAdd(CI->getArgOperand(0), OffsetI32);
120 CI->replaceAllUsesWith(ResultPtr);
121 CI->eraseFromParent();
142 "Pre-ISel intrinsics do lower into regular function calls");
154 M->getOrInsertFunction(NewFnName,
F.getFunctionType());
157 Fn->setLinkage(
F.getLinkage());
161 Fn->addFnAttr(Attribute::NonLazyBind);
170 if (CB->getCalledFunction() != &
F) {
172 "use expected to be the argument of operand bundle "
173 "\"clang.arc.attachedcall\"");
179 assert(CI->getCalledFunction() &&
"Cannot lower an indirect call!");
181 IRBuilder<> Builder(CI->getParent(), CI->getIterator());
184 CI->getOperandBundlesAsDefs(BundleList);
185 CallInst *NewCI = Builder.CreateCall(FCache, Args, BundleList);
203 if (
F.getAttributes().hasAttrSomewhere(Attribute::Returned, &Index) &&
205 NewCI->
addParamAttr(Index - AttributeList::FirstArgIndex,
206 Attribute::Returned);
208 if (!CI->use_empty())
209 CI->replaceAllUsesWith(NewCI);
210 CI->eraseFromParent();
218bool PreISelIntrinsicLowering::shouldExpandMemIntrinsicWithSize(
230 return SizeVal > Threshold || Threshold == 0;
238 const TargetLowering *TLI = TM->getSubtargetImpl(*F)->getTargetLowering();
246 const TargetLowering *TLI = TM->getSubtargetImpl(*F)->getTargetLowering();
263 Type *VTy = V->getType();
283 if (
DL.isBigEndian())
306bool PreISelIntrinsicLowering::expandMemIntrinsicUses(
307 Function &
F, DenseMap<Constant *, GlobalVariable *> &CMap)
const {
315 case Intrinsic::memcpy: {
317 Function *ParentFunc = Memcpy->getFunction();
318 const TargetTransformInfo &
TTI = LookupTTI(*ParentFunc);
319 if (shouldExpandMemIntrinsicWithSize(Memcpy->getLength(),
TTI)) {
326 Memcpy->eraseFromParent();
331 case Intrinsic::memcpy_inline: {
340 const TargetTransformInfo &
TTI = LookupTTI(*ParentFunc);
343 Memcpy->eraseFromParent();
346 case Intrinsic::memmove: {
349 const TargetTransformInfo &
TTI = LookupTTI(*ParentFunc);
350 if (shouldExpandMemIntrinsicWithSize(Memmove->getLength(),
TTI)) {
351 if (UseMemIntrinsicLibFunc &&
357 Memmove->eraseFromParent();
363 case Intrinsic::memset: {
366 const TargetTransformInfo &
TTI = LookupTTI(*ParentFunc);
367 if (shouldExpandMemIntrinsicWithSize(Memset->getLength(),
TTI)) {
368 if (UseMemIntrinsicLibFunc &&
374 Memset->eraseFromParent();
379 case Intrinsic::memset_inline: {
389 Memset->eraseFromParent();
392 case Intrinsic::experimental_memset_pattern: {
394 const TargetLibraryInfo &TLI = LookupTLI(*Memset->getFunction());
401 Memset->eraseFromParent();
407 Module *
M = Memset->getModule();
408 const DataLayout &
DL = Memset->getDataLayout();
410 Type *DestPtrTy = Memset->getRawDest()->getType();
412 StringRef FuncName =
"memset_pattern16";
414 Builder.getVoidTy(), DestPtrTy,
415 Builder.getPtrTy(), SizeTTy);
421 assert(Memset->getRawDest()->getType()->getPointerAddressSpace() == 0 &&
422 "Should have skipped if non-zero AS");
424 auto It = CMap.
find(PatternValue);
425 if (It != CMap.
end()) {
428 GV =
new GlobalVariable(
429 *M, PatternValue->
getType(),
true,
432 GlobalValue::UnnamedAddr::Global);
435 CMap[PatternValue] = GV;
437 Value *PatternPtr = GV;
438 Value *NumBytes = Builder.CreateMul(
439 TLI.
getAsSizeT(
DL.getTypeAllocSize(Memset->getValue()->getType()),
441 Builder.CreateZExtOrTrunc(Memset->getLength(), SizeTTy));
442 CallInst *MemsetPattern16Call =
443 Builder.CreateCall(MSP, {Memset->getRawDest(), PatternPtr, NumBytes});
447 AttrBuilder ArgAttrs(Memset->getContext(),
448 Memset->getAttributes().getParamAttrs(0));
451 Memset->getContext(), 0, ArgAttrs));
453 Memset->eraseFromParent();
464bool PreISelIntrinsicLowering::lowerIntrinsics(
Module &M)
const {
466 DenseMap<Constant *, GlobalVariable *> CMap;
468 for (Function &
F : M) {
469 switch (
F.getIntrinsicID()) {
472 case Intrinsic::memcpy:
473 case Intrinsic::memcpy_inline:
474 case Intrinsic::memmove:
475 case Intrinsic::memset:
476 case Intrinsic::memset_inline:
477 case Intrinsic::experimental_memset_pattern:
478 Changed |= expandMemIntrinsicUses(
F, CMap);
480 case Intrinsic::load_relative:
483 case Intrinsic::is_constant:
484 case Intrinsic::objectsize:
487 TargetLibraryInfo &TLI = LookupTLI(*Parent);
493#define BEGIN_REGISTER_VP_INTRINSIC(VPID, MASKPOS, VLENPOS) \
494 case Intrinsic::VPID:
495#include "llvm/IR/VPIntrinsics.def"
498 const TargetTransformInfo &
TTI = LookupTTI(*Parent);
504 Changed |= ED != VPExpansionDetails::IntrinsicUnchanged;
505 bool Removed = ED == VPExpansionDetails::IntrinsicReplaced;
509 case Intrinsic::objc_autorelease:
512 case Intrinsic::objc_autoreleasePoolPop:
515 case Intrinsic::objc_autoreleasePoolPush:
518 case Intrinsic::objc_autoreleaseReturnValue:
521 case Intrinsic::objc_copyWeak:
524 case Intrinsic::objc_destroyWeak:
527 case Intrinsic::objc_initWeak:
530 case Intrinsic::objc_loadWeak:
533 case Intrinsic::objc_loadWeakRetained:
536 case Intrinsic::objc_moveWeak:
539 case Intrinsic::objc_release:
542 case Intrinsic::objc_retain:
545 case Intrinsic::objc_retainAutorelease:
548 case Intrinsic::objc_retainAutoreleaseReturnValue:
552 case Intrinsic::objc_retainAutoreleasedReturnValue:
556 case Intrinsic::objc_claimAutoreleasedReturnValue:
560 case Intrinsic::objc_retainBlock:
563 case Intrinsic::objc_storeStrong:
566 case Intrinsic::objc_storeWeak:
569 case Intrinsic::objc_unsafeClaimAutoreleasedReturnValue:
571 lowerObjCCall(
F, RTLIB::impl_objc_unsafeClaimAutoreleasedReturnValue);
573 case Intrinsic::objc_retainedObject:
576 case Intrinsic::objc_unretainedObject:
579 case Intrinsic::objc_unretainedPointer:
582 case Intrinsic::objc_retain_autorelease:
585 case Intrinsic::objc_sync_enter:
588 case Intrinsic::objc_sync_exit:
592 case Intrinsic::exp2:
598 const TargetLowering *TL =
TM->getSubtargetImpl(
F)->getTargetLowering();
613class PreISelIntrinsicLoweringLegacyPass :
public ModulePass {
617 PreISelIntrinsicLoweringLegacyPass() : ModulePass(
ID) {}
619 void getAnalysisUsage(AnalysisUsage &AU)
const override {
625 bool runOnModule(
Module &M)
override {
626 auto LookupTTI = [
this](
Function &
F) -> TargetTransformInfo & {
627 return this->getAnalysis<TargetTransformInfoWrapperPass>().getTTI(
F);
629 auto LookupTLI = [
this](
Function &
F) -> TargetLibraryInfo & {
630 return this->getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(
F);
633 const auto *
TM = &getAnalysis<TargetPassConfig>().getTM<TargetMachine>();
634 PreISelIntrinsicLowering
Lowering(TM, LookupTTI, LookupTLI);
641char PreISelIntrinsicLoweringLegacyPass::ID;
644 "pre-isel-intrinsic-lowering",
645 "Pre-ISel Intrinsic Lowering",
false,
false)
650 "pre-isel-intrinsic-lowering",
654 return new PreISelIntrinsicLoweringLegacyPass();
668 PreISelIntrinsicLowering
Lowering(
TM, LookupTTI, LookupTLI);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static bool setNonLazyBind(Function &F)
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
Module.h This file contains the declarations for the Module class.
This defines the Use class.
The header file for the LowerConstantIntrinsics pass as used by the new pass manager.
Machine Check Debug Module
This file defines ARC utility functions which are used by various parts of the compiler.
FunctionAnalysisManager FAM
#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.
static bool forEachCall(Function &Intrin, T Callback)
pre isel intrinsic Pre ISel Intrinsic Lowering
static bool canEmitLibcall(const TargetMachine *TM, Function *F, RTLIB::Libcall LC)
static CallInst::TailCallKind getOverridingTailCallKind(const Function &F)
static Constant * getMemSetPattern16Value(MemSetPatternInst *Inst, const TargetLibraryInfo &TLI)
static bool canEmitMemcpy(const TargetMachine *TM, Function *F)
static bool lowerObjCCall(Function &F, RTLIB::LibcallImpl NewFn, bool setNonLazyBind=false)
static bool lowerLoadRelative(Function &F)
This file describes how to lower LLVM code to machine code.
Target-Independent Code Generator Pass Configuration Options pass.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
AnalysisUsage & addRequired()
static LLVM_ABI ArrayType * get(Type *ElementType, uint64_t NumElements)
This static method is the primary way to construct an ArrayType.
void setAttributes(AttributeList A)
Set the attributes for this call.
Value * getArgOperand(unsigned i) const
AttributeList getAttributes() const
Return the attributes for this call.
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)
static LLVM_ABI Constant * get(ArrayType *T, ArrayRef< Constant * > V)
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
This is an important base class in LLVM.
A parsed version of the target data layout string in and methods for querying it.
iterator find(const_arg_type_t< KeyT > Val)
A handy container for a FunctionType+Callee-pointer pair, which can be passed around as a single enti...
const Function & getFunction() const
void setUnnamedAddr(UnnamedAddr Val)
@ PrivateLinkage
Like Internal, but omit from symbol table.
void setAlignment(Align Align)
Sets the alignment attribute of the GlobalVariable.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
LLVM_ABI const Module * getModule() const
Return the module owning the function this instruction belongs to or nullptr it the function does not...
LLVM_ABI void setAAMetadata(const AAMDNodes &N)
Sets the AA metadata on this instruction from the AAMDNodes structure.
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this instruction belongs to.
static LLVM_ABI bool mayLowerToFunctionCall(Intrinsic::ID IID)
Check if the intrinsic might lower into a regular function call in the course of IR transformations.
Value * getRawDest() const
This class wraps the llvm.experimental.memset.pattern intrinsic.
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
A Module instance is used to store all the information related to an LLVM module.
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.
StringRef - Represent a constant reference to a string, i.e.
Analysis pass providing the TargetTransformInfo.
Analysis pass providing the TargetLibraryInfo.
Provides information about what library functions are available for the current target.
ConstantInt * getAsSizeT(uint64_t V, const Module &M) const
Returns a constant materialized as a size_t type.
IntegerType * getSizeTType(const Module &M) const
Returns an IntegerType corresponding to size_t.
bool isOperationExpand(unsigned Op, EVT VT) const
Return true if the specified operation is illegal on this target or unlikely to be made legal with cu...
const char * getMemcpyName() const
int IntrinsicIDToISD(Intrinsic::ID ID) const
Get the ISD node that corresponds to the Intrinsic ID.
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 LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
LLVM_ABI unsigned getPointerAddressSpace() const
Get the address space of this pointer or pointer vector type.
A Use represents the edge between a Value definition and its users.
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
LLVM_ABI void setName(const Twine &Name)
Change the name of the value.
An efficient, type-erasing, non-owning reference to a callable.
const ParentTy * getParent() const
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ C
The default llvm calling convention, compatible with C.
@ DELETED_NODE
DELETED_NODE - This is an illegal value that is used to catch errors.
initializer< Ty > init(const Ty &Val)
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.
std::optional< Function * > getAttachedARCFunction(const CallBase *CB)
This function returns operand bundle clang_arc_attachedcall's argument, which is the address of the A...
friend class Instruction
Iterator for Instructions in a `BasicBlock.
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
bool lowerUnaryVectorIntrinsicAsLoop(Module &M, CallInst *CI)
Lower CI as a loop.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
FunctionAddr VTableAddr uintptr_t uintptr_t Int32Ty
bool lowerConstantIntrinsics(Function &F, const TargetLibraryInfo &TLI, DominatorTree *DT)
LLVM_ABI void expandMemSetPatternAsLoop(MemSetPatternInst *MemSet)
Expand MemSetPattern as a loop. MemSet is not deleted.
LLVM_ABI 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...
InnerAnalysisManagerProxy< FunctionAnalysisManager, Module > FunctionAnalysisManagerModuleProxy
Provide the FunctionAnalysisManager to Module proxy.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
LLVM_ABI bool inferNonMandatoryLibFuncAttrs(Module *M, StringRef Name, const TargetLibraryInfo &TLI)
Analyze the name and prototype of the given function and set any applicable attributes.
LLVM_ABI bool isLibFuncEmittable(const Module *M, const TargetLibraryInfo *TLI, LibFunc TheLibFunc)
Check whether the library function is available on target and also that it in the current Module is a...
LLVM_ABI ModulePass * createPreISelIntrinsicLoweringPass()
This pass lowers the @llvm.load.relative and @llvm.objc.
LLVM_ABI FunctionCallee getOrInsertLibFunc(Module *M, const TargetLibraryInfo &TLI, LibFunc TheLibFunc, FunctionType *T, AttributeList AttributeList)
Calls getOrInsertFunction() and then makes sure to add mandatory argument attributes.
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
VPExpansionDetails expandVectorPredicationIntrinsic(VPIntrinsic &VPI, const TargetTransformInfo &TTI)
Expand a vector predication intrinsic.
IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >
DWARFExpression::Operation Op
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI void expandMemCpyAsLoop(MemCpyInst *MemCpy, const TargetTransformInfo &TTI, ScalarEvolution *SE=nullptr)
Expand MemCpy as a loop. MemCpy is not deleted.
VPExpansionDetails
Represents the details the expansion of a VP intrinsic.
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
LLVM_ABI 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.
static LLVM_ABI EVT getEVT(Type *Ty, bool HandleUnknown=false)
Return the value type corresponding to the specified type.
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
static StringRef getLibcallImplName(RTLIB::LibcallImpl CallImpl)
Get the libcall routine name for the specified libcall implementation.