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;
228 enum EfficiencyLevel :
unsigned {
237 static EfficiencyLevel
238 getComputationEfficiency(Kind CandidateKind,
const ConstantInt *Index,
239 const Value *Stride,
const SCEV *Base =
nullptr) {
240 bool IsConstantBase =
false;
241 bool IsZeroBase =
false;
245 IsConstantBase =
true;
246 IsZeroBase = ConstBase->getValue()->isZero();
253 if (IsConstantBase && IsConstantStride)
257 if (CandidateKind == Mul) {
261 return (IsConstantStride || IsConstantBase) ? OneInstOneVar
265 return IsZeroBase && (Index->isOne() || Index->isMinusOne())
269 if (IsConstantStride) {
271 return (CI->isOne() || CI->isMinusOne()) ? OneInstOneVar
274 return TwoInstTwoVar;
278 assert(CandidateKind == Add || CandidateKind == GEP);
279 if (Index->isZero() || IsZeroStride)
282 bool IsSimpleIndex = Index->isOne() || Index->isMinusOne();
285 return IsZeroBase ? (IsSimpleIndex ? ZeroInst : OneInstOneVar)
286 : (IsSimpleIndex ? OneInstOneVar : TwoInstOneVar);
288 if (IsConstantStride)
289 return IsZeroStride ? ZeroInst : OneInstOneVar;
292 return OneInstTwoVar;
294 return TwoInstTwoVar;
298 bool isProfitableRewrite(
const Value &Delta,
const DKind DeltaKind)
const {
310 return getComputationEfficiency(CandidateKind, Index, Stride, Base) <=
311 getRewriteEfficiency(Delta, DeltaKind);
315 EfficiencyLevel getRewriteEfficiency()
const {
316 return Basis ? getRewriteEfficiency(*Delta, DeltaKind) : Unknown;
320 EfficiencyLevel getRewriteEfficiency(
const Value &Delta,
321 const DKind DeltaKind)
const {
324 return getComputationEfficiency(
328 return getComputationEfficiency(CandidateKind, Index, &Delta);
330 return getComputationEfficiency(CandidateKind,
337 bool isHighEfficiency()
const {
338 return getComputationEfficiency(CandidateKind, Index, Stride, Base) >=
344 bool hasValidDelta(
const Candidate &Basis)
const {
348 return Base == Basis.Base && StrideSCEV == Basis.StrideSCEV;
351 return Base == Basis.Base && Index == Basis.Index;
354 return StrideSCEV == Basis.StrideSCEV && Index == Basis.Index;
366 void setBasisAndDeltaFor(Candidate &
C);
368 bool isFoldable(
const Candidate &
C, TargetTransformInfo *TTI);
372 void allocateCandidatesAndFindBasis(Instruction *
I);
375 void allocateCandidatesAndFindBasisForAdd(Instruction *
I);
382 void allocateCandidatesAndFindBasisForMul(Instruction *
I);
390 void allocateCandidatesAndFindBasisForGEP(GetElementPtrInst *
GEP);
394 void allocateCandidatesAndFindBasis(Candidate::Kind CT,
const SCEV *
B,
395 ConstantInt *Idx,
Value *S,
399 void rewriteCandidate(
const Candidate &
C);
402 static Value *emitBump(
const Candidate &Basis,
const Candidate &
C,
405 const DataLayout *DL =
nullptr;
406 DominatorTree *DT =
nullptr;
408 TargetTransformInfo *TTI =
nullptr;
409 std::list<Candidate> Candidates;
413 DenseMap<const SCEV *, SmallSetVector<Instruction *, 2>> SCEVToInsts;
417 MapVector<Instruction *, std::vector<Instruction *>> DependencyGraph;
420 DenseMap<Instruction *, SmallVector<Candidate *, 3>> RewriteCandidates;
424 std::vector<Instruction *> SortedCandidateInsts;
428 std::vector<Instruction *> DeadInstructions;
431 class CandidateDictTy {
433 using CandsTy = SmallVector<Candidate *, 8>;
434 using BBToCandsTy = DenseMap<const BasicBlock *, CandsTy>;
438 using IndexDeltaKeyTy = std::tuple<const SCEV *, const SCEV *, Type *>;
439 DenseMap<IndexDeltaKeyTy, BBToCandsTy> IndexDeltaCandidates;
442 using BaseDeltaKeyTy = std::tuple<const SCEV *, ConstantInt *, Type *>;
443 DenseMap<BaseDeltaKeyTy, BBToCandsTy> BaseDeltaCandidates;
446 using StrideDeltaKeyTy = std::tuple<const SCEV *, ConstantInt *, Type *>;
447 DenseMap<StrideDeltaKeyTy, BBToCandsTy> StrideDeltaCandidates;
452 const BBToCandsTy *getCandidatesWithDeltaKind(
const Candidate &
C,
453 Candidate::DKind K)
const {
454 assert(K != Candidate::InvalidDelta);
455 if (K == Candidate::IndexDelta) {
456 IndexDeltaKeyTy IndexDeltaKey(
C.Base,
C.StrideSCEV,
C.Ins->getType());
457 auto It = IndexDeltaCandidates.find(IndexDeltaKey);
458 if (It != IndexDeltaCandidates.end())
460 }
else if (K == Candidate::BaseDelta) {
461 BaseDeltaKeyTy BaseDeltaKey(
C.StrideSCEV,
C.Index,
C.Ins->getType());
462 auto It = BaseDeltaCandidates.find(BaseDeltaKey);
463 if (It != BaseDeltaCandidates.end())
466 assert(K == Candidate::StrideDelta);
467 StrideDeltaKeyTy StrideDeltaKey(
C.Base,
C.Index,
C.Ins->getType());
468 auto It = StrideDeltaCandidates.find(StrideDeltaKey);
469 if (It != StrideDeltaCandidates.end())
476 void add(Candidate &
C) {
479 IndexDeltaKeyTy IndexDeltaKey(
C.Base,
C.StrideSCEV,
ValueType);
480 BaseDeltaKeyTy BaseDeltaKey(
C.StrideSCEV,
C.Index,
ValueType);
481 StrideDeltaKeyTy StrideDeltaKey(
C.Base,
C.Index,
ValueType);
482 IndexDeltaCandidates[IndexDeltaKey][BB].push_back(&
C);
483 BaseDeltaCandidates[BaseDeltaKey][BB].push_back(&
C);
484 StrideDeltaCandidates[StrideDeltaKey][BB].push_back(&
C);
488 IndexDeltaCandidates.clear();
489 BaseDeltaCandidates.clear();
490 StrideDeltaCandidates.clear();
494 const SCEV *getAndRecordSCEV(
Value *V) {
495 auto *S = SE->getSCEV(V);
503 bool candidatePredicate(Candidate *Basis, Candidate &
C, Candidate::DKind K);
505 bool searchFrom(
const CandidateDictTy::BBToCandsTy &BBToCands, Candidate &
C,
511 Value *getNearestValueOfSCEV(
const SCEV *S,
const Instruction *CI)
const {
516 return SU->getValue();
518 return SC->getValue();
520 auto It = SCEVToInsts.find(S);
521 if (It == SCEVToInsts.end())
526 for (Instruction *
I :
reverse(It->second))
527 if (DT->dominates(
I, CI))
535 Candidate::DKind DeltaKind;
539 : Cand(nullptr), DeltaKind(Candidate::InvalidDelta), Delta(nullptr) {}
540 DeltaInfo(Candidate *Cand, Candidate::DKind DeltaKind,
Value *Delta)
541 : Cand(Cand), DeltaKind(DeltaKind), Delta(Delta) {}
542 operator bool()
const {
return Cand !=
nullptr; }
545 friend raw_ostream &
operator<<(raw_ostream &OS,
const DeltaInfo &DI);
547 DeltaInfo compressPath(Candidate &
C, Candidate *Basis)
const;
549 Candidate *pickRewriteCandidate(Instruction *
I)
const;
550 void sortCandidateInstructions();
551 Value *getDelta(
const Candidate &
C,
const Candidate &Basis,
552 Candidate::DKind K)
const;
553 static bool isSimilar(Candidate &
C, Candidate &Basis, Candidate::DKind K);
557 void addDependency(Candidate &
C, Candidate *Basis) {
559 DependencyGraph[Basis->Ins].emplace_back(
C.Ins);
564 auto PropagateDependency = [&](
Instruction *Inst) {
565 if (
auto CandsIt = RewriteCandidates.find(Inst);
566 CandsIt != RewriteCandidates.end() &&
568 [](Candidate *Cand) { return Cand->Basis; }))
569 DependencyGraph[Inst].emplace_back(
C.Ins);
575 PropagateDependency(DeltaInst);
579 PropagateDependency(StrideInst);
584 const StraightLineStrengthReduce::Candidate &
C) {
585 OS <<
"Ins: " << *
C.Ins <<
"\n Base: " << *
C.Base
586 <<
"\n Index: " << *
C.Index <<
"\n Stride: " << *
C.Stride
587 <<
"\n StrideSCEV: " << *
C.StrideSCEV;
589 OS <<
"\n Delta: " << *
C.Delta <<
"\n Basis: \n [ " << *
C.Basis <<
" ]";
595 OS <<
"Cand: " << *DI.Cand <<
"\n";
596 OS <<
"Delta Kind: ";
597 switch (DI.DeltaKind) {
598 case StraightLineStrengthReduce::Candidate::IndexDelta:
601 case StraightLineStrengthReduce::Candidate::BaseDelta:
604 case StraightLineStrengthReduce::Candidate::StrideDelta:
610 OS <<
"\nDelta: " << *DI.Delta;
616char StraightLineStrengthReduceLegacyPass::ID = 0;
619 "Straight line strength reduction",
false,
false)
627 return new StraightLineStrengthReduceLegacyPass();
632 if (
A.getBitWidth() <
B.getBitWidth())
633 A =
A.sext(
B.getBitWidth());
634 else if (
A.getBitWidth() >
B.getBitWidth())
635 B =
B.sext(
A.getBitWidth());
638Value *StraightLineStrengthReduce::getDelta(
const Candidate &
C,
639 const Candidate &Basis,
640 Candidate::DKind K)
const {
641 if (K == Candidate::IndexDelta) {
642 APInt Idx =
C.Index->getValue();
643 APInt BasisIdx = Basis.Index->getValue();
645 APInt IndexDelta = Idx - BasisIdx;
646 IntegerType *DeltaType =
648 return ConstantInt::get(DeltaType, IndexDelta);
649 }
else if (K == Candidate::BaseDelta || K == Candidate::StrideDelta) {
650 const SCEV *BasisPart =
651 (
K == Candidate::BaseDelta) ? Basis.Base : Basis.StrideSCEV;
652 const SCEV *CandPart = (
K == Candidate::BaseDelta) ?
C.Base :
C.StrideSCEV;
653 const SCEV *Diff = SE->
getMinusSCEV(CandPart, BasisPart);
654 return getNearestValueOfSCEV(Diff,
C.Ins);
659bool StraightLineStrengthReduce::isSimilar(Candidate &
C, Candidate &Basis,
660 Candidate::DKind K) {
661 bool SameType =
false;
663 case Candidate::StrideDelta:
664 SameType =
C.StrideSCEV->getType() == Basis.StrideSCEV->getType();
666 case Candidate::BaseDelta:
667 SameType =
C.Base->getType() == Basis.Base->getType();
669 case Candidate::IndexDelta:
674 return SameType && Basis.Ins !=
C.Ins &&
675 Basis.CandidateKind ==
C.CandidateKind;
682bool StraightLineStrengthReduce::candidatePredicate(Candidate *Basis,
684 Candidate::DKind K) {
687 if (!isSimilar(
C, *Basis, K) ||
690 DropPoisonGeneratingInsts)))
694 Value *Delta = getDelta(
C, *Basis, K);
704 if (K == Candidate::IndexDelta &&
705 !
C.isProfitableRewrite(*Delta, Candidate::IndexDelta))
711 for (Instruction *
I : DropPoisonGeneratingInsts)
712 I->dropPoisonGeneratingAnnotations();
727bool StraightLineStrengthReduce::searchFrom(
728 const CandidateDictTy::BBToCandsTy &BBToCands, Candidate &
C,
729 Candidate::DKind K) {
733 if (
C.CandidateKind == Candidate::Mul && K != Candidate::IndexDelta)
741 auto It = BBToCands.find(BB);
742 if (It != BBToCands.end())
743 for (Candidate *Basis :
reverse(It->second))
744 if (candidatePredicate(Basis,
C, K))
751 BB =
Node ?
Node->getBlock() :
nullptr;
756void StraightLineStrengthReduce::setBasisAndDeltaFor(Candidate &
C) {
757 if (
const auto *BaseDeltaCandidates =
758 CandidateDict.getCandidatesWithDeltaKind(
C, Candidate::BaseDelta))
759 if (searchFrom(*BaseDeltaCandidates,
C, Candidate::BaseDelta)) {
764 if (
const auto *StrideDeltaCandidates =
765 CandidateDict.getCandidatesWithDeltaKind(
C, Candidate::StrideDelta))
766 if (searchFrom(*StrideDeltaCandidates,
C, Candidate::StrideDelta)) {
771 if (
const auto *IndexDeltaCandidates =
772 CandidateDict.getCandidatesWithDeltaKind(
C, Candidate::IndexDelta))
773 if (searchFrom(*IndexDeltaCandidates,
C, Candidate::IndexDelta)) {
781 dbgs() <<
"Found delta from ";
782 if (
C.DeltaKind == Candidate::BaseDelta)
785 dbgs() <<
"Stride: ";
786 dbgs() << *
C.Delta <<
"\n";
788 assert(
C.DeltaKind != Candidate::InvalidDelta &&
C.Basis);
802auto StraightLineStrengthReduce::compressPath(Candidate &
C,
803 Candidate *Basis)
const
805 if (!Basis || !Basis->Basis ||
C.CandidateKind == Candidate::Mul)
807 Candidate *Root = Basis;
808 Value *NewDelta =
nullptr;
809 auto NewKind = Candidate::InvalidDelta;
811 while (Root->Basis) {
812 Candidate *NextRoot = Root->Basis;
813 if (
C.Base == NextRoot->Base &&
C.StrideSCEV == NextRoot->StrideSCEV &&
814 isSimilar(
C, *NextRoot, Candidate::IndexDelta)) {
819 NewKind = Candidate::IndexDelta;
825 const SCEV *CandPart =
nullptr;
826 const SCEV *BasisPart =
nullptr;
827 auto CurrKind = Candidate::InvalidDelta;
828 if (
C.Base == NextRoot->Base &&
C.Index == NextRoot->Index) {
829 CandPart =
C.StrideSCEV;
830 BasisPart = NextRoot->StrideSCEV;
831 CurrKind = Candidate::StrideDelta;
832 }
else if (
C.StrideSCEV == NextRoot->StrideSCEV &&
833 C.Index == NextRoot->Index) {
835 BasisPart = NextRoot->Base;
836 CurrKind = Candidate::BaseDelta;
840 assert(CandPart && BasisPart);
841 if (!isSimilar(
C, *NextRoot, CurrKind))
847 NewDelta = DeltaVal->getValue();
854 assert(NewKind != Candidate::InvalidDelta && NewDelta);
856 <<
" from path compression.\n");
857 return {Root, NewKind, NewDelta};
865void StraightLineStrengthReduce::sortCandidateInstructions() {
866 SortedCandidateInsts.clear();
872 DenseMap<Instruction *, int> InDegree;
873 for (
auto &KV : DependencyGraph) {
876 for (
auto *Child : KV.second) {
880 std::queue<Instruction *> WorkList;
881 DenseSet<Instruction *> Visited;
883 for (
auto &KV : DependencyGraph)
884 if (InDegree[KV.first] == 0)
885 WorkList.push(KV.first);
887 while (!WorkList.empty()) {
893 SortedCandidateInsts.push_back(
I);
895 for (
auto *
Next : DependencyGraph[
I]) {
896 auto &Degree = InDegree[
Next];
902 assert(SortedCandidateInsts.size() == DependencyGraph.size() &&
903 "Dependency graph should not have cycles");
906auto StraightLineStrengthReduce::pickRewriteCandidate(Instruction *
I)
const
909 auto It = RewriteCandidates.
find(
I);
910 if (It == RewriteCandidates.
end())
913 Candidate *BestC =
nullptr;
914 auto BestEfficiency = Candidate::Unknown;
915 for (Candidate *
C :
reverse(It->second))
917 auto Efficiency =
C->getRewriteEfficiency();
918 if (Efficiency > BestEfficiency) {
919 BestEfficiency = Efficiency;
930 return TTI->getGEPCost(
GEP->getSourceElementType(),
GEP->getPointerOperand(),
938 return Index->getBitWidth() <= 64 &&
939 TTI->isLegalAddressingMode(
Base->getType(),
nullptr, 0,
true,
943bool StraightLineStrengthReduce::isFoldable(
const Candidate &
C,
944 TargetTransformInfo *
TTI) {
945 if (
C.CandidateKind == Candidate::Add)
947 if (
C.CandidateKind == Candidate::GEP)
952void StraightLineStrengthReduce::allocateCandidatesAndFindBasis(
953 Candidate::Kind CT,
const SCEV *
B, ConstantInt *Idx,
Value *S,
958 Candidate
C(CT,
B, Idx, S,
I, getAndRecordSCEV(S));
969 if (!isFoldable(
C,
TTI) && !
C.isHighEfficiency()) {
970 setBasisAndDeltaFor(
C);
973 if (
auto Res = compressPath(
C,
C.Basis)) {
975 C.DeltaKind = Res.DeltaKind;
982 Candidates.push_back(
C);
983 RewriteCandidates[
C.Ins].push_back(&Candidates.back());
984 CandidateDict.add(Candidates.back());
987void StraightLineStrengthReduce::allocateCandidatesAndFindBasis(
989 switch (
I->getOpcode()) {
990 case Instruction::Add:
991 allocateCandidatesAndFindBasisForAdd(
I);
993 case Instruction::Mul:
994 allocateCandidatesAndFindBasisForMul(
I);
996 case Instruction::GetElementPtr:
1002void StraightLineStrengthReduce::allocateCandidatesAndFindBasisForAdd(
1008 assert(
I->getNumOperands() == 2 &&
"isn't I an add?");
1010 allocateCandidatesAndFindBasisForAdd(
LHS,
RHS,
I);
1012 allocateCandidatesAndFindBasisForAdd(
RHS,
LHS,
I);
1015void StraightLineStrengthReduce::allocateCandidatesAndFindBasisForAdd(
1018 ConstantInt *Idx =
nullptr;
1021 allocateCandidatesAndFindBasis(Candidate::Add, SE->
getSCEV(
LHS), Idx, S,
I);
1026 allocateCandidatesAndFindBasis(Candidate::Add, SE->
getSCEV(
LHS), Idx, S,
I);
1030 allocateCandidatesAndFindBasis(Candidate::Add, SE->
getSCEV(
LHS), One,
RHS,
1045void StraightLineStrengthReduce::allocateCandidatesAndFindBasisForMul(
1048 ConstantInt *Idx =
nullptr;
1052 allocateCandidatesAndFindBasis(Candidate::Mul, SE->
getSCEV(
B), Idx,
RHS,
I);
1058 allocateCandidatesAndFindBasis(Candidate::Mul, SE->
getSCEV(
B), Idx,
RHS,
I);
1062 allocateCandidatesAndFindBasis(Candidate::Mul, SE->
getSCEV(
LHS), Zero,
RHS,
1067void StraightLineStrengthReduce::allocateCandidatesAndFindBasisForMul(
1074 assert(
I->getNumOperands() == 2 &&
"isn't I a mul?");
1076 allocateCandidatesAndFindBasisForMul(
LHS,
RHS,
I);
1079 allocateCandidatesAndFindBasisForMul(
RHS,
LHS,
I);
1083void StraightLineStrengthReduce::allocateCandidatesAndFindBasisForGEP(
1084 GetElementPtrInst *
GEP) {
1086 if (
GEP->getType()->isVectorTy())
1090 for (Use &Idx :
GEP->indices())
1094 for (
unsigned I = 1,
E =
GEP->getNumOperands();
I !=
E; ++
I, ++GTI) {
1098 const SCEV *OrigIndexExpr = IndexExprs[
I - 1];
1107 ConstantInt *ElementSizeIdx = ConstantInt::get(PtrIdxTy, ElementSize,
true);
1109 DL->getIndexSizeInBits(
GEP->getAddressSpace())) {
1112 allocateCandidatesAndFindBasis(Candidate::GEP, BaseExpr, ElementSizeIdx,
1118 Value *TruncatedArrayIdx =
nullptr;
1121 DL->getIndexSizeInBits(
GEP->getAddressSpace())) {
1124 allocateCandidatesAndFindBasis(Candidate::GEP, BaseExpr, ElementSizeIdx,
1125 TruncatedArrayIdx,
GEP);
1128 IndexExprs[
I - 1] = OrigIndexExpr;
1132Value *StraightLineStrengthReduce::emitBump(
const Candidate &Basis,
1135 const DataLayout *
DL) {
1138 const APInt &ConstRHS = CR->getValue();
1139 IntegerType *DeltaType =
1143 ConstantInt::get(DeltaType, ConstRHS.
logBase2());
1148 ConstantInt::get(DeltaType, (-ConstRHS).logBase2());
1163 if (
C.DeltaKind == Candidate::IndexDelta) {
1174 if (IndexDelta == 1)
1180 IntegerType *DeltaType =
1187 assert(
C.DeltaKind == Candidate::StrideDelta ||
1188 C.DeltaKind == Candidate::BaseDelta);
1189 assert(
C.CandidateKind != Candidate::Mul);
1205 if (
C.DeltaKind == Candidate::StrideDelta) {
1208 if (
C.CandidateKind == Candidate::GEP) {
1210 Type *NewScalarIndexTy =
1211 DL->getIndexType(
GEP->getPointerOperandType()->getScalarType());
1214 if (!
C.Index->isOne()) {
1215 Value *ExtendedIndex =
1223void StraightLineStrengthReduce::rewriteCandidate(
const Candidate &
C) {
1227 const Candidate &Basis = *
C.Basis;
1228 assert(
C.Delta &&
C.CandidateKind == Basis.CandidateKind &&
1229 C.hasValidDelta(Basis));
1232 Value *Bump = emitBump(Basis,
C, Builder,
DL);
1233 Value *Reduced =
nullptr;
1237 Reduced = Basis.Ins;
1239 switch (
C.CandidateKind) {
1240 case Candidate::Add:
1241 case Candidate::Mul: {
1246 Reduced = Builder.
CreateSub(Basis.Ins, NegBump);
1260 Reduced = Builder.
CreateAdd(Basis.Ins, Bump);
1264 case Candidate::GEP: {
1267 Reduced = Builder.
CreatePtrAdd(Basis.Ins, Bump,
"", InBounds);
1275 C.Ins->replaceAllUsesWith(Reduced);
1276 DeadInstructions.push_back(
C.Ins);
1279bool StraightLineStrengthReduceLegacyPass::runOnFunction(Function &
F) {
1280 if (skipFunction(
F))
1283 auto *
TTI = &getAnalysis<TargetTransformInfoWrapperPass>().getTTI(
F);
1284 auto *DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
1285 auto *SE = &getAnalysis<ScalarEvolutionWrapperPass>().getSE();
1286 return StraightLineStrengthReduce(
DL, DT, SE,
TTI).runOnFunction(
F);
1289bool StraightLineStrengthReduce::runOnFunction(Function &
F) {
1294 for (
auto &
I : *(
Node->getBlock()))
1295 allocateCandidatesAndFindBasis(&
I);
1299 for (
auto &
C : Candidates) {
1300 DependencyGraph.try_emplace(
C.Ins);
1301 addDependency(
C,
C.Basis);
1303 sortCandidateInstructions();
1307 for (Instruction *
I :
reverse(SortedCandidateInsts))
1308 if (Candidate *
C = pickRewriteCandidate(
I))
1309 rewriteCandidate(*
C);
1311 for (
auto *DeadIns : DeadInstructions)
1314 if (DeadIns->getParent())
1317 bool Ret = !DeadInstructions.empty();
1318 DeadInstructions.clear();
1319 DependencyGraph.clear();
1320 RewriteCandidates.
clear();
1321 SortedCandidateInsts.clear();
1323 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"))
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.
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(const SCEV *LHS, const SCEV *RHS, SCEV::NoWrapFlags Flags=SCEV::FlagAnyWrap, unsigned Depth=0)
Return LHS-RHS.
LLVM_ABI const SCEV * getGEPExpr(GEPOperator *GEP, ArrayRef< const SCEV * > IndexExprs)
Returns an expression for a GEP.
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.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
Analysis pass providing the TargetTransformInfo.
LLVM_ABI unsigned getIntegerBitWidth() const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
LLVM_ABI 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)
class_match< ConstantInt > m_ConstantInt()
Match an arbitrary ConstantInt 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.
class_match< Value > m_Value()
Match an arbitrary value and ignore it.
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.
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.
FunctionAddr VTableAddr Value
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 &)
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 >
FunctionAddr VTableAddr Next
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
iterator_range< df_iterator< T > > depth_first(const T &G)
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
LLVM_ABI FunctionPass * createStraightLineStrengthReducePass()