177 "disable-separate-const-offset-from-gep",
cl::init(
false),
178 cl::desc(
"Do not separate the constant offset from a GEP instruction"),
186 cl::desc(
"Verify this pass produces no dead code"),
204class ConstantOffsetExtractor {
216 User *&UserChainTail,
bool &PreservesNUW);
225 : IP(InsertionPt),
DL(InsertionPt->getDataLayout()), SQ(
DL) {}
245 APInt findInEitherOperand(BinaryOperator *BO,
bool SignExtended,
263 Value *rebuildWithoutConstOffset();
281 Value *distributeCastsAndCloneChain(
unsigned ChainIndex);
284 Value *removeConstOffset(
unsigned ChainIndex);
299 bool canTraceInto(
bool SignExtended,
bool ZeroExtended, BinaryOperator *BO,
300 GetElementPtrInst *
GEP,
Value *Idx);
322 APInt extractDisjointBitsFromXor(BinaryOperator *XorInst);
327 ConstantInt *NonDisjointXorConstantBits =
nullptr;
344 const DataLayout &DL;
345 const SimplifyQuery SQ;
351class SeparateConstOffsetFromGEPLegacyPass :
public FunctionPass {
355 SeparateConstOffsetFromGEPLegacyPass(
bool LowerGEP =
false)
356 : FunctionPass(ID), LowerGEP(LowerGEP) {
361 void getAnalysisUsage(AnalysisUsage &AU)
const override {
378class SeparateConstOffsetFromGEP {
380 SeparateConstOffsetFromGEP(
381 DominatorTree *DT, LoopInfo *LI, TargetLibraryInfo *TLI,
382 function_ref<TargetTransformInfo &(
Function &)> GetTTI,
bool LowerGEP)
383 : DT(DT), LI(LI), TLI(TLI), GetTTI(GetTTI), LowerGEP(LowerGEP) {}
389 using ExprKey = std::pair<Value *, Value *>;
392 static ExprKey createNormalizedCommutablePair(
Value *
A,
Value *
B) {
400 bool splitGEP(GetElementPtrInst *
GEP);
405 bool reorderGEP(GetElementPtrInst *
GEP, TargetTransformInfo &
TTI);
414 void lowerToSingleIndexGEPs(GetElementPtrInst *Variadic,
415 const APInt &AccumulativeByteOffset);
423 APInt accumulateByteOffset(GetElementPtrInst *
GEP,
bool &NeedsExtraction,
424 bool &SignedOverflow);
441 bool canonicalizeArrayIndicesToIndexSize(GetElementPtrInst *
GEP);
455 bool reuniteExts(Instruction *
I);
459 ExprKey
Key, Instruction *Dominatee,
460 DenseMap<ExprKey, SmallVector<Instruction *, 2>> &DominatingExprs);
465 bool hasMoreThanOneUseInLoop(
Value *v,
Loop *L);
468 void swapGEPOperand(GetElementPtrInst *
First, GetElementPtrInst *Second);
471 bool isLegalToSwapOperand(GetElementPtrInst *
First, GetElementPtrInst *Second,
474 const DataLayout *DL =
nullptr;
475 DominatorTree *DT =
nullptr;
477 TargetLibraryInfo *TLI;
479 function_ref<TargetTransformInfo &(
Function &)> GetTTI;
485 DenseMap<ExprKey, SmallVector<Instruction *, 2>> DominatingAdds;
486 DenseMap<ExprKey, SmallVector<Instruction *, 2>> DominatingSubs;
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);
547 if (!
GEP->isInBounds())
550 const Value *Ptr =
GEP->getPointerOperand();
564 unsigned N =
Add->getType()->getIntegerBitWidth();
565 TypeSize ElemSize =
DL.getTypeAllocSize(
GEP->getSourceElementType());
605 if (
auto AllocSize = AI->getAllocationSize(
DL))
606 if (!AllocSize->isScalable())
607 ObjSize = AllocSize->getFixedValue();
609 TypeSize GVSize =
DL.getTypeAllocSize(GV->getValueType());
613 if (ObjSize > 0 &&
APInt(128, ObjSize).ult(Threshold))
619bool ConstantOffsetExtractor::canTraceInto(
bool SignExtended,
bool ZeroExtended,
625 if (BO->
getOpcode() != Instruction::Add &&
633 if (BO->
getOpcode() == Instruction::Or &&
640 if (ZeroExtended && !SignExtended && BO->
getOpcode() == Instruction::Sub)
654 if (BO->
getOpcode() == Instruction::Add && !ZeroExtended &&
GEP) {
669 bool GEPInboundsNUW =
671 if (BO->
getOpcode() == Instruction::Add && SignExtended && !ZeroExtended &&
677 if (BO->
getOpcode() == Instruction::Add ||
688APInt ConstantOffsetExtractor::findInEitherOperand(BinaryOperator *BO,
692 size_t ChainLength = UserChain.size();
695 APInt ConstantOffset =
696 find(BO->
getOperand(0),
nullptr,
nullptr, SignExtended, ZeroExtended);
702 if (ConstantOffset != 0)
return ConstantOffset;
706 UserChain.resize(ChainLength);
709 find(BO->
getOperand(1),
nullptr,
nullptr, SignExtended, ZeroExtended);
713 ConstantOffset = -ConstantOffset;
716 if (ConstantOffset == 0)
717 UserChain.resize(ChainLength);
719 return ConstantOffset;
722APInt ConstantOffsetExtractor::find(
Value *V, GetElementPtrInst *
GEP,
723 Value *Idx,
bool SignExtended,
732 if (U ==
nullptr)
return APInt(
BitWidth, 0);
737 ConstantOffset = CI->getValue();
740 if (canTraceInto(SignExtended, ZeroExtended, BO,
GEP, Idx))
741 ConstantOffset = findInEitherOperand(BO, SignExtended, ZeroExtended);
742 else if (BO->
getOpcode() == Instruction::Xor)
743 ConstantOffset = extractDisjointBitsFromXor(BO);
745 if (SignExtended || ZeroExtended)
746 return ConstantOffset;
748 find(
U->getOperand(0),
GEP, Idx, SignExtended, ZeroExtended)
752 find(
U->getOperand(0),
GEP, Idx,
true, ZeroExtended)
757 ConstantOffset =
find(
U->getOperand(0),
GEP, Idx,
false,
765 if (ConstantOffset != 0)
766 UserChain.push_back(U);
767 return ConstantOffset;
770Value *ConstantOffsetExtractor::applyCasts(
Value *V) {
797Value *ConstantOffsetExtractor::rebuildWithoutConstOffset() {
798 distributeCastsAndCloneChain(UserChain.size() - 1);
800 unsigned NewSize = 0;
801 for (User *
I : UserChain) {
803 UserChain[NewSize] =
I;
807 UserChain.resize(NewSize);
808 return removeConstOffset(UserChain.size() - 1);
812ConstantOffsetExtractor::distributeCastsAndCloneChain(
unsigned ChainIndex) {
813 User *
U = UserChain[ChainIndex];
814 if (ChainIndex == 0) {
823 "Only following instructions can be traced: sext, zext & trunc");
824 CastInsts.push_back(Cast);
825 UserChain[ChainIndex] =
nullptr;
826 return distributeCastsAndCloneChain(ChainIndex - 1);
832 unsigned OpNo = (BO->
getOperand(0) == UserChain[ChainIndex - 1] ? 0 : 1);
834 Value *NextInChain = distributeCastsAndCloneChain(ChainIndex - 1);
836 BinaryOperator *NewBO =
nullptr;
844 return UserChain[ChainIndex] = NewBO;
847Value *ConstantOffsetExtractor::removeConstOffset(
unsigned ChainIndex) {
848 if (ChainIndex == 0) {
850 return ConstantInt::getNullValue(UserChain[ChainIndex]->
getType());
855 "distributeCastsAndCloneChain clones each BinaryOperator in "
856 "UserChain, so no one should be used more than "
859 unsigned OpNo = (BO->
getOperand(0) == UserChain[ChainIndex - 1] ? 0 : 1);
861 Value *NextInChain = removeConstOffset(ChainIndex - 1);
868 if (BO->
getOpcode() == Instruction::Xor) {
871 assert(NonDisjointXorConstantBits &&
872 "XOR in UserChain without recorded non-disjoint bits");
874 NextInChain = applyCasts(NonDisjointXorConstantBits);
880 if (CI->isZero() && !(BO->
getOpcode() == Instruction::Sub && OpNo == 0))
884 BinaryOperator::BinaryOps NewOp = BO->
getOpcode();
885 if (BO->
getOpcode() == Instruction::Or) {
899 NewOp = Instruction::Add;
902 BinaryOperator *NewBO;
912APInt ConstantOffsetExtractor::extractDisjointBitsFromXor(
913 BinaryOperator *XorInst) {
915 "Expected XOR instruction");
919 ConstantInt *XorConstantOp;
925 const APInt &ConstantValue = XorConstantOp->
getValue();
931 const APInt DisjointBits = ConstantValue & BaseKnownBits.
Zero;
932 if (DisjointBits.
isZero())
941 const APInt NonDisjointBits = ConstantValue & ~DisjointBits;
942 NonDisjointXorConstantBits =
943 ConstantInt::get(XorInst->
getContext(), NonDisjointBits);
950 UserChain.push_back(XorConstantOp);
961 if (Opcode == BinaryOperator::Or) {
974 return TI->hasNoUnsignedWrap();
982 if (
auto IP =
I->getInsertionPointAfterDef())
984 return GEP->getIterator();
987Value *ConstantOffsetExtractor::Extract(
Value *Idx, GetElementPtrInst *
GEP,
988 User *&UserChainTail,
989 bool &PreservesNUW) {
992 APInt ConstantOffset = Extractor.find(Idx,
GEP, Idx,
false,
994 if (ConstantOffset == 0) {
995 UserChainTail =
nullptr;
1003 Value *IdxWithoutConstOffset = Extractor.rebuildWithoutConstOffset();
1004 UserChainTail = Extractor.UserChain.back();
1005 return IdxWithoutConstOffset;
1008APInt ConstantOffsetExtractor::Find(
Value *Idx, GetElementPtrInst *
GEP) {
1009 return ConstantOffsetExtractor(
GEP->getIterator())
1010 .find(Idx,
GEP, Idx,
false,
false);
1013bool SeparateConstOffsetFromGEP::canonicalizeArrayIndicesToIndexSize(
1014 GetElementPtrInst *
GEP) {
1016 Type *PtrIdxTy =
DL->getIndexType(
GEP->getType());
1019 I !=
E; ++
I, ++GTI) {
1022 if ((*I)->getType() != PtrIdxTy) {
1032APInt SeparateConstOffsetFromGEP::accumulateByteOffset(GetElementPtrInst *
GEP,
1033 bool &NeedsExtraction,
1034 bool &SignedOverflow) {
1035 NeedsExtraction =
false;
1036 SignedOverflow =
false;
1037 unsigned IdxWidth =
DL->getIndexTypeSizeInBits(
GEP->getType());
1038 APInt AccumulativeByteOffset(IdxWidth, 0);
1040 for (
unsigned I = 1,
E =
GEP->getNumOperands();
I !=
E; ++
I, ++GTI) {
1047 APInt ConstantOffset =
1048 ConstantOffsetExtractor::Find(
GEP->getOperand(
I),
GEP)
1050 if (ConstantOffset != 0) {
1051 NeedsExtraction =
true;
1056 auto ByteOffset = ConstantOffset.
smul_ov(
1060 SignedOverflow |= Overflow;
1061 AccumulativeByteOffset =
1062 AccumulativeByteOffset.sadd_ov(ByteOffset, Overflow);
1063 SignedOverflow |= Overflow;
1065 }
else if (LowerGEP) {
1070 NeedsExtraction =
true;
1071 AccumulativeByteOffset +=
1072 APInt(IdxWidth,
DL->getStructLayout(StTy)->getElementOffset(
Field),
1077 return AccumulativeByteOffset;
1080void SeparateConstOffsetFromGEP::lowerToSingleIndexGEPs(
1081 GetElementPtrInst *Variadic,
const APInt &AccumulativeByteOffset) {
1088 bool isSwapCandidate =
1089 L &&
L->isLoopInvariant(ResultPtr) &&
1090 !hasMoreThanOneUseInLoop(ResultPtr, L);
1091 Value *FirstResult =
nullptr;
1096 for (
unsigned I = 1,
E =
Variadic->getNumOperands();
I !=
E; ++
I, ++GTI) {
1107 if (ElementSize != 1) {
1109 Idx = Builder.CreateShl(
1110 Idx, ConstantInt::get(PtrIndexTy, ElementSize.
logBase2()));
1113 Builder.CreateMul(Idx, ConstantInt::get(PtrIndexTy, ElementSize));
1117 ResultPtr = Builder.CreatePtrAdd(ResultPtr, Idx,
"uglygep");
1118 if (FirstResult ==
nullptr)
1119 FirstResult = ResultPtr;
1124 if (AccumulativeByteOffset != 0) {
1125 Value *
Offset = ConstantInt::get(PtrIndexTy, AccumulativeByteOffset);
1126 ResultPtr = Builder.CreatePtrAdd(ResultPtr,
Offset,
"uglygep");
1128 isSwapCandidate =
false;
1135 if (isSwapCandidate && isLegalToSwapOperand(FirstGEP, SecondGEP, L))
1136 swapGEPOperand(FirstGEP, SecondGEP);
1138 Variadic->replaceAllUsesWith(ResultPtr);
1142bool SeparateConstOffsetFromGEP::reorderGEP(GetElementPtrInst *
GEP,
1143 TargetTransformInfo &
TTI) {
1148 bool NestedNeedsExtraction, OffsetOverflow;
1149 APInt NestedByteOffset =
1150 accumulateByteOffset(PtrGEP, NestedNeedsExtraction, OffsetOverflow);
1151 if (!NestedNeedsExtraction)
1154 unsigned AddrSpace = PtrGEP->getPointerAddressSpace();
1158 true, 0, AddrSpace))
1161 bool GEPInBounds =
GEP->isInBounds();
1162 bool PtrGEPInBounds = PtrGEP->isInBounds();
1163 bool IsChainInBounds = GEPInBounds && PtrGEPInBounds;
1164 if (IsChainInBounds) {
1165 auto IsKnownNonNegative = [
this](
Value *
V) {
1168 IsChainInBounds &=
all_of(
GEP->indices(), IsKnownNonNegative);
1169 if (IsChainInBounds)
1170 IsChainInBounds &=
all_of(PtrGEP->indices(), IsKnownNonNegative);
1175 Value *NewSrc = Builder.CreateGEP(
1176 GEP->getSourceElementType(), PtrGEP->getPointerOperand(),
1177 SmallVector<Value *, 4>(
GEP->indices()),
"", IsChainInBounds);
1178 Value *NewGEP = Builder.CreateGEP(PtrGEP->getSourceElementType(), NewSrc,
1179 SmallVector<Value *, 4>(PtrGEP->indices()),
1180 "", IsChainInBounds);
1181 GEP->replaceAllUsesWith(NewGEP);
1186bool SeparateConstOffsetFromGEP::splitGEP(GetElementPtrInst *
GEP) {
1188 if (
GEP->getType()->isVectorTy())
1195 const APInt *BaseOffset;
1196 bool ExtractBase =
match(
GEP->getPointerOperand(),
1199 unsigned IdxWidth =
DL->getIndexTypeSizeInBits(
GEP->getType());
1200 APInt BaseByteOffset =
1201 ExtractBase ? BaseOffset->
sextOrTrunc(IdxWidth) : APInt(IdxWidth, 0);
1205 if (
GEP->hasAllConstantIndices() && !ExtractBase)
1208 bool Changed = canonicalizeArrayIndicesToIndexSize(
GEP);
1210 bool NeedsExtraction, OffsetOverflow;
1211 APInt NonBaseByteOffset =
1212 accumulateByteOffset(
GEP, NeedsExtraction, OffsetOverflow);
1214 APInt AccumulativeByteOffset =
1218 TargetTransformInfo &
TTI = GetTTI(*
GEP->getFunction());
1220 if (!NeedsExtraction && !ExtractBase) {
1233 unsigned AddrSpace =
GEP->getPointerAddressSpace();
1235 GEP->getResultElementType(),
1237 true, 0, AddrSpace)) {
1243 ExtractBase =
false;
1244 BaseByteOffset = APInt(IdxWidth, 0);
1245 AccumulativeByteOffset = NonBaseByteOffset;
1247 GEP->getResultElementType(),
1249 true, 0, AddrSpace))
1252 NeedsExtraction =
true;
1257 bool AllOffsetsNonNegative =
1259 bool AllNUWPreserved =
GEP->hasNoUnsignedWrap();
1260 bool NewGEPInBounds =
GEP->isInBounds();
1261 bool NewGEPNUSW =
GEP->hasNoUnsignedSignedWrap();
1271 for (
unsigned I = 1,
E =
GEP->getNumOperands();
I !=
E; ++
I, ++GTI) {
1280 User *UserChainTail;
1282 Value *NewIdx = ConstantOffsetExtractor::Extract(Idx,
GEP, UserChainTail,
1284 if (NewIdx !=
nullptr) {
1286 GEP->setOperand(
I, NewIdx);
1292 AllNUWPreserved &= PreservesNUW;
1294 AllOffsetsNonNegative =
1300 AllNUWPreserved &=
Base->hasNoUnsignedWrap();
1301 NewGEPInBounds &=
Base->isInBounds();
1302 NewGEPNUSW &=
Base->hasNoUnsignedSignedWrap();
1305 GEP->setOperand(0, NewBase);
1331 bool CanPreserveInBoundsNUSW = AllOffsetsNonNegative;
1335 if (AllNUWPreserved) {
1343 CanPreserveInBoundsNUSW |= NewGEPNUSW;
1346 if (CanPreserveInBoundsNUSW) {
1349 else if (NewGEPNUSW)
1353 GEP->setNoWrapFlags(NewGEPFlags);
1357 lowerToSingleIndexGEPs(
GEP, AccumulativeByteOffset);
1362 if (AccumulativeByteOffset == 0)
1385 Type *PtrIdxTy =
DL->getIndexType(
GEP->getType());
1388 NewGEP, ConstantInt::get(PtrIdxTy, AccumulativeByteOffset),
1389 GEP->getName(), NewGEPFlags));
1392 GEP->replaceAllUsesWith(NewGEP);
1393 GEP->eraseFromParent();
1398bool SeparateConstOffsetFromGEPLegacyPass::runOnFunction(
Function &
F) {
1399 if (skipFunction(
F))
1401 auto *DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
1402 auto *LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
1403 auto *TLI = &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(
F);
1404 auto GetTTI = [
this](
Function &
F) -> TargetTransformInfo & {
1405 return this->getAnalysis<TargetTransformInfoWrapperPass>().getTTI(
F);
1407 SeparateConstOffsetFromGEP Impl(DT, LI, TLI, GetTTI, LowerGEP);
1411bool SeparateConstOffsetFromGEP::run(
Function &
F) {
1415 DL = &
F.getDataLayout();
1418 ReversePostOrderTraversal<Function *> RPOT(&
F);
1419 for (BasicBlock *
B : RPOT) {
1433 verifyNoDeadCode(
F);
1438Instruction *SeparateConstOffsetFromGEP::findClosestMatchingDominator(
1439 ExprKey
Key, Instruction *Dominatee,
1440 DenseMap<ExprKey, SmallVector<Instruction *, 2>> &DominatingExprs) {
1441 auto Pos = DominatingExprs.find(
Key);
1442 if (Pos == DominatingExprs.end())
1445 auto &Candidates = Pos->second;
1450 while (!Candidates.empty()) {
1452 if (DT->
dominates(Candidate, Dominatee))
1454 Candidates.pop_back();
1459bool SeparateConstOffsetFromGEP::reuniteExts(Instruction *
I) {
1460 if (!
I->getType()->isIntOrIntVectorTy())
1470 ExprKey
Key = createNormalizedCommutablePair(
LHS,
RHS);
1471 if (
auto *Dom = findClosestMatchingDominator(
Key,
I, DominatingAdds)) {
1473 new SExtInst(Dom,
I->getType(),
"",
I->getIterator());
1475 I->replaceAllUsesWith(NewSExt);
1484 findClosestMatchingDominator({
LHS,
RHS},
I, DominatingSubs)) {
1486 new SExtInst(Dom,
I->getType(),
"",
I->getIterator());
1488 I->replaceAllUsesWith(NewSExt);
1499 ExprKey
Key = createNormalizedCommutablePair(
LHS,
RHS);
1500 DominatingAdds[
Key].push_back(
I);
1504 DominatingSubs[{
LHS,
RHS}].push_back(
I);
1509bool SeparateConstOffsetFromGEP::reuniteExts(
Function &
F) {
1511 DominatingAdds.clear();
1512 DominatingSubs.clear();
1521void SeparateConstOffsetFromGEP::verifyNoDeadCode(
Function &
F) {
1522 for (BasicBlock &
B :
F) {
1523 for (Instruction &
I :
B) {
1525 std::string ErrMessage;
1526 raw_string_ostream RSO(ErrMessage);
1527 RSO <<
"Dead instruction detected!\n" <<
I <<
"\n";
1534bool SeparateConstOffsetFromGEP::isLegalToSwapOperand(
1535 GetElementPtrInst *FirstGEP, GetElementPtrInst *SecondGEP,
Loop *CurLoop) {
1536 if (!FirstGEP || !FirstGEP->
hasOneUse())
1542 if (FirstGEP == SecondGEP)
1548 if (FirstNum != SecondNum || FirstNum != 2)
1573 if (FirstOffsetDef && FirstOffsetDef->
isShift() &&
1582 if ((opc == Instruction::Add || opc == Instruction::Sub) &&
1590bool SeparateConstOffsetFromGEP::hasMoreThanOneUseInLoop(
Value *V,
Loop *L) {
1597 for (User *U :
V->users()) {
1599 if (
L->contains(User))
1600 if (++UsesInLoop > 1)
1606void SeparateConstOffsetFromGEP::swapGEPOperand(GetElementPtrInst *
First,
1607 GetElementPtrInst *Second) {
1610 First->setOperand(1, Offset2);
1615 const DataLayout &DAL =
First->getDataLayout();
1619 auto ClearNoWrapFlags = [&] {
1625 APInt FirstOffset(IdxBits, 0);
1626 if (!
First->accumulateConstantOffset(DAL, FirstOffset)) {
1631 APInt BaseOffset(IdxBits, 0);
1636 bool Overflow =
false;
1637 APInt TotalOffset = BaseOffset.
uadd_ov(FirstOffset, Overflow);
1639 if (Overflow || !
getObjectSize(NewBase, ObjectSize, DAL, TLI) ||
1640 TotalOffset.
ugt(ObjectSize)) {
1645 First->setIsInBounds(
true);
1650 static_cast<PassInfoMixin<SeparateConstOffsetFromGEPPass> *
>(
this)
1666 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< 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 GetElementPtrInst *GEP, const Value *Idx, const BinaryOperator *Add, const DataLayout &DL)
static BasicBlock::iterator getIndexInsertionPoint(Value *Idx, GetElementPtrInst *GEP)
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 unsigned getScalarSizeInBits() const LLVM_READONLY
If this is a vector type, return the getPrimitiveSizeInBits value for the element type.
LLVM_ABI bool isScalableTy() const
Return true if this is a type whose size is a known multiple of vscale.
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.
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.
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)
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.
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)
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.