112#define DEBUG_TYPE "slsr"
115 std::numeric_limits<unsigned>::max();
118 "Controls whether rewriteCandidate is executed.");
123 cl::desc(
"Enable poison-reuse guard"));
126 "Number of candidate-basis SCEV differences computed by SLSR");
130class StraightLineStrengthReduceLegacyPass :
public FunctionPass {
136 StraightLineStrengthReduceLegacyPass() :
FunctionPass(ID) {
141 void getAnalysisUsage(AnalysisUsage &AU)
const override {
149 bool doInitialization(
Module &M)
override {
150 DL = &
M.getDataLayout();
157class StraightLineStrengthReduce {
159 StraightLineStrengthReduce(
const DataLayout *DL, DominatorTree *DT,
160 ScalarEvolution *SE, TargetTransformInfo *TTI)
161 : DL(DL), DT(DT), SE(SE), TTI(TTI) {}
180 Candidate() =
default;
181 Candidate(Kind CT,
const SCEV *
B, ConstantInt *Idx,
Value *S,
182 Instruction *
I,
const SCEV *StrideSCEV)
183 : CandidateKind(CT), Base(
B), Index(Idx), Stride(S), Ins(
I),
184 StrideSCEV(StrideSCEV) {}
186 Kind CandidateKind = Invalid;
188 const SCEV *Base =
nullptr;
193 ConstantInt *Index =
nullptr;
195 Value *Stride =
nullptr;
215 Candidate *Basis =
nullptr;
217 DKind DeltaKind = InvalidDelta;
220 const SCEV *StrideSCEV =
nullptr;
223 Value *Delta =
nullptr;
227 SmallVector<Instruction *> DropList;
237 enum EfficiencyLevel :
unsigned {
246 static EfficiencyLevel
247 getComputationEfficiency(Kind CandidateKind,
const ConstantInt *Index,
248 const Value *Stride,
const SCEV *Base =
nullptr) {
249 bool IsConstantBase =
false;
250 bool IsZeroBase =
false;
254 IsConstantBase =
true;
255 IsZeroBase = ConstBase->getValue()->isZero();
262 if (IsConstantBase && IsConstantStride)
266 if (CandidateKind == Mul) {
270 return (IsConstantStride || IsConstantBase) ? OneInstOneVar
274 return IsZeroBase && (Index->isOne() || Index->isMinusOne())
278 if (IsConstantStride) {
280 return (CI->isOne() || CI->isMinusOne()) ? OneInstOneVar
283 return TwoInstTwoVar;
287 assert(CandidateKind == Add || CandidateKind == GEP);
288 if (Index->isZero() || IsZeroStride)
291 bool IsSimpleIndex = Index->isOne() || Index->isMinusOne();
294 return IsZeroBase ? (IsSimpleIndex ? ZeroInst : OneInstOneVar)
295 : (IsSimpleIndex ? OneInstOneVar : TwoInstOneVar);
297 if (IsConstantStride)
298 return IsZeroStride ? ZeroInst : OneInstOneVar;
301 return OneInstTwoVar;
303 return TwoInstTwoVar;
307 bool isProfitableRewrite(
const Value &Delta,
const DKind DeltaKind)
const {
319 return getComputationEfficiency(CandidateKind, Index, Stride, Base) <=
320 getRewriteEfficiency(Delta, DeltaKind);
324 EfficiencyLevel getRewriteEfficiency()
const {
325 return Basis ? getRewriteEfficiency(*Delta, DeltaKind) : Unknown;
329 EfficiencyLevel getRewriteEfficiency(
const Value &Delta,
330 const DKind DeltaKind)
const {
333 return getComputationEfficiency(
337 return getComputationEfficiency(CandidateKind, Index, &Delta);
339 return getComputationEfficiency(CandidateKind,
346 bool isHighEfficiency()
const {
347 return getComputationEfficiency(CandidateKind, Index, Stride, Base) >=
353 bool hasValidDelta(
const Candidate &Basis)
const {
357 return Base == Basis.Base && StrideSCEV == Basis.StrideSCEV;
360 return Base == Basis.Base && Index == Basis.Index;
363 return StrideSCEV == Basis.StrideSCEV && Index == Basis.Index;
375 void setBasisAndDeltaFor(Candidate &
C);
377 bool isFoldable(
const Candidate &
C, TargetTransformInfo *TTI);
381 void allocateCandidatesAndFindBasis(Instruction *
I);
384 void allocateCandidatesAndFindBasisForAdd(Instruction *
I);
391 void allocateCandidatesAndFindBasisForMul(Instruction *
I);
399 void allocateCandidatesAndFindBasisForGEP(GetElementPtrInst *
GEP);
403 void allocateCandidatesAndFindBasis(Candidate::Kind CT,
const SCEV *
B,
404 ConstantInt *Idx,
Value *S,
408 void rewriteCandidate(
const Candidate &
C);
411 static Value *emitBump(
const Candidate &Basis,
const Candidate &
C,
414 const DataLayout *DL =
nullptr;
415 DominatorTree *DT =
nullptr;
417 TargetTransformInfo *TTI =
nullptr;
418 std::list<Candidate> Candidates;
422 DenseMap<const SCEV *, SmallSetVector<Instruction *, 2>> SCEVToInsts;
424 using SCEVUnknownSet = SmallPtrSet<const SCEVUnknown *, 4>;
425 DenseMap<const SCEV *, SCEVUnknownSet> SCEVUnknownsCache;
429 MapVector<Instruction *, std::vector<Instruction *>> DependencyGraph;
432 DenseMap<Instruction *, SmallVector<Candidate *, 3>> RewriteCandidates;
436 std::vector<Instruction *> SortedCandidateInsts;
440 std::vector<Instruction *> DeadInstructions;
443 class CandidateDictTy {
445 using CandsTy = SmallVector<Candidate *, 8>;
446 using BBToCandsTy = DenseMap<const BasicBlock *, CandsTy>;
450 using IndexDeltaKeyTy = std::tuple<const SCEV *, const SCEV *, Type *>;
451 DenseMap<IndexDeltaKeyTy, BBToCandsTy> IndexDeltaCandidates;
454 using BaseDeltaKeyTy = std::tuple<const SCEV *, ConstantInt *, Type *>;
455 DenseMap<BaseDeltaKeyTy, BBToCandsTy> BaseDeltaCandidates;
458 using StrideDeltaKeyTy = std::tuple<const SCEV *, ConstantInt *, Type *>;
459 DenseMap<StrideDeltaKeyTy, BBToCandsTy> StrideDeltaCandidates;
464 const BBToCandsTy *getCandidatesWithDeltaKind(
const Candidate &
C,
465 Candidate::DKind K)
const {
466 assert(K != Candidate::InvalidDelta);
467 if (K == Candidate::IndexDelta) {
468 IndexDeltaKeyTy IndexDeltaKey(
C.Base,
C.StrideSCEV,
C.Ins->getType());
469 auto It = IndexDeltaCandidates.find(IndexDeltaKey);
470 if (It != IndexDeltaCandidates.end())
472 }
else if (K == Candidate::BaseDelta) {
473 BaseDeltaKeyTy BaseDeltaKey(
C.StrideSCEV,
C.Index,
C.Ins->getType());
474 auto It = BaseDeltaCandidates.find(BaseDeltaKey);
475 if (It != BaseDeltaCandidates.end())
478 assert(K == Candidate::StrideDelta);
479 StrideDeltaKeyTy StrideDeltaKey(
C.Base,
C.Index,
C.Ins->getType());
480 auto It = StrideDeltaCandidates.find(StrideDeltaKey);
481 if (It != StrideDeltaCandidates.end())
488 void add(Candidate &
C) {
491 IndexDeltaKeyTy IndexDeltaKey(
C.Base,
C.StrideSCEV,
ValueType);
492 BaseDeltaKeyTy BaseDeltaKey(
C.StrideSCEV,
C.Index,
ValueType);
493 StrideDeltaKeyTy StrideDeltaKey(
C.Base,
C.Index,
ValueType);
494 IndexDeltaCandidates[IndexDeltaKey][BB].push_back(&
C);
495 BaseDeltaCandidates[BaseDeltaKey][BB].push_back(&
C);
496 StrideDeltaCandidates[StrideDeltaKey][BB].push_back(&
C);
500 IndexDeltaCandidates.clear();
501 BaseDeltaCandidates.clear();
502 StrideDeltaCandidates.clear();
506 const SCEV *getAndRecordSCEV(
Value *V) {
507 auto *S = SE->getSCEV(V);
515 bool candidatePredicate(Candidate *Basis, Candidate &
C, Candidate::DKind K);
517 bool hasSameSCEVUnknowns(
const SCEV *
A,
const SCEV *
B);
519 bool searchFrom(
const CandidateDictTy::BBToCandsTy &BBToCands, Candidate &
C,
525 Value *getNearestValueOfSCEV(
const SCEV *S,
const Instruction *CI)
const {
530 return SU->getValue();
532 return SC->getValue();
534 auto It = SCEVToInsts.find(S);
535 if (It == SCEVToInsts.end())
540 for (Instruction *
I :
reverse(It->second))
541 if (DT->dominates(
I, CI))
549 Candidate::DKind DeltaKind;
553 : Cand(nullptr), DeltaKind(Candidate::InvalidDelta), Delta(nullptr) {}
554 DeltaInfo(Candidate *Cand, Candidate::DKind DeltaKind,
Value *Delta)
555 : Cand(Cand), DeltaKind(DeltaKind), Delta(Delta) {}
556 operator bool()
const {
return Cand !=
nullptr; }
559 friend raw_ostream &
operator<<(raw_ostream &OS,
const DeltaInfo &DI);
561 DeltaInfo compressPath(Candidate &
C, Candidate *Basis)
const;
563 Candidate *pickRewriteCandidate(Instruction *
I)
const;
564 void sortCandidateInstructions();
565 Value *getDelta(
const Candidate &
C,
const Candidate &Basis,
566 Candidate::DKind K)
const;
567 static bool isSimilar(Candidate &
C, Candidate &Basis, Candidate::DKind K);
571 void addDependency(Candidate &
C, Candidate *Basis) {
573 DependencyGraph[Basis->Ins].emplace_back(
C.Ins);
578 auto PropagateDependency = [&](
Instruction *Inst) {
579 if (
auto CandsIt = RewriteCandidates.find(Inst);
580 CandsIt != RewriteCandidates.end() &&
582 [](Candidate *Cand) { return Cand->Basis; }))
583 DependencyGraph[Inst].emplace_back(
C.Ins);
589 PropagateDependency(DeltaInst);
593 PropagateDependency(StrideInst);
598 const StraightLineStrengthReduce::Candidate &
C) {
599 OS <<
"Ins: " << *
C.Ins <<
"\n Base: " << *
C.Base
600 <<
"\n Index: " << *
C.Index <<
"\n Stride: " << *
C.Stride
601 <<
"\n StrideSCEV: " << *
C.StrideSCEV;
603 OS <<
"\n Delta: " << *
C.Delta <<
"\n Basis: \n [ " << *
C.Basis <<
" ]";
609 OS <<
"Cand: " << *DI.Cand <<
"\n";
610 OS <<
"Delta Kind: ";
611 switch (DI.DeltaKind) {
612 case StraightLineStrengthReduce::Candidate::IndexDelta:
615 case StraightLineStrengthReduce::Candidate::BaseDelta:
618 case StraightLineStrengthReduce::Candidate::StrideDelta:
624 OS <<
"\nDelta: " << *DI.Delta;
630char StraightLineStrengthReduceLegacyPass::ID = 0;
633 "Straight line strength reduction",
false,
false)
641 return new StraightLineStrengthReduceLegacyPass();
646 if (
A.getBitWidth() <
B.getBitWidth())
647 A =
A.sext(
B.getBitWidth());
648 else if (
A.getBitWidth() >
B.getBitWidth())
649 B =
B.sext(
A.getBitWidth());
661 return !OBO || !OBO->hasNoSignedWrap();
672 DL->getIndexSizeInBits(
GEP->getAddressSpace());
689Value *StraightLineStrengthReduce::getDelta(
const Candidate &
C,
690 const Candidate &Basis,
691 Candidate::DKind K)
const {
692 if (K == Candidate::IndexDelta) {
693 APInt Idx =
C.Index->getValue();
694 APInt BasisIdx = Basis.Index->getValue();
696 APInt IndexDelta = Idx - BasisIdx;
697 IntegerType *DeltaType =
699 return ConstantInt::get(DeltaType, IndexDelta);
700 }
else if (K == Candidate::BaseDelta || K == Candidate::StrideDelta) {
701 const SCEV *BasisPart =
702 (
K == Candidate::BaseDelta) ? Basis.Base : Basis.StrideSCEV;
703 const SCEV *CandPart = (
K == Candidate::BaseDelta) ?
C.Base :
C.StrideSCEV;
704 ++NumSCEVCandidateBasisDifferences;
705 const SCEV *Diff = SE->
getMinusSCEV(CandPart, BasisPart);
706 return getNearestValueOfSCEV(Diff,
C.Ins);
711bool StraightLineStrengthReduce::isSimilar(Candidate &
C, Candidate &Basis,
712 Candidate::DKind K) {
713 bool SameType =
false;
715 case Candidate::StrideDelta:
716 SameType =
C.StrideSCEV->getType() == Basis.StrideSCEV->getType();
718 case Candidate::BaseDelta:
719 SameType =
C.Base->getType() == Basis.Base->getType();
721 case Candidate::IndexDelta:
726 return SameType && Basis.Ins !=
C.Ins &&
727 Basis.CandidateKind ==
C.CandidateKind;
730bool StraightLineStrengthReduce::hasSameSCEVUnknowns(
const SCEV *
A,
732 auto CacheUnknowns = [&](
const SCEV *Root) {
738 SCEVUnknownSet &Unknowns;
740 bool follow(
const SCEV *S) {
745 bool isDone()
const {
return false; }
752 return SCEVUnknownsCache.
find(
A)->second == SCEVUnknownsCache.
find(
B)->second;
759bool StraightLineStrengthReduce::candidatePredicate(Candidate *Basis,
761 Candidate::DKind K) {
762 if (!isSimilar(
C, *Basis, K))
768 if (
C.Delta && K != Candidate::IndexDelta) {
769 const SCEV *CandidateSCEV =
770 K == Candidate::BaseDelta ?
C.Base :
C.StrideSCEV;
771 const SCEV *BasisSCEV =
772 K == Candidate::BaseDelta ? Basis->Base : Basis->StrideSCEV;
773 if (!hasSameSCEVUnknowns(CandidateSCEV, BasisSCEV))
778 Value *Delta = getDelta(
C, *Basis, K);
794 if (K == Candidate::StrideDelta &&
C.CandidateKind == Candidate::GEP &&
807 if (K == Candidate::IndexDelta &&
808 !
C.isProfitableRewrite(*Delta, Candidate::IndexDelta))
813 for (Instruction *
I : Basis->DropList)
814 I->dropPoisonGeneratingAnnotations();
829bool StraightLineStrengthReduce::searchFrom(
830 const CandidateDictTy::BBToCandsTy &BBToCands, Candidate &
C,
831 Candidate::DKind K) {
835 if (
C.CandidateKind == Candidate::Mul && K != Candidate::IndexDelta)
843 auto It = BBToCands.find(BB);
844 if (It != BBToCands.end())
845 for (Candidate *Basis :
reverse(It->second))
846 if (candidatePredicate(Basis,
C, K))
853 BB =
Node ?
Node->getBlock() :
nullptr;
858void StraightLineStrengthReduce::setBasisAndDeltaFor(Candidate &
C) {
859 if (
const auto *BaseDeltaCandidates =
860 CandidateDict.getCandidatesWithDeltaKind(
C, Candidate::BaseDelta))
861 if (searchFrom(*BaseDeltaCandidates,
C, Candidate::BaseDelta)) {
866 if (
const auto *StrideDeltaCandidates =
867 CandidateDict.getCandidatesWithDeltaKind(
C, Candidate::StrideDelta))
868 if (searchFrom(*StrideDeltaCandidates,
C, Candidate::StrideDelta)) {
873 if (
const auto *IndexDeltaCandidates =
874 CandidateDict.getCandidatesWithDeltaKind(
C, Candidate::IndexDelta))
875 if (searchFrom(*IndexDeltaCandidates,
C, Candidate::IndexDelta)) {
883 dbgs() <<
"Found delta from ";
884 if (
C.DeltaKind == Candidate::BaseDelta)
887 dbgs() <<
"Stride: ";
888 dbgs() << *
C.Delta <<
"\n";
890 assert(
C.DeltaKind != Candidate::InvalidDelta &&
C.Basis);
904auto StraightLineStrengthReduce::compressPath(Candidate &
C,
905 Candidate *Basis)
const
907 if (!Basis || !Basis->Basis ||
C.CandidateKind == Candidate::Mul)
909 Candidate *Root = Basis;
910 Value *NewDelta =
nullptr;
911 auto NewKind = Candidate::InvalidDelta;
913 while (Root->Basis) {
914 Candidate *NextRoot = Root->Basis;
915 if (
C.Base == NextRoot->Base &&
C.StrideSCEV == NextRoot->StrideSCEV &&
916 isSimilar(
C, *NextRoot, Candidate::IndexDelta)) {
921 NewKind = Candidate::IndexDelta;
927 const SCEV *CandPart =
nullptr;
928 const SCEV *BasisPart =
nullptr;
929 auto CurrKind = Candidate::InvalidDelta;
930 if (
C.Base == NextRoot->Base &&
C.Index == NextRoot->Index) {
931 CandPart =
C.StrideSCEV;
932 BasisPart = NextRoot->StrideSCEV;
933 CurrKind = Candidate::StrideDelta;
934 }
else if (
C.StrideSCEV == NextRoot->StrideSCEV &&
935 C.Index == NextRoot->Index) {
937 BasisPart = NextRoot->Base;
938 CurrKind = Candidate::BaseDelta;
942 assert(CandPart && BasisPart);
943 if (!isSimilar(
C, *NextRoot, CurrKind))
951 if (CurrKind == Candidate::StrideDelta &&
952 C.CandidateKind == Candidate::GEP &&
957 ++NumSCEVCandidateBasisDifferences;
961 NewDelta = DeltaVal->getValue();
968 assert(NewKind != Candidate::InvalidDelta && NewDelta);
970 <<
" from path compression.\n");
971 return {Root, NewKind, NewDelta};
979void StraightLineStrengthReduce::sortCandidateInstructions() {
980 SortedCandidateInsts.clear();
986 DenseMap<Instruction *, int> InDegree;
987 for (
auto &KV : DependencyGraph) {
990 for (
auto *Child : KV.second) {
994 std::queue<Instruction *> WorkList;
995 DenseSet<Instruction *> Visited;
997 for (
auto &KV : DependencyGraph)
998 if (InDegree[KV.first] == 0)
999 WorkList.push(KV.first);
1001 while (!WorkList.empty()) {
1004 if (!Visited.
insert(
I).second)
1007 SortedCandidateInsts.push_back(
I);
1009 for (
auto *
Next : DependencyGraph[
I]) {
1010 auto &Degree = InDegree[
Next];
1012 WorkList.push(
Next);
1016 assert(SortedCandidateInsts.size() == DependencyGraph.size() &&
1017 "Dependency graph should not have cycles");
1020auto StraightLineStrengthReduce::pickRewriteCandidate(Instruction *
I)
const
1023 auto It = RewriteCandidates.
find(
I);
1024 if (It == RewriteCandidates.
end())
1027 Candidate *BestC =
nullptr;
1028 auto BestEfficiency = Candidate::Unknown;
1029 for (Candidate *
C :
reverse(It->second))
1031 auto Efficiency =
C->getRewriteEfficiency();
1032 if (Efficiency > BestEfficiency) {
1033 BestEfficiency = Efficiency;
1044 return TTI->getGEPCost(
1045 GEP->getSourceElementType(),
GEP->getPointerOperand(), Indices,
1054 return Index->getBitWidth() <= 64 &&
1055 TTI->isLegalAddressingMode(
Base->getType(),
nullptr, 0,
true,
1059bool StraightLineStrengthReduce::isFoldable(
const Candidate &
C,
1060 TargetTransformInfo *
TTI) {
1061 if (
C.CandidateKind == Candidate::Add)
1063 if (
C.CandidateKind == Candidate::GEP)
1068void StraightLineStrengthReduce::allocateCandidatesAndFindBasis(
1069 Candidate::Kind CT,
const SCEV *
B, ConstantInt *Idx,
Value *S,
1071 bool IsSafe = CT != Candidate::GEP ||
1076 Candidate
C(CT,
B, Idx, S,
I, getAndRecordSCEV(S));
1087 if (IsSafe && !isFoldable(
C,
TTI) && !
C.isHighEfficiency()) {
1088 setBasisAndDeltaFor(
C);
1091 if (
auto Res = compressPath(
C,
C.Basis)) {
1093 C.DeltaKind = Res.DeltaKind;
1094 C.Delta = Res.Delta;
1100 Candidates.push_back(
C);
1101 RewriteCandidates[
C.Ins].push_back(&Candidates.back());
1108 CandidateDict.add(Candidates.back());
1112void StraightLineStrengthReduce::allocateCandidatesAndFindBasis(
1114 switch (
I->getOpcode()) {
1115 case Instruction::Add:
1116 allocateCandidatesAndFindBasisForAdd(
I);
1118 case Instruction::Mul:
1119 allocateCandidatesAndFindBasisForMul(
I);
1121 case Instruction::GetElementPtr:
1127void StraightLineStrengthReduce::allocateCandidatesAndFindBasisForAdd(
1133 assert(
I->getNumOperands() == 2 &&
"isn't I an add?");
1135 allocateCandidatesAndFindBasisForAdd(
LHS,
RHS,
I);
1137 allocateCandidatesAndFindBasisForAdd(
RHS,
LHS,
I);
1140void StraightLineStrengthReduce::allocateCandidatesAndFindBasisForAdd(
1143 ConstantInt *Idx =
nullptr;
1146 allocateCandidatesAndFindBasis(Candidate::Add, SE->
getSCEV(
LHS), Idx, S,
I);
1151 allocateCandidatesAndFindBasis(Candidate::Add, SE->
getSCEV(
LHS), Idx, S,
I);
1155 allocateCandidatesAndFindBasis(Candidate::Add, SE->
getSCEV(
LHS), One,
RHS,
1170void StraightLineStrengthReduce::allocateCandidatesAndFindBasisForMul(
1173 ConstantInt *Idx =
nullptr;
1177 allocateCandidatesAndFindBasis(Candidate::Mul, SE->
getSCEV(
B), Idx,
RHS,
I);
1183 allocateCandidatesAndFindBasis(Candidate::Mul, SE->
getSCEV(
B), Idx,
RHS,
I);
1187 allocateCandidatesAndFindBasis(Candidate::Mul, SE->
getSCEV(
LHS), Zero,
RHS,
1192void StraightLineStrengthReduce::allocateCandidatesAndFindBasisForMul(
1199 assert(
I->getNumOperands() == 2 &&
"isn't I a mul?");
1201 allocateCandidatesAndFindBasisForMul(
LHS,
RHS,
I);
1204 allocateCandidatesAndFindBasisForMul(
RHS,
LHS,
I);
1208void StraightLineStrengthReduce::allocateCandidatesAndFindBasisForGEP(
1209 GetElementPtrInst *
GEP) {
1211 if (
GEP->getType()->isVectorTy())
1215 for (Use &Idx :
GEP->indices())
1219 for (
unsigned I = 1,
E =
GEP->getNumOperands();
I !=
E; ++
I, ++GTI) {
1223 SCEVUse OrigIndexExpr = IndexExprs[
I - 1];
1233 ConstantInt *ElementSizeIdx =
1236 DL->getIndexSizeInBits(
GEP->getAddressSpace())) {
1239 allocateCandidatesAndFindBasis(Candidate::GEP, BaseExpr, ElementSizeIdx,
1245 Value *TruncatedArrayIdx =
nullptr;
1248 DL->getIndexSizeInBits(
GEP->getAddressSpace())) {
1251 allocateCandidatesAndFindBasis(Candidate::GEP, BaseExpr, ElementSizeIdx,
1252 TruncatedArrayIdx,
GEP);
1255 IndexExprs[
I - 1] = OrigIndexExpr;
1259Value *StraightLineStrengthReduce::emitBump(
const Candidate &Basis,
1262 const DataLayout *
DL) {
1265 const APInt &ConstRHS = CR->getValue();
1266 IntegerType *DeltaType =
1270 ConstantInt::get(DeltaType, ConstRHS.
logBase2());
1275 ConstantInt::get(DeltaType, (-ConstRHS).logBase2());
1290 if (
C.DeltaKind == Candidate::IndexDelta) {
1301 if (IndexDelta == 1)
1307 IntegerType *DeltaType =
1314 assert(
C.DeltaKind == Candidate::StrideDelta ||
1315 C.DeltaKind == Candidate::BaseDelta);
1316 assert(
C.CandidateKind != Candidate::Mul);
1332 if (
C.DeltaKind == Candidate::StrideDelta) {
1335 if (
C.CandidateKind == Candidate::GEP) {
1337 Type *NewScalarIndexTy =
1338 DL->getIndexType(
GEP->getPointerOperandType()->getScalarType());
1341 if (!
C.Index->isOne()) {
1342 Value *ExtendedIndex =
1350void StraightLineStrengthReduce::rewriteCandidate(
const Candidate &
C) {
1354 const Candidate &Basis = *
C.Basis;
1355 assert(
C.Delta &&
C.CandidateKind == Basis.CandidateKind &&
1356 C.hasValidDelta(Basis));
1359 Value *Bump = emitBump(Basis,
C, Builder,
DL);
1360 Value *Reduced =
nullptr;
1364 Reduced = Basis.Ins;
1366 switch (
C.CandidateKind) {
1367 case Candidate::Add:
1368 case Candidate::Mul: {
1373 Reduced = Builder.
CreateSub(Basis.Ins, NegBump);
1387 Reduced = Builder.
CreateAdd(Basis.Ins, Bump);
1391 case Candidate::GEP: {
1394 Reduced = Builder.
CreatePtrAdd(Basis.Ins, Bump,
"", InBounds);
1402 C.Ins->replaceAllUsesWith(Reduced);
1403 DeadInstructions.push_back(
C.Ins);
1406bool StraightLineStrengthReduceLegacyPass::runOnFunction(
Function &
F) {
1407 if (skipFunction(
F))
1410 auto *
TTI = &getAnalysis<TargetTransformInfoWrapperPass>().getTTI(
F);
1411 auto *DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
1412 auto *SE = &getAnalysis<ScalarEvolutionWrapperPass>().getSE();
1413 return StraightLineStrengthReduce(
DL, DT, SE,
TTI).runOnFunction(
F);
1416bool StraightLineStrengthReduce::runOnFunction(
Function &
F) {
1421 for (
auto &
I : *(
Node->getBlock()))
1422 allocateCandidatesAndFindBasis(&
I);
1426 for (
auto &
C : Candidates) {
1427 DependencyGraph.try_emplace(
C.Ins);
1428 addDependency(
C,
C.Basis);
1430 sortCandidateInstructions();
1434 for (Instruction *
I :
reverse(SortedCandidateInsts))
1435 if (Candidate *
C = pickRewriteCandidate(
I))
1436 rewriteCandidate(*
C);
1438 for (
auto *DeadIns : DeadInstructions)
1441 if (DeadIns->getParent())
1444 bool Ret = !DeadInstructions.empty();
1445 DeadInstructions.clear();
1446 DependencyGraph.clear();
1447 RewriteCandidates.
clear();
1448 SortedCandidateInsts.clear();
1450 CandidateDict.clear();
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 cl::opt< bool > EnablePoisonReuseGuard("enable-poison-reuse-guard", cl::init(true), cl::desc("Enable poison-reuse guard"))
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.
unsigned getBitWidth() const
getBitWidth - Return the scalar bitwidth of this constant.
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.
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 * getSCEV(Value *V)
Return a SCEV expression for the full generality of the specified expression.
LLVM_ABI const SCEV * getMinusSCEV(SCEVUse LHS, SCEVUse RHS, SCEV::NoWrapFlags Flags=SCEV::FlagAnyWrap, unsigned Depth=0)
Return LHS-RHS.
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.
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.
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.
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.
initializer< Ty > init(const Ty &Val)
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.
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.
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...
IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >
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