202 "disable-separate-const-offset-from-gep",
cl::init(
false),
203 cl::desc(
"Do not separate the constant offset from a GEP instruction"),
211 cl::desc(
"Verify this pass produces no dead code"),
229class ConstantOffsetExtractor {
239 User *&UserChainTail);
248 : IP(InsertionPt),
DL(InsertionPt->getModule()->getDataLayout()) {}
285 Value *rebuildWithoutConstOffset();
302 Value *distributeExtsAndCloneChain(
unsigned ChainIndex);
305 Value *removeConstOffset(
unsigned ChainIndex);
319 bool CanTraceInto(
bool SignExtended,
bool ZeroExtended,
BinaryOperator *BO,
343class SeparateConstOffsetFromGEPLegacyPass :
public FunctionPass {
347 SeparateConstOffsetFromGEPLegacyPass(
bool LowerGEP =
false)
370class SeparateConstOffsetFromGEP {
372 SeparateConstOffsetFromGEP(
375 : DT(DT), LI(LI), TLI(TLI), GetTTI(GetTTI), LowerGEP(LowerGEP) {}
381 using ExprKey = std::pair<Value *, Value *>;
384 static ExprKey createNormalizedCommutablePair(
Value *
A,
Value *
B) {
407 int64_t AccumulativeByteOffset);
417 int64_t AccumulativeByteOffset);
465 bool hasMoreThanOneUseInLoop(
Value *v,
Loop *L);
491char SeparateConstOffsetFromGEPLegacyPass::ID = 0;
494 SeparateConstOffsetFromGEPLegacyPass,
"separate-const-offset-from-gep",
495 "Split GEPs to a variadic base and a constant offset for better CSE",
false,
503 SeparateConstOffsetFromGEPLegacyPass, "separate-
const-offset-from-
gep",
504 "Split GEPs to a variadic base and a constant offset
for better
CSE",
false,
508 return new SeparateConstOffsetFromGEPLegacyPass(LowerGEP);
511bool ConstantOffsetExtractor::CanTraceInto(
bool SignExtended,
518 if (BO->
getOpcode() != Instruction::Add &&
527 if (BO->
getOpcode() == Instruction::Or &&
528 !cast<PossiblyDisjointInst>(BO)->isDisjoint())
534 if (ZeroExtended && !SignExtended && BO->
getOpcode() == Instruction::Sub)
557 if (
ConstantInt *ConstLHS = dyn_cast<ConstantInt>(LHS)) {
558 if (!ConstLHS->isNegative())
561 if (
ConstantInt *ConstRHS = dyn_cast<ConstantInt>(RHS)) {
562 if (!ConstRHS->isNegative())
569 if (BO->
getOpcode() == Instruction::Add ||
584 size_t ChainLength = UserChain.size();
595 if (ConstantOffset != 0)
return ConstantOffset;
599 UserChain.resize(ChainLength);
601 ConstantOffset =
find(BO->
getOperand(1), SignExtended, ZeroExtended,
606 ConstantOffset = -ConstantOffset;
609 if (ConstantOffset == 0)
610 UserChain.resize(ChainLength);
612 return ConstantOffset;
615APInt ConstantOffsetExtractor::find(
Value *V,
bool SignExtended,
620 unsigned BitWidth = cast<IntegerType>(
V->getType())->getBitWidth();
623 User *
U = dyn_cast<User>(V);
629 ConstantOffset = CI->getValue();
632 if (CanTraceInto(SignExtended, ZeroExtended, BO,
NonNegative))
633 ConstantOffset = findInEitherOperand(BO, SignExtended, ZeroExtended);
634 }
else if (isa<TruncInst>(V)) {
638 }
else if (isa<SExtInst>(V)) {
639 ConstantOffset =
find(
U->getOperand(0),
true,
641 }
else if (isa<ZExtInst>(V)) {
647 find(
U->getOperand(0),
false,
654 if (ConstantOffset != 0)
655 UserChain.push_back(U);
656 return ConstantOffset;
659Value *ConstantOffsetExtractor::applyExts(
Value *V) {
664 if (
Constant *
C = dyn_cast<Constant>(Current)) {
672 Ext->setOperand(0, Current);
673 Ext->insertBefore(*IP->getParent(), IP);
679Value *ConstantOffsetExtractor::rebuildWithoutConstOffset() {
680 distributeExtsAndCloneChain(UserChain.size() - 1);
682 unsigned NewSize = 0;
683 for (
User *
I : UserChain) {
685 UserChain[NewSize] =
I;
689 UserChain.resize(NewSize);
690 return removeConstOffset(UserChain.size() - 1);
694ConstantOffsetExtractor::distributeExtsAndCloneChain(
unsigned ChainIndex) {
695 User *
U = UserChain[ChainIndex];
696 if (ChainIndex == 0) {
697 assert(isa<ConstantInt>(U));
699 return UserChain[ChainIndex] = cast<ConstantInt>(applyExts(U));
702 if (
CastInst *Cast = dyn_cast<CastInst>(U)) {
704 (isa<SExtInst>(Cast) || isa<ZExtInst>(Cast) || isa<TruncInst>(Cast)) &&
705 "Only following instructions can be traced: sext, zext & trunc");
706 ExtInsts.push_back(Cast);
707 UserChain[ChainIndex] =
nullptr;
708 return distributeExtsAndCloneChain(ChainIndex - 1);
714 unsigned OpNo = (BO->
getOperand(0) == UserChain[ChainIndex - 1] ? 0 : 1);
716 Value *NextInChain = distributeExtsAndCloneChain(ChainIndex - 1);
726 return UserChain[ChainIndex] = NewBO;
729Value *ConstantOffsetExtractor::removeConstOffset(
unsigned ChainIndex) {
730 if (ChainIndex == 0) {
731 assert(isa<ConstantInt>(UserChain[ChainIndex]));
732 return ConstantInt::getNullValue(UserChain[ChainIndex]->
getType());
737 "distributeExtsAndCloneChain clones each BinaryOperator in "
738 "UserChain, so no one should be used more than "
741 unsigned OpNo = (BO->
getOperand(0) == UserChain[ChainIndex - 1] ? 0 : 1);
743 Value *NextInChain = removeConstOffset(ChainIndex - 1);
748 if (
ConstantInt *CI = dyn_cast<ConstantInt>(NextInChain)) {
749 if (CI->isZero() && !(BO->
getOpcode() == Instruction::Sub && OpNo == 0))
754 if (BO->
getOpcode() == Instruction::Or) {
768 NewOp = Instruction::Add;
782 User *&UserChainTail) {
783 ConstantOffsetExtractor Extractor(
GEP->getIterator());
785 APInt ConstantOffset =
786 Extractor.find(
Idx,
false,
false,
788 if (ConstantOffset == 0) {
789 UserChainTail =
nullptr;
793 Value *IdxWithoutConstOffset = Extractor.rebuildWithoutConstOffset();
794 UserChainTail = Extractor.UserChain.back();
795 return IdxWithoutConstOffset;
800 return ConstantOffsetExtractor(
GEP->getIterator())
801 .find(
Idx,
false,
false,
806bool SeparateConstOffsetFromGEP::canonicalizeArrayIndicesToIndexSize(
808 bool Changed =
false;
809 Type *PtrIdxTy =
DL->getIndexType(
GEP->getType());
812 I !=
E; ++
I, ++GTI) {
815 if ((*I)->getType() != PtrIdxTy) {
827 bool &NeedsExtraction) {
828 NeedsExtraction =
false;
829 int64_t AccumulativeByteOffset = 0;
831 for (
unsigned I = 1,
E =
GEP->getNumOperands();
I !=
E; ++
I, ++GTI) {
838 int64_t ConstantOffset =
839 ConstantOffsetExtractor::Find(
GEP->getOperand(
I),
GEP);
840 if (ConstantOffset != 0) {
841 NeedsExtraction =
true;
845 AccumulativeByteOffset +=
848 }
else if (LowerGEP) {
853 NeedsExtraction =
true;
854 AccumulativeByteOffset +=
855 DL->getStructLayout(StTy)->getElementOffset(
Field);
859 return AccumulativeByteOffset;
862void SeparateConstOffsetFromGEP::lowerToSingleIndexGEPs(
870 bool isSwapCandidate =
871 L &&
L->isLoopInvariant(ResultPtr) &&
872 !hasMoreThanOneUseInLoop(ResultPtr, L);
873 Value *FirstResult =
nullptr;
878 for (
unsigned I = 1,
E =
Variadic->getNumOperands();
I !=
E; ++
I, ++GTI) {
889 if (ElementSize != 1) {
891 Idx = Builder.CreateShl(
892 Idx, ConstantInt::get(PtrIndexTy, ElementSize.
logBase2()));
895 Builder.CreateMul(
Idx, ConstantInt::get(PtrIndexTy, ElementSize));
899 ResultPtr = Builder.CreatePtrAdd(ResultPtr,
Idx,
"uglygep");
900 if (FirstResult ==
nullptr)
901 FirstResult = ResultPtr;
906 if (AccumulativeByteOffset != 0) {
907 Value *
Offset = ConstantInt::get(PtrIndexTy, AccumulativeByteOffset);
908 ResultPtr = Builder.CreatePtrAdd(ResultPtr,
Offset,
"uglygep");
910 isSwapCandidate =
false;
915 auto *FirstGEP = dyn_cast_or_null<GetElementPtrInst>(FirstResult);
916 auto *SecondGEP = dyn_cast<GetElementPtrInst>(ResultPtr);
917 if (isSwapCandidate && isLegalToSwapOperand(FirstGEP, SecondGEP, L))
918 swapGEPOperand(FirstGEP, SecondGEP);
920 Variadic->replaceAllUsesWith(ResultPtr);
926 int64_t AccumulativeByteOffset) {
930 "Pointer type must match index type for arithmetic-based lowering of "
933 Value *ResultPtr = Builder.CreatePtrToInt(
Variadic->getOperand(0), IntPtrTy);
938 for (
unsigned I = 1,
E =
Variadic->getNumOperands();
I !=
E; ++
I, ++GTI) {
949 if (ElementSize != 1) {
951 Idx = Builder.CreateShl(
952 Idx, ConstantInt::get(IntPtrTy, ElementSize.
logBase2()));
954 Idx = Builder.CreateMul(
Idx, ConstantInt::get(IntPtrTy, ElementSize));
958 ResultPtr = Builder.CreateAdd(ResultPtr,
Idx);
963 if (AccumulativeByteOffset != 0) {
964 ResultPtr = Builder.CreateAdd(
965 ResultPtr, ConstantInt::get(IntPtrTy, AccumulativeByteOffset));
968 ResultPtr = Builder.CreateIntToPtr(ResultPtr,
Variadic->getType());
969 Variadic->replaceAllUsesWith(ResultPtr);
975 Type *GEPType =
GEP->getResultElementType();
980 auto PtrGEP = dyn_cast<GetElementPtrInst>(
GEP->getPointerOperand());
983 Type *PtrGEPType = PtrGEP->getResultElementType();
989 if (PtrGEPType != GEPType ||
990 PtrGEP->getSourceElementType() !=
GEP->getSourceElementType())
993 bool NestedNeedsExtraction;
994 int64_t NestedByteOffset =
995 accumulateByteOffset(PtrGEP, NestedNeedsExtraction);
996 if (!NestedNeedsExtraction)
999 unsigned AddrSpace = PtrGEP->getPointerAddressSpace();
1001 nullptr, NestedByteOffset,
1002 true, 0, AddrSpace))
1006 Builder.SetCurrentDebugLocation(
GEP->getDebugLoc());
1007 bool GEPInBounds =
GEP->isInBounds();
1008 bool PtrGEPInBounds = PtrGEP->isInBounds();
1009 bool IsChainInBounds = GEPInBounds && PtrGEPInBounds;
1010 if (IsChainInBounds) {
1011 auto GEPIdx =
GEP->indices().begin();
1013 IsChainInBounds &= KnownGEPIdx.isNonNegative();
1014 if (IsChainInBounds) {
1015 auto PtrGEPIdx =
GEP->indices().begin();
1017 IsChainInBounds &= KnownPtrGEPIdx.isNonNegative();
1022 auto NewSrc = Builder.CreateGEP(PtrGEPType, PtrGEP->getPointerOperand(),
1024 cast<GetElementPtrInst>(NewSrc)->setIsInBounds(IsChainInBounds);
1025 auto NewGEP = Builder.CreateGEP(GEPType, NewSrc,
1027 cast<GetElementPtrInst>(NewGEP)->setIsInBounds(IsChainInBounds);
1028 GEP->replaceAllUsesWith(NewGEP);
1035 if (
GEP->getType()->isVectorTy())
1040 if (
GEP->hasAllConstantIndices())
1043 bool Changed = canonicalizeArrayIndicesToIndexSize(
GEP);
1045 bool NeedsExtraction;
1046 int64_t AccumulativeByteOffset = accumulateByteOffset(
GEP, NeedsExtraction);
1050 if (!NeedsExtraction) {
1051 Changed |= reorderGEP(
GEP,
TTI);
1063 unsigned AddrSpace =
GEP->getPointerAddressSpace();
1065 nullptr, AccumulativeByteOffset,
1080 for (
unsigned I = 1,
E =
GEP->getNumOperands();
I !=
E; ++
I, ++GTI) {
1089 User *UserChainTail;
1091 ConstantOffsetExtractor::Extract(OldIdx,
GEP, UserChainTail);
1092 if (NewIdx !=
nullptr) {
1094 GEP->setOperand(
I, NewIdx);
1122 bool GEPWasInBounds =
GEP->isInBounds();
1123 GEP->setIsInBounds(
false);
1133 unsigned AddrSpace =
GEP->getPointerAddressSpace();
1134 bool PointerHasExtraData =
DL->getPointerSizeInBits(AddrSpace) !=
1135 DL->getIndexSizeInBits(AddrSpace);
1136 if (
TTI.
useAA() ||
DL->isNonIntegralAddressSpace(AddrSpace) ||
1137 PointerHasExtraData)
1138 lowerToSingleIndexGEPs(
GEP, AccumulativeByteOffset);
1140 lowerToArithmetics(
GEP, AccumulativeByteOffset);
1145 if (AccumulativeByteOffset == 0)
1168 Type *PtrIdxTy =
DL->getIndexType(
GEP->getType());
1170 NewGEP = cast<Instruction>(Builder.CreatePtrAdd(
1171 NewGEP, ConstantInt::get(PtrIdxTy, AccumulativeByteOffset,
true),
1172 GEP->getName(), GEPWasInBounds));
1175 GEP->replaceAllUsesWith(NewGEP);
1176 GEP->eraseFromParent();
1181bool SeparateConstOffsetFromGEPLegacyPass::runOnFunction(
Function &
F) {
1182 if (skipFunction(
F))
1184 auto *DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
1185 auto *LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
1186 auto *TLI = &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(
F);
1188 return this->getAnalysis<TargetTransformInfoWrapperPass>().getTTI(
F);
1190 SeparateConstOffsetFromGEP Impl(DT, LI, TLI, GetTTI, LowerGEP);
1194bool SeparateConstOffsetFromGEP::run(
Function &
F) {
1198 DL = &
F.getParent()->getDataLayout();
1199 bool Changed =
false;
1201 if (!DT->isReachableFromEntry(&
B))
1206 Changed |= splitGEP(
GEP);
1211 Changed |= reuniteExts(
F);
1214 verifyNoDeadCode(
F);
1219Instruction *SeparateConstOffsetFromGEP::findClosestMatchingDominator(
1222 auto Pos = DominatingExprs.find(Key);
1223 if (Pos == DominatingExprs.end())
1226 auto &Candidates = Pos->second;
1231 while (!Candidates.empty()) {
1233 if (DT->dominates(Candidate, Dominatee))
1235 Candidates.pop_back();
1240bool SeparateConstOffsetFromGEP::reuniteExts(
Instruction *
I) {
1241 if (!
I->getType()->isIntOrIntVectorTy())
1251 ExprKey
Key = createNormalizedCommutablePair(LHS, RHS);
1252 if (
auto *Dom = findClosestMatchingDominator(Key,
I, DominatingAdds)) {
1254 new SExtInst(Dom,
I->getType(),
"",
I->getIterator());
1256 I->replaceAllUsesWith(NewSExt);
1264 findClosestMatchingDominator({
LHS,
RHS},
I, DominatingSubs)) {
1266 new SExtInst(Dom,
I->getType(),
"",
I->getIterator());
1268 I->replaceAllUsesWith(NewSExt);
1278 ExprKey
Key = createNormalizedCommutablePair(LHS, RHS);
1279 DominatingAdds[
Key].push_back(
I);
1283 DominatingSubs[{
LHS,
RHS}].push_back(
I);
1288bool SeparateConstOffsetFromGEP::reuniteExts(
Function &
F) {
1289 bool Changed =
false;
1290 DominatingAdds.clear();
1291 DominatingSubs.clear();
1295 Changed |= reuniteExts(&
I);
1300void SeparateConstOffsetFromGEP::verifyNoDeadCode(
Function &
F) {
1304 std::string ErrMessage;
1306 RSO <<
"Dead instruction detected!\n" <<
I <<
"\n";
1313bool SeparateConstOffsetFromGEP::isLegalToSwapOperand(
1315 if (!FirstGEP || !FirstGEP->
hasOneUse())
1321 if (FirstGEP == SecondGEP)
1327 if (FirstNum != SecondNum || FirstNum != 2)
1341 Instruction *FirstOffsetDef = dyn_cast<Instruction>(FirstOffset);
1352 if (FirstOffsetDef && FirstOffsetDef->
isShift() &&
1353 isa<ConstantInt>(FirstOffsetDef->
getOperand(1)))
1354 FirstOffsetDef = dyn_cast<Instruction>(FirstOffsetDef->
getOperand(0));
1359 if (
BinaryOperator *BO = dyn_cast<BinaryOperator>(FirstOffsetDef)) {
1361 if ((opc == Instruction::Add || opc == Instruction::Sub) &&
1369bool SeparateConstOffsetFromGEP::hasMoreThanOneUseInLoop(
Value *V,
Loop *L) {
1371 for (
User *U :
V->users()) {
1373 if (
L->contains(
User))
1374 if (++UsesInLoop > 1)
1384 First->setOperand(1, Offset2);
1390 cast<PointerType>(
First->getType())->getAddressSpace()),
1393 First->stripAndAccumulateInBoundsConstantOffsets(DAL,
Offset);
1396 Offset.ugt(ObjectSize)) {
1397 First->setIsInBounds(
false);
1400 First->setIsInBounds(
true);
1421 SeparateConstOffsetFromGEP Impl(DT, LI, TLI, GetTTI, LowerGEP);
for(const MachineOperand &MO :llvm::drop_begin(OldMI.operands(), Desc.getNumOperands()))
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
This file implements a class to represent arbitrary precision integral constant values and operations...
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
This file defines the DenseMap class.
This file builds on the ADT/GraphTraits.h file to build generic depth first graph iterator.
static const T * Find(StringRef S, ArrayRef< T > A)
Find KV in array using binary search.
Module.h This file contains the declarations for the Module class.
This header defines various interfaces for pass management in LLVM.
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static cl::opt< bool > DisableSeparateConstOffsetFromGEP("disable-separate-const-offset-from-gep", cl::init(false), cl::desc("Do not separate the constant offset from a GEP instruction"), cl::Hidden)
static cl::opt< bool > VerifyNoDeadCode("reassociate-geps-verify-no-dead-code", cl::init(false), cl::desc("Verify this pass produces no dead code"), cl::Hidden)
separate const offset from gep
separate const offset from Split GEPs to a variadic base and a constant offset for better CSE
This file defines the SmallVector class.
static SymbolRef::Type getType(const Symbol *Sym)
Class for arbitrary precision integers.
unsigned logBase2() const
bool isPowerOf2() const
Check if this APInt's value is a power of two greater than zero.
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 setPreservesCFG()
This function should be called by the pass, iff they do not:
LLVM Basic Block Representation.
InstListType::iterator iterator
Instruction iterators...
static BinaryOperator * Create(BinaryOps Op, Value *S1, Value *S2, const Twine &Name, BasicBlock::iterator InsertBefore)
Construct a binary instruction, given the opcode and the two operands.
BinaryOps getOpcode() const
Represents analyses that only rely on functions' control flow.
This is the base class for all instructions that perform data casts.
static CastInst * CreateIntegerCast(Value *S, Type *Ty, bool isSigned, const Twine &Name, BasicBlock::iterator InsertBefore)
Create a ZExt, BitCast, or Trunc for int -> int casts.
This is the shared class of boolean and integer constants.
This is an important base class in LLVM.
A parsed version of the target data layout string in and methods for querying it.
unsigned getIndexSizeInBits(unsigned AS) const
Size in bits of index used for address calculation in getelementptr.
Analysis pass which computes a DominatorTree.
Legacy analysis pass which computes a DominatorTree.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
FunctionPass class - This class is used to implement most global optimizations.
virtual bool runOnFunction(Function &F)=0
runOnFunction - Virtual method overriden by subclasses to do the per-function processing of the pass.
an instruction for type-safe pointer arithmetic to access elements of arrays and structs
void setIsInBounds(bool b=true)
Set or clear the inbounds flag on this GEP instruction.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
bool hasNoUnsignedWrap() const LLVM_READONLY
Determine whether the no unsigned wrap flag is set.
bool hasNoSignedWrap() const LLVM_READONLY
Determine whether the no signed wrap flag is set.
void insertBefore(Instruction *InsertPos)
Insert an unlinked instruction into a basic block immediately before the specified instruction.
const BasicBlock * getParent() const
void copyMetadata(const Instruction &SrcInst, ArrayRef< unsigned > WL=ArrayRef< unsigned >())
Copy metadata from SrcInst to this instruction.
Analysis pass that exposes the LoopInfo for a function.
The legacy pass manager's analysis pass to compute loop information.
Represents a single loop in the control flow graph.
bool isLoopInvariant(const Value *V) const
Return true if the specified value is loop invariant.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
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 all()
Construct a special preserved set that preserves all passes.
void preserveSet()
Mark an analysis set as preserved.
This class represents a sign extension of integer types.
void printPipeline(raw_ostream &OS, function_ref< StringRef(StringRef)> MapClassName2PassName)
PreservedAnalyses run(Function &F, FunctionAnalysisManager &)
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.
Class to represent struct types.
Analysis pass providing the TargetTransformInfo.
Analysis pass providing the TargetLibraryInfo.
Provides information about what library functions are available for the current target.
The instances of the Type class are immutable: once they are created, they are never changed.
unsigned getIntegerBitWidth() const
bool isAggregateType() const
Return true if the type is an aggregate type.
bool isScalableTy() const
Return true if this is a type whose size is a known multiple of vscale.
A Use represents the edge between a Value definition and its users.
void setOperand(unsigned i, Value *Val)
Value * getOperand(unsigned i) const
unsigned getNumOperands() const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
bool hasOneUse() const
Return true if there is exactly one use of this value.
StringRef getName() const
Return a constant reference to the value's name.
void takeName(Value *V)
Transfer the name from V to this value.
An efficient, type-erasing, non-owning reference to a callable.
bool isSequential() const
StructType * getStructType() const
TypeSize getSequentialElementStride(const DataLayout &DL) const
Type * getIndexedType() const
This class implements an extremely fast bulk output stream that can only output to a stream.
A raw_ostream that writes to an std::string.
#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.
@ C
The default llvm calling convention, compatible with C.
BinaryOp_match< LHS, RHS, Instruction::Add > m_Add(const LHS &L, const RHS &R)
OverflowingBinaryOp_match< LHS, RHS, Instruction::Sub, OverflowingBinaryOperator::NoSignedWrap > m_NSWSub(const LHS &L, const RHS &R)
bool match(Val *V, const Pattern &P)
class_match< Value > m_Value()
Match an arbitrary value and ignore it.
OverflowingBinaryOp_match< LHS, RHS, Instruction::Add, OverflowingBinaryOperator::NoSignedWrap > m_NSWAdd(const LHS &L, const RHS &R)
CastInst_match< OpTy, SExtInst > m_SExt(const OpTy &Op)
Matches SExt.
BinaryOp_match< LHS, RHS, Instruction::Sub > m_Sub(const LHS &L, const RHS &R)
initializer< Ty > init(const Ty &Val)
PointerTypeMap run(const Module &M)
Compute the PointerTypeMap for the module M.
This is an optimization pass for GlobalISel generic memory operations.
auto find(R &&Range, const T &Val)
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly.
bool RecursivelyDeleteTriviallyDeadInstructions(Value *V, const TargetLibraryInfo *TLI=nullptr, MemorySSAUpdater *MSSAU=nullptr, std::function< void(Value *)> AboutToDeleteCallback=std::function< void(Value *)>())
If the specified value is a trivially dead instruction, delete it.
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...
bool isInstructionTriviallyDead(Instruction *I, const TargetLibraryInfo *TLI=nullptr)
Return true if the result produced by the instruction is not used, and the instruction will return.
bool getObjectSize(const Value *Ptr, uint64_t &Size, const DataLayout &DL, const TargetLibraryInfo *TLI, ObjectSizeOpts Opts={})
Compute the size of the object pointed by Ptr.
auto reverse(ContainerTy &&C)
bool programUndefinedIfPoison(const Instruction *Inst)
void initializeSeparateConstOffsetFromGEPLegacyPassPass(PassRegistry &)
Constant * ConstantFoldCastOperand(unsigned Opcode, Constant *C, Type *DestTy, const DataLayout &DL)
Attempt to constant fold a cast with the specified operand.
FunctionPass * createSeparateConstOffsetFromGEPPass(bool LowerGEP=false)
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
void computeKnownBits(const Value *V, KnownBits &Known, const DataLayout &DL, unsigned Depth=0, AssumptionCache *AC=nullptr, const Instruction *CxtI=nullptr, const DominatorTree *DT=nullptr, bool UseInstrInfo=true)
Determine which bits of V are known to be either zero or one and return them in the KnownZero/KnownOn...
constexpr unsigned BitWidth
gep_type_iterator gep_type_begin(const User *GEP)
iterator_range< df_iterator< T > > depth_first(const T &G)
A CRTP mix-in to automatically provide informational APIs needed for passes.