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 DataLayout *DL, DominatorTree *DT,
156 ScalarEvolution *SE, TargetTransformInfo *TTI)
157 : DL(DL), DT(DT), SE(SE), TTI(TTI) {}
176 Candidate() =
default;
177 Candidate(Kind CT,
const SCEV *
B, ConstantInt *Idx,
Value *S,
178 Instruction *
I,
const SCEV *StrideSCEV)
179 : CandidateKind(CT), Base(
B), Index(
Idx), Stride(S), Ins(
I),
180 StrideSCEV(StrideSCEV) {}
182 Kind CandidateKind = Invalid;
184 const SCEV *Base =
nullptr;
189 ConstantInt *Index =
nullptr;
191 Value *Stride =
nullptr;
211 Candidate *Basis =
nullptr;
213 DKind DeltaKind = InvalidDelta;
216 const SCEV *StrideSCEV =
nullptr;
219 Value *Delta =
nullptr;
223 SmallVector<Instruction *> DropList;
233 enum EfficiencyLevel :
unsigned {
242 static EfficiencyLevel
243 getComputationEfficiency(Kind CandidateKind,
const ConstantInt *Index,
244 const Value *Stride,
const SCEV *Base =
nullptr) {
245 bool IsConstantBase =
false;
246 bool IsZeroBase =
false;
250 IsConstantBase =
true;
251 IsZeroBase = ConstBase->getValue()->isZero();
258 if (IsConstantBase && IsConstantStride)
262 if (CandidateKind == Mul) {
266 return (IsConstantStride || IsConstantBase) ? OneInstOneVar
270 return IsZeroBase && (Index->isOne() || Index->isMinusOne())
274 if (IsConstantStride) {
276 return (CI->isOne() || CI->isMinusOne()) ? OneInstOneVar
279 return TwoInstTwoVar;
283 assert(CandidateKind == Add || CandidateKind == GEP);
284 if (Index->isZero() || IsZeroStride)
287 bool IsSimpleIndex = Index->isOne() || Index->isMinusOne();
290 return IsZeroBase ? (IsSimpleIndex ? ZeroInst : OneInstOneVar)
291 : (IsSimpleIndex ? OneInstOneVar : TwoInstOneVar);
293 if (IsConstantStride)
294 return IsZeroStride ? ZeroInst : OneInstOneVar;
297 return OneInstTwoVar;
299 return TwoInstTwoVar;
303 bool isProfitableRewrite(
const Value &Delta,
const DKind DeltaKind)
const {
315 return getComputationEfficiency(CandidateKind, Index, Stride, Base) <=
316 getRewriteEfficiency(Delta, DeltaKind);
320 EfficiencyLevel getRewriteEfficiency()
const {
321 return Basis ? getRewriteEfficiency(*Delta, DeltaKind) : Unknown;
325 EfficiencyLevel getRewriteEfficiency(
const Value &Delta,
326 const DKind DeltaKind)
const {
329 return getComputationEfficiency(
333 return getComputationEfficiency(CandidateKind, Index, &Delta);
335 return getComputationEfficiency(CandidateKind,
342 bool isHighEfficiency()
const {
343 return getComputationEfficiency(CandidateKind, Index, Stride, Base) >=
349 bool hasValidDelta(
const Candidate &Basis)
const {
353 return Base == Basis.Base && StrideSCEV == Basis.StrideSCEV;
356 return Base == Basis.Base && Index == Basis.Index;
359 return StrideSCEV == Basis.StrideSCEV && Index == Basis.Index;
371 void setBasisAndDeltaFor(Candidate &
C);
373 bool isFoldable(
const Candidate &
C, TargetTransformInfo *TTI);
377 void allocateCandidatesAndFindBasis(Instruction *
I);
380 void allocateCandidatesAndFindBasisForAdd(Instruction *
I);
387 void allocateCandidatesAndFindBasisForMul(Instruction *
I);
395 void allocateCandidatesAndFindBasisForGEP(GetElementPtrInst *
GEP);
399 void allocateCandidatesAndFindBasis(Candidate::Kind CT,
const SCEV *
B,
400 ConstantInt *Idx,
Value *S,
404 void rewriteCandidate(
const Candidate &
C);
407 static Value *emitBump(
const Candidate &Basis,
const Candidate &
C,
410 const DataLayout *DL =
nullptr;
411 DominatorTree *DT =
nullptr;
413 TargetTransformInfo *TTI =
nullptr;
414 std::list<Candidate> Candidates;
418 DenseMap<const SCEV *, SmallSetVector<Instruction *, 2>> SCEVToInsts;
420 using SCEVUnknownSet = SmallPtrSet<const SCEVUnknown *, 4>;
421 DenseMap<const SCEV *, SCEVUnknownSet> SCEVUnknownsCache;
425 MapVector<Instruction *, std::vector<Instruction *>> DependencyGraph;
428 DenseMap<Instruction *, SmallVector<Candidate *, 3>> RewriteCandidates;
432 std::vector<Instruction *> SortedCandidateInsts;
436 std::vector<Instruction *> DeadInstructions;
439 class CandidateDictTy {
441 using CandsTy = SmallVector<Candidate *, 8>;
442 using BBToCandsTy = DenseMap<const BasicBlock *, CandsTy>;
446 using IndexDeltaKeyTy = std::tuple<const SCEV *, const SCEV *, Type *>;
447 DenseMap<IndexDeltaKeyTy, BBToCandsTy> IndexDeltaCandidates;
450 using BaseDeltaKeyTy = std::tuple<const SCEV *, ConstantInt *, Type *>;
451 DenseMap<BaseDeltaKeyTy, BBToCandsTy> BaseDeltaCandidates;
454 using StrideDeltaKeyTy = std::tuple<const SCEV *, ConstantInt *, Type *>;
455 DenseMap<StrideDeltaKeyTy, BBToCandsTy> StrideDeltaCandidates;
460 const BBToCandsTy *getCandidatesWithDeltaKind(
const Candidate &
C,
461 Candidate::DKind K)
const {
462 assert(K != Candidate::InvalidDelta);
463 if (K == Candidate::IndexDelta) {
464 IndexDeltaKeyTy IndexDeltaKey(
C.Base,
C.StrideSCEV,
C.Ins->getType());
465 auto It = IndexDeltaCandidates.find(IndexDeltaKey);
466 if (It != IndexDeltaCandidates.end())
468 }
else if (K == Candidate::BaseDelta) {
469 BaseDeltaKeyTy BaseDeltaKey(
C.StrideSCEV,
C.Index,
C.Ins->getType());
470 auto It = BaseDeltaCandidates.find(BaseDeltaKey);
471 if (It != BaseDeltaCandidates.end())
474 assert(K == Candidate::StrideDelta);
475 StrideDeltaKeyTy StrideDeltaKey(
C.Base,
C.Index,
C.Ins->getType());
476 auto It = StrideDeltaCandidates.find(StrideDeltaKey);
477 if (It != StrideDeltaCandidates.end())
484 void add(Candidate &
C) {
487 IndexDeltaKeyTy IndexDeltaKey(
C.Base,
C.StrideSCEV,
ValueType);
488 BaseDeltaKeyTy BaseDeltaKey(
C.StrideSCEV,
C.Index,
ValueType);
489 StrideDeltaKeyTy StrideDeltaKey(
C.Base,
C.Index,
ValueType);
490 IndexDeltaCandidates[IndexDeltaKey][BB].push_back(&
C);
491 BaseDeltaCandidates[BaseDeltaKey][BB].push_back(&
C);
492 StrideDeltaCandidates[StrideDeltaKey][BB].push_back(&
C);
496 IndexDeltaCandidates.clear();
497 BaseDeltaCandidates.clear();
498 StrideDeltaCandidates.clear();
502 const SCEV *getAndRecordSCEV(
Value *V) {
503 auto *S = SE->getSCEV(V);
511 bool candidatePredicate(Candidate *Basis, Candidate &
C, Candidate::DKind K);
513 bool hasSameSCEVUnknowns(
const SCEV *
A,
const SCEV *
B);
515 bool searchFrom(
const CandidateDictTy::BBToCandsTy &BBToCands, Candidate &
C,
521 Value *getNearestValueOfSCEV(
const SCEV *S,
const Instruction *CI)
const {
526 return SU->getValue();
528 return SC->getValue();
530 auto It = SCEVToInsts.find(S);
531 if (It == SCEVToInsts.end())
536 for (Instruction *
I :
reverse(It->second))
537 if (DT->dominates(
I, CI))
545 Candidate::DKind DeltaKind;
549 : Cand(nullptr), DeltaKind(Candidate::InvalidDelta), Delta(nullptr) {}
550 DeltaInfo(Candidate *Cand, Candidate::DKind DeltaKind,
Value *Delta)
551 : Cand(Cand), DeltaKind(DeltaKind), Delta(Delta) {}
552 operator bool()
const {
return Cand !=
nullptr; }
555 friend raw_ostream &
operator<<(raw_ostream &OS,
const DeltaInfo &DI);
557 DeltaInfo compressPath(Candidate &
C, Candidate *Basis)
const;
559 Candidate *pickRewriteCandidate(Instruction *
I)
const;
560 void sortCandidateInstructions();
561 Value *getDelta(
const Candidate &
C,
const Candidate &Basis,
562 Candidate::DKind K)
const;
563 static bool isSimilar(Candidate &
C, Candidate &Basis, Candidate::DKind K);
567 void addDependency(Candidate &
C, Candidate *Basis) {
569 DependencyGraph[Basis->Ins].emplace_back(
C.Ins);
574 auto PropagateDependency = [&](
Instruction *Inst) {
575 if (
auto CandsIt = RewriteCandidates.find(Inst);
576 CandsIt != RewriteCandidates.end() &&
578 [](Candidate *Cand) { return Cand->Basis; }))
579 DependencyGraph[Inst].emplace_back(
C.Ins);
585 PropagateDependency(DeltaInst);
589 PropagateDependency(StrideInst);
594 const StraightLineStrengthReduce::Candidate &
C) {
595 OS <<
"Ins: " << *
C.Ins <<
"\n Base: " << *
C.Base
596 <<
"\n Index: " << *
C.Index <<
"\n Stride: " << *
C.Stride
597 <<
"\n StrideSCEV: " << *
C.StrideSCEV;
599 OS <<
"\n Delta: " << *
C.Delta <<
"\n Basis: \n [ " << *
C.Basis <<
" ]";
605 OS <<
"Cand: " << *DI.Cand <<
"\n";
606 OS <<
"Delta Kind: ";
607 switch (DI.DeltaKind) {
608 case StraightLineStrengthReduce::Candidate::IndexDelta:
611 case StraightLineStrengthReduce::Candidate::BaseDelta:
614 case StraightLineStrengthReduce::Candidate::StrideDelta:
620 OS <<
"\nDelta: " << *DI.Delta;
626char StraightLineStrengthReduceLegacyPass::ID = 0;
629 "Straight line strength reduction",
false,
false)
637 return new StraightLineStrengthReduceLegacyPass();
642 if (
A.getBitWidth() <
B.getBitWidth())
643 A =
A.sext(
B.getBitWidth());
644 else if (
A.getBitWidth() >
B.getBitWidth())
645 B =
B.sext(
A.getBitWidth());
657 return !OBO || !OBO->hasNoSignedWrap();
667 return Idx->getType()->getIntegerBitWidth() <
668 DL->getIndexSizeInBits(
GEP->getAddressSpace());
685Value *StraightLineStrengthReduce::getDelta(
const Candidate &
C,
686 const Candidate &Basis,
687 Candidate::DKind
K)
const {
688 if (K == Candidate::IndexDelta) {
689 APInt
Idx =
C.Index->getValue();
690 APInt BasisIdx = Basis.Index->getValue();
692 APInt IndexDelta =
Idx - BasisIdx;
693 IntegerType *DeltaType =
695 return ConstantInt::get(DeltaType, IndexDelta);
696 }
else if (K == Candidate::BaseDelta || K == Candidate::StrideDelta) {
697 const SCEV *BasisPart =
698 (
K == Candidate::BaseDelta) ? Basis.Base : Basis.StrideSCEV;
699 const SCEV *CandPart = (
K == Candidate::BaseDelta) ?
C.Base :
C.StrideSCEV;
700 ++NumSCEVCandidateBasisDifferences;
701 const SCEV *Diff = SE->
getMinusSCEV(CandPart, BasisPart);
702 return getNearestValueOfSCEV(Diff,
C.Ins);
707bool StraightLineStrengthReduce::isSimilar(Candidate &
C, Candidate &Basis,
708 Candidate::DKind K) {
709 bool SameType =
false;
711 case Candidate::StrideDelta:
712 SameType =
C.StrideSCEV->getType() == Basis.StrideSCEV->getType();
714 case Candidate::BaseDelta:
715 SameType =
C.Base->getType() == Basis.Base->getType();
717 case Candidate::IndexDelta:
722 return SameType && Basis.Ins !=
C.Ins &&
723 Basis.CandidateKind ==
C.CandidateKind;
726bool StraightLineStrengthReduce::hasSameSCEVUnknowns(
const SCEV *
A,
728 auto CacheUnknowns = [&](
const SCEV *Root) {
734 SCEVUnknownSet &Unknowns;
736 bool follow(
const SCEV *S) {
741 bool isDone()
const {
return false; }
748 return SCEVUnknownsCache.
find(
A)->second == SCEVUnknownsCache.
find(
B)->second;
755bool StraightLineStrengthReduce::candidatePredicate(Candidate *Basis,
757 Candidate::DKind K) {
758 if (!isSimilar(
C, *Basis, K))
764 if (
C.Delta && K != Candidate::IndexDelta) {
765 const SCEV *CandidateSCEV =
766 K == Candidate::BaseDelta ?
C.Base :
C.StrideSCEV;
767 const SCEV *BasisSCEV =
768 K == Candidate::BaseDelta ? Basis->Base : Basis->StrideSCEV;
769 if (!hasSameSCEVUnknowns(CandidateSCEV, BasisSCEV))
774 Value *Delta = getDelta(
C, *Basis, K);
790 if (K == Candidate::StrideDelta &&
C.CandidateKind == Candidate::GEP &&
803 if (K == Candidate::IndexDelta &&
804 !
C.isProfitableRewrite(*Delta, Candidate::IndexDelta))
820bool StraightLineStrengthReduce::searchFrom(
821 const CandidateDictTy::BBToCandsTy &BBToCands, Candidate &
C,
822 Candidate::DKind K) {
826 if (
C.CandidateKind == Candidate::Mul && K != Candidate::IndexDelta)
834 auto It = BBToCands.find(BB);
835 if (It != BBToCands.end())
836 for (Candidate *Basis :
reverse(It->second))
837 if (candidatePredicate(Basis,
C, K))
844 BB =
Node ?
Node->getBlock() :
nullptr;
849void StraightLineStrengthReduce::setBasisAndDeltaFor(Candidate &
C) {
850 if (
const auto *BaseDeltaCandidates =
851 CandidateDict.getCandidatesWithDeltaKind(
C, Candidate::BaseDelta))
852 if (searchFrom(*BaseDeltaCandidates,
C, Candidate::BaseDelta)) {
857 if (
const auto *StrideDeltaCandidates =
858 CandidateDict.getCandidatesWithDeltaKind(
C, Candidate::StrideDelta))
859 if (searchFrom(*StrideDeltaCandidates,
C, Candidate::StrideDelta)) {
864 if (
const auto *IndexDeltaCandidates =
865 CandidateDict.getCandidatesWithDeltaKind(
C, Candidate::IndexDelta))
866 if (searchFrom(*IndexDeltaCandidates,
C, Candidate::IndexDelta)) {
874 dbgs() <<
"Found delta from ";
875 if (
C.DeltaKind == Candidate::BaseDelta)
878 dbgs() <<
"Stride: ";
879 dbgs() << *
C.Delta <<
"\n";
881 assert(
C.DeltaKind != Candidate::InvalidDelta &&
C.Basis);
895auto StraightLineStrengthReduce::compressPath(Candidate &
C,
896 Candidate *Basis)
const
898 if (!Basis || !Basis->Basis ||
C.CandidateKind == Candidate::Mul)
900 Candidate *Root = Basis;
901 Value *NewDelta =
nullptr;
902 auto NewKind = Candidate::InvalidDelta;
904 while (Root->Basis) {
905 Candidate *NextRoot = Root->Basis;
906 if (
C.Base == NextRoot->Base &&
C.StrideSCEV == NextRoot->StrideSCEV &&
907 isSimilar(
C, *NextRoot, Candidate::IndexDelta)) {
912 NewKind = Candidate::IndexDelta;
918 const SCEV *CandPart =
nullptr;
919 const SCEV *BasisPart =
nullptr;
920 auto CurrKind = Candidate::InvalidDelta;
921 if (
C.Base == NextRoot->Base &&
C.Index == NextRoot->Index) {
922 CandPart =
C.StrideSCEV;
923 BasisPart = NextRoot->StrideSCEV;
924 CurrKind = Candidate::StrideDelta;
925 }
else if (
C.StrideSCEV == NextRoot->StrideSCEV &&
926 C.Index == NextRoot->Index) {
928 BasisPart = NextRoot->Base;
929 CurrKind = Candidate::BaseDelta;
933 assert(CandPart && BasisPart);
934 if (!isSimilar(
C, *NextRoot, CurrKind))
942 if (CurrKind == Candidate::StrideDelta &&
943 C.CandidateKind == Candidate::GEP &&
948 ++NumSCEVCandidateBasisDifferences;
952 NewDelta = DeltaVal->getValue();
959 assert(NewKind != Candidate::InvalidDelta && NewDelta);
961 <<
" from path compression.\n");
962 return {Root, NewKind, NewDelta};
970void StraightLineStrengthReduce::sortCandidateInstructions() {
971 SortedCandidateInsts.clear();
977 DenseMap<Instruction *, int> InDegree;
978 for (
auto &KV : DependencyGraph) {
981 for (
auto *Child : KV.second) {
985 std::queue<Instruction *> WorkList;
986 DenseSet<Instruction *> Visited;
988 for (
auto &KV : DependencyGraph)
989 if (InDegree[KV.first] == 0)
990 WorkList.push(KV.first);
992 while (!WorkList.empty()) {
998 SortedCandidateInsts.push_back(
I);
1000 for (
auto *
Next : DependencyGraph[
I]) {
1001 auto &Degree = InDegree[
Next];
1003 WorkList.push(
Next);
1007 assert(SortedCandidateInsts.size() == DependencyGraph.size() &&
1008 "Dependency graph should not have cycles");
1011auto StraightLineStrengthReduce::pickRewriteCandidate(Instruction *
I)
const
1014 auto It = RewriteCandidates.
find(
I);
1015 if (It == RewriteCandidates.
end())
1018 Candidate *BestC =
nullptr;
1019 auto BestEfficiency = Candidate::Unknown;
1020 for (Candidate *
C :
reverse(It->second))
1022 auto Efficiency =
C->getRewriteEfficiency();
1023 if (Efficiency > BestEfficiency) {
1024 BestEfficiency = Efficiency;
1035 return TTI->getGEPCost(
1036 GEP->getSourceElementType(),
GEP->getPointerOperand(), Indices,
1045 return Index->getBitWidth() <= 64 &&
1046 TTI->isLegalAddressingMode(
Base->getType(),
nullptr, 0,
true,
1050bool StraightLineStrengthReduce::isFoldable(
const Candidate &
C,
1051 TargetTransformInfo *
TTI) {
1052 if (
C.CandidateKind == Candidate::Add)
1054 if (
C.CandidateKind == Candidate::GEP)
1059void StraightLineStrengthReduce::allocateCandidatesAndFindBasis(
1060 Candidate::Kind CT,
const SCEV *
B, ConstantInt *Idx,
Value *S,
1062 bool IsSafe = CT != Candidate::GEP ||
1067 Candidate
C(CT,
B, Idx, S,
I, getAndRecordSCEV(S));
1078 if (IsSafe && !isFoldable(
C,
TTI) && !
C.isHighEfficiency()) {
1079 setBasisAndDeltaFor(
C);
1082 if (
auto Res = compressPath(
C,
C.Basis)) {
1084 C.DeltaKind = Res.DeltaKind;
1085 C.Delta = Res.Delta;
1091 Candidates.push_back(
C);
1092 RewriteCandidates[
C.Ins].push_back(&Candidates.back());
1097 if (!ScalarOptions::Global.enable_poison_reuse_guard ||
1099 CandidateDict.add(Candidates.back());
1103void StraightLineStrengthReduce::allocateCandidatesAndFindBasis(
1105 switch (
I->getOpcode()) {
1106 case Instruction::Add:
1107 allocateCandidatesAndFindBasisForAdd(
I);
1109 case Instruction::Mul:
1110 allocateCandidatesAndFindBasisForMul(
I);
1112 case Instruction::GetElementPtr:
1118void StraightLineStrengthReduce::allocateCandidatesAndFindBasisForAdd(
1124 assert(
I->getNumOperands() == 2 &&
"isn't I an add?");
1126 allocateCandidatesAndFindBasisForAdd(
LHS,
RHS,
I);
1128 allocateCandidatesAndFindBasisForAdd(
RHS,
LHS,
I);
1131void StraightLineStrengthReduce::allocateCandidatesAndFindBasisForAdd(
1134 ConstantInt *
Idx =
nullptr;
1137 allocateCandidatesAndFindBasis(Candidate::Add, SE->
getSCEV(
LHS), Idx, S,
I);
1140 APInt One(
Idx->getBitWidth(), 1);
1141 Idx = ConstantInt::get(
Idx->getContext(), One <<
Idx->getValue());
1142 allocateCandidatesAndFindBasis(Candidate::Add, SE->
getSCEV(
LHS), Idx, S,
I);
1146 allocateCandidatesAndFindBasis(Candidate::Add, SE->
getSCEV(
LHS), One,
RHS,
1161void StraightLineStrengthReduce::allocateCandidatesAndFindBasisForMul(
1164 ConstantInt *
Idx =
nullptr;
1168 allocateCandidatesAndFindBasis(Candidate::Mul, SE->
getSCEV(
B), Idx,
RHS,
I);
1174 allocateCandidatesAndFindBasis(Candidate::Mul, SE->
getSCEV(
B), Idx,
RHS,
I);
1178 allocateCandidatesAndFindBasis(Candidate::Mul, SE->
getSCEV(
LHS), Zero,
RHS,
1183void StraightLineStrengthReduce::allocateCandidatesAndFindBasisForMul(
1190 assert(
I->getNumOperands() == 2 &&
"isn't I a mul?");
1192 allocateCandidatesAndFindBasisForMul(
LHS,
RHS,
I);
1195 allocateCandidatesAndFindBasisForMul(
RHS,
LHS,
I);
1199void StraightLineStrengthReduce::allocateCandidatesAndFindBasisForGEP(
1200 GetElementPtrInst *
GEP) {
1202 if (
GEP->getType()->isVectorTy())
1206 for (Use &Idx :
GEP->indices())
1210 for (
unsigned I = 1,
E =
GEP->getNumOperands();
I !=
E; ++
I, ++GTI) {
1214 SCEVUse OrigIndexExpr = IndexExprs[
I - 1];
1224 ConstantInt *ElementSizeIdx =
1227 DL->getIndexSizeInBits(
GEP->getAddressSpace())) {
1230 allocateCandidatesAndFindBasis(Candidate::GEP, BaseExpr, ElementSizeIdx,
1236 Value *TruncatedArrayIdx =
nullptr;
1239 DL->getIndexSizeInBits(
GEP->getAddressSpace())) {
1242 allocateCandidatesAndFindBasis(Candidate::GEP, BaseExpr, ElementSizeIdx,
1243 TruncatedArrayIdx,
GEP);
1246 IndexExprs[
I - 1] = OrigIndexExpr;
1250Value *StraightLineStrengthReduce::emitBump(
const Candidate &Basis,
1253 const DataLayout *
DL) {
1256 const APInt &ConstRHS = CR->getValue();
1257 IntegerType *DeltaType =
1261 ConstantInt::get(DeltaType, ConstRHS.
logBase2());
1266 ConstantInt::get(DeltaType, (-ConstRHS).logBase2());
1281 if (
C.DeltaKind == Candidate::IndexDelta) {
1292 if (IndexDelta == 1)
1298 IntegerType *DeltaType =
1305 assert(
C.DeltaKind == Candidate::StrideDelta ||
1306 C.DeltaKind == Candidate::BaseDelta);
1307 assert(
C.CandidateKind != Candidate::Mul);
1323 if (
C.DeltaKind == Candidate::StrideDelta) {
1326 if (
C.CandidateKind == Candidate::GEP) {
1328 Type *NewScalarIndexTy =
1329 DL->getIndexType(
GEP->getPointerOperandType()->getScalarType());
1332 if (!
C.Index->isOne()) {
1333 Value *ExtendedIndex =
1341void StraightLineStrengthReduce::rewriteCandidate(
const Candidate &
C) {
1345 const Candidate &Basis = *
C.Basis;
1346 assert(
C.Delta &&
C.CandidateKind == Basis.CandidateKind &&
1347 C.hasValidDelta(Basis));
1349 for (Instruction *
I : Basis.DropList)
1350 I->dropPoisonGeneratingAnnotations();
1353 Value *Bump = emitBump(Basis,
C, Builder,
DL);
1354 Value *Reduced =
nullptr;
1358 Reduced = Basis.Ins;
1360 switch (
C.CandidateKind) {
1361 case Candidate::Add:
1362 case Candidate::Mul: {
1367 Reduced = Builder.
CreateSub(Basis.Ins, NegBump);
1381 Reduced = Builder.
CreateAdd(Basis.Ins, Bump);
1385 case Candidate::GEP: {
1388 Reduced = Builder.
CreatePtrAdd(Basis.Ins, Bump,
"", InBounds);
1396 C.Ins->replaceAllUsesWith(Reduced);
1397 DeadInstructions.push_back(
C.Ins);
1400bool StraightLineStrengthReduceLegacyPass::runOnFunction(
Function &
F) {
1401 if (skipFunction(
F))
1404 auto *
TTI = &getAnalysis<TargetTransformInfoWrapperPass>().getTTI(
F);
1405 auto *DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
1406 auto *SE = &getAnalysis<ScalarEvolutionWrapperPass>().getSE();
1407 return StraightLineStrengthReduce(
DL, DT, SE,
TTI).runOnFunction(
F);
1410bool StraightLineStrengthReduce::runOnFunction(
Function &
F) {
1415 for (
auto &
I : *(
Node->getBlock()))
1416 allocateCandidatesAndFindBasis(&
I);
1420 for (
auto &
C : Candidates) {
1421 DependencyGraph.try_emplace(
C.Ins);
1422 addDependency(
C,
C.Basis);
1424 sortCandidateInstructions();
1428 for (Instruction *
I :
reverse(SortedCandidateInsts))
1429 if (Candidate *
C = pickRewriteCandidate(
I))
1430 rewriteCandidate(*
C);
1432 for (
auto *DeadIns : DeadInstructions)
1435 if (DeadIns->getParent())
1438 bool Ret = !DeadInstructions.empty();
1439 DeadInstructions.clear();
1440 DependencyGraph.clear();
1441 RewriteCandidates.
clear();
1442 SortedCandidateInsts.clear();
1444 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 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.
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.
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.
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