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->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 auto PtrGEP = dyn_cast<GetElementPtrInst>(
GEP->getPointerOperand());
979 bool NestedNeedsExtraction;
980 int64_t NestedByteOffset =
981 accumulateByteOffset(PtrGEP, NestedNeedsExtraction);
982 if (!NestedNeedsExtraction)
985 unsigned AddrSpace = PtrGEP->getPointerAddressSpace();
987 nullptr, NestedByteOffset,
991 bool GEPInBounds =
GEP->isInBounds();
992 bool PtrGEPInBounds = PtrGEP->isInBounds();
993 bool IsChainInBounds = GEPInBounds && PtrGEPInBounds;
994 if (IsChainInBounds) {
995 auto IsKnownNonNegative = [
this](
Value *
V) {
998 IsChainInBounds &=
all_of(
GEP->indices(), IsKnownNonNegative);
1000 IsChainInBounds &=
all_of(PtrGEP->indices(), IsKnownNonNegative);
1005 Value *NewSrc = Builder.CreateGEP(
1006 GEP->getSourceElementType(), PtrGEP->getPointerOperand(),
1008 Value *NewGEP = Builder.CreateGEP(PtrGEP->getSourceElementType(), NewSrc,
1010 "", IsChainInBounds);
1011 GEP->replaceAllUsesWith(NewGEP);
1018 if (
GEP->getType()->isVectorTy())
1023 if (
GEP->hasAllConstantIndices())
1026 bool Changed = canonicalizeArrayIndicesToIndexSize(
GEP);
1028 bool NeedsExtraction;
1029 int64_t AccumulativeByteOffset = accumulateByteOffset(
GEP, NeedsExtraction);
1033 if (!NeedsExtraction) {
1034 Changed |= reorderGEP(
GEP,
TTI);
1046 unsigned AddrSpace =
GEP->getPointerAddressSpace();
1048 nullptr, AccumulativeByteOffset,
1063 for (
unsigned I = 1, E =
GEP->getNumOperands();
I != E; ++
I, ++GTI) {
1072 User *UserChainTail;
1074 ConstantOffsetExtractor::Extract(OldIdx,
GEP, UserChainTail);
1075 if (NewIdx !=
nullptr) {
1077 GEP->setOperand(
I, NewIdx);
1106 bool GEPWasInBounds =
GEP->isInBounds();
1117 unsigned AddrSpace =
GEP->getPointerAddressSpace();
1118 bool PointerHasExtraData =
DL->getPointerSizeInBits(AddrSpace) !=
1119 DL->getIndexSizeInBits(AddrSpace);
1120 if (
TTI.
useAA() ||
DL->isNonIntegralAddressSpace(AddrSpace) ||
1121 PointerHasExtraData)
1122 lowerToSingleIndexGEPs(
GEP, AccumulativeByteOffset);
1124 lowerToArithmetics(
GEP, AccumulativeByteOffset);
1129 if (AccumulativeByteOffset == 0)
1152 Type *PtrIdxTy =
DL->getIndexType(
GEP->getType());
1154 NewGEP = cast<Instruction>(Builder.CreatePtrAdd(
1155 NewGEP, ConstantInt::get(PtrIdxTy, AccumulativeByteOffset,
true),
1156 GEP->getName(), GEPWasInBounds));
1159 GEP->replaceAllUsesWith(NewGEP);
1160 GEP->eraseFromParent();
1165bool SeparateConstOffsetFromGEPLegacyPass::runOnFunction(
Function &
F) {
1166 if (skipFunction(
F))
1168 auto *DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
1169 auto *LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
1170 auto *TLI = &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(
F);
1172 return this->getAnalysis<TargetTransformInfoWrapperPass>().getTTI(
F);
1174 SeparateConstOffsetFromGEP Impl(DT, LI, TLI, GetTTI, LowerGEP);
1178bool SeparateConstOffsetFromGEP::run(
Function &
F) {
1182 DL = &
F.getDataLayout();
1183 bool Changed =
false;
1185 if (!DT->isReachableFromEntry(&
B))
1190 Changed |= splitGEP(
GEP);
1195 Changed |= reuniteExts(
F);
1198 verifyNoDeadCode(
F);
1203Instruction *SeparateConstOffsetFromGEP::findClosestMatchingDominator(
1206 auto Pos = DominatingExprs.find(Key);
1207 if (Pos == DominatingExprs.end())
1210 auto &Candidates = Pos->second;
1215 while (!Candidates.empty()) {
1217 if (DT->dominates(Candidate, Dominatee))
1219 Candidates.pop_back();
1224bool SeparateConstOffsetFromGEP::reuniteExts(
Instruction *
I) {
1225 if (!
I->getType()->isIntOrIntVectorTy())
1235 ExprKey
Key = createNormalizedCommutablePair(LHS, RHS);
1236 if (
auto *Dom = findClosestMatchingDominator(Key,
I, DominatingAdds)) {
1238 new SExtInst(Dom,
I->getType(),
"",
I->getIterator());
1240 I->replaceAllUsesWith(NewSExt);
1249 findClosestMatchingDominator({
LHS,
RHS},
I, DominatingSubs)) {
1251 new SExtInst(Dom,
I->getType(),
"",
I->getIterator());
1253 I->replaceAllUsesWith(NewSExt);
1264 ExprKey
Key = createNormalizedCommutablePair(LHS, RHS);
1265 DominatingAdds[
Key].push_back(
I);
1269 DominatingSubs[{
LHS,
RHS}].push_back(
I);
1274bool SeparateConstOffsetFromGEP::reuniteExts(
Function &
F) {
1275 bool Changed =
false;
1276 DominatingAdds.clear();
1277 DominatingSubs.clear();
1281 Changed |= reuniteExts(&
I);
1286void SeparateConstOffsetFromGEP::verifyNoDeadCode(
Function &
F) {
1290 std::string ErrMessage;
1292 RSO <<
"Dead instruction detected!\n" <<
I <<
"\n";
1299bool SeparateConstOffsetFromGEP::isLegalToSwapOperand(
1301 if (!FirstGEP || !FirstGEP->
hasOneUse())
1307 if (FirstGEP == SecondGEP)
1313 if (FirstNum != SecondNum || FirstNum != 2)
1327 Instruction *FirstOffsetDef = dyn_cast<Instruction>(FirstOffset);
1338 if (FirstOffsetDef && FirstOffsetDef->
isShift() &&
1339 isa<ConstantInt>(FirstOffsetDef->
getOperand(1)))
1340 FirstOffsetDef = dyn_cast<Instruction>(FirstOffsetDef->
getOperand(0));
1345 if (
BinaryOperator *BO = dyn_cast<BinaryOperator>(FirstOffsetDef)) {
1347 if ((opc == Instruction::Add || opc == Instruction::Sub) &&
1355bool SeparateConstOffsetFromGEP::hasMoreThanOneUseInLoop(
Value *V,
Loop *L) {
1357 for (
User *U :
V->users()) {
1359 if (
L->contains(
User))
1360 if (++UsesInLoop > 1)
1370 First->setOperand(1, Offset2);
1376 cast<PointerType>(
First->getType())->getAddressSpace()),
1379 First->stripAndAccumulateInBoundsConstantOffsets(DAL,
Offset);
1382 Offset.ugt(ObjectSize)) {
1387 First->setIsInBounds(
true);
1408 SeparateConstOffsetFromGEP Impl(DT, LI, TLI, GetTTI, LowerGEP);
for(const MachineOperand &MO :llvm::drop_begin(OldMI.operands(), Desc.getNumOperands()))
This file implements a class to represent arbitrary precision integral constant values and operations...
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
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...
BinaryOps getOpcode() const
static BinaryOperator * Create(BinaryOps Op, Value *S1, Value *S2, const Twine &Name=Twine(), InsertPosition InsertBefore=nullptr)
Construct a binary instruction, given the opcode and the two operands.
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="", InsertPosition InsertBefore=nullptr)
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.
static GEPNoWrapFlags none()
an instruction for type-safe pointer arithmetic to access elements of arrays and structs
void setNoWrapFlags(GEPNoWrapFlags NW)
Set nowrap flags for 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.
void setDebugLoc(DebugLoc Loc)
Set the debug location information for this instruction.
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 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
const ParentTy * getParent() 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 all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of 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.
constexpr unsigned BitWidth
gep_type_iterator gep_type_begin(const User *GEP)
iterator_range< df_iterator< T > > depth_first(const T &G)
bool isKnownNonNegative(const Value *V, const SimplifyQuery &SQ, unsigned Depth=0)
Returns true if the give value is known to be non-negative.
A CRTP mix-in to automatically provide informational APIs needed for passes.