178 "disable-separate-const-offset-from-gep",
cl::init(
false),
179 cl::desc(
"Do not separate the constant offset from a GEP instruction"),
187 cl::desc(
"Verify this pass produces no dead code"),
205class ConstantOffsetExtractor {
215 static Value *Extract(
const Use &Idx,
User *&UserChainTail,
221 static std::optional<APInt>
Find(
const Use &Idx);
225 : IP(InsertionPt),
DL(InsertionPt->getDataLayout()), SQ(
DL) {}
238 std::optional<APInt>
find(
Value *V,
const Use *Idx,
bool SignExtended,
243 findInEitherOperand(BinaryOperator *BO,
bool SignExtended,
bool ZeroExtended);
260 Value *rebuildWithoutConstOffset();
278 Value *distributeCastsAndCloneChain(
unsigned ChainIndex);
281 Value *removeConstOffset(
unsigned ChainIndex);
295 bool canTraceInto(
bool SignExtended,
bool ZeroExtended, BinaryOperator *BO,
318 std::optional<APInt> extractDisjointBitsFromXor(BinaryOperator *XorInst);
323 ConstantInt *NonDisjointXorConstantBits =
nullptr;
340 const DataLayout &DL;
341 const SimplifyQuery SQ;
347class SeparateConstOffsetFromGEPLegacyPass :
public FunctionPass {
351 SeparateConstOffsetFromGEPLegacyPass(
bool LowerGEP =
false)
352 : FunctionPass(ID), LowerGEP(LowerGEP) {
357 void getAnalysisUsage(AnalysisUsage &AU)
const override {
374class SeparateConstOffsetFromGEP {
376 SeparateConstOffsetFromGEP(
377 DominatorTree *DT, LoopInfo *LI, TargetLibraryInfo *TLI,
378 function_ref<TargetTransformInfo &(
Function &)> GetTTI,
bool LowerGEP)
379 : DT(DT), LI(LI), TLI(TLI), GetTTI(GetTTI), LowerGEP(LowerGEP) {}
385 using ExprKey = std::pair<Value *, Value *>;
388 static ExprKey createNormalizedCommutablePair(
Value *
A,
Value *
B) {
396 bool splitGEP(GetElementPtrInst *
GEP);
401 bool reorderGEP(GetElementPtrInst *
GEP, TargetTransformInfo &
TTI);
410 void lowerToSingleIndexGEPs(GetElementPtrInst *Variadic,
411 const APInt &AccumulativeByteOffset);
419 APInt accumulateByteOffset(GetElementPtrInst *
GEP,
bool &NeedsExtraction,
420 bool &SignedOverflow);
437 bool canonicalizeArrayIndicesToIndexSize(GetElementPtrInst *
GEP);
451 bool reuniteExts(Instruction *
I);
455 ExprKey
Key, Instruction *Dominatee,
456 DenseMap<ExprKey, SmallVector<Instruction *, 2>> &DominatingExprs);
461 bool hasMoreThanOneUseInLoop(
Value *v,
Loop *L);
464 void swapGEPOperand(GetElementPtrInst *
First, GetElementPtrInst *Second);
467 bool isLegalToSwapOperand(GetElementPtrInst *
First, GetElementPtrInst *Second,
470 const DataLayout *DL =
nullptr;
471 DominatorTree *DT =
nullptr;
473 TargetLibraryInfo *TLI;
475 function_ref<TargetTransformInfo &(
Function &)> GetTTI;
481 DenseMap<ExprKey, SmallVector<Instruction *, 2>> DominatingAdds;
482 DenseMap<ExprKey, SmallVector<Instruction *, 2>> DominatingSubs;
487char SeparateConstOffsetFromGEPLegacyPass::ID = 0;
490 SeparateConstOffsetFromGEPLegacyPass,
"separate-const-offset-from-gep",
491 "Split GEPs to a variadic base and a constant offset for better CSE",
false,
499 SeparateConstOffsetFromGEPLegacyPass,
"separate-const-offset-from-gep",
500 "Split GEPs to a variadic base and a constant offset for better CSE",
false,
504 return new SeparateConstOffsetFromGEPLegacyPass(LowerGEP);
544 if (!
GEP->isInBounds())
547 const Value *Ptr =
GEP->getPointerOperand();
561 unsigned N =
Add->getType()->getIntegerBitWidth();
564 TypeSize ElemSize = GTI.getSequentialElementStride(
DL);
582 if (Idx->getOperandNo() == 1 &&
Base &&
606 if (
auto AllocSize = AI->getAllocationSize(
DL))
607 if (!AllocSize->isScalable())
608 ObjSize = AllocSize->getFixedValue();
610 TypeSize GVSize =
DL.getTypeAllocSize(GV->getValueType());
614 if (ObjSize > 0 &&
APInt(128, ObjSize).ult(Threshold))
620bool ConstantOffsetExtractor::canTraceInto(
bool SignExtended,
bool ZeroExtended,
630 if (BO->
getOpcode() != Instruction::Add &&
637 if (ZeroExtended && !SignExtended && BO->
getOpcode() == Instruction::Sub)
649 if (BO->
getOpcode() == Instruction::Add && !ZeroExtended && Idx) {
654 GEP->hasNoUnsignedWrap())
668std::optional<APInt> ConstantOffsetExtractor::findInEitherOperand(
669 BinaryOperator *BO,
bool SignExtended,
bool ZeroExtended) {
671 size_t ChainLength = UserChain.size();
675 std::optional<APInt> ConstantOffset =
683 return ConstantOffset;
687 UserChain.resize(ChainLength);
689 ConstantOffset =
find(BO->
getOperand(1),
nullptr, SignExtended, ZeroExtended);
692 if (ConstantOffset && BO->
getOpcode() == Instruction::Sub)
693 *ConstantOffset = -*ConstantOffset;
697 UserChain.resize(ChainLength);
699 return ConstantOffset;
702std::optional<APInt> ConstantOffsetExtractor::find(
Value *V,
const Use *Idx,
715 std::optional<APInt> ConstantOffset;
721 ConstantOffset = CI->getValue();
724 if (canTraceInto(SignExtended, ZeroExtended, BO, Idx))
725 ConstantOffset = findInEitherOperand(BO, SignExtended, ZeroExtended);
726 else if (BO->
getOpcode() == Instruction::Xor)
727 ConstantOffset = extractDisjointBitsFromXor(BO);
729 if (SignExtended || ZeroExtended)
730 return ConstantOffset;
731 ConstantOffset =
find(
U->getOperand(0), Idx, SignExtended, ZeroExtended);
733 *ConstantOffset = ConstantOffset->trunc(
BitWidth);
736 find(
U->getOperand(0), Idx,
true, ZeroExtended);
738 *ConstantOffset = ConstantOffset->sext(
BitWidth);
742 ConstantOffset =
find(
U->getOperand(0), Idx,
false,
745 *ConstantOffset = ConstantOffset->zext(
BitWidth);
751 UserChain.push_back(U);
752 return ConstantOffset;
755Value *ConstantOffsetExtractor::applyCasts(
Value *V) {
782Value *ConstantOffsetExtractor::rebuildWithoutConstOffset() {
783 distributeCastsAndCloneChain(UserChain.size() - 1);
785 unsigned NewSize = 0;
786 for (User *
I : UserChain) {
788 UserChain[NewSize] =
I;
792 UserChain.resize(NewSize);
793 return removeConstOffset(UserChain.size() - 1);
797ConstantOffsetExtractor::distributeCastsAndCloneChain(
unsigned ChainIndex) {
798 User *
U = UserChain[ChainIndex];
799 if (ChainIndex == 0) {
808 "Only following instructions can be traced: sext, zext & trunc");
809 CastInsts.push_back(Cast);
810 UserChain[ChainIndex] =
nullptr;
811 return distributeCastsAndCloneChain(ChainIndex - 1);
817 unsigned OpNo = (BO->
getOperand(0) == UserChain[ChainIndex - 1] ? 0 : 1);
819 Value *NextInChain = distributeCastsAndCloneChain(ChainIndex - 1);
821 BinaryOperator *NewBO =
nullptr;
829 return UserChain[ChainIndex] = NewBO;
832Value *ConstantOffsetExtractor::removeConstOffset(
unsigned ChainIndex) {
833 if (ChainIndex == 0) {
835 return ConstantInt::getNullValue(UserChain[ChainIndex]->
getType());
840 "distributeCastsAndCloneChain clones each BinaryOperator in "
841 "UserChain, so no one should be used more than "
844 unsigned OpNo = (BO->
getOperand(0) == UserChain[ChainIndex - 1] ? 0 : 1);
846 Value *NextInChain = removeConstOffset(ChainIndex - 1);
853 if (BO->
getOpcode() == Instruction::Xor) {
856 assert(NonDisjointXorConstantBits &&
857 "XOR in UserChain without recorded non-disjoint bits");
859 NextInChain = applyCasts(NonDisjointXorConstantBits);
862 Value *
LHS = OpNo == 0 ? NextInChain : TheOther;
863 Value *
RHS = OpNo == 0 ? TheOther : NextInChain;
872 BinaryOperator::BinaryOps NewOp = BO->
getOpcode();
873 if (BO->
getOpcode() == Instruction::Or) {
887 NewOp = Instruction::Add;
896ConstantOffsetExtractor::extractDisjointBitsFromXor(BinaryOperator *XorInst) {
898 "Expected XOR instruction");
901 ConstantInt *XorConstantOp;
907 const APInt &ConstantValue = XorConstantOp->
getValue();
913 const APInt DisjointBits = ConstantValue & BaseKnownBits.
Zero;
914 if (DisjointBits.
isZero())
923 const APInt NonDisjointBits = ConstantValue & ~DisjointBits;
924 NonDisjointXorConstantBits =
925 ConstantInt::get(XorInst->
getContext(), NonDisjointBits);
932 UserChain.push_back(XorConstantOp);
943 if (Opcode == BinaryOperator::Or) {
956 return TI->hasNoUnsignedWrap();
963 if (
auto IP =
I->getInsertionPointAfterDef())
968Value *ConstantOffsetExtractor::Extract(
const Use &Idx, User *&UserChainTail,
969 bool &PreservesNUW) {
972 if (!Extractor.find(Idx, &Idx,
false,
974 UserChainTail =
nullptr;
982 Value *IdxWithoutConstOffset = Extractor.rebuildWithoutConstOffset();
983 UserChainTail = Extractor.UserChain.back();
984 return IdxWithoutConstOffset;
987std::optional<APInt> ConstantOffsetExtractor::Find(
const Use &Idx) {
989 return ConstantOffsetExtractor(
GEP->getIterator())
990 .find(Idx, &Idx,
false,
false);
993bool SeparateConstOffsetFromGEP::canonicalizeArrayIndicesToIndexSize(
994 GetElementPtrInst *
GEP) {
996 Type *PtrIdxTy =
DL->getIndexType(
GEP->getType());
999 I !=
E; ++
I, ++GTI) {
1002 if ((*I)->getType() != PtrIdxTy) {
1012APInt SeparateConstOffsetFromGEP::accumulateByteOffset(GetElementPtrInst *
GEP,
1013 bool &NeedsExtraction,
1014 bool &SignedOverflow) {
1015 NeedsExtraction =
false;
1016 SignedOverflow =
false;
1017 unsigned IdxWidth =
DL->getIndexTypeSizeInBits(
GEP->getType());
1018 APInt AccumulativeByteOffset(IdxWidth, 0);
1020 for (
unsigned I = 1,
E =
GEP->getNumOperands();
I !=
E; ++
I, ++GTI) {
1027 if (std::optional<APInt> ConstantOffset =
1028 ConstantOffsetExtractor::Find(
GEP->getOperandUse(
I))) {
1029 NeedsExtraction =
true;
1034 auto ByteOffset = ConstantOffset->sextOrTrunc(IdxWidth).smul_ov(
1038 SignedOverflow |= Overflow;
1039 AccumulativeByteOffset =
1040 AccumulativeByteOffset.sadd_ov(ByteOffset, Overflow);
1041 SignedOverflow |= Overflow;
1043 }
else if (LowerGEP) {
1048 NeedsExtraction =
true;
1049 AccumulativeByteOffset +=
1050 APInt(IdxWidth,
DL->getStructLayout(StTy)->getElementOffset(
Field),
1055 return AccumulativeByteOffset;
1058void SeparateConstOffsetFromGEP::lowerToSingleIndexGEPs(
1059 GetElementPtrInst *Variadic,
const APInt &AccumulativeByteOffset) {
1066 bool isSwapCandidate =
1067 L &&
L->isLoopInvariant(ResultPtr) &&
1068 !hasMoreThanOneUseInLoop(ResultPtr, L);
1069 Value *FirstResult =
nullptr;
1074 for (
unsigned I = 1,
E =
Variadic->getNumOperands();
I !=
E; ++
I, ++GTI) {
1085 if (ElementSize != 1) {
1087 Idx = Builder.CreateShl(
1088 Idx, ConstantInt::get(PtrIndexTy, ElementSize.
logBase2()));
1091 Builder.CreateMul(Idx, ConstantInt::get(PtrIndexTy, ElementSize));
1095 ResultPtr = Builder.CreatePtrAdd(ResultPtr, Idx,
"uglygep");
1096 if (FirstResult ==
nullptr)
1097 FirstResult = ResultPtr;
1102 if (AccumulativeByteOffset != 0) {
1103 Value *
Offset = ConstantInt::get(PtrIndexTy, AccumulativeByteOffset);
1104 ResultPtr = Builder.CreatePtrAdd(ResultPtr,
Offset,
"uglygep");
1106 isSwapCandidate =
false;
1113 if (isSwapCandidate && isLegalToSwapOperand(FirstGEP, SecondGEP, L))
1114 swapGEPOperand(FirstGEP, SecondGEP);
1116 Variadic->replaceAllUsesWith(ResultPtr);
1120bool SeparateConstOffsetFromGEP::reorderGEP(GetElementPtrInst *
GEP,
1121 TargetTransformInfo &
TTI) {
1126 bool NestedNeedsExtraction, OffsetOverflow;
1127 APInt NestedByteOffset =
1128 accumulateByteOffset(PtrGEP, NestedNeedsExtraction, OffsetOverflow);
1129 if (!NestedNeedsExtraction)
1132 unsigned AddrSpace = PtrGEP->getPointerAddressSpace();
1136 true, 0, AddrSpace))
1139 bool GEPInBounds =
GEP->isInBounds();
1140 bool PtrGEPInBounds = PtrGEP->isInBounds();
1141 bool IsChainInBounds = GEPInBounds && PtrGEPInBounds;
1142 if (IsChainInBounds) {
1143 auto IsKnownNonNegative = [
this](
Value *
V) {
1146 IsChainInBounds &=
all_of(
GEP->indices(), IsKnownNonNegative);
1147 if (IsChainInBounds)
1148 IsChainInBounds &=
all_of(PtrGEP->indices(), IsKnownNonNegative);
1153 Value *NewSrc = Builder.CreateGEP(
1154 GEP->getSourceElementType(), PtrGEP->getPointerOperand(),
1155 SmallVector<Value *, 4>(
GEP->indices()),
"", IsChainInBounds);
1156 Value *NewGEP = Builder.CreateGEP(PtrGEP->getSourceElementType(), NewSrc,
1157 SmallVector<Value *, 4>(PtrGEP->indices()),
1158 "", IsChainInBounds);
1159 GEP->replaceAllUsesWith(NewGEP);
1164bool SeparateConstOffsetFromGEP::splitGEP(GetElementPtrInst *
GEP) {
1166 if (
GEP->getType()->isVectorTy())
1173 const APInt *BaseOffset;
1174 bool ExtractBase =
match(
GEP->getPointerOperand(),
1177 unsigned IdxWidth =
DL->getIndexTypeSizeInBits(
GEP->getType());
1178 APInt BaseByteOffset =
1179 ExtractBase ? BaseOffset->
sextOrTrunc(IdxWidth) : APInt(IdxWidth, 0);
1183 if (
GEP->hasAllConstantIndices() && !ExtractBase)
1186 bool Changed = canonicalizeArrayIndicesToIndexSize(
GEP);
1188 bool NeedsExtraction, OffsetOverflow;
1189 APInt NonBaseByteOffset =
1190 accumulateByteOffset(
GEP, NeedsExtraction, OffsetOverflow);
1192 APInt AccumulativeByteOffset =
1196 TargetTransformInfo &
TTI = GetTTI(*
GEP->getFunction());
1198 if (!NeedsExtraction && !ExtractBase) {
1211 unsigned AddrSpace =
GEP->getPointerAddressSpace();
1213 GEP->getResultElementType(),
1215 true, 0, AddrSpace)) {
1221 ExtractBase =
false;
1222 BaseByteOffset = APInt(IdxWidth, 0);
1223 AccumulativeByteOffset = NonBaseByteOffset;
1225 GEP->getResultElementType(),
1227 true, 0, AddrSpace))
1230 NeedsExtraction =
true;
1235 bool AllOffsetsNonNegative =
1237 bool AllNUWPreserved =
GEP->hasNoUnsignedWrap();
1238 bool NewGEPInBounds =
GEP->isInBounds();
1239 bool NewGEPNUSW =
GEP->hasNoUnsignedSignedWrap();
1249 for (
unsigned I = 1,
E =
GEP->getNumOperands();
I !=
E; ++
I, ++GTI) {
1258 User *UserChainTail;
1260 Value *NewIdx = ConstantOffsetExtractor::Extract(
1261 GEP->getOperandUse(
I), UserChainTail, PreservesNUW);
1262 if (NewIdx !=
nullptr) {
1264 GEP->setOperand(
I, NewIdx);
1270 AllNUWPreserved &= PreservesNUW;
1272 AllOffsetsNonNegative =
1278 AllNUWPreserved &=
Base->hasNoUnsignedWrap();
1279 NewGEPInBounds &=
Base->isInBounds();
1280 NewGEPNUSW &=
Base->hasNoUnsignedSignedWrap();
1283 GEP->setOperand(0, NewBase);
1309 bool CanPreserveInBoundsNUSW = AllOffsetsNonNegative;
1313 if (AllNUWPreserved) {
1321 CanPreserveInBoundsNUSW |= NewGEPNUSW;
1324 if (CanPreserveInBoundsNUSW) {
1327 else if (NewGEPNUSW)
1331 GEP->setNoWrapFlags(NewGEPFlags);
1335 lowerToSingleIndexGEPs(
GEP, AccumulativeByteOffset);
1340 if (AccumulativeByteOffset == 0)
1363 Type *PtrIdxTy =
DL->getIndexType(
GEP->getType());
1366 NewGEP, ConstantInt::get(PtrIdxTy, AccumulativeByteOffset),
1367 GEP->getName(), NewGEPFlags));
1370 GEP->replaceAllUsesWith(NewGEP);
1371 GEP->eraseFromParent();
1376bool SeparateConstOffsetFromGEPLegacyPass::runOnFunction(
Function &
F) {
1377 if (skipFunction(
F))
1379 auto *DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
1380 auto *LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
1381 auto *TLI = &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(
F);
1382 auto GetTTI = [
this](
Function &
F) -> TargetTransformInfo & {
1383 return this->getAnalysis<TargetTransformInfoWrapperPass>().getTTI(
F);
1385 SeparateConstOffsetFromGEP Impl(DT, LI, TLI, GetTTI, LowerGEP);
1389bool SeparateConstOffsetFromGEP::run(
Function &
F) {
1393 DL = &
F.getDataLayout();
1396 ReversePostOrderTraversal<Function *> RPOT(&
F);
1397 for (BasicBlock *
B : RPOT) {
1411 verifyNoDeadCode(
F);
1416Instruction *SeparateConstOffsetFromGEP::findClosestMatchingDominator(
1417 ExprKey
Key, Instruction *Dominatee,
1418 DenseMap<ExprKey, SmallVector<Instruction *, 2>> &DominatingExprs) {
1419 auto Pos = DominatingExprs.find(
Key);
1420 if (Pos == DominatingExprs.end())
1423 auto &Candidates = Pos->second;
1428 while (!Candidates.empty()) {
1430 if (DT->
dominates(Candidate, Dominatee))
1432 Candidates.pop_back();
1437bool SeparateConstOffsetFromGEP::reuniteExts(Instruction *
I) {
1438 if (!
I->getType()->isIntOrIntVectorTy())
1448 ExprKey
Key = createNormalizedCommutablePair(
LHS,
RHS);
1449 if (
auto *Dom = findClosestMatchingDominator(
Key,
I, DominatingAdds)) {
1451 new SExtInst(Dom,
I->getType(),
"",
I->getIterator());
1453 I->replaceAllUsesWith(NewSExt);
1462 findClosestMatchingDominator({
LHS,
RHS},
I, DominatingSubs)) {
1464 new SExtInst(Dom,
I->getType(),
"",
I->getIterator());
1466 I->replaceAllUsesWith(NewSExt);
1477 ExprKey
Key = createNormalizedCommutablePair(
LHS,
RHS);
1478 DominatingAdds[
Key].push_back(
I);
1482 DominatingSubs[{
LHS,
RHS}].push_back(
I);
1487bool SeparateConstOffsetFromGEP::reuniteExts(
Function &
F) {
1489 DominatingAdds.clear();
1490 DominatingSubs.clear();
1499void SeparateConstOffsetFromGEP::verifyNoDeadCode(
Function &
F) {
1500 for (BasicBlock &
B :
F) {
1501 for (Instruction &
I :
B) {
1503 std::string ErrMessage;
1504 raw_string_ostream RSO(ErrMessage);
1505 RSO <<
"Dead instruction detected!\n" <<
I <<
"\n";
1512bool SeparateConstOffsetFromGEP::isLegalToSwapOperand(
1513 GetElementPtrInst *FirstGEP, GetElementPtrInst *SecondGEP,
Loop *CurLoop) {
1514 if (!FirstGEP || !FirstGEP->
hasOneUse())
1520 if (FirstGEP == SecondGEP)
1526 if (FirstNum != SecondNum || FirstNum != 2)
1551 if (FirstOffsetDef && FirstOffsetDef->
isShift() &&
1560 if ((opc == Instruction::Add || opc == Instruction::Sub) &&
1568bool SeparateConstOffsetFromGEP::hasMoreThanOneUseInLoop(
Value *V,
Loop *L) {
1575 for (User *U :
V->users()) {
1577 if (
L->contains(User))
1578 if (++UsesInLoop > 1)
1584void SeparateConstOffsetFromGEP::swapGEPOperand(GetElementPtrInst *
First,
1585 GetElementPtrInst *Second) {
1588 First->setOperand(1, Offset2);
1593 const DataLayout &DAL =
First->getDataLayout();
1597 auto ClearNoWrapFlags = [&] {
1603 APInt FirstOffset(IdxBits, 0);
1604 if (!
First->accumulateConstantOffset(DAL, FirstOffset)) {
1609 APInt BaseOffset(IdxBits, 0);
1614 bool Overflow =
false;
1615 APInt TotalOffset = BaseOffset.
uadd_ov(FirstOffset, Overflow);
1617 if (Overflow || !
getObjectSize(NewBase, ObjectSize, DAL, TLI) ||
1618 TotalOffset.
ugt(ObjectSize)) {
1623 First->setIsInBounds(
true);
1628 static_cast<PassInfoMixin<SeparateConstOffsetFromGEPPass> *
>(
this)
1644 SeparateConstOffsetFromGEP Impl(DT, LI, TLI, GetTTI, LowerGEP);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file implements a class to represent arbitrary precision integral constant values and operations...
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
This file defines the DenseMap class.
This file builds on the ADT/GraphTraits.h file to build generic depth first graph iterator.
static bool runOnFunction(Function &F, bool PostInlining)
Module.h This file contains the declarations for the Module class.
This header defines various interfaces for pass management in LLVM.
static const T * Find(StringRef S, ArrayRef< T > A)
Find KV in array using binary search.
OptimizedStructLayoutField Field
#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< 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 bool allowsPreservingNUW(const User *U)
A helper function to check if reassociating through an entry in the user chain would invalidate the G...
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)
static bool canReorderAddSextToGEP(const Use *Idx, const BinaryOperator *Add, const DataLayout &DL)
static BasicBlock::iterator getIndexInsertionPoint(const Use &Idx)
This file defines the SmallVector class.
static SymbolRef::Type getType(const Symbol *Sym)
Class for arbitrary precision integers.
LLVM_ABI APInt zext(unsigned width) const
Zero extend to a new width.
LLVM_ABI APInt zextOrTrunc(unsigned width) const
Zero extend or truncate to width.
bool ugt(const APInt &RHS) const
Unsigned greater than comparison.
bool isZero() const
Determine if this value is zero, i.e. all bits are clear.
LLVM_ABI APInt sadd_ov(const APInt &RHS, bool &Overflow) const
LLVM_ABI APInt uadd_ov(const APInt &RHS, bool &Overflow) const
static APInt getSignedMinValue(unsigned numBits)
Gets minimum signed value of APInt for a specific bit width.
LLVM_ABI APInt sextOrTrunc(unsigned width) const
Sign extend or truncate to width.
unsigned logBase2() const
bool isNonNegative() const
Determine if this APInt Value is non-negative (>= 0)
bool isPowerOf2() const
Check if this APInt's value is a power of two greater than zero.
bool isSignBitSet() const
Determine if sign bit of this APInt is set.
int64_t getSExtValue() const
Get sign extended value.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
AnalysisUsage & addRequired()
LLVM_ABI void setPreservesCFG()
This function should be called by the pass, iff they do not:
InstListType::iterator iterator
Instruction iterators...
BinaryOps getOpcode() const
static LLVM_ABI 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.
static LLVM_ABI 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.
const APInt & getValue() const
Return the constant as an APInt value reference.
A parsed version of the target data layout string in and methods for querying it.
unsigned getIndexSizeInBits(unsigned AS) const
The size in bits of indices used for address calculation in getelementptr and for addresses in the gi...
Analysis pass which computes a DominatorTree.
Legacy analysis pass which computes a DominatorTree.
LLVM_ABI bool isReachableFromEntry(const Use &U) const
Provide an overload for a Use.
LLVM_ABI bool dominates(const BasicBlock *BB, const Use &U) const
Return true if the (end of the) basic block BB dominates the use U.
FunctionPass class - This class is used to implement most global optimizations.
static GEPNoWrapFlags inBounds()
static GEPNoWrapFlags noUnsignedWrap()
static GEPNoWrapFlags noUnsignedSignedWrap()
static GEPNoWrapFlags none()
LLVM_ABI void setNoWrapFlags(GEPNoWrapFlags NW)
Set nowrap flags for GEP instruction.
LLVM_ABI bool hasNoUnsignedWrap() const LLVM_READONLY
Determine whether the no unsigned wrap flag is set.
LLVM_ABI bool hasNoSignedWrap() const LLVM_READONLY
Determine whether the no signed wrap flag is set.
LLVM_ABI void insertBefore(InstListType::iterator InsertPos)
Insert an unlinked instruction into a basic block immediately before the specified position.
LLVM_ABI void dropPoisonGeneratingFlags()
Drops flags that may cause this instruction to evaluate to poison despite having non-poison inputs.
void setDebugLoc(DebugLoc Loc)
Set the debug location information for this instruction.
LLVM_ABI 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.
LoopT * getLoopFor(const BlockT *BB) const
Return the inner most loop that BB lives in.
The legacy pass manager's analysis pass to compute loop information.
bool isLoopInvariant(const Value *V) const
Return true if the specified value is loop invariant.
static LLVM_ABI PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
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.
PreservedAnalyses & preserveSet()
Mark an analysis set as preserved.
LLVM_ABI void printPipeline(raw_ostream &OS, function_ref< StringRef(StringRef)> MapClassName2PassName)
LLVM_ABI PreservedAnalyses run(Function &F, FunctionAnalysisManager &)
Represent a constant reference to a string, i.e.
Analysis pass providing the TargetTransformInfo.
Analysis pass providing the TargetLibraryInfo.
This class represents a truncation of integer types.
LLVM_ABI unsigned getIntegerBitWidth() const
LLVM_ABI 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.
const Value * stripAndAccumulateInBoundsConstantOffsets(const DataLayout &DL, APInt &Offset) const
This is a wrapper around stripAndAccumulateConstantOffsets with the in-bounds requirement set to fals...
bool hasOneUse() const
Return true if there is exactly one use of this value.
LLVMContext & getContext() const
All values hold a context through their type.
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
LLVM_ABI void takeName(Value *V)
Transfer the name from V to this value.
constexpr ScalarTy getFixedValue() const
constexpr bool isScalable() const
Returns whether the quantity is scaled by a runtime quantity (vscale).
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.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ BasicBlock
Various leaf nodes.
PtrAdd_match< PointerOpTy, OffsetOpTy > m_PtrAdd(const PointerOpTy &PointerOp, const OffsetOpTy &OffsetOp)
Matches GEP with i8 source element type.
BinaryOp_match< LHS, RHS, Instruction::Add > m_Add(const LHS &L, const RHS &R)
ap_match< APInt > m_APInt(const APInt *&Res)
Match a ConstantInt or splatted ConstantVector, binding the specified pointer to the contained APInt.
BinaryOp_match< LHS, RHS, Instruction::Xor > m_Xor(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)
auto 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.
is_zero m_Zero()
Match any null constant or a vector with all elements equal to 0.
BinaryOp_match< LHS, RHS, Instruction::Sub > m_Sub(const LHS &L, const RHS &R)
auto m_ConstantInt()
Match an arbitrary ConstantInt and ignore it.
initializer< Ty > init(const Ty &Val)
PointerTypeMap run(const Module &M)
Compute the PointerTypeMap for the module M.
@ User
could "use" a pointer
NodeAddr< NodeBase * > Node
friend class Instruction
Iterator for Instructions in a `BasicBlock.
This is an optimization pass for GlobalISel generic memory operations.
@ NeverOverflows
Never overflows.
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.
LLVM_ABI 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.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Value * GetPointerBaseWithConstantOffset(Value *Ptr, int64_t &Offset, const DataLayout &DL, bool AllowNonInbounds=true)
Analyze the specified pointer to see if it can be expressed as a base pointer plus a constant offset.
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...
LLVM_ABI void computeKnownBits(const Value *V, KnownBits &Known, const DataLayout &DL, AssumptionCache *AC=nullptr, const Instruction *CtxI=nullptr, const DominatorTree *DT=nullptr, bool UseInstrInfo=true, unsigned Depth=0)
Determine which bits of V are known to be either zero or one and return them in the KnownZero/KnownOn...
constexpr std::enable_if_t< std::is_signed_v< T >, std::pair< T, bool > > AddOverflow(T X, T Y)
Add two signed integers, computing the two's complement truncated result, returning a pair {result,...
LLVM_ABI void initializeSeparateConstOffsetFromGEPLegacyPassPass(PassRegistry &)
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
auto dyn_cast_or_null(const Y &Val)
LLVM_ABI 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.
LLVM_ABI 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)
LLVM_ABI bool programUndefinedIfPoison(const Instruction *Inst)
IRBuilder(LLVMContext &, FolderTy, InserterTy) -> IRBuilder< FolderTy, InserterTy >
generic_gep_type_iterator<> gep_type_iterator
LLVM_ABI Constant * ConstantFoldCastOperand(unsigned Opcode, Constant *C, Type *DestTy, const DataLayout &DL)
Attempt to constant fold a cast with the specified operand.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
LLVM_ABI const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=MaxLookupSearchDepth, bool MustPreserveProvenance=false)
This method strips off any GEP address adjustments, pointer casts or llvm.threadlocal....
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...
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
LLVM_ABI FunctionPass * createSeparateConstOffsetFromGEPPass(bool LowerGEP=false)
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
LLVM_ABI OverflowResult computeOverflowForSignedAdd(const WithCache< const Value * > &LHS, const WithCache< const Value * > &RHS, const SimplifyQuery &SQ)
constexpr unsigned BitWidth
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
gep_type_iterator gep_type_begin(const User *GEP)
iterator_range< df_iterator< T > > depth_first(const T &G)
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
LLVM_ABI bool isKnownNonNegative(const Value *V, const SimplifyQuery &SQ, unsigned Depth=0)
Returns true if the give value is known to be non-negative.