176 "disable-separate-const-offset-from-gep",
cl::init(
false),
177 cl::desc(
"Do not separate the constant offset from a GEP instruction"),
185 cl::desc(
"Verify this pass produces no dead code"),
203class ConstantOffsetExtractor {
215 User *&UserChainTail,
bool &PreservesNUW);
224 : IP(InsertionPt),
DL(InsertionPt->getDataLayout()), SQ(
DL) {}
244 APInt findInEitherOperand(BinaryOperator *BO,
bool SignExtended,
262 Value *rebuildWithoutConstOffset();
280 Value *distributeCastsAndCloneChain(
unsigned ChainIndex);
283 Value *removeConstOffset(
unsigned ChainIndex);
298 bool canTraceInto(
bool SignExtended,
bool ZeroExtended, BinaryOperator *BO,
299 GetElementPtrInst *
GEP,
Value *Idx);
321 APInt extractDisjointBitsFromXor(BinaryOperator *XorInst);
326 ConstantInt *NonDisjointXorConstantBits =
nullptr;
343 const DataLayout &DL;
344 const SimplifyQuery SQ;
350class SeparateConstOffsetFromGEPLegacyPass :
public FunctionPass {
354 SeparateConstOffsetFromGEPLegacyPass(
bool LowerGEP =
false)
355 : FunctionPass(ID), LowerGEP(LowerGEP) {
360 void getAnalysisUsage(AnalysisUsage &AU)
const override {
377class SeparateConstOffsetFromGEP {
379 SeparateConstOffsetFromGEP(
380 DominatorTree *DT, LoopInfo *LI, TargetLibraryInfo *TLI,
381 function_ref<TargetTransformInfo &(Function &)> GetTTI,
bool LowerGEP)
382 : DT(DT), LI(LI), TLI(TLI), GetTTI(GetTTI), LowerGEP(LowerGEP) {}
384 bool run(Function &
F);
388 using ExprKey = std::pair<Value *, Value *>;
391 static ExprKey createNormalizedCommutablePair(
Value *
A,
Value *
B) {
399 bool splitGEP(GetElementPtrInst *
GEP);
404 bool reorderGEP(GetElementPtrInst *
GEP, TargetTransformInfo &
TTI);
413 void lowerToSingleIndexGEPs(GetElementPtrInst *Variadic,
414 const APInt &AccumulativeByteOffset);
422 APInt accumulateByteOffset(GetElementPtrInst *
GEP,
bool &NeedsExtraction,
423 bool &SignedOverflow);
440 bool canonicalizeArrayIndicesToIndexSize(GetElementPtrInst *
GEP);
451 bool reuniteExts(Function &
F);
454 bool reuniteExts(Instruction *
I);
458 ExprKey
Key, Instruction *Dominatee,
459 DenseMap<ExprKey, SmallVector<Instruction *, 2>> &DominatingExprs);
462 void verifyNoDeadCode(Function &
F);
464 bool hasMoreThanOneUseInLoop(
Value *v, Loop *L);
467 void swapGEPOperand(GetElementPtrInst *
First, GetElementPtrInst *Second);
470 bool isLegalToSwapOperand(GetElementPtrInst *
First, GetElementPtrInst *Second,
473 const DataLayout *DL =
nullptr;
474 DominatorTree *DT =
nullptr;
476 TargetLibraryInfo *TLI;
478 function_ref<TargetTransformInfo &(
Function &)> GetTTI;
484 DenseMap<ExprKey, SmallVector<Instruction *, 2>> DominatingAdds;
485 DenseMap<ExprKey, SmallVector<Instruction *, 2>> DominatingSubs;
490char SeparateConstOffsetFromGEPLegacyPass::ID = 0;
493 SeparateConstOffsetFromGEPLegacyPass,
"separate-const-offset-from-gep",
494 "Split GEPs to a variadic base and a constant offset for better CSE",
false,
502 SeparateConstOffsetFromGEPLegacyPass,
"separate-const-offset-from-gep",
503 "Split GEPs to a variadic base and a constant offset for better CSE",
false,
507 return new SeparateConstOffsetFromGEPLegacyPass(LowerGEP);
546 if (!
GEP->isInBounds())
549 const Value *Ptr =
GEP->getPointerOperand();
563 unsigned N =
Add->getType()->getIntegerBitWidth();
564 TypeSize ElemSize =
DL.getTypeAllocSize(
GEP->getSourceElementType());
604 if (
auto AllocSize = AI->getAllocationSize(
DL))
605 if (!AllocSize->isScalable())
606 ObjSize = AllocSize->getFixedValue();
608 TypeSize GVSize =
DL.getTypeAllocSize(GV->getValueType());
612 if (ObjSize > 0 &&
APInt(128, ObjSize).ult(Threshold))
618bool ConstantOffsetExtractor::canTraceInto(
bool SignExtended,
bool ZeroExtended,
624 if (BO->
getOpcode() != Instruction::Add &&
632 if (BO->
getOpcode() == Instruction::Or &&
639 if (ZeroExtended && !SignExtended && BO->
getOpcode() == Instruction::Sub)
653 if (BO->
getOpcode() == Instruction::Add && !ZeroExtended &&
GEP) {
668 bool GEPInboundsNUW =
670 if (BO->
getOpcode() == Instruction::Add && SignExtended && !ZeroExtended &&
676 if (BO->
getOpcode() == Instruction::Add ||
687APInt ConstantOffsetExtractor::findInEitherOperand(BinaryOperator *BO,
691 size_t ChainLength = UserChain.size();
694 APInt ConstantOffset =
695 find(BO->
getOperand(0),
nullptr,
nullptr, SignExtended, ZeroExtended);
701 if (ConstantOffset != 0)
return ConstantOffset;
705 UserChain.resize(ChainLength);
708 find(BO->
getOperand(1),
nullptr,
nullptr, SignExtended, ZeroExtended);
712 ConstantOffset = -ConstantOffset;
715 if (ConstantOffset == 0)
716 UserChain.resize(ChainLength);
718 return ConstantOffset;
721APInt ConstantOffsetExtractor::find(
Value *V, GetElementPtrInst *
GEP,
722 Value *Idx,
bool SignExtended,
731 if (U ==
nullptr)
return APInt(
BitWidth, 0);
736 ConstantOffset = CI->getValue();
739 if (canTraceInto(SignExtended, ZeroExtended, BO,
GEP, Idx))
740 ConstantOffset = findInEitherOperand(BO, SignExtended, ZeroExtended);
741 else if (BO->
getOpcode() == Instruction::Xor)
742 ConstantOffset = extractDisjointBitsFromXor(BO);
745 find(
U->getOperand(0),
GEP, Idx, SignExtended, ZeroExtended)
749 find(
U->getOperand(0),
GEP, Idx,
true, ZeroExtended)
754 ConstantOffset =
find(
U->getOperand(0),
GEP, Idx,
false,
762 if (ConstantOffset != 0)
763 UserChain.push_back(U);
764 return ConstantOffset;
767Value *ConstantOffsetExtractor::applyCasts(
Value *V) {
794Value *ConstantOffsetExtractor::rebuildWithoutConstOffset() {
795 distributeCastsAndCloneChain(UserChain.size() - 1);
797 unsigned NewSize = 0;
798 for (User *
I : UserChain) {
800 UserChain[NewSize] =
I;
804 UserChain.resize(NewSize);
805 return removeConstOffset(UserChain.size() - 1);
809ConstantOffsetExtractor::distributeCastsAndCloneChain(
unsigned ChainIndex) {
810 User *
U = UserChain[ChainIndex];
811 if (ChainIndex == 0) {
820 "Only following instructions can be traced: sext, zext & trunc");
821 CastInsts.push_back(Cast);
822 UserChain[ChainIndex] =
nullptr;
823 return distributeCastsAndCloneChain(ChainIndex - 1);
829 unsigned OpNo = (BO->
getOperand(0) == UserChain[ChainIndex - 1] ? 0 : 1);
831 Value *NextInChain = distributeCastsAndCloneChain(ChainIndex - 1);
833 BinaryOperator *NewBO =
nullptr;
841 return UserChain[ChainIndex] = NewBO;
844Value *ConstantOffsetExtractor::removeConstOffset(
unsigned ChainIndex) {
845 if (ChainIndex == 0) {
847 return ConstantInt::getNullValue(UserChain[ChainIndex]->
getType());
852 "distributeCastsAndCloneChain clones each BinaryOperator in "
853 "UserChain, so no one should be used more than "
856 unsigned OpNo = (BO->
getOperand(0) == UserChain[ChainIndex - 1] ? 0 : 1);
858 Value *NextInChain = removeConstOffset(ChainIndex - 1);
865 if (BO->
getOpcode() == Instruction::Xor) {
868 assert(NonDisjointXorConstantBits &&
869 "XOR in UserChain without recorded non-disjoint bits");
871 NextInChain = applyCasts(NonDisjointXorConstantBits);
877 if (CI->isZero() && !(BO->
getOpcode() == Instruction::Sub && OpNo == 0))
881 BinaryOperator::BinaryOps NewOp = BO->
getOpcode();
882 if (BO->
getOpcode() == Instruction::Or) {
896 NewOp = Instruction::Add;
899 BinaryOperator *NewBO;
909APInt ConstantOffsetExtractor::extractDisjointBitsFromXor(
910 BinaryOperator *XorInst) {
912 "Expected XOR instruction");
916 ConstantInt *XorConstantOp;
922 const APInt &ConstantValue = XorConstantOp->
getValue();
928 const APInt DisjointBits = ConstantValue & BaseKnownBits.
Zero;
929 if (DisjointBits.
isZero())
938 const APInt NonDisjointBits = ConstantValue & ~DisjointBits;
939 NonDisjointXorConstantBits =
940 ConstantInt::get(XorInst->
getContext(), NonDisjointBits);
947 UserChain.push_back(XorConstantOp);
958 if (Opcode == BinaryOperator::Or) {
971 return TI->hasNoUnsignedWrap();
976Value *ConstantOffsetExtractor::Extract(
Value *Idx, GetElementPtrInst *
GEP,
977 User *&UserChainTail,
978 bool &PreservesNUW) {
979 ConstantOffsetExtractor Extractor(
GEP->getIterator());
981 APInt ConstantOffset = Extractor.find(Idx,
GEP, Idx,
false,
983 if (ConstantOffset == 0) {
984 UserChainTail =
nullptr;
992 Value *IdxWithoutConstOffset = Extractor.rebuildWithoutConstOffset();
993 UserChainTail = Extractor.UserChain.back();
994 return IdxWithoutConstOffset;
997APInt ConstantOffsetExtractor::Find(
Value *Idx, GetElementPtrInst *
GEP) {
998 return ConstantOffsetExtractor(
GEP->getIterator())
999 .find(Idx,
GEP, Idx,
false,
false);
1002bool SeparateConstOffsetFromGEP::canonicalizeArrayIndicesToIndexSize(
1003 GetElementPtrInst *
GEP) {
1005 Type *PtrIdxTy =
DL->getIndexType(
GEP->getType());
1008 I !=
E; ++
I, ++GTI) {
1011 if ((*I)->getType() != PtrIdxTy) {
1013 GEP->getIterator());
1021APInt SeparateConstOffsetFromGEP::accumulateByteOffset(GetElementPtrInst *
GEP,
1022 bool &NeedsExtraction,
1023 bool &SignedOverflow) {
1024 NeedsExtraction =
false;
1025 SignedOverflow =
false;
1026 unsigned IdxWidth =
DL->getIndexTypeSizeInBits(
GEP->getType());
1027 APInt AccumulativeByteOffset(IdxWidth, 0);
1029 for (
unsigned I = 1,
E =
GEP->getNumOperands();
I !=
E; ++
I, ++GTI) {
1036 APInt ConstantOffset =
1037 ConstantOffsetExtractor::Find(
GEP->getOperand(
I),
GEP)
1039 if (ConstantOffset != 0) {
1040 NeedsExtraction =
true;
1045 auto ByteOffset = ConstantOffset.
smul_ov(
1049 SignedOverflow |= Overflow;
1050 AccumulativeByteOffset =
1051 AccumulativeByteOffset.sadd_ov(ByteOffset, Overflow);
1052 SignedOverflow |= Overflow;
1054 }
else if (LowerGEP) {
1059 NeedsExtraction =
true;
1060 AccumulativeByteOffset +=
1061 APInt(IdxWidth,
DL->getStructLayout(StTy)->getElementOffset(
Field),
1066 return AccumulativeByteOffset;
1069void SeparateConstOffsetFromGEP::lowerToSingleIndexGEPs(
1070 GetElementPtrInst *Variadic,
const APInt &AccumulativeByteOffset) {
1077 bool isSwapCandidate =
1078 L &&
L->isLoopInvariant(ResultPtr) &&
1079 !hasMoreThanOneUseInLoop(ResultPtr, L);
1080 Value *FirstResult =
nullptr;
1085 for (
unsigned I = 1,
E =
Variadic->getNumOperands();
I !=
E; ++
I, ++GTI) {
1096 if (ElementSize != 1) {
1098 Idx = Builder.CreateShl(
1099 Idx, ConstantInt::get(PtrIndexTy, ElementSize.
logBase2()));
1102 Builder.CreateMul(Idx, ConstantInt::get(PtrIndexTy, ElementSize));
1106 ResultPtr = Builder.CreatePtrAdd(ResultPtr, Idx,
"uglygep");
1107 if (FirstResult ==
nullptr)
1108 FirstResult = ResultPtr;
1113 if (AccumulativeByteOffset != 0) {
1114 Value *
Offset = ConstantInt::get(PtrIndexTy, AccumulativeByteOffset);
1115 ResultPtr = Builder.CreatePtrAdd(ResultPtr,
Offset,
"uglygep");
1117 isSwapCandidate =
false;
1124 if (isSwapCandidate && isLegalToSwapOperand(FirstGEP, SecondGEP, L))
1125 swapGEPOperand(FirstGEP, SecondGEP);
1127 Variadic->replaceAllUsesWith(ResultPtr);
1131bool SeparateConstOffsetFromGEP::reorderGEP(GetElementPtrInst *
GEP,
1132 TargetTransformInfo &
TTI) {
1137 bool NestedNeedsExtraction, OffsetOverflow;
1138 APInt NestedByteOffset =
1139 accumulateByteOffset(PtrGEP, NestedNeedsExtraction, OffsetOverflow);
1140 if (!NestedNeedsExtraction)
1143 unsigned AddrSpace = PtrGEP->getPointerAddressSpace();
1147 true, 0, AddrSpace))
1150 bool GEPInBounds =
GEP->isInBounds();
1151 bool PtrGEPInBounds = PtrGEP->isInBounds();
1152 bool IsChainInBounds = GEPInBounds && PtrGEPInBounds;
1153 if (IsChainInBounds) {
1154 auto IsKnownNonNegative = [
this](
Value *
V) {
1157 IsChainInBounds &=
all_of(
GEP->indices(), IsKnownNonNegative);
1158 if (IsChainInBounds)
1159 IsChainInBounds &=
all_of(PtrGEP->indices(), IsKnownNonNegative);
1164 Value *NewSrc = Builder.CreateGEP(
1165 GEP->getSourceElementType(), PtrGEP->getPointerOperand(),
1166 SmallVector<Value *, 4>(
GEP->indices()),
"", IsChainInBounds);
1167 Value *NewGEP = Builder.CreateGEP(PtrGEP->getSourceElementType(), NewSrc,
1168 SmallVector<Value *, 4>(PtrGEP->indices()),
1169 "", IsChainInBounds);
1170 GEP->replaceAllUsesWith(NewGEP);
1175bool SeparateConstOffsetFromGEP::splitGEP(GetElementPtrInst *
GEP) {
1177 if (
GEP->getType()->isVectorTy())
1184 const APInt *BaseOffset;
1185 bool ExtractBase =
match(
GEP->getPointerOperand(),
1188 unsigned IdxWidth =
DL->getIndexTypeSizeInBits(
GEP->getType());
1189 APInt BaseByteOffset =
1190 ExtractBase ? BaseOffset->
sextOrTrunc(IdxWidth) : APInt(IdxWidth, 0);
1194 if (
GEP->hasAllConstantIndices() && !ExtractBase)
1197 bool Changed = canonicalizeArrayIndicesToIndexSize(
GEP);
1199 bool NeedsExtraction, OffsetOverflow;
1200 APInt NonBaseByteOffset =
1201 accumulateByteOffset(
GEP, NeedsExtraction, OffsetOverflow);
1203 APInt AccumulativeByteOffset =
1207 TargetTransformInfo &
TTI = GetTTI(*
GEP->getFunction());
1209 if (!NeedsExtraction && !ExtractBase) {
1222 unsigned AddrSpace =
GEP->getPointerAddressSpace();
1224 GEP->getResultElementType(),
1226 true, 0, AddrSpace)) {
1232 ExtractBase =
false;
1233 BaseByteOffset = APInt(IdxWidth, 0);
1234 AccumulativeByteOffset = NonBaseByteOffset;
1236 GEP->getResultElementType(),
1238 true, 0, AddrSpace))
1241 NeedsExtraction =
true;
1246 bool AllOffsetsNonNegative =
1248 bool AllNUWPreserved =
GEP->hasNoUnsignedWrap();
1249 bool NewGEPInBounds =
GEP->isInBounds();
1250 bool NewGEPNUSW =
GEP->hasNoUnsignedSignedWrap();
1260 for (
unsigned I = 1,
E =
GEP->getNumOperands();
I !=
E; ++
I, ++GTI) {
1269 User *UserChainTail;
1271 Value *NewIdx = ConstantOffsetExtractor::Extract(Idx,
GEP, UserChainTail,
1273 if (NewIdx !=
nullptr) {
1275 GEP->setOperand(
I, NewIdx);
1281 AllNUWPreserved &= PreservesNUW;
1283 AllOffsetsNonNegative =
1289 AllNUWPreserved &=
Base->hasNoUnsignedWrap();
1290 NewGEPInBounds &=
Base->isInBounds();
1291 NewGEPNUSW &=
Base->hasNoUnsignedSignedWrap();
1294 GEP->setOperand(0, NewBase);
1320 bool CanPreserveInBoundsNUSW = AllOffsetsNonNegative;
1324 if (AllNUWPreserved) {
1332 CanPreserveInBoundsNUSW |= NewGEPNUSW;
1335 if (CanPreserveInBoundsNUSW) {
1338 else if (NewGEPNUSW)
1342 GEP->setNoWrapFlags(NewGEPFlags);
1346 lowerToSingleIndexGEPs(
GEP, AccumulativeByteOffset);
1351 if (AccumulativeByteOffset == 0)
1374 Type *PtrIdxTy =
DL->getIndexType(
GEP->getType());
1377 NewGEP, ConstantInt::get(PtrIdxTy, AccumulativeByteOffset),
1378 GEP->getName(), NewGEPFlags));
1381 GEP->replaceAllUsesWith(NewGEP);
1382 GEP->eraseFromParent();
1387bool SeparateConstOffsetFromGEPLegacyPass::runOnFunction(Function &
F) {
1388 if (skipFunction(
F))
1390 auto *DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
1391 auto *LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
1392 auto *TLI = &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(
F);
1393 auto GetTTI = [
this](
Function &
F) -> TargetTransformInfo & {
1394 return this->getAnalysis<TargetTransformInfoWrapperPass>().getTTI(
F);
1396 SeparateConstOffsetFromGEP Impl(DT, LI, TLI, GetTTI, LowerGEP);
1400bool SeparateConstOffsetFromGEP::run(Function &
F) {
1404 DL = &
F.getDataLayout();
1407 ReversePostOrderTraversal<Function *> RPOT(&
F);
1408 for (BasicBlock *
B : RPOT) {
1422 verifyNoDeadCode(
F);
1427Instruction *SeparateConstOffsetFromGEP::findClosestMatchingDominator(
1428 ExprKey
Key, Instruction *Dominatee,
1429 DenseMap<ExprKey, SmallVector<Instruction *, 2>> &DominatingExprs) {
1430 auto Pos = DominatingExprs.find(
Key);
1431 if (Pos == DominatingExprs.end())
1434 auto &Candidates = Pos->second;
1439 while (!Candidates.empty()) {
1441 if (DT->
dominates(Candidate, Dominatee))
1443 Candidates.pop_back();
1448bool SeparateConstOffsetFromGEP::reuniteExts(Instruction *
I) {
1449 if (!
I->getType()->isIntOrIntVectorTy())
1459 ExprKey
Key = createNormalizedCommutablePair(
LHS,
RHS);
1460 if (
auto *Dom = findClosestMatchingDominator(
Key,
I, DominatingAdds)) {
1462 new SExtInst(Dom,
I->getType(),
"",
I->getIterator());
1464 I->replaceAllUsesWith(NewSExt);
1473 findClosestMatchingDominator({
LHS,
RHS},
I, DominatingSubs)) {
1475 new SExtInst(Dom,
I->getType(),
"",
I->getIterator());
1477 I->replaceAllUsesWith(NewSExt);
1488 ExprKey
Key = createNormalizedCommutablePair(
LHS,
RHS);
1489 DominatingAdds[
Key].push_back(
I);
1493 DominatingSubs[{
LHS,
RHS}].push_back(
I);
1498bool SeparateConstOffsetFromGEP::reuniteExts(Function &
F) {
1500 DominatingAdds.clear();
1501 DominatingSubs.clear();
1510void SeparateConstOffsetFromGEP::verifyNoDeadCode(Function &
F) {
1511 for (BasicBlock &
B :
F) {
1512 for (Instruction &
I :
B) {
1514 std::string ErrMessage;
1515 raw_string_ostream RSO(ErrMessage);
1516 RSO <<
"Dead instruction detected!\n" <<
I <<
"\n";
1523bool SeparateConstOffsetFromGEP::isLegalToSwapOperand(
1524 GetElementPtrInst *FirstGEP, GetElementPtrInst *SecondGEP, Loop *CurLoop) {
1525 if (!FirstGEP || !FirstGEP->
hasOneUse())
1531 if (FirstGEP == SecondGEP)
1537 if (FirstNum != SecondNum || FirstNum != 2)
1562 if (FirstOffsetDef && FirstOffsetDef->
isShift() &&
1571 if ((opc == Instruction::Add || opc == Instruction::Sub) &&
1579bool SeparateConstOffsetFromGEP::hasMoreThanOneUseInLoop(
Value *V, Loop *L) {
1586 for (User *U :
V->users()) {
1588 if (
L->contains(User))
1589 if (++UsesInLoop > 1)
1595void SeparateConstOffsetFromGEP::swapGEPOperand(GetElementPtrInst *
First,
1596 GetElementPtrInst *Second) {
1599 First->setOperand(1, Offset2);
1604 const DataLayout &DAL =
First->getDataLayout();
1608 auto ClearNoWrapFlags = [&] {
1614 APInt FirstOffset(IdxBits, 0);
1615 if (!
First->accumulateConstantOffset(DAL, FirstOffset)) {
1620 APInt BaseOffset(IdxBits, 0);
1625 bool Overflow =
false;
1626 APInt TotalOffset = BaseOffset.
uadd_ov(FirstOffset, Overflow);
1627 uint64_t ObjectSize;
1628 if (Overflow || !
getObjectSize(NewBase, ObjectSize, DAL, TLI) ||
1629 TotalOffset.
ugt(ObjectSize)) {
1634 First->setIsInBounds(
true);
1655 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
Function Alias Analysis false
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 GetElementPtrInst *GEP, const Value *Idx, const BinaryOperator *Add, const DataLayout &DL)
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.
LLVM_ABI APInt trunc(unsigned width) const
Truncate to new 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
LLVM_ABI APInt smul_ov(const APInt &RHS, bool &Overflow) const
bool isNonNegative() const
Determine if this APInt Value is non-negative (>= 0)
LLVM_ABI APInt sext(unsigned width) const
Sign extend to a new width.
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.
static APInt getZero(unsigned numBits)
Get the '0' value for the specified bit-width.
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()
an instruction for type-safe pointer arithmetic to access elements of arrays and structs
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(SmallPtrSetImpl< const Type * > &Visited) const
Return true if this is a type whose size is a known multiple of vscale.
LLVM_ABI unsigned getScalarSizeInBits() const LLVM_READONLY
If this is a vector type, return the getPrimitiveSizeInBits value for the element type.
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.
@ C
The default llvm calling convention, compatible with C.
@ 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.
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)
DXILDebugInfoMap run(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.
FunctionAddr VTableAddr Value
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 initializeSeparateConstOffsetFromGEPLegacyPassPass(PassRegistry &)
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 void computeKnownBits(const Value *V, KnownBits &Known, const DataLayout &DL, AssumptionCache *AC=nullptr, const Instruction *CxtI=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...
LLVM_ABI bool programUndefinedIfPoison(const Instruction *Inst)
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...
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.
IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >
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)
std::enable_if_t< std::is_signed_v< T >, T > AddOverflow(T X, T Y, T &Result)
Add two signed integers, computing the two's complement truncated result, returning true if overflow ...
iterator_range< df_iterator< T > > depth_first(const T &G)
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
LLVM_ABI const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=MaxLookupSearchDepth)
This method strips off any GEP address adjustments, pointer casts or llvm.threadlocal....
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.
A CRTP mix-in to automatically provide informational APIs needed for passes.