110#define DEBUG_TYPE "slsr"
113 std::numeric_limits<unsigned>::max();
116 "Controls whether rewriteCandidate is executed.");
121 cl::desc(
"Enable poison-reuse guard"));
125class StraightLineStrengthReduceLegacyPass :
public FunctionPass {
136 void getAnalysisUsage(AnalysisUsage &AU)
const override {
144 bool doInitialization(
Module &M)
override {
145 DL = &
M.getDataLayout();
152class StraightLineStrengthReduce {
154 StraightLineStrengthReduce(
const DataLayout *DL, DominatorTree *DT,
155 ScalarEvolution *SE, TargetTransformInfo *TTI)
156 : DL(DL), DT(DT), SE(SE), TTI(TTI) {}
175 Candidate() =
default;
176 Candidate(Kind CT,
const SCEV *
B, ConstantInt *Idx,
Value *S,
177 Instruction *
I,
const SCEV *StrideSCEV)
178 : CandidateKind(CT), Base(
B), Index(Idx), Stride(S), Ins(
I),
179 StrideSCEV(StrideSCEV) {}
181 Kind CandidateKind = Invalid;
183 const SCEV *Base =
nullptr;
188 ConstantInt *Index =
nullptr;
190 Value *Stride =
nullptr;
210 Candidate *Basis =
nullptr;
212 DKind DeltaKind = InvalidDelta;
215 const SCEV *StrideSCEV =
nullptr;
218 Value *Delta =
nullptr;
222 SmallVector<Instruction *> DropList;
232 enum EfficiencyLevel :
unsigned {
241 static EfficiencyLevel
242 getComputationEfficiency(Kind CandidateKind,
const ConstantInt *Index,
243 const Value *Stride,
const SCEV *Base =
nullptr) {
244 bool IsConstantBase =
false;
245 bool IsZeroBase =
false;
249 IsConstantBase =
true;
250 IsZeroBase = ConstBase->getValue()->isZero();
257 if (IsConstantBase && IsConstantStride)
261 if (CandidateKind == Mul) {
265 return (IsConstantStride || IsConstantBase) ? OneInstOneVar
269 return IsZeroBase && (Index->isOne() || Index->isMinusOne())
273 if (IsConstantStride) {
275 return (CI->isOne() || CI->isMinusOne()) ? OneInstOneVar
278 return TwoInstTwoVar;
282 assert(CandidateKind == Add || CandidateKind == GEP);
283 if (Index->isZero() || IsZeroStride)
286 bool IsSimpleIndex = Index->isOne() || Index->isMinusOne();
289 return IsZeroBase ? (IsSimpleIndex ? ZeroInst : OneInstOneVar)
290 : (IsSimpleIndex ? OneInstOneVar : TwoInstOneVar);
292 if (IsConstantStride)
293 return IsZeroStride ? ZeroInst : OneInstOneVar;
296 return OneInstTwoVar;
298 return TwoInstTwoVar;
302 bool isProfitableRewrite(
const Value &Delta,
const DKind DeltaKind)
const {
314 return getComputationEfficiency(CandidateKind, Index, Stride, Base) <=
315 getRewriteEfficiency(Delta, DeltaKind);
319 EfficiencyLevel getRewriteEfficiency()
const {
320 return Basis ? getRewriteEfficiency(*Delta, DeltaKind) : Unknown;
324 EfficiencyLevel getRewriteEfficiency(
const Value &Delta,
325 const DKind DeltaKind)
const {
328 return getComputationEfficiency(
332 return getComputationEfficiency(CandidateKind, Index, &Delta);
334 return getComputationEfficiency(CandidateKind,
341 bool isHighEfficiency()
const {
342 return getComputationEfficiency(CandidateKind, Index, Stride, Base) >=
348 bool hasValidDelta(
const Candidate &Basis)
const {
352 return Base == Basis.Base && StrideSCEV == Basis.StrideSCEV;
355 return Base == Basis.Base && Index == Basis.Index;
358 return StrideSCEV == Basis.StrideSCEV && Index == Basis.Index;
370 void setBasisAndDeltaFor(Candidate &
C);
372 bool isFoldable(
const Candidate &
C, TargetTransformInfo *TTI);
376 void allocateCandidatesAndFindBasis(Instruction *
I);
379 void allocateCandidatesAndFindBasisForAdd(Instruction *
I);
386 void allocateCandidatesAndFindBasisForMul(Instruction *
I);
394 void allocateCandidatesAndFindBasisForGEP(GetElementPtrInst *
GEP);
398 void allocateCandidatesAndFindBasis(Candidate::Kind CT,
const SCEV *
B,
399 ConstantInt *Idx,
Value *S,
403 void rewriteCandidate(
const Candidate &
C);
406 static Value *emitBump(
const Candidate &Basis,
const Candidate &
C,
409 const DataLayout *DL =
nullptr;
410 DominatorTree *DT =
nullptr;
412 TargetTransformInfo *TTI =
nullptr;
413 std::list<Candidate> Candidates;
417 DenseMap<const SCEV *, SmallSetVector<Instruction *, 2>> SCEVToInsts;
421 MapVector<Instruction *, std::vector<Instruction *>> DependencyGraph;
424 DenseMap<Instruction *, SmallVector<Candidate *, 3>> RewriteCandidates;
428 std::vector<Instruction *> SortedCandidateInsts;
432 std::vector<Instruction *> DeadInstructions;
435 class CandidateDictTy {
437 using CandsTy = SmallVector<Candidate *, 8>;
438 using BBToCandsTy = DenseMap<const BasicBlock *, CandsTy>;
442 using IndexDeltaKeyTy = std::tuple<const SCEV *, const SCEV *, Type *>;
443 DenseMap<IndexDeltaKeyTy, BBToCandsTy> IndexDeltaCandidates;
446 using BaseDeltaKeyTy = std::tuple<const SCEV *, ConstantInt *, Type *>;
447 DenseMap<BaseDeltaKeyTy, BBToCandsTy> BaseDeltaCandidates;
450 using StrideDeltaKeyTy = std::tuple<const SCEV *, ConstantInt *, Type *>;
451 DenseMap<StrideDeltaKeyTy, BBToCandsTy> StrideDeltaCandidates;
456 const BBToCandsTy *getCandidatesWithDeltaKind(
const Candidate &
C,
457 Candidate::DKind K)
const {
458 assert(K != Candidate::InvalidDelta);
459 if (K == Candidate::IndexDelta) {
460 IndexDeltaKeyTy IndexDeltaKey(
C.Base,
C.StrideSCEV,
C.Ins->getType());
461 auto It = IndexDeltaCandidates.find(IndexDeltaKey);
462 if (It != IndexDeltaCandidates.end())
464 }
else if (K == Candidate::BaseDelta) {
465 BaseDeltaKeyTy BaseDeltaKey(
C.StrideSCEV,
C.Index,
C.Ins->getType());
466 auto It = BaseDeltaCandidates.find(BaseDeltaKey);
467 if (It != BaseDeltaCandidates.end())
470 assert(K == Candidate::StrideDelta);
471 StrideDeltaKeyTy StrideDeltaKey(
C.Base,
C.Index,
C.Ins->getType());
472 auto It = StrideDeltaCandidates.find(StrideDeltaKey);
473 if (It != StrideDeltaCandidates.end())
480 void add(Candidate &
C) {
483 IndexDeltaKeyTy IndexDeltaKey(
C.Base,
C.StrideSCEV,
ValueType);
484 BaseDeltaKeyTy BaseDeltaKey(
C.StrideSCEV,
C.Index,
ValueType);
485 StrideDeltaKeyTy StrideDeltaKey(
C.Base,
C.Index,
ValueType);
486 IndexDeltaCandidates[IndexDeltaKey][BB].push_back(&
C);
487 BaseDeltaCandidates[BaseDeltaKey][BB].push_back(&
C);
488 StrideDeltaCandidates[StrideDeltaKey][BB].push_back(&
C);
492 IndexDeltaCandidates.clear();
493 BaseDeltaCandidates.clear();
494 StrideDeltaCandidates.clear();
498 const SCEV *getAndRecordSCEV(
Value *V) {
499 auto *S = SE->getSCEV(V);
507 bool candidatePredicate(Candidate *Basis, Candidate &
C, Candidate::DKind K);
509 bool searchFrom(
const CandidateDictTy::BBToCandsTy &BBToCands, Candidate &
C,
515 Value *getNearestValueOfSCEV(
const SCEV *S,
const Instruction *CI)
const {
520 return SU->getValue();
522 return SC->getValue();
524 auto It = SCEVToInsts.find(S);
525 if (It == SCEVToInsts.end())
530 for (Instruction *
I :
reverse(It->second))
531 if (DT->dominates(
I, CI))
539 Candidate::DKind DeltaKind;
543 : Cand(nullptr), DeltaKind(Candidate::InvalidDelta), Delta(nullptr) {}
544 DeltaInfo(Candidate *Cand, Candidate::DKind DeltaKind,
Value *Delta)
545 : Cand(Cand), DeltaKind(DeltaKind), Delta(Delta) {}
546 operator bool()
const {
return Cand !=
nullptr; }
549 friend raw_ostream &
operator<<(raw_ostream &OS,
const DeltaInfo &DI);
551 DeltaInfo compressPath(Candidate &
C, Candidate *Basis)
const;
553 Candidate *pickRewriteCandidate(Instruction *
I)
const;
554 void sortCandidateInstructions();
555 Value *getDelta(
const Candidate &
C,
const Candidate &Basis,
556 Candidate::DKind K)
const;
557 static bool isSimilar(Candidate &
C, Candidate &Basis, Candidate::DKind K);
561 void addDependency(Candidate &
C, Candidate *Basis) {
563 DependencyGraph[Basis->Ins].emplace_back(
C.Ins);
568 auto PropagateDependency = [&](
Instruction *Inst) {
569 if (
auto CandsIt = RewriteCandidates.find(Inst);
570 CandsIt != RewriteCandidates.end() &&
572 [](Candidate *Cand) { return Cand->Basis; }))
573 DependencyGraph[Inst].emplace_back(
C.Ins);
579 PropagateDependency(DeltaInst);
583 PropagateDependency(StrideInst);
588 const StraightLineStrengthReduce::Candidate &
C) {
589 OS <<
"Ins: " << *
C.Ins <<
"\n Base: " << *
C.Base
590 <<
"\n Index: " << *
C.Index <<
"\n Stride: " << *
C.Stride
591 <<
"\n StrideSCEV: " << *
C.StrideSCEV;
593 OS <<
"\n Delta: " << *
C.Delta <<
"\n Basis: \n [ " << *
C.Basis <<
" ]";
599 OS <<
"Cand: " << *DI.Cand <<
"\n";
600 OS <<
"Delta Kind: ";
601 switch (DI.DeltaKind) {
602 case StraightLineStrengthReduce::Candidate::IndexDelta:
605 case StraightLineStrengthReduce::Candidate::BaseDelta:
608 case StraightLineStrengthReduce::Candidate::StrideDelta:
614 OS <<
"\nDelta: " << *DI.Delta;
620char StraightLineStrengthReduceLegacyPass::ID = 0;
623 "Straight line strength reduction",
false,
false)
631 return new StraightLineStrengthReduceLegacyPass();
636 if (
A.getBitWidth() <
B.getBitWidth())
637 A =
A.sext(
B.getBitWidth());
638 else if (
A.getBitWidth() >
B.getBitWidth())
639 B =
B.sext(
A.getBitWidth());
651 return !OBO || !OBO->hasNoSignedWrap();
662 DL->getIndexSizeInBits(
GEP->getAddressSpace());
679Value *StraightLineStrengthReduce::getDelta(
const Candidate &
C,
680 const Candidate &Basis,
681 Candidate::DKind K)
const {
682 if (K == Candidate::IndexDelta) {
683 APInt Idx =
C.Index->getValue();
684 APInt BasisIdx = Basis.Index->getValue();
686 APInt IndexDelta = Idx - BasisIdx;
687 IntegerType *DeltaType =
689 return ConstantInt::get(DeltaType, IndexDelta);
690 }
else if (K == Candidate::BaseDelta || K == Candidate::StrideDelta) {
691 const SCEV *BasisPart =
692 (
K == Candidate::BaseDelta) ? Basis.Base : Basis.StrideSCEV;
693 const SCEV *CandPart = (
K == Candidate::BaseDelta) ?
C.Base :
C.StrideSCEV;
694 const SCEV *Diff = SE->
getMinusSCEV(CandPart, BasisPart);
695 return getNearestValueOfSCEV(Diff,
C.Ins);
700bool StraightLineStrengthReduce::isSimilar(Candidate &
C, Candidate &Basis,
701 Candidate::DKind K) {
702 bool SameType =
false;
704 case Candidate::StrideDelta:
705 SameType =
C.StrideSCEV->getType() == Basis.StrideSCEV->getType();
707 case Candidate::BaseDelta:
708 SameType =
C.Base->getType() == Basis.Base->getType();
710 case Candidate::IndexDelta:
715 return SameType && Basis.Ins !=
C.Ins &&
716 Basis.CandidateKind ==
C.CandidateKind;
723bool StraightLineStrengthReduce::candidatePredicate(Candidate *Basis,
725 Candidate::DKind K) {
726 if (!isSimilar(
C, *Basis, K))
730 Value *Delta = getDelta(
C, *Basis, K);
746 if (K == Candidate::StrideDelta &&
C.CandidateKind == Candidate::GEP &&
759 if (K == Candidate::IndexDelta &&
760 !
C.isProfitableRewrite(*Delta, Candidate::IndexDelta))
765 for (Instruction *
I : Basis->DropList)
766 I->dropPoisonGeneratingAnnotations();
781bool StraightLineStrengthReduce::searchFrom(
782 const CandidateDictTy::BBToCandsTy &BBToCands, Candidate &
C,
783 Candidate::DKind K) {
787 if (
C.CandidateKind == Candidate::Mul && K != Candidate::IndexDelta)
795 auto It = BBToCands.find(BB);
796 if (It != BBToCands.end())
797 for (Candidate *Basis :
reverse(It->second))
798 if (candidatePredicate(Basis,
C, K))
805 BB =
Node ?
Node->getBlock() :
nullptr;
810void StraightLineStrengthReduce::setBasisAndDeltaFor(Candidate &
C) {
811 if (
const auto *BaseDeltaCandidates =
812 CandidateDict.getCandidatesWithDeltaKind(
C, Candidate::BaseDelta))
813 if (searchFrom(*BaseDeltaCandidates,
C, Candidate::BaseDelta)) {
818 if (
const auto *StrideDeltaCandidates =
819 CandidateDict.getCandidatesWithDeltaKind(
C, Candidate::StrideDelta))
820 if (searchFrom(*StrideDeltaCandidates,
C, Candidate::StrideDelta)) {
825 if (
const auto *IndexDeltaCandidates =
826 CandidateDict.getCandidatesWithDeltaKind(
C, Candidate::IndexDelta))
827 if (searchFrom(*IndexDeltaCandidates,
C, Candidate::IndexDelta)) {
835 dbgs() <<
"Found delta from ";
836 if (
C.DeltaKind == Candidate::BaseDelta)
839 dbgs() <<
"Stride: ";
840 dbgs() << *
C.Delta <<
"\n";
842 assert(
C.DeltaKind != Candidate::InvalidDelta &&
C.Basis);
856auto StraightLineStrengthReduce::compressPath(Candidate &
C,
857 Candidate *Basis)
const
859 if (!Basis || !Basis->Basis ||
C.CandidateKind == Candidate::Mul)
861 Candidate *Root = Basis;
862 Value *NewDelta =
nullptr;
863 auto NewKind = Candidate::InvalidDelta;
865 while (Root->Basis) {
866 Candidate *NextRoot = Root->Basis;
867 if (
C.Base == NextRoot->Base &&
C.StrideSCEV == NextRoot->StrideSCEV &&
868 isSimilar(
C, *NextRoot, Candidate::IndexDelta)) {
873 NewKind = Candidate::IndexDelta;
879 const SCEV *CandPart =
nullptr;
880 const SCEV *BasisPart =
nullptr;
881 auto CurrKind = Candidate::InvalidDelta;
882 if (
C.Base == NextRoot->Base &&
C.Index == NextRoot->Index) {
883 CandPart =
C.StrideSCEV;
884 BasisPart = NextRoot->StrideSCEV;
885 CurrKind = Candidate::StrideDelta;
886 }
else if (
C.StrideSCEV == NextRoot->StrideSCEV &&
887 C.Index == NextRoot->Index) {
889 BasisPart = NextRoot->Base;
890 CurrKind = Candidate::BaseDelta;
894 assert(CandPart && BasisPart);
895 if (!isSimilar(
C, *NextRoot, CurrKind))
903 if (CurrKind == Candidate::StrideDelta &&
904 C.CandidateKind == Candidate::GEP &&
912 NewDelta = DeltaVal->getValue();
919 assert(NewKind != Candidate::InvalidDelta && NewDelta);
921 <<
" from path compression.\n");
922 return {Root, NewKind, NewDelta};
930void StraightLineStrengthReduce::sortCandidateInstructions() {
931 SortedCandidateInsts.clear();
937 DenseMap<Instruction *, int> InDegree;
938 for (
auto &KV : DependencyGraph) {
941 for (
auto *Child : KV.second) {
945 std::queue<Instruction *> WorkList;
946 DenseSet<Instruction *> Visited;
948 for (
auto &KV : DependencyGraph)
949 if (InDegree[KV.first] == 0)
950 WorkList.push(KV.first);
952 while (!WorkList.empty()) {
958 SortedCandidateInsts.push_back(
I);
960 for (
auto *
Next : DependencyGraph[
I]) {
961 auto &Degree = InDegree[
Next];
967 assert(SortedCandidateInsts.size() == DependencyGraph.size() &&
968 "Dependency graph should not have cycles");
971auto StraightLineStrengthReduce::pickRewriteCandidate(Instruction *
I)
const
974 auto It = RewriteCandidates.
find(
I);
975 if (It == RewriteCandidates.
end())
978 Candidate *BestC =
nullptr;
979 auto BestEfficiency = Candidate::Unknown;
980 for (Candidate *
C :
reverse(It->second))
982 auto Efficiency =
C->getRewriteEfficiency();
983 if (Efficiency > BestEfficiency) {
984 BestEfficiency = Efficiency;
995 return TTI->getGEPCost(
GEP->getSourceElementType(),
GEP->getPointerOperand(),
1003 return Index->getBitWidth() <= 64 &&
1004 TTI->isLegalAddressingMode(
Base->getType(),
nullptr, 0,
true,
1008bool StraightLineStrengthReduce::isFoldable(
const Candidate &
C,
1009 TargetTransformInfo *
TTI) {
1010 if (
C.CandidateKind == Candidate::Add)
1012 if (
C.CandidateKind == Candidate::GEP)
1017void StraightLineStrengthReduce::allocateCandidatesAndFindBasis(
1018 Candidate::Kind CT,
const SCEV *
B, ConstantInt *Idx,
Value *S,
1020 bool IsSafe = CT != Candidate::GEP ||
1025 Candidate
C(CT,
B, Idx, S,
I, getAndRecordSCEV(S));
1036 if (IsSafe && !isFoldable(
C,
TTI) && !
C.isHighEfficiency()) {
1037 setBasisAndDeltaFor(
C);
1040 if (
auto Res = compressPath(
C,
C.Basis)) {
1042 C.DeltaKind = Res.DeltaKind;
1043 C.Delta = Res.Delta;
1049 Candidates.push_back(
C);
1050 RewriteCandidates[
C.Ins].push_back(&Candidates.back());
1057 CandidateDict.add(Candidates.back());
1061void StraightLineStrengthReduce::allocateCandidatesAndFindBasis(
1063 switch (
I->getOpcode()) {
1064 case Instruction::Add:
1065 allocateCandidatesAndFindBasisForAdd(
I);
1067 case Instruction::Mul:
1068 allocateCandidatesAndFindBasisForMul(
I);
1070 case Instruction::GetElementPtr:
1076void StraightLineStrengthReduce::allocateCandidatesAndFindBasisForAdd(
1082 assert(
I->getNumOperands() == 2 &&
"isn't I an add?");
1084 allocateCandidatesAndFindBasisForAdd(
LHS,
RHS,
I);
1086 allocateCandidatesAndFindBasisForAdd(
RHS,
LHS,
I);
1089void StraightLineStrengthReduce::allocateCandidatesAndFindBasisForAdd(
1092 ConstantInt *Idx =
nullptr;
1095 allocateCandidatesAndFindBasis(Candidate::Add, SE->
getSCEV(
LHS), Idx, S,
I);
1100 allocateCandidatesAndFindBasis(Candidate::Add, SE->
getSCEV(
LHS), Idx, S,
I);
1104 allocateCandidatesAndFindBasis(Candidate::Add, SE->
getSCEV(
LHS), One,
RHS,
1119void StraightLineStrengthReduce::allocateCandidatesAndFindBasisForMul(
1122 ConstantInt *Idx =
nullptr;
1126 allocateCandidatesAndFindBasis(Candidate::Mul, SE->
getSCEV(
B), Idx,
RHS,
I);
1132 allocateCandidatesAndFindBasis(Candidate::Mul, SE->
getSCEV(
B), Idx,
RHS,
I);
1136 allocateCandidatesAndFindBasis(Candidate::Mul, SE->
getSCEV(
LHS), Zero,
RHS,
1141void StraightLineStrengthReduce::allocateCandidatesAndFindBasisForMul(
1148 assert(
I->getNumOperands() == 2 &&
"isn't I a mul?");
1150 allocateCandidatesAndFindBasisForMul(
LHS,
RHS,
I);
1153 allocateCandidatesAndFindBasisForMul(
RHS,
LHS,
I);
1157void StraightLineStrengthReduce::allocateCandidatesAndFindBasisForGEP(
1158 GetElementPtrInst *
GEP) {
1160 if (
GEP->getType()->isVectorTy())
1164 for (Use &Idx :
GEP->indices())
1168 for (
unsigned I = 1,
E =
GEP->getNumOperands();
I !=
E; ++
I, ++GTI) {
1172 SCEVUse OrigIndexExpr = IndexExprs[
I - 1];
1182 ConstantInt *ElementSizeIdx =
1185 DL->getIndexSizeInBits(
GEP->getAddressSpace())) {
1188 allocateCandidatesAndFindBasis(Candidate::GEP, BaseExpr, ElementSizeIdx,
1194 Value *TruncatedArrayIdx =
nullptr;
1197 DL->getIndexSizeInBits(
GEP->getAddressSpace())) {
1200 allocateCandidatesAndFindBasis(Candidate::GEP, BaseExpr, ElementSizeIdx,
1201 TruncatedArrayIdx,
GEP);
1204 IndexExprs[
I - 1] = OrigIndexExpr;
1208Value *StraightLineStrengthReduce::emitBump(
const Candidate &Basis,
1211 const DataLayout *
DL) {
1214 const APInt &ConstRHS = CR->getValue();
1215 IntegerType *DeltaType =
1219 ConstantInt::get(DeltaType, ConstRHS.
logBase2());
1224 ConstantInt::get(DeltaType, (-ConstRHS).logBase2());
1239 if (
C.DeltaKind == Candidate::IndexDelta) {
1250 if (IndexDelta == 1)
1256 IntegerType *DeltaType =
1263 assert(
C.DeltaKind == Candidate::StrideDelta ||
1264 C.DeltaKind == Candidate::BaseDelta);
1265 assert(
C.CandidateKind != Candidate::Mul);
1281 if (
C.DeltaKind == Candidate::StrideDelta) {
1284 if (
C.CandidateKind == Candidate::GEP) {
1286 Type *NewScalarIndexTy =
1287 DL->getIndexType(
GEP->getPointerOperandType()->getScalarType());
1290 if (!
C.Index->isOne()) {
1291 Value *ExtendedIndex =
1299void StraightLineStrengthReduce::rewriteCandidate(
const Candidate &
C) {
1303 const Candidate &Basis = *
C.Basis;
1304 assert(
C.Delta &&
C.CandidateKind == Basis.CandidateKind &&
1305 C.hasValidDelta(Basis));
1308 Value *Bump = emitBump(Basis,
C, Builder,
DL);
1309 Value *Reduced =
nullptr;
1313 Reduced = Basis.Ins;
1315 switch (
C.CandidateKind) {
1316 case Candidate::Add:
1317 case Candidate::Mul: {
1322 Reduced = Builder.
CreateSub(Basis.Ins, NegBump);
1336 Reduced = Builder.
CreateAdd(Basis.Ins, Bump);
1340 case Candidate::GEP: {
1343 Reduced = Builder.
CreatePtrAdd(Basis.Ins, Bump,
"", InBounds);
1351 C.Ins->replaceAllUsesWith(Reduced);
1352 DeadInstructions.push_back(
C.Ins);
1355bool StraightLineStrengthReduceLegacyPass::runOnFunction(Function &
F) {
1356 if (skipFunction(
F))
1359 auto *
TTI = &getAnalysis<TargetTransformInfoWrapperPass>().getTTI(
F);
1360 auto *DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
1361 auto *SE = &getAnalysis<ScalarEvolutionWrapperPass>().getSE();
1362 return StraightLineStrengthReduce(
DL, DT, SE,
TTI).runOnFunction(
F);
1365bool StraightLineStrengthReduce::runOnFunction(Function &
F) {
1370 for (
auto &
I : *(
Node->getBlock()))
1371 allocateCandidatesAndFindBasis(&
I);
1375 for (
auto &
C : Candidates) {
1376 DependencyGraph.try_emplace(
C.Ins);
1377 addDependency(
C,
C.Basis);
1379 sortCandidateInstructions();
1383 for (Instruction *
I :
reverse(SortedCandidateInsts))
1384 if (Candidate *
C = pickRewriteCandidate(
I))
1385 rewriteCandidate(*
C);
1387 for (
auto *DeadIns : DeadInstructions)
1390 if (DeadIns->getParent())
1393 bool Ret = !DeadInstructions.empty();
1394 DeadInstructions.clear();
1395 DependencyGraph.clear();
1396 RewriteCandidates.
clear();
1397 SortedCandidateInsts.clear();
1399 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< 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)
Machine Check Debug Module
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.
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.
LLVM_ABI 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.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ C
The default llvm calling convention, compatible with C.
@ 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