111#define DEBUG_TYPE "slsr"
114 std::numeric_limits<unsigned>::max();
117 "Controls whether rewriteCandidate is executed.");
122 cl::desc(
"Enable poison-reuse guard"));
125 "Number of candidate-basis SCEV differences computed by SLSR");
129class StraightLineStrengthReduceLegacyPass :
public FunctionPass {
135 StraightLineStrengthReduceLegacyPass() :
FunctionPass(ID) {
140 void getAnalysisUsage(AnalysisUsage &AU)
const override {
148 bool doInitialization(
Module &M)
override {
149 DL = &
M.getDataLayout();
156class StraightLineStrengthReduce {
158 StraightLineStrengthReduce(
const DataLayout *DL, DominatorTree *DT,
159 ScalarEvolution *SE, TargetTransformInfo *TTI)
160 : DL(DL), DT(DT), SE(SE), TTI(TTI) {}
179 Candidate() =
default;
180 Candidate(Kind CT,
const SCEV *
B, ConstantInt *Idx,
Value *S,
181 Instruction *
I,
const SCEV *StrideSCEV)
182 : CandidateKind(CT), Base(
B), Index(Idx), Stride(S), Ins(
I),
183 StrideSCEV(StrideSCEV) {}
185 Kind CandidateKind = Invalid;
187 const SCEV *Base =
nullptr;
192 ConstantInt *Index =
nullptr;
194 Value *Stride =
nullptr;
214 Candidate *Basis =
nullptr;
216 DKind DeltaKind = InvalidDelta;
219 const SCEV *StrideSCEV =
nullptr;
222 Value *Delta =
nullptr;
226 SmallVector<Instruction *> DropList;
236 enum EfficiencyLevel :
unsigned {
245 static EfficiencyLevel
246 getComputationEfficiency(Kind CandidateKind,
const ConstantInt *Index,
247 const Value *Stride,
const SCEV *Base =
nullptr) {
248 bool IsConstantBase =
false;
249 bool IsZeroBase =
false;
253 IsConstantBase =
true;
254 IsZeroBase = ConstBase->getValue()->isZero();
261 if (IsConstantBase && IsConstantStride)
265 if (CandidateKind == Mul) {
269 return (IsConstantStride || IsConstantBase) ? OneInstOneVar
273 return IsZeroBase && (Index->isOne() || Index->isMinusOne())
277 if (IsConstantStride) {
279 return (CI->isOne() || CI->isMinusOne()) ? OneInstOneVar
282 return TwoInstTwoVar;
286 assert(CandidateKind == Add || CandidateKind == GEP);
287 if (Index->isZero() || IsZeroStride)
290 bool IsSimpleIndex = Index->isOne() || Index->isMinusOne();
293 return IsZeroBase ? (IsSimpleIndex ? ZeroInst : OneInstOneVar)
294 : (IsSimpleIndex ? OneInstOneVar : TwoInstOneVar);
296 if (IsConstantStride)
297 return IsZeroStride ? ZeroInst : OneInstOneVar;
300 return OneInstTwoVar;
302 return TwoInstTwoVar;
306 bool isProfitableRewrite(
const Value &Delta,
const DKind DeltaKind)
const {
318 return getComputationEfficiency(CandidateKind, Index, Stride, Base) <=
319 getRewriteEfficiency(Delta, DeltaKind);
323 EfficiencyLevel getRewriteEfficiency()
const {
324 return Basis ? getRewriteEfficiency(*Delta, DeltaKind) : Unknown;
328 EfficiencyLevel getRewriteEfficiency(
const Value &Delta,
329 const DKind DeltaKind)
const {
332 return getComputationEfficiency(
336 return getComputationEfficiency(CandidateKind, Index, &Delta);
338 return getComputationEfficiency(CandidateKind,
345 bool isHighEfficiency()
const {
346 return getComputationEfficiency(CandidateKind, Index, Stride, Base) >=
352 bool hasValidDelta(
const Candidate &Basis)
const {
356 return Base == Basis.Base && StrideSCEV == Basis.StrideSCEV;
359 return Base == Basis.Base && Index == Basis.Index;
362 return StrideSCEV == Basis.StrideSCEV && Index == Basis.Index;
374 void setBasisAndDeltaFor(Candidate &
C);
376 bool isFoldable(
const Candidate &
C, TargetTransformInfo *TTI);
380 void allocateCandidatesAndFindBasis(Instruction *
I);
383 void allocateCandidatesAndFindBasisForAdd(Instruction *
I);
390 void allocateCandidatesAndFindBasisForMul(Instruction *
I);
398 void allocateCandidatesAndFindBasisForGEP(GetElementPtrInst *
GEP);
402 void allocateCandidatesAndFindBasis(Candidate::Kind CT,
const SCEV *
B,
403 ConstantInt *Idx,
Value *S,
407 void rewriteCandidate(
const Candidate &
C);
410 static Value *emitBump(
const Candidate &Basis,
const Candidate &
C,
413 const DataLayout *DL =
nullptr;
414 DominatorTree *DT =
nullptr;
416 TargetTransformInfo *TTI =
nullptr;
417 std::list<Candidate> Candidates;
421 DenseMap<const SCEV *, SmallSetVector<Instruction *, 2>> SCEVToInsts;
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 searchFrom(
const CandidateDictTy::BBToCandsTy &BBToCands, Candidate &
C,
519 Value *getNearestValueOfSCEV(
const SCEV *S,
const Instruction *CI)
const {
524 return SU->getValue();
526 return SC->getValue();
528 auto It = SCEVToInsts.find(S);
529 if (It == SCEVToInsts.end())
534 for (Instruction *
I :
reverse(It->second))
535 if (DT->dominates(
I, CI))
543 Candidate::DKind DeltaKind;
547 : Cand(nullptr), DeltaKind(Candidate::InvalidDelta), Delta(nullptr) {}
548 DeltaInfo(Candidate *Cand, Candidate::DKind DeltaKind,
Value *Delta)
549 : Cand(Cand), DeltaKind(DeltaKind), Delta(Delta) {}
550 operator bool()
const {
return Cand !=
nullptr; }
553 friend raw_ostream &
operator<<(raw_ostream &OS,
const DeltaInfo &DI);
555 DeltaInfo compressPath(Candidate &
C, Candidate *Basis)
const;
557 Candidate *pickRewriteCandidate(Instruction *
I)
const;
558 void sortCandidateInstructions();
559 Value *getDelta(
const Candidate &
C,
const Candidate &Basis,
560 Candidate::DKind K)
const;
561 static bool isSimilar(Candidate &
C, Candidate &Basis, Candidate::DKind K);
565 void addDependency(Candidate &
C, Candidate *Basis) {
567 DependencyGraph[Basis->Ins].emplace_back(
C.Ins);
572 auto PropagateDependency = [&](
Instruction *Inst) {
573 if (
auto CandsIt = RewriteCandidates.find(Inst);
574 CandsIt != RewriteCandidates.end() &&
576 [](Candidate *Cand) { return Cand->Basis; }))
577 DependencyGraph[Inst].emplace_back(
C.Ins);
583 PropagateDependency(DeltaInst);
587 PropagateDependency(StrideInst);
592 const StraightLineStrengthReduce::Candidate &
C) {
593 OS <<
"Ins: " << *
C.Ins <<
"\n Base: " << *
C.Base
594 <<
"\n Index: " << *
C.Index <<
"\n Stride: " << *
C.Stride
595 <<
"\n StrideSCEV: " << *
C.StrideSCEV;
597 OS <<
"\n Delta: " << *
C.Delta <<
"\n Basis: \n [ " << *
C.Basis <<
" ]";
603 OS <<
"Cand: " << *DI.Cand <<
"\n";
604 OS <<
"Delta Kind: ";
605 switch (DI.DeltaKind) {
606 case StraightLineStrengthReduce::Candidate::IndexDelta:
609 case StraightLineStrengthReduce::Candidate::BaseDelta:
612 case StraightLineStrengthReduce::Candidate::StrideDelta:
618 OS <<
"\nDelta: " << *DI.Delta;
624char StraightLineStrengthReduceLegacyPass::ID = 0;
627 "Straight line strength reduction",
false,
false)
635 return new StraightLineStrengthReduceLegacyPass();
640 if (
A.getBitWidth() <
B.getBitWidth())
641 A =
A.sext(
B.getBitWidth());
642 else if (
A.getBitWidth() >
B.getBitWidth())
643 B =
B.sext(
A.getBitWidth());
655 return !OBO || !OBO->hasNoSignedWrap();
666 DL->getIndexSizeInBits(
GEP->getAddressSpace());
683Value *StraightLineStrengthReduce::getDelta(
const Candidate &
C,
684 const Candidate &Basis,
685 Candidate::DKind K)
const {
686 if (K == Candidate::IndexDelta) {
687 APInt Idx =
C.Index->getValue();
688 APInt BasisIdx = Basis.Index->getValue();
690 APInt IndexDelta = Idx - BasisIdx;
691 IntegerType *DeltaType =
693 return ConstantInt::get(DeltaType, IndexDelta);
694 }
else if (K == Candidate::BaseDelta || K == Candidate::StrideDelta) {
695 const SCEV *BasisPart =
696 (
K == Candidate::BaseDelta) ? Basis.Base : Basis.StrideSCEV;
697 const SCEV *CandPart = (
K == Candidate::BaseDelta) ?
C.Base :
C.StrideSCEV;
698 ++NumSCEVCandidateBasisDifferences;
699 const SCEV *Diff = SE->
getMinusSCEV(CandPart, BasisPart);
700 return getNearestValueOfSCEV(Diff,
C.Ins);
705bool StraightLineStrengthReduce::isSimilar(Candidate &
C, Candidate &Basis,
706 Candidate::DKind K) {
707 bool SameType =
false;
709 case Candidate::StrideDelta:
710 SameType =
C.StrideSCEV->getType() == Basis.StrideSCEV->getType();
712 case Candidate::BaseDelta:
713 SameType =
C.Base->getType() == Basis.Base->getType();
715 case Candidate::IndexDelta:
720 return SameType && Basis.Ins !=
C.Ins &&
721 Basis.CandidateKind ==
C.CandidateKind;
728bool StraightLineStrengthReduce::candidatePredicate(Candidate *Basis,
730 Candidate::DKind K) {
731 if (!isSimilar(
C, *Basis, K))
735 Value *Delta = getDelta(
C, *Basis, K);
751 if (K == Candidate::StrideDelta &&
C.CandidateKind == Candidate::GEP &&
764 if (K == Candidate::IndexDelta &&
765 !
C.isProfitableRewrite(*Delta, Candidate::IndexDelta))
770 for (Instruction *
I : Basis->DropList)
771 I->dropPoisonGeneratingAnnotations();
786bool StraightLineStrengthReduce::searchFrom(
787 const CandidateDictTy::BBToCandsTy &BBToCands, Candidate &
C,
788 Candidate::DKind K) {
792 if (
C.CandidateKind == Candidate::Mul && K != Candidate::IndexDelta)
800 auto It = BBToCands.find(BB);
801 if (It != BBToCands.end())
802 for (Candidate *Basis :
reverse(It->second))
803 if (candidatePredicate(Basis,
C, K))
810 BB =
Node ?
Node->getBlock() :
nullptr;
815void StraightLineStrengthReduce::setBasisAndDeltaFor(Candidate &
C) {
816 if (
const auto *BaseDeltaCandidates =
817 CandidateDict.getCandidatesWithDeltaKind(
C, Candidate::BaseDelta))
818 if (searchFrom(*BaseDeltaCandidates,
C, Candidate::BaseDelta)) {
823 if (
const auto *StrideDeltaCandidates =
824 CandidateDict.getCandidatesWithDeltaKind(
C, Candidate::StrideDelta))
825 if (searchFrom(*StrideDeltaCandidates,
C, Candidate::StrideDelta)) {
830 if (
const auto *IndexDeltaCandidates =
831 CandidateDict.getCandidatesWithDeltaKind(
C, Candidate::IndexDelta))
832 if (searchFrom(*IndexDeltaCandidates,
C, Candidate::IndexDelta)) {
840 dbgs() <<
"Found delta from ";
841 if (
C.DeltaKind == Candidate::BaseDelta)
844 dbgs() <<
"Stride: ";
845 dbgs() << *
C.Delta <<
"\n";
847 assert(
C.DeltaKind != Candidate::InvalidDelta &&
C.Basis);
861auto StraightLineStrengthReduce::compressPath(Candidate &
C,
862 Candidate *Basis)
const
864 if (!Basis || !Basis->Basis ||
C.CandidateKind == Candidate::Mul)
866 Candidate *Root = Basis;
867 Value *NewDelta =
nullptr;
868 auto NewKind = Candidate::InvalidDelta;
870 while (Root->Basis) {
871 Candidate *NextRoot = Root->Basis;
872 if (
C.Base == NextRoot->Base &&
C.StrideSCEV == NextRoot->StrideSCEV &&
873 isSimilar(
C, *NextRoot, Candidate::IndexDelta)) {
878 NewKind = Candidate::IndexDelta;
884 const SCEV *CandPart =
nullptr;
885 const SCEV *BasisPart =
nullptr;
886 auto CurrKind = Candidate::InvalidDelta;
887 if (
C.Base == NextRoot->Base &&
C.Index == NextRoot->Index) {
888 CandPart =
C.StrideSCEV;
889 BasisPart = NextRoot->StrideSCEV;
890 CurrKind = Candidate::StrideDelta;
891 }
else if (
C.StrideSCEV == NextRoot->StrideSCEV &&
892 C.Index == NextRoot->Index) {
894 BasisPart = NextRoot->Base;
895 CurrKind = Candidate::BaseDelta;
899 assert(CandPart && BasisPart);
900 if (!isSimilar(
C, *NextRoot, CurrKind))
908 if (CurrKind == Candidate::StrideDelta &&
909 C.CandidateKind == Candidate::GEP &&
914 ++NumSCEVCandidateBasisDifferences;
918 NewDelta = DeltaVal->getValue();
925 assert(NewKind != Candidate::InvalidDelta && NewDelta);
927 <<
" from path compression.\n");
928 return {Root, NewKind, NewDelta};
936void StraightLineStrengthReduce::sortCandidateInstructions() {
937 SortedCandidateInsts.clear();
943 DenseMap<Instruction *, int> InDegree;
944 for (
auto &KV : DependencyGraph) {
947 for (
auto *Child : KV.second) {
951 std::queue<Instruction *> WorkList;
952 DenseSet<Instruction *> Visited;
954 for (
auto &KV : DependencyGraph)
955 if (InDegree[KV.first] == 0)
956 WorkList.push(KV.first);
958 while (!WorkList.empty()) {
964 SortedCandidateInsts.push_back(
I);
966 for (
auto *
Next : DependencyGraph[
I]) {
967 auto &Degree = InDegree[
Next];
973 assert(SortedCandidateInsts.size() == DependencyGraph.size() &&
974 "Dependency graph should not have cycles");
977auto StraightLineStrengthReduce::pickRewriteCandidate(Instruction *
I)
const
980 auto It = RewriteCandidates.
find(
I);
981 if (It == RewriteCandidates.
end())
984 Candidate *BestC =
nullptr;
985 auto BestEfficiency = Candidate::Unknown;
986 for (Candidate *
C :
reverse(It->second))
988 auto Efficiency =
C->getRewriteEfficiency();
989 if (Efficiency > BestEfficiency) {
990 BestEfficiency = Efficiency;
1001 return TTI->getGEPCost(
GEP->getSourceElementType(),
GEP->getPointerOperand(),
1009 return Index->getBitWidth() <= 64 &&
1010 TTI->isLegalAddressingMode(
Base->getType(),
nullptr, 0,
true,
1014bool StraightLineStrengthReduce::isFoldable(
const Candidate &
C,
1015 TargetTransformInfo *
TTI) {
1016 if (
C.CandidateKind == Candidate::Add)
1018 if (
C.CandidateKind == Candidate::GEP)
1023void StraightLineStrengthReduce::allocateCandidatesAndFindBasis(
1024 Candidate::Kind CT,
const SCEV *
B, ConstantInt *Idx,
Value *S,
1026 bool IsSafe = CT != Candidate::GEP ||
1031 Candidate
C(CT,
B, Idx, S,
I, getAndRecordSCEV(S));
1042 if (IsSafe && !isFoldable(
C,
TTI) && !
C.isHighEfficiency()) {
1043 setBasisAndDeltaFor(
C);
1046 if (
auto Res = compressPath(
C,
C.Basis)) {
1048 C.DeltaKind = Res.DeltaKind;
1049 C.Delta = Res.Delta;
1055 Candidates.push_back(
C);
1056 RewriteCandidates[
C.Ins].push_back(&Candidates.back());
1063 CandidateDict.add(Candidates.back());
1067void StraightLineStrengthReduce::allocateCandidatesAndFindBasis(
1069 switch (
I->getOpcode()) {
1070 case Instruction::Add:
1071 allocateCandidatesAndFindBasisForAdd(
I);
1073 case Instruction::Mul:
1074 allocateCandidatesAndFindBasisForMul(
I);
1076 case Instruction::GetElementPtr:
1082void StraightLineStrengthReduce::allocateCandidatesAndFindBasisForAdd(
1088 assert(
I->getNumOperands() == 2 &&
"isn't I an add?");
1090 allocateCandidatesAndFindBasisForAdd(
LHS,
RHS,
I);
1092 allocateCandidatesAndFindBasisForAdd(
RHS,
LHS,
I);
1095void StraightLineStrengthReduce::allocateCandidatesAndFindBasisForAdd(
1098 ConstantInt *Idx =
nullptr;
1101 allocateCandidatesAndFindBasis(Candidate::Add, SE->
getSCEV(
LHS), Idx, S,
I);
1106 allocateCandidatesAndFindBasis(Candidate::Add, SE->
getSCEV(
LHS), Idx, S,
I);
1110 allocateCandidatesAndFindBasis(Candidate::Add, SE->
getSCEV(
LHS), One,
RHS,
1125void StraightLineStrengthReduce::allocateCandidatesAndFindBasisForMul(
1128 ConstantInt *Idx =
nullptr;
1132 allocateCandidatesAndFindBasis(Candidate::Mul, SE->
getSCEV(
B), Idx,
RHS,
I);
1138 allocateCandidatesAndFindBasis(Candidate::Mul, SE->
getSCEV(
B), Idx,
RHS,
I);
1142 allocateCandidatesAndFindBasis(Candidate::Mul, SE->
getSCEV(
LHS), Zero,
RHS,
1147void StraightLineStrengthReduce::allocateCandidatesAndFindBasisForMul(
1154 assert(
I->getNumOperands() == 2 &&
"isn't I a mul?");
1156 allocateCandidatesAndFindBasisForMul(
LHS,
RHS,
I);
1159 allocateCandidatesAndFindBasisForMul(
RHS,
LHS,
I);
1163void StraightLineStrengthReduce::allocateCandidatesAndFindBasisForGEP(
1164 GetElementPtrInst *
GEP) {
1166 if (
GEP->getType()->isVectorTy())
1170 for (Use &Idx :
GEP->indices())
1174 for (
unsigned I = 1,
E =
GEP->getNumOperands();
I !=
E; ++
I, ++GTI) {
1178 SCEVUse OrigIndexExpr = IndexExprs[
I - 1];
1188 ConstantInt *ElementSizeIdx =
1191 DL->getIndexSizeInBits(
GEP->getAddressSpace())) {
1194 allocateCandidatesAndFindBasis(Candidate::GEP, BaseExpr, ElementSizeIdx,
1200 Value *TruncatedArrayIdx =
nullptr;
1203 DL->getIndexSizeInBits(
GEP->getAddressSpace())) {
1206 allocateCandidatesAndFindBasis(Candidate::GEP, BaseExpr, ElementSizeIdx,
1207 TruncatedArrayIdx,
GEP);
1210 IndexExprs[
I - 1] = OrigIndexExpr;
1214Value *StraightLineStrengthReduce::emitBump(
const Candidate &Basis,
1217 const DataLayout *
DL) {
1220 const APInt &ConstRHS = CR->getValue();
1221 IntegerType *DeltaType =
1225 ConstantInt::get(DeltaType, ConstRHS.
logBase2());
1230 ConstantInt::get(DeltaType, (-ConstRHS).logBase2());
1245 if (
C.DeltaKind == Candidate::IndexDelta) {
1256 if (IndexDelta == 1)
1262 IntegerType *DeltaType =
1269 assert(
C.DeltaKind == Candidate::StrideDelta ||
1270 C.DeltaKind == Candidate::BaseDelta);
1271 assert(
C.CandidateKind != Candidate::Mul);
1287 if (
C.DeltaKind == Candidate::StrideDelta) {
1290 if (
C.CandidateKind == Candidate::GEP) {
1292 Type *NewScalarIndexTy =
1293 DL->getIndexType(
GEP->getPointerOperandType()->getScalarType());
1296 if (!
C.Index->isOne()) {
1297 Value *ExtendedIndex =
1305void StraightLineStrengthReduce::rewriteCandidate(
const Candidate &
C) {
1309 const Candidate &Basis = *
C.Basis;
1310 assert(
C.Delta &&
C.CandidateKind == Basis.CandidateKind &&
1311 C.hasValidDelta(Basis));
1314 Value *Bump = emitBump(Basis,
C, Builder,
DL);
1315 Value *Reduced =
nullptr;
1319 Reduced = Basis.Ins;
1321 switch (
C.CandidateKind) {
1322 case Candidate::Add:
1323 case Candidate::Mul: {
1328 Reduced = Builder.
CreateSub(Basis.Ins, NegBump);
1342 Reduced = Builder.
CreateAdd(Basis.Ins, Bump);
1346 case Candidate::GEP: {
1349 Reduced = Builder.
CreatePtrAdd(Basis.Ins, Bump,
"", InBounds);
1357 C.Ins->replaceAllUsesWith(Reduced);
1358 DeadInstructions.push_back(
C.Ins);
1361bool StraightLineStrengthReduceLegacyPass::runOnFunction(
Function &
F) {
1362 if (skipFunction(
F))
1365 auto *
TTI = &getAnalysis<TargetTransformInfoWrapperPass>().getTTI(
F);
1366 auto *DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
1367 auto *SE = &getAnalysis<ScalarEvolutionWrapperPass>().getSE();
1368 return StraightLineStrengthReduce(
DL, DT, SE,
TTI).runOnFunction(
F);
1371bool StraightLineStrengthReduce::runOnFunction(
Function &
F) {
1376 for (
auto &
I : *(
Node->getBlock()))
1377 allocateCandidatesAndFindBasis(&
I);
1381 for (
auto &
C : Candidates) {
1382 DependencyGraph.try_emplace(
C.Ins);
1383 addDependency(
C,
C.Basis);
1385 sortCandidateInstructions();
1389 for (Instruction *
I :
reverse(SortedCandidateInsts))
1390 if (Candidate *
C = pickRewriteCandidate(
I))
1391 rewriteCandidate(*
C);
1393 for (
auto *DeadIns : DeadInstructions)
1396 if (DeadIns->getParent())
1399 bool Ret = !DeadInstructions.empty();
1400 DeadInstructions.clear();
1401 DependencyGraph.clear();
1402 RewriteCandidates.
clear();
1403 SortedCandidateInsts.clear();
1405 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)
This file implements a set that has insertion order iteration characteristics.
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.
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