113#define DEBUG_TYPE "slsr"
116 std::numeric_limits<unsigned>::max();
119 "Controls whether rewriteCandidate is executed.");
122 "Number of candidate-basis SCEV differences computed by SLSR");
126class StraightLineStrengthReduceLegacyPass :
public FunctionPass {
132 StraightLineStrengthReduceLegacyPass() :
FunctionPass(ID) {
137 void getAnalysisUsage(AnalysisUsage &AU)
const override {
145 bool doInitialization(
Module &M)
override {
146 DL = &
M.getDataLayout();
153class StraightLineStrengthReduce {
155 StraightLineStrengthReduce(
const ScalarOptions &Opts,
const DataLayout *DL,
156 DominatorTree *DT, ScalarEvolution *SE,
157 TargetTransformInfo *TTI)
158 : Opts(Opts), DL(DL), DT(DT), SE(SE), TTI(TTI) {}
177 Candidate() =
default;
178 Candidate(Kind CT,
const SCEV *
B, ConstantInt *Idx,
Value *S,
179 Instruction *
I,
const SCEV *StrideSCEV)
180 : CandidateKind(CT), Base(
B), Index(
Idx), Stride(S), Ins(
I),
181 StrideSCEV(StrideSCEV) {}
183 Kind CandidateKind = Invalid;
185 const SCEV *Base =
nullptr;
190 ConstantInt *Index =
nullptr;
192 Value *Stride =
nullptr;
212 Candidate *Basis =
nullptr;
214 DKind DeltaKind = InvalidDelta;
217 const SCEV *StrideSCEV =
nullptr;
220 Value *Delta =
nullptr;
224 SmallVector<Instruction *> DropList;
234 enum EfficiencyLevel :
unsigned {
243 static EfficiencyLevel
244 getComputationEfficiency(Kind CandidateKind,
const ConstantInt *Index,
245 const Value *Stride,
const SCEV *Base =
nullptr) {
246 bool IsConstantBase =
false;
247 bool IsZeroBase =
false;
251 IsConstantBase =
true;
252 IsZeroBase = ConstBase->getValue()->isZero();
259 if (IsConstantBase && IsConstantStride)
263 if (CandidateKind == Mul) {
267 return (IsConstantStride || IsConstantBase) ? OneInstOneVar
271 return IsZeroBase && (Index->isOne() || Index->isMinusOne())
275 if (IsConstantStride) {
277 return (CI->isOne() || CI->isMinusOne()) ? OneInstOneVar
280 return TwoInstTwoVar;
284 assert(CandidateKind == Add || CandidateKind == GEP);
285 if (Index->isZero() || IsZeroStride)
288 bool IsSimpleIndex = Index->isOne() || Index->isMinusOne();
291 return IsZeroBase ? (IsSimpleIndex ? ZeroInst : OneInstOneVar)
292 : (IsSimpleIndex ? OneInstOneVar : TwoInstOneVar);
294 if (IsConstantStride)
295 return IsZeroStride ? ZeroInst : OneInstOneVar;
298 return OneInstTwoVar;
300 return TwoInstTwoVar;
304 bool isProfitableRewrite(
const Value &Delta,
const DKind DeltaKind)
const {
316 return getComputationEfficiency(CandidateKind, Index, Stride, Base) <=
317 getRewriteEfficiency(Delta, DeltaKind);
321 EfficiencyLevel getRewriteEfficiency()
const {
322 return Basis ? getRewriteEfficiency(*Delta, DeltaKind) : Unknown;
326 EfficiencyLevel getRewriteEfficiency(
const Value &Delta,
327 const DKind DeltaKind)
const {
330 return getComputationEfficiency(
334 return getComputationEfficiency(CandidateKind, Index, &Delta);
336 return getComputationEfficiency(CandidateKind,
343 bool isHighEfficiency()
const {
344 return getComputationEfficiency(CandidateKind, Index, Stride, Base) >=
350 bool hasValidDelta(
const Candidate &Basis)
const {
354 return Base == Basis.Base && StrideSCEV == Basis.StrideSCEV;
357 return Base == Basis.Base && Index == Basis.Index;
360 return StrideSCEV == Basis.StrideSCEV && Index == Basis.Index;
372 void setBasisAndDeltaFor(Candidate &
C);
374 bool isFoldable(
const Candidate &
C, TargetTransformInfo *TTI);
378 void allocateCandidatesAndFindBasis(Instruction *
I);
381 void allocateCandidatesAndFindBasisForAdd(Instruction *
I);
388 void allocateCandidatesAndFindBasisForMul(Instruction *
I);
396 void allocateCandidatesAndFindBasisForGEP(GetElementPtrInst *
GEP);
400 void allocateCandidatesAndFindBasis(Candidate::Kind CT,
const SCEV *
B,
401 ConstantInt *Idx,
Value *S,
405 void rewriteCandidate(
const Candidate &
C);
408 static Value *emitBump(
const Candidate &Basis,
const Candidate &
C,
411 const ScalarOptions &Opts;
412 const DataLayout *DL =
nullptr;
413 DominatorTree *DT =
nullptr;
415 TargetTransformInfo *TTI =
nullptr;
416 std::list<Candidate> Candidates;
420 DenseMap<const SCEV *, SmallSetVector<Instruction *, 2>> SCEVToInsts;
422 using SCEVUnknownSet = SmallPtrSet<const SCEVUnknown *, 4>;
423 DenseMap<const SCEV *, SCEVUnknownSet> SCEVUnknownsCache;
427 MapVector<Instruction *, std::vector<Instruction *>> DependencyGraph;
430 DenseMap<Instruction *, SmallVector<Candidate *, 3>> RewriteCandidates;
434 std::vector<Instruction *> SortedCandidateInsts;
438 std::vector<Instruction *> DeadInstructions;
441 class CandidateDictTy {
443 using CandsTy = SmallVector<Candidate *, 8>;
444 using BBToCandsTy = DenseMap<const BasicBlock *, CandsTy>;
448 using IndexDeltaKeyTy = std::tuple<const SCEV *, const SCEV *, Type *>;
449 DenseMap<IndexDeltaKeyTy, BBToCandsTy> IndexDeltaCandidates;
452 using BaseDeltaKeyTy = std::tuple<const SCEV *, ConstantInt *, Type *>;
453 DenseMap<BaseDeltaKeyTy, BBToCandsTy> BaseDeltaCandidates;
456 using StrideDeltaKeyTy = std::tuple<const SCEV *, ConstantInt *, Type *>;
457 DenseMap<StrideDeltaKeyTy, BBToCandsTy> StrideDeltaCandidates;
462 const BBToCandsTy *getCandidatesWithDeltaKind(
const Candidate &
C,
463 Candidate::DKind K)
const {
464 assert(K != Candidate::InvalidDelta);
465 if (K == Candidate::IndexDelta) {
466 IndexDeltaKeyTy IndexDeltaKey(
C.Base,
C.StrideSCEV,
C.Ins->getType());
467 auto It = IndexDeltaCandidates.find(IndexDeltaKey);
468 if (It != IndexDeltaCandidates.end())
470 }
else if (K == Candidate::BaseDelta) {
471 BaseDeltaKeyTy BaseDeltaKey(
C.StrideSCEV,
C.Index,
C.Ins->getType());
472 auto It = BaseDeltaCandidates.find(BaseDeltaKey);
473 if (It != BaseDeltaCandidates.end())
476 assert(K == Candidate::StrideDelta);
477 StrideDeltaKeyTy StrideDeltaKey(
C.Base,
C.Index,
C.Ins->getType());
478 auto It = StrideDeltaCandidates.find(StrideDeltaKey);
479 if (It != StrideDeltaCandidates.end())
486 void add(Candidate &
C) {
489 IndexDeltaKeyTy IndexDeltaKey(
C.Base,
C.StrideSCEV,
ValueType);
490 BaseDeltaKeyTy BaseDeltaKey(
C.StrideSCEV,
C.Index,
ValueType);
491 StrideDeltaKeyTy StrideDeltaKey(
C.Base,
C.Index,
ValueType);
492 IndexDeltaCandidates[IndexDeltaKey][BB].push_back(&
C);
493 BaseDeltaCandidates[BaseDeltaKey][BB].push_back(&
C);
494 StrideDeltaCandidates[StrideDeltaKey][BB].push_back(&
C);
498 IndexDeltaCandidates.clear();
499 BaseDeltaCandidates.clear();
500 StrideDeltaCandidates.clear();
504 const SCEV *getAndRecordSCEV(
Value *V) {
505 auto *S = SE->getSCEV(V);
513 bool candidatePredicate(Candidate *Basis, Candidate &
C, Candidate::DKind K);
515 bool hasSameSCEVUnknowns(
const SCEV *
A,
const SCEV *
B);
517 bool searchFrom(
const CandidateDictTy::BBToCandsTy &BBToCands, Candidate &
C,
523 Value *getNearestValueOfSCEV(
const SCEV *S,
const Instruction *CI)
const {
528 return SU->getValue();
530 return SC->getValue();
532 auto It = SCEVToInsts.find(S);
533 if (It == SCEVToInsts.end())
538 for (Instruction *
I :
reverse(It->second))
539 if (DT->dominates(
I, CI))
547 Candidate::DKind DeltaKind;
551 : Cand(nullptr), DeltaKind(Candidate::InvalidDelta), Delta(nullptr) {}
552 DeltaInfo(Candidate *Cand, Candidate::DKind DeltaKind,
Value *Delta)
553 : Cand(Cand), DeltaKind(DeltaKind), Delta(Delta) {}
554 operator bool()
const {
return Cand !=
nullptr; }
557 friend raw_ostream &
operator<<(raw_ostream &OS,
const DeltaInfo &DI);
559 DeltaInfo compressPath(Candidate &
C, Candidate *Basis)
const;
561 Candidate *pickRewriteCandidate(Instruction *
I)
const;
562 void sortCandidateInstructions();
563 Value *getDelta(
const Candidate &
C,
const Candidate &Basis,
564 Candidate::DKind K)
const;
565 static bool isSimilar(Candidate &
C, Candidate &Basis, Candidate::DKind K);
569 void addDependency(Candidate &
C, Candidate *Basis) {
571 DependencyGraph[Basis->Ins].emplace_back(
C.Ins);
576 auto PropagateDependency = [&](
Instruction *Inst) {
577 if (
auto CandsIt = RewriteCandidates.find(Inst);
578 CandsIt != RewriteCandidates.end() &&
580 [](Candidate *Cand) { return Cand->Basis; }))
581 DependencyGraph[Inst].emplace_back(
C.Ins);
587 PropagateDependency(DeltaInst);
591 PropagateDependency(StrideInst);
596 const StraightLineStrengthReduce::Candidate &
C) {
597 OS <<
"Ins: " << *
C.Ins <<
"\n Base: " << *
C.Base
598 <<
"\n Index: " << *
C.Index <<
"\n Stride: " << *
C.Stride
599 <<
"\n StrideSCEV: " << *
C.StrideSCEV;
601 OS <<
"\n Delta: " << *
C.Delta <<
"\n Basis: \n [ " << *
C.Basis <<
" ]";
607 OS <<
"Cand: " << *DI.Cand <<
"\n";
608 OS <<
"Delta Kind: ";
609 switch (DI.DeltaKind) {
610 case StraightLineStrengthReduce::Candidate::IndexDelta:
613 case StraightLineStrengthReduce::Candidate::BaseDelta:
616 case StraightLineStrengthReduce::Candidate::StrideDelta:
622 OS <<
"\nDelta: " << *DI.Delta;
628char StraightLineStrengthReduceLegacyPass::ID = 0;
631 "Straight line strength reduction",
false,
false)
639 return new StraightLineStrengthReduceLegacyPass();
644 if (
A.getBitWidth() <
B.getBitWidth())
645 A =
A.sext(
B.getBitWidth());
646 else if (
A.getBitWidth() >
B.getBitWidth())
647 B =
B.sext(
A.getBitWidth());
659 return !OBO || !OBO->hasNoSignedWrap();
669 return Idx->getType()->getIntegerBitWidth() <
670 DL->getIndexSizeInBits(
GEP->getAddressSpace());
687Value *StraightLineStrengthReduce::getDelta(
const Candidate &
C,
688 const Candidate &Basis,
689 Candidate::DKind
K)
const {
690 if (K == Candidate::IndexDelta) {
691 APInt
Idx =
C.Index->getValue();
692 APInt BasisIdx = Basis.Index->getValue();
694 APInt IndexDelta =
Idx - BasisIdx;
695 IntegerType *DeltaType =
697 return ConstantInt::get(DeltaType, IndexDelta);
698 }
else if (K == Candidate::BaseDelta || K == Candidate::StrideDelta) {
699 const SCEV *BasisPart =
700 (
K == Candidate::BaseDelta) ? Basis.Base : Basis.StrideSCEV;
701 const SCEV *CandPart = (
K == Candidate::BaseDelta) ?
C.Base :
C.StrideSCEV;
702 ++NumSCEVCandidateBasisDifferences;
703 const SCEV *Diff = SE->
getMinusSCEV(CandPart, BasisPart);
704 return getNearestValueOfSCEV(Diff,
C.Ins);
709bool StraightLineStrengthReduce::isSimilar(Candidate &
C, Candidate &Basis,
710 Candidate::DKind K) {
711 bool SameType =
false;
713 case Candidate::StrideDelta:
714 SameType =
C.StrideSCEV->getType() == Basis.StrideSCEV->getType();
716 case Candidate::BaseDelta:
717 SameType =
C.Base->getType() == Basis.Base->getType();
719 case Candidate::IndexDelta:
724 return SameType && Basis.Ins !=
C.Ins &&
725 Basis.CandidateKind ==
C.CandidateKind;
728bool StraightLineStrengthReduce::hasSameSCEVUnknowns(
const SCEV *
A,
730 auto CacheUnknowns = [&](
const SCEV *Root) {
736 SCEVUnknownSet &Unknowns;
738 bool follow(
const SCEV *S) {
743 bool isDone()
const {
return false; }
750 return SCEVUnknownsCache.
find(
A)->second == SCEVUnknownsCache.
find(
B)->second;
757bool StraightLineStrengthReduce::candidatePredicate(Candidate *Basis,
759 Candidate::DKind K) {
760 if (!isSimilar(
C, *Basis, K))
766 if (
C.Delta && K != Candidate::IndexDelta) {
767 const SCEV *CandidateSCEV =
768 K == Candidate::BaseDelta ?
C.Base :
C.StrideSCEV;
769 const SCEV *BasisSCEV =
770 K == Candidate::BaseDelta ? Basis->Base : Basis->StrideSCEV;
771 if (!hasSameSCEVUnknowns(CandidateSCEV, BasisSCEV))
776 Value *Delta = getDelta(
C, *Basis, K);
792 if (K == Candidate::StrideDelta &&
C.CandidateKind == Candidate::GEP &&
805 if (K == Candidate::IndexDelta &&
806 !
C.isProfitableRewrite(*Delta, Candidate::IndexDelta))
822bool StraightLineStrengthReduce::searchFrom(
823 const CandidateDictTy::BBToCandsTy &BBToCands, Candidate &
C,
824 Candidate::DKind K) {
828 if (
C.CandidateKind == Candidate::Mul && K != Candidate::IndexDelta)
836 auto It = BBToCands.find(BB);
837 if (It != BBToCands.end())
838 for (Candidate *Basis :
reverse(It->second))
839 if (candidatePredicate(Basis,
C, K))
846 BB =
Node ?
Node->getBlock() :
nullptr;
851void StraightLineStrengthReduce::setBasisAndDeltaFor(Candidate &
C) {
852 if (
const auto *BaseDeltaCandidates =
853 CandidateDict.getCandidatesWithDeltaKind(
C, Candidate::BaseDelta))
854 if (searchFrom(*BaseDeltaCandidates,
C, Candidate::BaseDelta)) {
859 if (
const auto *StrideDeltaCandidates =
860 CandidateDict.getCandidatesWithDeltaKind(
C, Candidate::StrideDelta))
861 if (searchFrom(*StrideDeltaCandidates,
C, Candidate::StrideDelta)) {
866 if (
const auto *IndexDeltaCandidates =
867 CandidateDict.getCandidatesWithDeltaKind(
C, Candidate::IndexDelta))
868 if (searchFrom(*IndexDeltaCandidates,
C, Candidate::IndexDelta)) {
876 dbgs() <<
"Found delta from ";
877 if (
C.DeltaKind == Candidate::BaseDelta)
880 dbgs() <<
"Stride: ";
881 dbgs() << *
C.Delta <<
"\n";
883 assert(
C.DeltaKind != Candidate::InvalidDelta &&
C.Basis);
897auto StraightLineStrengthReduce::compressPath(Candidate &
C,
898 Candidate *Basis)
const
900 if (!Basis || !Basis->Basis ||
C.CandidateKind == Candidate::Mul)
902 Candidate *Root = Basis;
903 Value *NewDelta =
nullptr;
904 auto NewKind = Candidate::InvalidDelta;
906 while (Root->Basis) {
907 Candidate *NextRoot = Root->Basis;
908 if (
C.Base == NextRoot->Base &&
C.StrideSCEV == NextRoot->StrideSCEV &&
909 isSimilar(
C, *NextRoot, Candidate::IndexDelta)) {
914 NewKind = Candidate::IndexDelta;
920 const SCEV *CandPart =
nullptr;
921 const SCEV *BasisPart =
nullptr;
922 auto CurrKind = Candidate::InvalidDelta;
923 if (
C.Base == NextRoot->Base &&
C.Index == NextRoot->Index) {
924 CandPart =
C.StrideSCEV;
925 BasisPart = NextRoot->StrideSCEV;
926 CurrKind = Candidate::StrideDelta;
927 }
else if (
C.StrideSCEV == NextRoot->StrideSCEV &&
928 C.Index == NextRoot->Index) {
930 BasisPart = NextRoot->Base;
931 CurrKind = Candidate::BaseDelta;
935 assert(CandPart && BasisPart);
936 if (!isSimilar(
C, *NextRoot, CurrKind))
944 if (CurrKind == Candidate::StrideDelta &&
945 C.CandidateKind == Candidate::GEP &&
950 ++NumSCEVCandidateBasisDifferences;
954 NewDelta = DeltaVal->getValue();
961 assert(NewKind != Candidate::InvalidDelta && NewDelta);
963 <<
" from path compression.\n");
964 return {Root, NewKind, NewDelta};
972void StraightLineStrengthReduce::sortCandidateInstructions() {
973 SortedCandidateInsts.clear();
979 DenseMap<Instruction *, int> InDegree;
980 for (
auto &KV : DependencyGraph) {
983 for (
auto *Child : KV.second) {
987 std::queue<Instruction *> WorkList;
988 DenseSet<Instruction *> Visited;
990 for (
auto &KV : DependencyGraph)
991 if (InDegree[KV.first] == 0)
992 WorkList.push(KV.first);
994 while (!WorkList.empty()) {
1000 SortedCandidateInsts.push_back(
I);
1002 for (
auto *
Next : DependencyGraph[
I]) {
1003 auto &Degree = InDegree[
Next];
1005 WorkList.push(
Next);
1009 assert(SortedCandidateInsts.size() == DependencyGraph.size() &&
1010 "Dependency graph should not have cycles");
1013auto StraightLineStrengthReduce::pickRewriteCandidate(Instruction *
I)
const
1016 auto It = RewriteCandidates.
find(
I);
1017 if (It == RewriteCandidates.
end())
1020 Candidate *BestC =
nullptr;
1021 auto BestEfficiency = Candidate::Unknown;
1022 for (Candidate *
C :
reverse(It->second))
1024 auto Efficiency =
C->getRewriteEfficiency();
1025 if (Efficiency > BestEfficiency) {
1026 BestEfficiency = Efficiency;
1037 return TTI->getGEPCost(
1038 GEP->getSourceElementType(),
GEP->getPointerOperand(), Indices,
1047 return Index->getBitWidth() <= 64 &&
1048 TTI->isLegalAddressingMode(
Base->getType(),
nullptr, 0,
true,
1052bool StraightLineStrengthReduce::isFoldable(
const Candidate &
C,
1053 TargetTransformInfo *
TTI) {
1054 if (
C.CandidateKind == Candidate::Add)
1056 if (
C.CandidateKind == Candidate::GEP)
1061void StraightLineStrengthReduce::allocateCandidatesAndFindBasis(
1062 Candidate::Kind CT,
const SCEV *
B, ConstantInt *Idx,
Value *S,
1064 bool IsSafe = CT != Candidate::GEP ||
1069 Candidate
C(CT,
B, Idx, S,
I, getAndRecordSCEV(S));
1080 if (IsSafe && !isFoldable(
C,
TTI) && !
C.isHighEfficiency()) {
1081 setBasisAndDeltaFor(
C);
1084 if (
auto Res = compressPath(
C,
C.Basis)) {
1086 C.DeltaKind = Res.DeltaKind;
1087 C.Delta = Res.Delta;
1093 Candidates.push_back(
C);
1094 RewriteCandidates[
C.Ins].push_back(&Candidates.back());
1099 if (!Opts.enable_poison_reuse_guard ||
1101 CandidateDict.add(Candidates.back());
1105void StraightLineStrengthReduce::allocateCandidatesAndFindBasis(
1107 switch (
I->getOpcode()) {
1108 case Instruction::Add:
1109 allocateCandidatesAndFindBasisForAdd(
I);
1111 case Instruction::Mul:
1112 allocateCandidatesAndFindBasisForMul(
I);
1114 case Instruction::GetElementPtr:
1120void StraightLineStrengthReduce::allocateCandidatesAndFindBasisForAdd(
1126 assert(
I->getNumOperands() == 2 &&
"isn't I an add?");
1128 allocateCandidatesAndFindBasisForAdd(
LHS,
RHS,
I);
1130 allocateCandidatesAndFindBasisForAdd(
RHS,
LHS,
I);
1133void StraightLineStrengthReduce::allocateCandidatesAndFindBasisForAdd(
1136 ConstantInt *
Idx =
nullptr;
1139 allocateCandidatesAndFindBasis(Candidate::Add, SE->
getSCEV(
LHS), Idx, S,
I);
1142 APInt One(
Idx->getBitWidth(), 1);
1143 Idx = ConstantInt::get(
Idx->getContext(), One <<
Idx->getValue());
1144 allocateCandidatesAndFindBasis(Candidate::Add, SE->
getSCEV(
LHS), Idx, S,
I);
1148 allocateCandidatesAndFindBasis(Candidate::Add, SE->
getSCEV(
LHS), One,
RHS,
1163void StraightLineStrengthReduce::allocateCandidatesAndFindBasisForMul(
1166 ConstantInt *
Idx =
nullptr;
1170 allocateCandidatesAndFindBasis(Candidate::Mul, SE->
getSCEV(
B), Idx,
RHS,
I);
1176 allocateCandidatesAndFindBasis(Candidate::Mul, SE->
getSCEV(
B), Idx,
RHS,
I);
1180 allocateCandidatesAndFindBasis(Candidate::Mul, SE->
getSCEV(
LHS), Zero,
RHS,
1185void StraightLineStrengthReduce::allocateCandidatesAndFindBasisForMul(
1192 assert(
I->getNumOperands() == 2 &&
"isn't I a mul?");
1194 allocateCandidatesAndFindBasisForMul(
LHS,
RHS,
I);
1197 allocateCandidatesAndFindBasisForMul(
RHS,
LHS,
I);
1201void StraightLineStrengthReduce::allocateCandidatesAndFindBasisForGEP(
1202 GetElementPtrInst *
GEP) {
1204 if (
GEP->getType()->isVectorTy())
1208 for (Use &Idx :
GEP->indices())
1212 for (
unsigned I = 1,
E =
GEP->getNumOperands();
I !=
E; ++
I, ++GTI) {
1216 SCEVUse OrigIndexExpr = IndexExprs[
I - 1];
1226 ConstantInt *ElementSizeIdx =
1229 DL->getIndexSizeInBits(
GEP->getAddressSpace())) {
1232 allocateCandidatesAndFindBasis(Candidate::GEP, BaseExpr, ElementSizeIdx,
1238 Value *TruncatedArrayIdx =
nullptr;
1241 DL->getIndexSizeInBits(
GEP->getAddressSpace())) {
1244 allocateCandidatesAndFindBasis(Candidate::GEP, BaseExpr, ElementSizeIdx,
1245 TruncatedArrayIdx,
GEP);
1248 IndexExprs[
I - 1] = OrigIndexExpr;
1252Value *StraightLineStrengthReduce::emitBump(
const Candidate &Basis,
1255 const DataLayout *
DL) {
1258 const APInt &ConstRHS = CR->getValue();
1259 IntegerType *DeltaType =
1263 ConstantInt::get(DeltaType, ConstRHS.
logBase2());
1268 ConstantInt::get(DeltaType, (-ConstRHS).logBase2());
1283 if (
C.DeltaKind == Candidate::IndexDelta) {
1294 if (IndexDelta == 1)
1300 IntegerType *DeltaType =
1307 assert(
C.DeltaKind == Candidate::StrideDelta ||
1308 C.DeltaKind == Candidate::BaseDelta);
1309 assert(
C.CandidateKind != Candidate::Mul);
1325 if (
C.DeltaKind == Candidate::StrideDelta) {
1328 if (
C.CandidateKind == Candidate::GEP) {
1330 Type *NewScalarIndexTy =
1331 DL->getIndexType(
GEP->getPointerOperandType()->getScalarType());
1334 if (!
C.Index->isOne()) {
1335 Value *ExtendedIndex =
1343void StraightLineStrengthReduce::rewriteCandidate(
const Candidate &
C) {
1347 const Candidate &Basis = *
C.Basis;
1348 assert(
C.Delta &&
C.CandidateKind == Basis.CandidateKind &&
1349 C.hasValidDelta(Basis));
1351 for (Instruction *
I : Basis.DropList)
1352 I->dropPoisonGeneratingAnnotations();
1355 Value *Bump = emitBump(Basis,
C, Builder,
DL);
1356 Value *Reduced =
nullptr;
1360 Reduced = Basis.Ins;
1362 switch (
C.CandidateKind) {
1363 case Candidate::Add:
1364 case Candidate::Mul: {
1369 Reduced = Builder.
CreateSub(Basis.Ins, NegBump);
1383 Reduced = Builder.
CreateAdd(Basis.Ins, Bump);
1387 case Candidate::GEP: {
1390 Reduced = Builder.
CreatePtrAdd(Basis.Ins, Bump,
"", InBounds);
1398 C.Ins->replaceAllUsesWith(Reduced);
1399 DeadInstructions.push_back(
C.Ins);
1402bool StraightLineStrengthReduceLegacyPass::runOnFunction(
Function &
F) {
1403 if (skipFunction(
F))
1406 auto *
TTI = &getAnalysis<TargetTransformInfoWrapperPass>().getTTI(
F);
1407 auto *DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
1408 auto *SE = &getAnalysis<ScalarEvolutionWrapperPass>().getSE();
1409 const ScalarOptions &Opts =
1411 return StraightLineStrengthReduce(Opts,
DL, DT, SE,
TTI).runOnFunction(
F);
1414bool StraightLineStrengthReduce::runOnFunction(
Function &
F) {
1419 for (
auto &
I : *(
Node->getBlock()))
1420 allocateCandidatesAndFindBasis(&
I);
1424 for (
auto &
C : Candidates) {
1425 DependencyGraph.try_emplace(
C.Ins);
1426 addDependency(
C,
C.Basis);
1428 sortCandidateInstructions();
1432 for (Instruction *
I :
reverse(SortedCandidateInsts))
1433 if (Candidate *
C = pickRewriteCandidate(
I))
1434 rewriteCandidate(*
C);
1436 for (
auto *DeadIns : DeadInstructions)
1439 if (DeadIns->getParent())
1442 bool Ret = !DeadInstructions.empty();
1443 DeadInstructions.clear();
1444 DependencyGraph.clear();
1445 RewriteCandidates.
clear();
1446 SortedCandidateInsts.clear();
1448 CandidateDict.clear();
1461 const ScalarOptions &Opts =
1462 F.getContext().getLibraryOptions().get<ScalarOptions>();
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")
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
This file contains the declarations for the subclasses of Constant, which represent the different fla...
This file provides an implementation of debug counters.
#define DEBUG_COUNTER(VARNAME, COUNTERNAME, DESC)
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.
static bool isZero(Value *V, const DataLayout &DL, DominatorTree *DT, AssumptionCache *AC)
static bool isGEPFoldable(GetElementPtrInst *GEP, const TargetTransformInfo *TTI)
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
static BinaryOperator * CreateMul(Value *S1, Value *S2, const Twine &Name, BasicBlock::iterator InsertBefore, Value *FlagsOp)
Register Usage Information Collector
This file implements a set that has insertion order iteration characteristics.
This file defines the SmallPtrSet class.
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
static bool matchesOr(Value *A, Value *&B, ConstantInt *&C)
static bool isAddFoldable(const SCEV *Base, ConstantInt *Index, Value *Stride, TargetTransformInfo *TTI)
static void unifyBitWidth(APInt &A, APInt &B)
static bool matchesAdd(Value *A, Value *&B, ConstantInt *&C)
static const unsigned UnknownAddressSpace
static bool mayHaveSignedWrap(const Value *V)
static bool isSignExtendedGepIndex(const Value *Idx, GetElementPtrInst *GEP, const DataLayout *DL)
static bool isSafeToFactorGepIndex(const Value *Idx, GetElementPtrInst *GEP, const DataLayout *DL)
Class for arbitrary precision integers.
bool isNegatedPowerOf2() const
Check if this APInt's negated value is a power of two greater than zero.
bool isAllOnes() const
Determine if all bits are set. This is true for zero-width values.
unsigned getBitWidth() const
Return the number of bits in the APInt.
unsigned logBase2() const
bool isPowerOf2() const
Check if this APInt's value is a power of two greater than zero.
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:
const Function * getParent() const
Return the enclosing method, or null if none.
Represents analyses that only rely on functions' control flow.
This is the shared class of boolean and integer constants.
bool isOne() const
This is just a convenience method to make client code smaller for a common case.
static ConstantInt * getSigned(IntegerType *Ty, int64_t V, bool ImplicitTrunc=false)
Return a ConstantInt with the specified value for the specified type.
bool isZero() const
This is just a convenience method to make client code smaller for a common code.
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.
static bool shouldExecute(CounterInfo &Counter)
iterator find(const_arg_type_t< KeyT > Val)
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
Analysis pass which computes a DominatorTree.
DomTreeNodeBase< NodeT > * getNode(const NodeT *BB) const
getNode - return the (Post)DominatorTree node for the specified basic block.
Legacy analysis pass which computes a DominatorTree.
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.
an instruction for type-safe pointer arithmetic to access elements of arrays and structs
Value * CreatePtrAdd(Value *Ptr, Value *Offset, const Twine &Name="", GEPNoWrapFlags NW=GEPNoWrapFlags::none())
Value * CreateNeg(Value *V, const Twine &Name="", bool HasNSW=false)
Value * CreateSub(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Value * CreateShl(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Value * CreateAdd(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Value * CreateSExtOrTrunc(Value *V, Type *DestTy, const Twine &Name="")
Create a SExt or Trunc from the integer value V to DestTy.
Value * CreateMul(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
static LLVM_ABI IntegerType * get(LLVMContext &C, unsigned NumBits)
This static method is the primary way of constructing an IntegerType.
LLVM_ABI cl::LibraryOptionsContext & getLibraryOptions() const
The library options this context reads in place of their process-wide values.
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.
PreservedAnalyses & preserve()
Mark an analysis as preserved.
This class represents an analyzed expression in the program.
Type * getType() const
Return the LLVM type of this SCEV expression.
Analysis pass that exposes the ScalarEvolution for a function.
const SCEV * getZero(Type *Ty)
Return a SCEV for the constant 0 of a specific type.
LLVM_ABI const SCEV * getMinusSCEV(SCEVUse LHS, SCEVUse RHS, SCEVFlags Flags=SCEV::FlagNone, unsigned Depth=0)
Return LHS-RHS.
LLVM_ABI const SCEV * getSCEV(Value *V)
Return a SCEV expression for the full generality of the specified expression.
LLVM_ABI bool canReuseInstruction(const SCEV *S, Instruction *I, SmallVectorImpl< Instruction * > &DropPoisonGeneratingInsts)
Check whether it is poison-safe to represent the expression S using the instruction I.
LLVM_ABI const SCEV * getGEPExpr(GEPOperator *GEP, ArrayRef< SCEVUse > IndexExprs)
Returns an expression for a GEP.
LLVMContext & getContext() const
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
LLVM_ABI PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
Analysis pass providing the TargetTransformInfo.
LLVM_ABI unsigned getIntegerBitWidth() const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
LLVM_ABI void takeName(Value *V)
Transfer the name from V to this value.
std::pair< iterator, bool > insert(const ValueT &V)
TypeSize getSequentialElementStride(const DataLayout &DL) 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.
BinaryOp_match< SpecificConstantMatch, SrcTy, TargetOpcode::G_SUB > m_Neg(const SrcTy &&Src)
Matches a register negated by a G_SUB.
bool match(Val *V, const Pattern &P)
auto m_Value()
Match an arbitrary value and ignore it.
BinaryOp_match< LHS, RHS, Instruction::Mul > m_Mul(const LHS &L, const RHS &R)
BinaryOp_match< LHS, RHS, Instruction::Add, true > m_c_Add(const LHS &L, const RHS &R)
Matches a Add with LHS and RHS in either order.
BinaryOp_match< LHS, RHS, Instruction::Shl > m_Shl(const LHS &L, const RHS &R)
CastInst_match< OpTy, SExtInst > m_SExt(const OpTy &Op)
Matches SExt.
BinaryOp_match< LHS, RHS, Instruction::Or, true > m_c_Or(const LHS &L, const RHS &R)
Matches an Or with LHS and RHS in either order.
auto m_ConstantInt()
Match an arbitrary ConstantInt and ignore it.
NodeAddr< NodeBase * > Node
friend class Instruction
Iterator for Instructions in a `BasicBlock.
This is an optimization pass for GlobalISel generic memory operations.
void visitAll(const SCEV *Root, SV &Visitor)
Use SCEVTraversal to visit all nodes in the given expression tree.
LLVM_ABI bool haveNoCommonBitsSet(const WithCache< const Value * > &LHSCache, const WithCache< const Value * > &RHSCache, const SimplifyQuery &SQ)
Return true if LHS and RHS have no common bits set.
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.
@ Unknown
Not known to have no common set bits.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI void initializeStraightLineStrengthReduceLegacyPassPass(PassRegistry &)
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
DomTreeNodeBase< BasicBlock > DomTreeNode
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.
auto reverse(ContainerTy &&C)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
IRBuilder(LLVMContext &, FolderTy, InserterTy) -> IRBuilder< FolderTy, InserterTy >
generic_gep_type_iterator<> gep_type_iterator
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...
raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)
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)
PointerUnion< const Value *, const PseudoSourceValue * > ValueType
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Next
iterator_range< df_iterator< T > > depth_first(const T &G)
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
LLVM_ABI FunctionPass * createStraightLineStrengthReducePass()
SCEVUseT< const SCEV * > SCEVUse
SCEVPtrT getPointer() const