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))
824bool StraightLineStrengthReduce::searchFrom(
825 const CandidateDictTy::BBToCandsTy &BBToCands, Candidate &
C,
826 Candidate::DKind K) {
830 if (
C.CandidateKind == Candidate::Mul && K != Candidate::IndexDelta)
838 auto It = BBToCands.find(BB);
839 if (It != BBToCands.end())
840 for (Candidate *Basis :
reverse(It->second))
841 if (candidatePredicate(Basis,
C, K))
848 BB =
Node ?
Node->getBlock() :
nullptr;
853void StraightLineStrengthReduce::setBasisAndDeltaFor(Candidate &
C) {
854 if (
const auto *BaseDeltaCandidates =
855 CandidateDict.getCandidatesWithDeltaKind(
C, Candidate::BaseDelta))
856 if (searchFrom(*BaseDeltaCandidates,
C, Candidate::BaseDelta)) {
861 if (
const auto *StrideDeltaCandidates =
862 CandidateDict.getCandidatesWithDeltaKind(
C, Candidate::StrideDelta))
863 if (searchFrom(*StrideDeltaCandidates,
C, Candidate::StrideDelta)) {
868 if (
const auto *IndexDeltaCandidates =
869 CandidateDict.getCandidatesWithDeltaKind(
C, Candidate::IndexDelta))
870 if (searchFrom(*IndexDeltaCandidates,
C, Candidate::IndexDelta)) {
878 dbgs() <<
"Found delta from ";
879 if (
C.DeltaKind == Candidate::BaseDelta)
882 dbgs() <<
"Stride: ";
883 dbgs() << *
C.Delta <<
"\n";
885 assert(
C.DeltaKind != Candidate::InvalidDelta &&
C.Basis);
899auto StraightLineStrengthReduce::compressPath(Candidate &
C,
900 Candidate *Basis)
const
902 if (!Basis || !Basis->Basis ||
C.CandidateKind == Candidate::Mul)
904 Candidate *Root = Basis;
905 Value *NewDelta =
nullptr;
906 auto NewKind = Candidate::InvalidDelta;
908 while (Root->Basis) {
909 Candidate *NextRoot = Root->Basis;
910 if (
C.Base == NextRoot->Base &&
C.StrideSCEV == NextRoot->StrideSCEV &&
911 isSimilar(
C, *NextRoot, Candidate::IndexDelta)) {
916 NewKind = Candidate::IndexDelta;
922 const SCEV *CandPart =
nullptr;
923 const SCEV *BasisPart =
nullptr;
924 auto CurrKind = Candidate::InvalidDelta;
925 if (
C.Base == NextRoot->Base &&
C.Index == NextRoot->Index) {
926 CandPart =
C.StrideSCEV;
927 BasisPart = NextRoot->StrideSCEV;
928 CurrKind = Candidate::StrideDelta;
929 }
else if (
C.StrideSCEV == NextRoot->StrideSCEV &&
930 C.Index == NextRoot->Index) {
932 BasisPart = NextRoot->Base;
933 CurrKind = Candidate::BaseDelta;
937 assert(CandPart && BasisPart);
938 if (!isSimilar(
C, *NextRoot, CurrKind))
946 if (CurrKind == Candidate::StrideDelta &&
947 C.CandidateKind == Candidate::GEP &&
952 ++NumSCEVCandidateBasisDifferences;
956 NewDelta = DeltaVal->getValue();
963 assert(NewKind != Candidate::InvalidDelta && NewDelta);
965 <<
" from path compression.\n");
966 return {Root, NewKind, NewDelta};
974void StraightLineStrengthReduce::sortCandidateInstructions() {
975 SortedCandidateInsts.clear();
981 DenseMap<Instruction *, int> InDegree;
982 for (
auto &KV : DependencyGraph) {
985 for (
auto *Child : KV.second) {
989 std::queue<Instruction *> WorkList;
990 DenseSet<Instruction *> Visited;
992 for (
auto &KV : DependencyGraph)
993 if (InDegree[KV.first] == 0)
994 WorkList.push(KV.first);
996 while (!WorkList.empty()) {
1002 SortedCandidateInsts.push_back(
I);
1004 for (
auto *
Next : DependencyGraph[
I]) {
1005 auto &Degree = InDegree[
Next];
1007 WorkList.push(
Next);
1011 assert(SortedCandidateInsts.size() == DependencyGraph.size() &&
1012 "Dependency graph should not have cycles");
1015auto StraightLineStrengthReduce::pickRewriteCandidate(Instruction *
I)
const
1018 auto It = RewriteCandidates.
find(
I);
1019 if (It == RewriteCandidates.
end())
1022 Candidate *BestC =
nullptr;
1023 auto BestEfficiency = Candidate::Unknown;
1024 for (Candidate *
C :
reverse(It->second))
1026 auto Efficiency =
C->getRewriteEfficiency();
1027 if (Efficiency > BestEfficiency) {
1028 BestEfficiency = Efficiency;
1039 return TTI->getGEPCost(
1040 GEP->getSourceElementType(),
GEP->getPointerOperand(), Indices,
1049 return Index->getBitWidth() <= 64 &&
1050 TTI->isLegalAddressingMode(
Base->getType(),
nullptr, 0,
true,
1054bool StraightLineStrengthReduce::isFoldable(
const Candidate &
C,
1055 TargetTransformInfo *
TTI) {
1056 if (
C.CandidateKind == Candidate::Add)
1058 if (
C.CandidateKind == Candidate::GEP)
1063void StraightLineStrengthReduce::allocateCandidatesAndFindBasis(
1064 Candidate::Kind CT,
const SCEV *
B, ConstantInt *Idx,
Value *S,
1066 bool IsSafe = CT != Candidate::GEP ||
1071 Candidate
C(CT,
B, Idx, S,
I, getAndRecordSCEV(S));
1082 if (IsSafe && !isFoldable(
C,
TTI) && !
C.isHighEfficiency()) {
1083 setBasisAndDeltaFor(
C);
1086 if (
auto Res = compressPath(
C,
C.Basis)) {
1088 C.DeltaKind = Res.DeltaKind;
1089 C.Delta = Res.Delta;
1095 Candidates.push_back(
C);
1096 RewriteCandidates[
C.Ins].push_back(&Candidates.back());
1103 CandidateDict.add(Candidates.back());
1107void StraightLineStrengthReduce::allocateCandidatesAndFindBasis(
1109 switch (
I->getOpcode()) {
1110 case Instruction::Add:
1111 allocateCandidatesAndFindBasisForAdd(
I);
1113 case Instruction::Mul:
1114 allocateCandidatesAndFindBasisForMul(
I);
1116 case Instruction::GetElementPtr:
1122void StraightLineStrengthReduce::allocateCandidatesAndFindBasisForAdd(
1128 assert(
I->getNumOperands() == 2 &&
"isn't I an add?");
1130 allocateCandidatesAndFindBasisForAdd(
LHS,
RHS,
I);
1132 allocateCandidatesAndFindBasisForAdd(
RHS,
LHS,
I);
1135void StraightLineStrengthReduce::allocateCandidatesAndFindBasisForAdd(
1138 ConstantInt *Idx =
nullptr;
1141 allocateCandidatesAndFindBasis(Candidate::Add, SE->
getSCEV(
LHS), Idx, S,
I);
1146 allocateCandidatesAndFindBasis(Candidate::Add, SE->
getSCEV(
LHS), Idx, S,
I);
1150 allocateCandidatesAndFindBasis(Candidate::Add, SE->
getSCEV(
LHS), One,
RHS,
1165void StraightLineStrengthReduce::allocateCandidatesAndFindBasisForMul(
1168 ConstantInt *Idx =
nullptr;
1172 allocateCandidatesAndFindBasis(Candidate::Mul, SE->
getSCEV(
B), Idx,
RHS,
I);
1178 allocateCandidatesAndFindBasis(Candidate::Mul, SE->
getSCEV(
B), Idx,
RHS,
I);
1182 allocateCandidatesAndFindBasis(Candidate::Mul, SE->
getSCEV(
LHS), Zero,
RHS,
1187void StraightLineStrengthReduce::allocateCandidatesAndFindBasisForMul(
1194 assert(
I->getNumOperands() == 2 &&
"isn't I a mul?");
1196 allocateCandidatesAndFindBasisForMul(
LHS,
RHS,
I);
1199 allocateCandidatesAndFindBasisForMul(
RHS,
LHS,
I);
1203void StraightLineStrengthReduce::allocateCandidatesAndFindBasisForGEP(
1204 GetElementPtrInst *
GEP) {
1206 if (
GEP->getType()->isVectorTy())
1210 for (Use &Idx :
GEP->indices())
1214 for (
unsigned I = 1,
E =
GEP->getNumOperands();
I !=
E; ++
I, ++GTI) {
1218 SCEVUse OrigIndexExpr = IndexExprs[
I - 1];
1228 ConstantInt *ElementSizeIdx =
1231 DL->getIndexSizeInBits(
GEP->getAddressSpace())) {
1234 allocateCandidatesAndFindBasis(Candidate::GEP, BaseExpr, ElementSizeIdx,
1240 Value *TruncatedArrayIdx =
nullptr;
1243 DL->getIndexSizeInBits(
GEP->getAddressSpace())) {
1246 allocateCandidatesAndFindBasis(Candidate::GEP, BaseExpr, ElementSizeIdx,
1247 TruncatedArrayIdx,
GEP);
1250 IndexExprs[
I - 1] = OrigIndexExpr;
1254Value *StraightLineStrengthReduce::emitBump(
const Candidate &Basis,
1257 const DataLayout *
DL) {
1260 const APInt &ConstRHS = CR->getValue();
1261 IntegerType *DeltaType =
1265 ConstantInt::get(DeltaType, ConstRHS.
logBase2());
1270 ConstantInt::get(DeltaType, (-ConstRHS).logBase2());
1285 if (
C.DeltaKind == Candidate::IndexDelta) {
1296 if (IndexDelta == 1)
1302 IntegerType *DeltaType =
1309 assert(
C.DeltaKind == Candidate::StrideDelta ||
1310 C.DeltaKind == Candidate::BaseDelta);
1311 assert(
C.CandidateKind != Candidate::Mul);
1327 if (
C.DeltaKind == Candidate::StrideDelta) {
1330 if (
C.CandidateKind == Candidate::GEP) {
1332 Type *NewScalarIndexTy =
1333 DL->getIndexType(
GEP->getPointerOperandType()->getScalarType());
1336 if (!
C.Index->isOne()) {
1337 Value *ExtendedIndex =
1345void StraightLineStrengthReduce::rewriteCandidate(
const Candidate &
C) {
1349 const Candidate &Basis = *
C.Basis;
1350 assert(
C.Delta &&
C.CandidateKind == Basis.CandidateKind &&
1351 C.hasValidDelta(Basis));
1353 for (Instruction *
I : Basis.DropList)
1354 I->dropPoisonGeneratingAnnotations();
1357 Value *Bump = emitBump(Basis,
C, Builder,
DL);
1358 Value *Reduced =
nullptr;
1362 Reduced = Basis.Ins;
1364 switch (
C.CandidateKind) {
1365 case Candidate::Add:
1366 case Candidate::Mul: {
1371 Reduced = Builder.
CreateSub(Basis.Ins, NegBump);
1385 Reduced = Builder.
CreateAdd(Basis.Ins, Bump);
1389 case Candidate::GEP: {
1392 Reduced = Builder.
CreatePtrAdd(Basis.Ins, Bump,
"", InBounds);
1400 C.Ins->replaceAllUsesWith(Reduced);
1401 DeadInstructions.push_back(
C.Ins);
1404bool StraightLineStrengthReduceLegacyPass::runOnFunction(
Function &
F) {
1405 if (skipFunction(
F))
1408 auto *
TTI = &getAnalysis<TargetTransformInfoWrapperPass>().getTTI(
F);
1409 auto *DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
1410 auto *SE = &getAnalysis<ScalarEvolutionWrapperPass>().getSE();
1411 return StraightLineStrengthReduce(
DL, DT, SE,
TTI).runOnFunction(
F);
1414bool StraightLineStrengthReduce::runOnFunction(
Function &
F) {
1419 for (
auto &
I : *(
Node->getBlock()))
1420 allocateCandidatesAndFindBasis(&
I);
1424 for (
auto &
C : Candidates) {
1425 DependencyGraph.try_emplace(
C.Ins);
1426 addDependency(
C,
C.Basis);
1428 sortCandidateInstructions();
1432 for (Instruction *
I :
reverse(SortedCandidateInsts))
1433 if (Candidate *
C = pickRewriteCandidate(
I))
1434 rewriteCandidate(*
C);
1436 for (
auto *DeadIns : DeadInstructions)
1439 if (DeadIns->getParent())
1442 bool Ret = !DeadInstructions.empty();
1443 DeadInstructions.clear();
1444 DependencyGraph.clear();
1445 RewriteCandidates.
clear();
1446 SortedCandidateInsts.clear();
1448 CandidateDict.clear();
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