39 #define DEBUG_TYPE "load-store-vectorizer"
40 STATISTIC(NumVectorInstructions,
"Number of vector accesses generated");
41 STATISTIC(NumScalarsVectorized,
"Number of scalar accesses vectorized");
46 static const unsigned StackAdjustedAlignment = 4;
62 : F(F), AA(AA), DT(DT), SE(SE), TTI(TTI),
70 unsigned getPointerAddressSpace(
Value *
I);
77 return DL.getABITypeAlignment(LI->
getType());
95 std::pair<BasicBlock::iterator, BasicBlock::iterator>
117 std::pair<InstrListMap, InstrListMap> collectInstructions(
BasicBlock *BB);
121 bool vectorizeChains(InstrListMap &Map);
137 bool accessIsMisaligned(
unsigned SzInBytes,
unsigned AddressSpace,
149 bool runOnFunction(
Function &
F)
override;
152 return "GPU Load and Store Vectorizer";
166 "Vectorize load and Store instructions",
false,
false)
175 char LoadStoreVectorizer::
ID = 0;
178 return new LoadStoreVectorizer();
188 bool LoadStoreVectorizer::runOnFunction(
Function &
F) {
190 if (skipFunction(F) || F.
hasFnAttribute(Attribute::NoImplicitFloat))
193 AliasAnalysis &AA = getAnalysis<AAResultsWrapperPass>().getAAResults();
194 DominatorTree &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree();
195 ScalarEvolution &SE = getAnalysis<ScalarEvolutionWrapperPass>().getSE();
197 getAnalysis<TargetTransformInfoWrapperPass>().getTTI(F);
199 Vectorizer V(F, AA, DT, SE, TTI);
204 bool Vectorizer::run() {
205 bool Changed =
false;
209 InstrListMap LoadRefs, StoreRefs;
210 std::tie(LoadRefs, StoreRefs) = collectInstructions(BB);
211 Changed |= vectorizeChains(LoadRefs);
212 Changed |= vectorizeChains(StoreRefs);
219 if (
LoadInst *LI = dyn_cast<LoadInst>(I))
221 if (
StoreInst *SI = dyn_cast<StoreInst>(I))
226 unsigned Vectorizer::getPointerAddressSpace(
Value *I) {
228 return L->getPointerAddressSpace();
229 if (
StoreInst *S = dyn_cast<StoreInst>(I))
230 return S->getPointerAddressSpace();
238 unsigned ASA = getPointerAddressSpace(A);
239 unsigned ASB = getPointerAddressSpace(B);
242 if (!PtrA || !PtrB || (ASA != ASB))
246 unsigned PtrBitWidth =
DL.getPointerSizeInBits(ASA);
250 DL.getTypeStoreSize(PtrATy) !=
DL.getTypeStoreSize(PtrBTy) ||
255 APInt Size(PtrBitWidth,
DL.getTypeStoreSize(PtrATy));
257 APInt OffsetA(PtrBitWidth, 0), OffsetB(PtrBitWidth, 0);
261 APInt OffsetDelta = OffsetB - OffsetA;
266 return OffsetDelta == Size;
270 APInt BaseDelta = Size - OffsetDelta;
288 if (!GEPA || !GEPB || GEPA->
getNumOperands() != GEPB->getNumOperands())
291 for (
unsigned i = 0;
i < FinalIndex;
i++)
297 if (!OpA || !OpB || OpA->
getOpcode() != OpB->getOpcode() ||
298 OpA->
getType() != OpB->getType())
302 if (!isa<SExtInst>(OpA) && !isa<ZExtInst>(OpA))
305 bool Signed = isa<SExtInst>(OpA);
309 if (!OpA || !OpB || OpA->getType() != OpB->getType())
317 isa<ConstantInt>(OpB->getOperand(1)) &&
318 cast<ConstantInt>(OpB->getOperand(1))->getSExtValue() > 0) {
320 Safe = cast<BinaryOperator>(OpB)->hasNoSignedWrap();
322 Safe = cast<BinaryOperator>(OpB)->hasNoUnsignedWrap();
325 unsigned BitWidth = OpA->getType()->getScalarSizeInBits();
331 APInt KnownZero(BitWidth, 0);
332 APInt KnownOne(BitWidth, 0);
334 KnownZero &= ~
APInt::getHighBitsSet(BitWidth, 1);
346 return X2 == OffsetSCEVB;
355 while (!Worklist.
empty()) {
358 for (
int i = 0;
i < NumOperands;
i++) {
360 if (!IM || IM->
getOpcode() == Instruction::PHI)
368 if (!OBB.dominates(IM, I)) {
369 InstructionsToMove.insert(IM);
378 if (!InstructionsToMove.count(&*BBI))
387 std::pair<BasicBlock::iterator, BasicBlock::iterator>
394 unsigned NumFound = 0;
403 if (NumFound == Chain.
size()) {
410 return std::make_pair(FirstInstr, ++LastInstr);
417 assert(PtrOperand &&
"Instruction must have a pointer operand.");
431 unsigned ElementSizeBits) {
432 unsigned ElementSizeBytes = ElementSizeBits / 8;
433 unsigned SizeBytes = ElementSizeBytes * Chain.
size();
434 unsigned NumLeft = (SizeBytes - (SizeBytes % 4)) / ElementSizeBytes;
435 if (NumLeft == Chain.
size())
437 else if (NumLeft == 0)
439 return std::make_pair(Chain.
slice(0, NumLeft), Chain.
slice(NumLeft));
448 bool IsLoadChain = isa<LoadInst>(Chain[0]);
452 assert(isa<LoadInst>(I) &&
453 "All elements of Chain must be loads, or all must be stores.");
455 assert(isa<StoreInst>(I) &&
456 "All elements of Chain must be loads, or all must be stores.");
461 if (isa<LoadInst>(I) || isa<StoreInst>(
I)) {
467 DEBUG(
dbgs() <<
"LSV: Found may-write/throw operation: " << I <<
'\n');
470 DEBUG(
dbgs() <<
"LSV: Found may-read/write/throw operation: " << I
479 unsigned ChainInstrIdx = 0;
482 for (
unsigned E = ChainInstrs.
size(); ChainInstrIdx <
E; ++ChainInstrIdx) {
483 Instruction *ChainInstr = ChainInstrs[ChainInstrIdx];
487 if (BarrierMemoryInstr && OBB.dominates(BarrierMemoryInstr, ChainInstr))
494 if (BarrierMemoryInstr && OBB.dominates(BarrierMemoryInstr, MemInstr))
497 if (isa<LoadInst>(MemInstr) && isa<LoadInst>(ChainInstr))
504 if (isa<StoreInst>(MemInstr) && isa<LoadInst>(ChainInstr) &&
505 OBB.dominates(ChainInstr, MemInstr))
509 if (isa<LoadInst>(MemInstr) && isa<StoreInst>(ChainInstr) &&
510 OBB.dominates(MemInstr, ChainInstr))
516 dbgs() <<
"LSV: Found alias:\n"
517 " Aliasing instruction and pointer:\n"
518 <<
" " << *MemInstr <<
'\n'
520 <<
" Aliased instruction and pointer:\n"
521 <<
" " << *ChainInstr <<
'\n'
526 BarrierMemoryInstr = MemInstr;
534 if (IsLoadChain && BarrierMemoryInstr) {
536 assert(OBB.dominates(BarrierMemoryInstr, ChainInstr));
546 ChainInstrs.
begin(), ChainInstrs.
begin() + ChainInstrIdx);
547 unsigned ChainIdx = 0;
548 for (
unsigned ChainLen = Chain.size(); ChainIdx < ChainLen; ++ChainIdx) {
549 if (!VectorizableChainInstrs.count(Chain[ChainIdx]))
552 return Chain.slice(0, ChainIdx);
555 std::pair<InstrListMap, InstrListMap>
556 Vectorizer::collectInstructions(
BasicBlock *BB) {
557 InstrListMap LoadRefs;
558 InstrListMap StoreRefs;
564 if (
LoadInst *LI = dyn_cast<LoadInst>(&I)) {
578 unsigned TySize =
DL.getTypeSizeInBits(Ty);
587 if (TySize > VecRegSize / 2)
593 return EEI && isa<ConstantInt>(EEI->
getOperand(1));
599 LoadRefs[ObjPtr].push_back(LI);
601 }
else if (
StoreInst *SI = dyn_cast<StoreInst>(&I)) {
615 unsigned TySize =
DL.getTypeSizeInBits(Ty);
622 if (TySize > VecRegSize / 2)
627 return EEI && isa<ConstantInt>(EEI->
getOperand(1));
633 StoreRefs[ObjPtr].push_back(SI);
637 return {LoadRefs, StoreRefs};
640 bool Vectorizer::vectorizeChains(InstrListMap &Map) {
641 bool Changed =
false;
643 for (
const std::pair<Value *, InstrList> &Chain : Map) {
644 unsigned Size = Chain.second.size();
648 DEBUG(
dbgs() <<
"LSV: Analyzing a chain of length " << Size <<
".\n");
651 for (
unsigned CI = 0, CE = Size; CI <
CE; CI += 64) {
652 unsigned Len = std::min<unsigned>(CE - CI, 64);
654 Changed |= vectorizeInstructions(Chunk);
662 DEBUG(
dbgs() <<
"LSV: Vectorizing " << Instrs.
size() <<
" instructions.\n");
664 int ConsecutiveChain[64];
668 for (
int i = 0, e = Instrs.
size();
i < e; ++
i) {
669 ConsecutiveChain[
i] = -1;
670 for (
int j = e - 1; j >= 0; --j) {
675 if (ConsecutiveChain[i] != -1) {
676 int CurDistance =
std::abs(ConsecutiveChain[i] - i);
677 int NewDistance =
std::abs(ConsecutiveChain[i] - j);
678 if (j < i || NewDistance > CurDistance)
684 ConsecutiveChain[
i] = j;
689 bool Changed =
false;
692 for (
int Head : Heads) {
693 if (InstructionsProcessed.
count(Instrs[Head]))
695 bool LongerChainExists =
false;
696 for (
unsigned TIt = 0; TIt < Tails.size(); TIt++)
697 if (Head == Tails[TIt] &&
698 !InstructionsProcessed.
count(Instrs[Heads[TIt]])) {
699 LongerChainExists =
true;
702 if (LongerChainExists)
710 if (InstructionsProcessed.
count(Instrs[I]))
714 I = ConsecutiveChain[
I];
717 bool Vectorized =
false;
718 if (isa<LoadInst>(*Operands.
begin()))
719 Vectorized = vectorizeLoadChain(Operands, &InstructionsProcessed);
721 Vectorized = vectorizeStoreChain(Operands, &InstructionsProcessed);
723 Changed |= Vectorized;
729 bool Vectorizer::vectorizeStoreChain(
732 StoreInst *S0 = cast<StoreInst>(Chain[0]);
737 StoreTy = cast<StoreInst>(
I)->getValueOperand()->getType();
738 if (StoreTy->isIntOrIntVectorTy())
741 if (StoreTy->isPtrOrPtrVectorTy()) {
743 DL.getTypeSizeInBits(StoreTy));
748 unsigned Sz =
DL.getTypeSizeInBits(StoreTy);
751 unsigned VF = VecRegSize / Sz;
752 unsigned ChainSize = Chain.size();
756 InstructionsProcessed->
insert(Chain.begin(), Chain.end());
761 if (NewChain.
empty()) {
763 InstructionsProcessed->
insert(Chain.begin(), Chain.end());
766 if (NewChain.
size() == 1) {
774 ChainSize = Chain.size();
778 unsigned EltSzInBytes = Sz / 8;
779 unsigned SzInBytes = EltSzInBytes * ChainSize;
781 auto Chains = splitOddVectorElts(Chain, Sz);
782 return vectorizeStoreChain(Chains.first, InstructionsProcessed) |
783 vectorizeStoreChain(Chains.second, InstructionsProcessed);
797 if (ChainSize > VF || (VF != TargetVF && TargetVF < ChainSize)) {
798 DEBUG(
dbgs() <<
"LSV: Chain doesn't match with the vector factor."
799 " Creating two separate arrays.\n");
800 return vectorizeStoreChain(Chain.slice(0, TargetVF),
801 InstructionsProcessed) |
802 vectorizeStoreChain(Chain.slice(TargetVF), InstructionsProcessed);
806 dbgs() <<
"LSV: Stores to vectorize:\n";
808 dbgs() <<
" " << *I <<
"\n";
813 InstructionsProcessed->
insert(Chain.begin(), Chain.end());
816 if (accessIsMisaligned(SzInBytes, AS, Alignment)) {
821 StackAdjustedAlignment,
822 DL, S0,
nullptr, &DT);
823 if (NewAlign < StackAdjustedAlignment)
828 std::tie(First, Last) = getBoundaryInstrs(Chain);
829 Builder.SetInsertPoint(&*Last);
835 for (
unsigned I = 0, E = Chain.size(); I !=
E; ++
I) {
838 unsigned NewIdx = J + I * VecWidth;
840 Builder.getInt32(J));
842 Extract = Builder.CreateBitCast(Extract, StoreTy->getScalarType());
845 Builder.CreateInsertElement(Vec, Extract, Builder.getInt32(NewIdx));
850 for (
unsigned I = 0, E = Chain.size(); I !=
E; ++
I) {
853 if (Extract->getType() != StoreTy->getScalarType())
855 Builder.CreateBitOrPointerCast(Extract, StoreTy->getScalarType());
858 Builder.CreateInsertElement(Vec, Extract, Builder.getInt32(I));
866 Builder.CreateStore(Vec, Builder.CreateBitCast(S0->getPointerOperand(),
867 VecTy->getPointerTo(AS))));
871 eraseInstructions(Chain);
872 ++NumVectorInstructions;
873 NumScalarsVectorized += Chain.size();
877 bool Vectorizer::vectorizeLoadChain(
880 LoadInst *L0 = cast<LoadInst>(Chain[0]);
884 for (
const auto &V : Chain) {
885 LoadTy = cast<LoadInst>(V)->
getType();
886 if (LoadTy->isIntOrIntVectorTy())
889 if (LoadTy->isPtrOrPtrVectorTy()) {
891 DL.getTypeSizeInBits(LoadTy));
896 unsigned Sz = DL.getTypeSizeInBits(LoadTy);
899 unsigned VF = VecRegSize / Sz;
900 unsigned ChainSize = Chain.size();
904 InstructionsProcessed->
insert(Chain.begin(), Chain.end());
909 if (NewChain.
empty()) {
911 InstructionsProcessed->
insert(Chain.begin(), Chain.end());
914 if (NewChain.
size() == 1) {
922 ChainSize = Chain.size();
926 unsigned EltSzInBytes = Sz / 8;
927 unsigned SzInBytes = EltSzInBytes * ChainSize;
929 auto Chains = splitOddVectorElts(Chain, Sz);
930 return vectorizeLoadChain(Chains.first, InstructionsProcessed) |
931 vectorizeLoadChain(Chains.second, InstructionsProcessed);
945 if (ChainSize > VF || (VF != TargetVF && TargetVF < ChainSize)) {
946 DEBUG(
dbgs() <<
"LSV: Chain doesn't match with the vector factor."
947 " Creating two separate arrays.\n");
948 return vectorizeLoadChain(Chain.slice(0, TargetVF), InstructionsProcessed) |
949 vectorizeLoadChain(Chain.slice(TargetVF), InstructionsProcessed);
954 InstructionsProcessed->
insert(Chain.begin(), Chain.end());
957 if (accessIsMisaligned(SzInBytes, AS, Alignment)) {
962 StackAdjustedAlignment,
963 DL, L0,
nullptr, &DT);
964 if (NewAlign < StackAdjustedAlignment)
967 Alignment = NewAlign;
971 dbgs() <<
"LSV: Loads to vectorize:\n";
980 std::tie(First, Last) = getBoundaryInstrs(Chain);
981 Builder.SetInsertPoint(&*First);
984 Builder.CreateBitCast(L0->getPointerOperand(), VecTy->getPointerTo(AS));
987 LoadInst *LI = cast<LoadInst>(Builder.CreateLoad(Bitcast));
995 for (
unsigned I = 0, E = Chain.size(); I !=
E; ++
I) {
996 for (
auto Use : Chain[I]->
users()) {
1000 unsigned Idx = cast<ConstantInt>(UI->
getOperand(1))->getZExtValue();
1001 unsigned NewIdx = Idx + I * VecWidth;
1002 Value *V = Builder.CreateExtractElement(LI, Builder.getInt32(NewIdx),
1005 V = Builder.CreateBitCast(V, UI->
getType());
1015 if (
Instruction *BitcastInst = dyn_cast<Instruction>(Bitcast))
1016 reorder(BitcastInst);
1018 for (
auto I : InstrsToErase)
1019 I->eraseFromParent();
1021 for (
unsigned I = 0, E = Chain.size(); I !=
E; ++
I) {
1024 Builder.CreateExtractElement(LI, Builder.getInt32(I), CV->
getName());
1026 V = Builder.CreateBitOrPointerCast(V, CV->
getType());
1033 if (
Instruction *BitcastInst = dyn_cast<Instruction>(Bitcast))
1034 reorder(BitcastInst);
1037 eraseInstructions(Chain);
1039 ++NumVectorInstructions;
1040 NumScalarsVectorized += Chain.size();
1044 bool Vectorizer::accessIsMisaligned(
unsigned SzInBytes,
unsigned AddressSpace,
1045 unsigned Alignment) {
1046 if (Alignment % SzInBytes == 0)
1053 DEBUG(
dbgs() <<
"LSV: Target said misaligned is allowed? " << Allows
1054 <<
" and fast? " << Fast <<
"\n";);
1055 return !Allows || !
Fast;
Legacy wrapper pass to provide the GlobalsAAResult object.
Pass interface - Implemented by all 'passes'.
Value * getValueOperand()
SymbolTableList< Instruction >::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
void computeKnownBits(const Value *V, APInt &KnownZero, APInt &KnownOne, const DataLayout &DL, unsigned Depth=0, AssumptionCache *AC=nullptr, const Instruction *CxtI=nullptr, const DominatorTree *DT=nullptr)
Determine which bits of V are known to be either zero or one and return them in the KnownZero/KnownOn...
void push_back(const T &Elt)
A parsed version of the target data layout string in and methods for querying it. ...
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
unsigned getOrEnforceKnownAlignment(Value *V, unsigned PrefAlign, const DataLayout &DL, const Instruction *CxtI=nullptr, AssumptionCache *AC=nullptr, const DominatorTree *DT=nullptr)
Try to ensure that the alignment of V is at least PrefAlign bytes.
const SCEV * getConstant(ConstantInt *V)
STATISTIC(NumFunctions,"Total number of functions")
const T & front() const
front - Get the first element.
INITIALIZE_PASS_BEGIN(LoadStoreVectorizer, DEBUG_TYPE,"Vectorize load and Store instructions", false, false) INITIALIZE_PASS_END(LoadStoreVectorizer
unsigned getNumOperands() const
bool isNoAlias(const MemoryLocation &LocA, const MemoryLocation &LocB)
A trivial helper function to check to see if the specified pointers are no-alias. ...
The main scalar evolution driver.
size_type count(PtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
This class implements a map that also provides access to all stored values in a deterministic order...
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly...
An instruction for reading from memory.
FunctionType * getType(LLVMContext &Context, ID id, ArrayRef< Type * > Tys=None)
Return the function type for an intrinsic.
Type * getPointerElementType() const
StringRef getName() const
Return a constant reference to the value's name.
ArrayRef< T > slice(size_t N, size_t M) const
slice(n, m) - Chop off the first N elements of the array, and keep M elements in the array...
AnalysisUsage & addRequired()
#define INITIALIZE_PASS_DEPENDENCY(depName)
static Value * getPointerOperand(Instruction &Inst)
A Use represents the edge between a Value definition and its users.
Pass * createLoadStoreVectorizerPass()
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Windows NT (Windows on ARM)
Value * stripAndAccumulateInBoundsConstantOffsets(const DataLayout &DL, APInt &Offset)
Accumulate offsets from stripInBoundsConstantOffsets().
LLVM_NODISCARD bool empty() const
unsigned getPointerAddressSpace() const
Returns the address space of the pointer operand.
static unsigned getAlignment(GlobalVariable *GV)
void initializeLoadStoreVectorizerPass(PassRegistry &)
static bool isValidElementType(Type *ElemTy)
Return true if the specified type is valid as a element type.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory)...
static GCRegistry::Add< OcamlGC > B("ocaml","ocaml 3.10-compatible GC")
An instruction for storing to memory.
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree...
Type * getScalarType() const LLVM_READONLY
If this is a vector type, return the element type, otherwise return 'this'.
size_t size() const
size - Get the array size.
bool mayReadOrWriteMemory() const
Return true if this instruction may read or write memory.
static GCRegistry::Add< CoreCLRGC > E("coreclr","CoreCLR-compatible GC")
bool isConsecutiveAccess(Value *A, Value *B, const DataLayout &DL, ScalarEvolution &SE, bool CheckType=true)
Returns true if the memory operations A and B are consecutive.
an instruction for type-safe pointer arithmetic to access elements of arrays and structs ...
static MemoryLocation get(const LoadInst *LI)
Return a location with information about the memory reference by the given instruction.
unsigned getAlignment() const
Return the alignment of the access that is being performed.
constexpr bool isPowerOf2_32(uint32_t Value)
isPowerOf2_32 - This function returns true if the argument is a power of two > 0. ...
void insertBefore(Instruction *InsertPos)
Insert an unlinked instruction into a basic block immediately before the specified instruction...
LLVM Basic Block Representation.
The instances of the Type class are immutable: once they are created, they are never changed...
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator begin()
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
Represent the analysis usage information of a pass.
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang","erlang-compatible garbage collector")
INITIALIZE_PASS_END(RegBankSelect, DEBUG_TYPE,"Assign register bank of generic virtual registers", false, false) RegBankSelect
uint64_t getNumElements() const
FunctionPass class - This class is used to implement most global optimizations.
Value * getOperand(unsigned i) const
Value * getPointerOperand()
iterator_range< po_iterator< T > > post_order(const T &G)
self_iterator getIterator()
Vectorize load and store false
bool empty() const
empty - Check if the array is empty.
void setAlignment(unsigned Align)
static UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
Value * GetUnderlyingObject(Value *V, const DataLayout &DL, unsigned MaxLookup=6)
This method strips off any GEP address adjustments and pointer casts from the specified value...
bool mayWriteToMemory() const
Return true if this instruction may modify memory.
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
Iterator for intrusive lists based on ilist_node.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements...
Legacy wrapper pass to provide the SCEVAAResult object.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
Module.h This file contains the declarations for the Module class.
Type * getType() const
All values are typed, get the type of this value.
LLVM_NODISCARD T pop_back_val()
static IntegerType * getIntNTy(LLVMContext &C, unsigned N)
void setPreservesCFG()
This function should be called by the pass, iff they do not:
unsigned getPointerAddressSpace() const
Returns the address space of the pointer operand.
static GCRegistry::Add< ShadowStackGC > C("shadow-stack","Very portable GC for uncooperative code generators")
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Class to represent vector types.
Class for arbitrary precision integers.
iterator_range< user_iterator > users()
const SCEV * getAddExpr(SmallVectorImpl< const SCEV * > &Ops, SCEV::NoWrapFlags Flags=SCEV::FlagAnyWrap)
Get a canonical add expression, or something simpler if possible.
void removeFromParent()
This method unlinks 'this' from the containing basic block, but does not delete it.
bool mayThrow() const
Return true if this instruction may throw an exception.
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
This class represents an analyzed expression in the program.
unsigned getAlignment() const
Return the alignment of the access that is being performed.
LLVM_ATTRIBUTE_ALWAYS_INLINE size_type size() const
APFloat abs(APFloat X)
Returns the absolute value of the argument.
LLVM_NODISCARD std::enable_if<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
LLVMContext & getContext() const
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Module * getParent()
Get the module that this global value is contained inside of...
LLVM Value Representation.
void setAlignment(unsigned Align)
const SCEV * getSCEV(Value *V)
Return a SCEV expression for the full generality of the specified expression.
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
static VectorType * get(Type *ElementType, unsigned NumElements)
This static method is the primary way to construct an VectorType.
static const Function * getParent(const Value *V)
StringRef - Represent a constant reference to a string, i.e.
inst_range instructions(Function *F)
Legacy analysis pass which computes a DominatorTree.
A wrapper pass to provide the legacy pass manager access to a suitably prepared AAResults object...
unsigned getPointerAddressSpace() const
Get the address space of this pointer or pointer vector type.
static GCRegistry::Add< ErlangGC > A("erlang","erlang-compatible garbage collector")
Value * getPointerOperand()
Fast - This calling convention attempts to make calls as fast as possible (e.g.
const BasicBlock * getParent() const
LLVMContext & getContext() const
Get the global data context.
Instruction * propagateMetadata(Instruction *I, ArrayRef< Value * > VL)
Specifically, let Kinds = [MD_tbaa, MD_alias_scope, MD_noalias, MD_fpmath, MD_nontemporal].
bool is_contained(R &&Range, const E &Element)
Wrapper function around std::find to detect if an element exists in a container.