192class ConstantOffsetExtractor {
202 static Value *Extract(
const Use &Idx, User *&UserChainTail,
208 static std::optional<APInt>
Find(
const Use &Idx);
214 void pushCast(CastInst *Cast) {
216 Casts.push_back(Cast);
219 void popCast() { Casts.pop_back(); }
221 bool hasSignExtension()
const {
232 bool hasExtensions()
const {
253 : IP(InsertionPt), DL(InsertionPt->getDataLayout()), SQ(DL) {}
263 std::optional<APInt>
find(
Value *V,
const Use *Idx, CastState &Casts);
266 std::optional<APInt> findInEitherOperand(BinaryOperator *BO,
276 Value *rebuildWithoutConstOffset(
unsigned ChainIndex, CastState &Casts);
278 Value *rebuildWithoutConstOffset() {
280 return rebuildWithoutConstOffset(UserChain.size() - 1, Casts);
286 Value *applyCasts(
Value *V,
const CastState &Casts);
294 bool canTraceInto(
const CastState &Casts, BinaryOperator *BO,
const Use *Idx);
316 std::optional<APInt> extractDisjointBitsFromXor(BinaryOperator *XorInst);
321 ConstantInt *NonDisjointXorConstantBits =
nullptr;
334 const DataLayout &DL;
335 const SimplifyQuery SQ;
341class SeparateConstOffsetFromGEPLegacyPass :
public FunctionPass {
345 SeparateConstOffsetFromGEPLegacyPass(
bool LowerGEP =
false)
346 : FunctionPass(ID), LowerGEP(LowerGEP) {
351 void getAnalysisUsage(AnalysisUsage &AU)
const override {
368class SeparateConstOffsetFromGEP {
370 SeparateConstOffsetFromGEP(
371 DominatorTree *DT, LoopInfo *LI, TargetLibraryInfo *TLI,
372 function_ref<TargetTransformInfo &(
Function &)> GetTTI,
bool LowerGEP)
373 : DT(DT), LI(LI), TLI(TLI), GetTTI(GetTTI), LowerGEP(LowerGEP) {}
379 using ExprKey = std::pair<Value *, Value *>;
382 static ExprKey createNormalizedCommutablePair(
Value *
A,
Value *
B) {
390 bool splitGEP(GetElementPtrInst *
GEP);
395 bool reorderGEP(GetElementPtrInst *
GEP, TargetTransformInfo &
TTI);
404 void lowerToSingleIndexGEPs(GetElementPtrInst *Variadic,
405 const APInt &AccumulativeByteOffset);
413 APInt accumulateByteOffset(GetElementPtrInst *
GEP,
bool &NeedsExtraction,
414 bool &SignedOverflow);
431 bool canonicalizeArrayIndicesToIndexSize(GetElementPtrInst *
GEP);
445 bool reuniteExts(Instruction *
I);
449 ExprKey
Key, Instruction *Dominatee,
450 DenseMap<ExprKey, SmallVector<Instruction *, 2>> &DominatingExprs);
455 bool hasMoreThanOneUseInLoop(
Value *v,
Loop *L);
458 void swapGEPOperand(GetElementPtrInst *
First, GetElementPtrInst *Second);
461 bool isLegalToSwapOperand(GetElementPtrInst *
First, GetElementPtrInst *Second,
464 const DataLayout *DL =
nullptr;
465 DominatorTree *DT =
nullptr;
467 TargetLibraryInfo *TLI;
469 function_ref<TargetTransformInfo &(
Function &)> GetTTI;
475 DenseMap<ExprKey, SmallVector<Instruction *, 2>> DominatingAdds;
476 DenseMap<ExprKey, SmallVector<Instruction *, 2>> DominatingSubs;
481char SeparateConstOffsetFromGEPLegacyPass::ID = 0;
484 SeparateConstOffsetFromGEPLegacyPass,
"separate-const-offset-from-gep",
485 "Split GEPs to a variadic base and a constant offset for better CSE",
false,
493 SeparateConstOffsetFromGEPLegacyPass,
"separate-const-offset-from-gep",
494 "Split GEPs to a variadic base and a constant offset for better CSE",
false,
498 return new SeparateConstOffsetFromGEPLegacyPass(LowerGEP);
538 if (!
GEP->isInBounds())
541 const Value *Ptr =
GEP->getPointerOperand();
555 unsigned N =
Add->getType()->getIntegerBitWidth();
558 TypeSize ElemSize = GTI.getSequentialElementStride(
DL);
576 if (Idx->getOperandNo() == 1 &&
Base &&
600 if (
auto AllocSize = AI->getAllocationSize(
DL))
601 if (!AllocSize->isScalable())
602 ObjSize = AllocSize->getFixedValue();
604 TypeSize GVSize =
DL.getTypeAllocSize(GV->getValueType());
608 if (ObjSize > 0 &&
APInt(128, ObjSize).ult(Threshold))
614bool ConstantOffsetExtractor::canTraceInto(
const CastState &Casts,
616 bool SignExtended = Casts.hasSignExtension();
617 bool ZeroExtended = Casts.hasZeroExtension();
626 if (BO->
getOpcode() != Instruction::Add &&
639 if (BO->
getOpcode() == Instruction::Add && !ZeroExtended && Idx) {
644 GEP->hasNoUnsignedWrap())
659ConstantOffsetExtractor::findInEitherOperand(BinaryOperator *BO,
662 size_t ChainLength = UserChain.size();
666 std::optional<APInt> ConstantOffset =
find(BO->
getOperand(0),
nullptr, Casts);
673 return ConstantOffset;
677 UserChain.resize(ChainLength);
682 if (ConstantOffset && BO->
getOpcode() == Instruction::Sub)
683 *ConstantOffset = -*ConstantOffset;
687 UserChain.resize(ChainLength);
689 return ConstantOffset;
692std::optional<APInt> ConstantOffsetExtractor::find(
Value *V,
const Use *Idx,
703 std::optional<APInt> ConstantOffset;
709 ConstantOffset = Casts.apply(CI->getValue());
712 if (canTraceInto(Casts, BO, Idx))
713 ConstantOffset = findInEitherOperand(BO, Casts);
714 else if (BO->
getOpcode() == Instruction::Xor) {
715 ConstantOffset = extractDisjointBitsFromXor(BO);
717 *ConstantOffset = Casts.apply(*ConstantOffset);
722 ConstantOffset =
find(
U->getOperand(0), Idx, Casts);
729 UserChain.push_back(U);
730 return ConstantOffset;
733Value *ConstantOffsetExtractor::applyCasts(
Value *V,
const CastState &Casts) {
760Value *ConstantOffsetExtractor::rebuildWithoutConstOffset(
unsigned ChainIndex,
762 User *
U = UserChain[ChainIndex];
763 if (ChainIndex == 0) {
765 return applyCasts(ConstantInt::getNullValue(
U->getType()), Casts);
771 "Only following instructions can be traced: sext, zext & trunc");
772 Casts.pushCast(Cast);
773 Value *
Result = rebuildWithoutConstOffset(ChainIndex - 1, Casts);
779 unsigned OpNo = (BO->
getOperand(0) == UserChain[ChainIndex - 1] ? 0 : 1);
783 if (BO->
getOpcode() == Instruction::Xor) {
788 assert(NonDisjointXorConstantBits &&
789 "XOR in UserChain without recorded non-disjoint bits");
790 NextInChain = applyCasts(NonDisjointXorConstantBits, Casts);
792 NextInChain = rebuildWithoutConstOffset(ChainIndex - 1, Casts);
795 Value *
LHS = OpNo == 0 ? NextInChain : TheOther;
796 Value *
RHS = OpNo == 0 ? TheOther : NextInChain;
805 BinaryOperator::BinaryOps NewOp = BO->
getOpcode();
806 if (BO->
getOpcode() == Instruction::Or) {
820 NewOp = Instruction::Add;
829ConstantOffsetExtractor::extractDisjointBitsFromXor(BinaryOperator *XorInst) {
831 "Expected XOR instruction");
834 ConstantInt *XorConstantOp;
840 const APInt &ConstantValue = XorConstantOp->
getValue();
846 const APInt DisjointBits = ConstantValue & BaseKnownBits.
Zero;
847 if (DisjointBits.
isZero())
856 const APInt NonDisjointBits = ConstantValue & ~DisjointBits;
857 NonDisjointXorConstantBits =
858 ConstantInt::get(XorInst->
getContext(), NonDisjointBits);
865 UserChain.push_back(XorConstantOp);
876 if (Opcode == BinaryOperator::Or) {
889 return TI->hasNoUnsignedWrap();
896 if (
auto IP =
I->getInsertionPointAfterDef())
901Value *ConstantOffsetExtractor::Extract(
const Use &Idx, User *&UserChainTail,
902 bool &PreservesNUW) {
906 if (!Extractor.find(Idx, &Idx, Casts)) {
907 UserChainTail =
nullptr;
915 Value *IdxWithoutConstOffset = Extractor.rebuildWithoutConstOffset();
917 return IdxWithoutConstOffset;
920std::optional<APInt> ConstantOffsetExtractor::Find(
const Use &Idx) {
923 return ConstantOffsetExtractor(
GEP->getIterator()).find(Idx, &Idx, Casts);
926bool SeparateConstOffsetFromGEP::canonicalizeArrayIndicesToIndexSize(
927 GetElementPtrInst *
GEP) {
929 Type *PtrIdxTy =
DL->getIndexType(
GEP->getType());
932 I !=
E; ++
I, ++GTI) {
935 if ((*I)->getType() != PtrIdxTy) {
945APInt SeparateConstOffsetFromGEP::accumulateByteOffset(GetElementPtrInst *
GEP,
946 bool &NeedsExtraction,
947 bool &SignedOverflow) {
948 NeedsExtraction =
false;
949 SignedOverflow =
false;
950 unsigned IdxWidth =
DL->getIndexTypeSizeInBits(
GEP->getType());
951 APInt AccumulativeByteOffset(IdxWidth, 0);
953 for (
unsigned I = 1,
E =
GEP->getNumOperands();
I !=
E; ++
I, ++GTI) {
960 if (std::optional<APInt> ConstantOffset =
961 ConstantOffsetExtractor::Find(
GEP->getOperandUse(
I))) {
962 NeedsExtraction =
true;
968 auto ByteOffset = ConstantOffset->sextOrTrunc(IdxWidth).smul_ov(
969 APInt(IdxWidth, Stride,
true,
true),
971 SignedOverflow |= Overflow;
976 auto *
Offset = ConstantInt::get(
GEP->getContext(), *ConstantOffset);
979 OverflowResult::NeverOverflows;
981 AccumulativeByteOffset =
982 AccumulativeByteOffset.sadd_ov(ByteOffset, Overflow);
983 SignedOverflow |= Overflow;
985 }
else if (LowerGEP) {
990 NeedsExtraction =
true;
991 AccumulativeByteOffset +=
992 APInt(IdxWidth,
DL->getStructLayout(StTy)->getElementOffset(
Field),
997 return AccumulativeByteOffset;
1000void SeparateConstOffsetFromGEP::lowerToSingleIndexGEPs(
1001 GetElementPtrInst *Variadic,
const APInt &AccumulativeByteOffset) {
1008 bool isSwapCandidate =
1009 L &&
L->isLoopInvariant(ResultPtr) &&
1010 !hasMoreThanOneUseInLoop(ResultPtr, L);
1011 Value *FirstResult =
nullptr;
1016 for (
unsigned I = 1,
E =
Variadic->getNumOperands();
I !=
E; ++
I, ++GTI) {
1027 if (ElementSize != 1) {
1029 Idx = Builder.CreateShl(
1030 Idx, ConstantInt::get(PtrIndexTy, ElementSize.
logBase2()));
1033 Builder.CreateMul(Idx, ConstantInt::get(PtrIndexTy, ElementSize));
1037 ResultPtr = Builder.CreatePtrAdd(ResultPtr, Idx,
"uglygep");
1038 if (FirstResult ==
nullptr)
1039 FirstResult = ResultPtr;
1044 if (AccumulativeByteOffset != 0) {
1045 Value *
Offset = ConstantInt::get(PtrIndexTy, AccumulativeByteOffset);
1046 ResultPtr = Builder.CreatePtrAdd(ResultPtr,
Offset,
"uglygep");
1048 isSwapCandidate =
false;
1055 if (isSwapCandidate && isLegalToSwapOperand(FirstGEP, SecondGEP, L))
1056 swapGEPOperand(FirstGEP, SecondGEP);
1058 Variadic->replaceAllUsesWith(ResultPtr);
1062bool SeparateConstOffsetFromGEP::reorderGEP(GetElementPtrInst *
GEP,
1063 TargetTransformInfo &
TTI) {
1068 bool NestedNeedsExtraction, OffsetOverflow;
1069 APInt NestedByteOffset =
1070 accumulateByteOffset(PtrGEP, NestedNeedsExtraction, OffsetOverflow);
1071 if (!NestedNeedsExtraction)
1074 unsigned AddrSpace = PtrGEP->getPointerAddressSpace();
1078 true, 0, AddrSpace))
1081 bool GEPInBounds =
GEP->isInBounds();
1082 bool PtrGEPInBounds = PtrGEP->isInBounds();
1083 bool IsChainInBounds = GEPInBounds && PtrGEPInBounds;
1084 if (IsChainInBounds) {
1085 auto IsKnownNonNegative = [
this](
Value *
V) {
1088 IsChainInBounds &=
all_of(
GEP->indices(), IsKnownNonNegative);
1089 if (IsChainInBounds)
1090 IsChainInBounds &=
all_of(PtrGEP->indices(), IsKnownNonNegative);
1095 Value *NewSrc = Builder.CreateGEP(
1096 GEP->getSourceElementType(), PtrGEP->getPointerOperand(),
1097 SmallVector<Value *, 4>(
GEP->indices()),
"", IsChainInBounds);
1098 Value *NewGEP = Builder.CreateGEP(PtrGEP->getSourceElementType(), NewSrc,
1099 SmallVector<Value *, 4>(PtrGEP->indices()),
1100 "", IsChainInBounds);
1101 GEP->replaceAllUsesWith(NewGEP);
1106bool SeparateConstOffsetFromGEP::splitGEP(GetElementPtrInst *
GEP) {
1108 if (
GEP->getType()->isVectorTy())
1115 const APInt *BaseOffset;
1116 bool ExtractBase =
match(
GEP->getPointerOperand(),
1119 unsigned IdxWidth =
DL->getIndexTypeSizeInBits(
GEP->getType());
1120 APInt BaseByteOffset =
1121 ExtractBase ? BaseOffset->
sextOrTrunc(IdxWidth) : APInt(IdxWidth, 0);
1125 if (
GEP->hasAllConstantIndices() && !ExtractBase)
1128 bool Changed = canonicalizeArrayIndicesToIndexSize(
GEP);
1130 bool NeedsExtraction, OffsetOverflow;
1131 APInt NonBaseByteOffset =
1132 accumulateByteOffset(
GEP, NeedsExtraction, OffsetOverflow);
1134 APInt AccumulativeByteOffset =
1138 TargetTransformInfo &
TTI = GetTTI(*
GEP->getFunction());
1140 if (!NeedsExtraction && !ExtractBase) {
1153 unsigned AddrSpace =
GEP->getPointerAddressSpace();
1155 GEP->getResultElementType(),
1157 true, 0, AddrSpace)) {
1163 ExtractBase =
false;
1164 BaseByteOffset = APInt(IdxWidth, 0);
1165 AccumulativeByteOffset = NonBaseByteOffset;
1167 GEP->getResultElementType(),
1169 true, 0, AddrSpace))
1172 NeedsExtraction =
true;
1177 bool AllOffsetsNonNegative =
1179 bool AllNUWPreserved =
GEP->hasNoUnsignedWrap();
1180 bool NewGEPInBounds =
GEP->isInBounds();
1181 bool NewGEPNUSW =
GEP->hasNoUnsignedSignedWrap();
1191 for (
unsigned I = 1,
E =
GEP->getNumOperands();
I !=
E; ++
I, ++GTI) {
1200 User *UserChainTail;
1202 Value *NewIdx = ConstantOffsetExtractor::Extract(
1203 GEP->getOperandUse(
I), UserChainTail, PreservesNUW);
1204 if (NewIdx !=
nullptr) {
1206 GEP->setOperand(
I, NewIdx);
1214 AllNUWPreserved &= PreservesNUW;
1216 AllOffsetsNonNegative =
1222 AllNUWPreserved &=
Base->hasNoUnsignedWrap();
1223 NewGEPInBounds &=
Base->isInBounds();
1224 NewGEPNUSW &=
Base->hasNoUnsignedSignedWrap();
1227 GEP->setOperand(0, NewBase);
1253 bool CanPreserveInBoundsNUSW = AllOffsetsNonNegative;
1257 if (AllNUWPreserved) {
1265 CanPreserveInBoundsNUSW |= NewGEPNUSW;
1268 if (CanPreserveInBoundsNUSW) {
1271 else if (NewGEPNUSW)
1275 GEP->setNoWrapFlags(NewGEPFlags);
1279 lowerToSingleIndexGEPs(
GEP, AccumulativeByteOffset);
1284 if (AccumulativeByteOffset == 0)
1307 Type *PtrIdxTy =
DL->getIndexType(
GEP->getType());
1310 NewGEP, ConstantInt::get(PtrIdxTy, AccumulativeByteOffset),
1311 GEP->getName(), NewGEPFlags));
1314 GEP->replaceAllUsesWith(NewGEP);
1315 GEP->eraseFromParent();
1320bool SeparateConstOffsetFromGEPLegacyPass::runOnFunction(
Function &
F) {
1321 if (skipFunction(
F))
1323 auto *DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
1324 auto *LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
1325 auto *TLI = &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(
F);
1326 auto GetTTI = [
this](
Function &
F) -> TargetTransformInfo & {
1327 return this->getAnalysis<TargetTransformInfoWrapperPass>().getTTI(
F);
1329 SeparateConstOffsetFromGEP Impl(DT, LI, TLI, GetTTI, LowerGEP);
1333bool SeparateConstOffsetFromGEP::run(
Function &
F) {
1334 const ScalarOptions &Opts = ScalarOptions::Global;
1335 if (Opts.disable_separate_const_offset_from_gep)
1338 DL = &
F.getDataLayout();
1341 ReversePostOrderTraversal<Function *> RPOT(&
F);
1342 for (BasicBlock *
B : RPOT) {
1355 if (Opts.reassociate_geps_verify_no_dead_code)
1356 verifyNoDeadCode(
F);
1361Instruction *SeparateConstOffsetFromGEP::findClosestMatchingDominator(
1362 ExprKey
Key, Instruction *Dominatee,
1363 DenseMap<ExprKey, SmallVector<Instruction *, 2>> &DominatingExprs) {
1364 auto Pos = DominatingExprs.find(
Key);
1365 if (Pos == DominatingExprs.end())
1368 auto &Candidates = Pos->second;
1373 while (!Candidates.empty()) {
1375 if (DT->
dominates(Candidate, Dominatee))
1377 Candidates.pop_back();
1382bool SeparateConstOffsetFromGEP::reuniteExts(Instruction *
I) {
1383 if (!
I->getType()->isIntOrIntVectorTy())
1393 ExprKey
Key = createNormalizedCommutablePair(
LHS,
RHS);
1394 if (
auto *Dom = findClosestMatchingDominator(
Key,
I, DominatingAdds)) {
1396 new SExtInst(Dom,
I->getType(),
"",
I->getIterator());
1398 I->replaceAllUsesWith(NewSExt);
1407 findClosestMatchingDominator({
LHS,
RHS},
I, DominatingSubs)) {
1409 new SExtInst(Dom,
I->getType(),
"",
I->getIterator());
1411 I->replaceAllUsesWith(NewSExt);
1422 ExprKey
Key = createNormalizedCommutablePair(
LHS,
RHS);
1423 DominatingAdds[
Key].push_back(
I);
1427 DominatingSubs[{
LHS,
RHS}].push_back(
I);
1432bool SeparateConstOffsetFromGEP::reuniteExts(
Function &
F) {
1434 DominatingAdds.clear();
1435 DominatingSubs.clear();
1444void SeparateConstOffsetFromGEP::verifyNoDeadCode(
Function &
F) {
1445 for (BasicBlock &
B :
F) {
1446 for (Instruction &
I :
B) {
1448 std::string ErrMessage;
1449 raw_string_ostream RSO(ErrMessage);
1450 RSO <<
"Dead instruction detected!\n" <<
I <<
"\n";
1457bool SeparateConstOffsetFromGEP::isLegalToSwapOperand(
1458 GetElementPtrInst *FirstGEP, GetElementPtrInst *SecondGEP,
Loop *CurLoop) {
1459 if (!FirstGEP || !FirstGEP->
hasOneUse())
1465 if (FirstGEP == SecondGEP)
1471 if (FirstNum != SecondNum || FirstNum != 2)
1496 if (FirstOffsetDef && FirstOffsetDef->
isShift() &&
1505 if ((opc == Instruction::Add || opc == Instruction::Sub) &&
1513bool SeparateConstOffsetFromGEP::hasMoreThanOneUseInLoop(
Value *V,
Loop *L) {
1520 for (User *U :
V->users()) {
1522 if (
L->contains(User))
1523 if (++UsesInLoop > 1)
1529void SeparateConstOffsetFromGEP::swapGEPOperand(GetElementPtrInst *
First,
1530 GetElementPtrInst *Second) {
1533 First->setOperand(1, Offset2);
1538 const DataLayout &DAL =
First->getDataLayout();
1542 auto ClearNoWrapFlags = [&] {
1548 APInt FirstOffset(IdxBits, 0);
1549 if (!
First->accumulateConstantOffset(DAL, FirstOffset)) {
1554 APInt BaseOffset(IdxBits, 0);
1559 bool Overflow =
false;
1560 APInt TotalOffset = BaseOffset.
uadd_ov(FirstOffset, Overflow);
1562 if (Overflow || !
getObjectSize(NewBase, ObjectSize, DAL, TLI) ||
1563 TotalOffset.
ugt(ObjectSize)) {
1568 First->setIsInBounds(
true);
1573 static_cast<PassInfoMixin<SeparateConstOffsetFromGEPPass> *
>(
this)
1589 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 bool allowsPreservingNUW(const User *U)
A helper function to check if reassociating through an entry in the user chain would invalidate the G...
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.
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 Instruction * clone() const
Create a copy of 'this' instruction that is identical in all ways except the following:
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 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.
void apply(Opt *O, const Mod &M, const Mods &... Ms)
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)
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
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 OverflowResult computeOverflowForSignedSub(const Value *LHS, const Value *RHS, const SimplifyQuery &SQ)
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.
constexpr detail::IsaCheckPredicate< Types... > IsaPred
Function object wrapper for the llvm::isa type check.