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;
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());
642Value *StraightLineStrengthReduce::getDelta(
const Candidate &
C,
643 const Candidate &Basis,
644 Candidate::DKind K)
const {
645 if (K == Candidate::IndexDelta) {
646 APInt Idx =
C.Index->getValue();
647 APInt BasisIdx = Basis.Index->getValue();
649 APInt IndexDelta = Idx - BasisIdx;
650 IntegerType *DeltaType =
652 return ConstantInt::get(DeltaType, IndexDelta);
653 }
else if (K == Candidate::BaseDelta || K == Candidate::StrideDelta) {
654 const SCEV *BasisPart =
655 (
K == Candidate::BaseDelta) ? Basis.Base : Basis.StrideSCEV;
656 const SCEV *CandPart = (
K == Candidate::BaseDelta) ?
C.Base :
C.StrideSCEV;
657 const SCEV *Diff = SE->
getMinusSCEV(CandPart, BasisPart);
658 return getNearestValueOfSCEV(Diff,
C.Ins);
663bool StraightLineStrengthReduce::isSimilar(Candidate &
C, Candidate &Basis,
664 Candidate::DKind K) {
665 bool SameType =
false;
667 case Candidate::StrideDelta:
668 SameType =
C.StrideSCEV->getType() == Basis.StrideSCEV->getType();
670 case Candidate::BaseDelta:
671 SameType =
C.Base->getType() == Basis.Base->getType();
673 case Candidate::IndexDelta:
678 return SameType && Basis.Ins !=
C.Ins &&
679 Basis.CandidateKind ==
C.CandidateKind;
686bool StraightLineStrengthReduce::candidatePredicate(Candidate *Basis,
688 Candidate::DKind K) {
689 if (!isSimilar(
C, *Basis, K))
693 Value *Delta = getDelta(
C, *Basis, K);
703 if (K == Candidate::IndexDelta &&
704 !
C.isProfitableRewrite(*Delta, Candidate::IndexDelta))
709 for (Instruction *
I : Basis->DropList)
710 I->dropPoisonGeneratingAnnotations();
725bool StraightLineStrengthReduce::searchFrom(
726 const CandidateDictTy::BBToCandsTy &BBToCands, Candidate &
C,
727 Candidate::DKind K) {
731 if (
C.CandidateKind == Candidate::Mul && K != Candidate::IndexDelta)
739 auto It = BBToCands.find(BB);
740 if (It != BBToCands.end())
741 for (Candidate *Basis :
reverse(It->second))
742 if (candidatePredicate(Basis,
C, K))
749 BB =
Node ?
Node->getBlock() :
nullptr;
754void StraightLineStrengthReduce::setBasisAndDeltaFor(Candidate &
C) {
755 if (
const auto *BaseDeltaCandidates =
756 CandidateDict.getCandidatesWithDeltaKind(
C, Candidate::BaseDelta))
757 if (searchFrom(*BaseDeltaCandidates,
C, Candidate::BaseDelta)) {
762 if (
const auto *StrideDeltaCandidates =
763 CandidateDict.getCandidatesWithDeltaKind(
C, Candidate::StrideDelta))
764 if (searchFrom(*StrideDeltaCandidates,
C, Candidate::StrideDelta)) {
769 if (
const auto *IndexDeltaCandidates =
770 CandidateDict.getCandidatesWithDeltaKind(
C, Candidate::IndexDelta))
771 if (searchFrom(*IndexDeltaCandidates,
C, Candidate::IndexDelta)) {
779 dbgs() <<
"Found delta from ";
780 if (
C.DeltaKind == Candidate::BaseDelta)
783 dbgs() <<
"Stride: ";
784 dbgs() << *
C.Delta <<
"\n";
786 assert(
C.DeltaKind != Candidate::InvalidDelta &&
C.Basis);
800auto StraightLineStrengthReduce::compressPath(Candidate &
C,
801 Candidate *Basis)
const
803 if (!Basis || !Basis->Basis ||
C.CandidateKind == Candidate::Mul)
805 Candidate *Root = Basis;
806 Value *NewDelta =
nullptr;
807 auto NewKind = Candidate::InvalidDelta;
809 while (Root->Basis) {
810 Candidate *NextRoot = Root->Basis;
811 if (
C.Base == NextRoot->Base &&
C.StrideSCEV == NextRoot->StrideSCEV &&
812 isSimilar(
C, *NextRoot, Candidate::IndexDelta)) {
817 NewKind = Candidate::IndexDelta;
823 const SCEV *CandPart =
nullptr;
824 const SCEV *BasisPart =
nullptr;
825 auto CurrKind = Candidate::InvalidDelta;
826 if (
C.Base == NextRoot->Base &&
C.Index == NextRoot->Index) {
827 CandPart =
C.StrideSCEV;
828 BasisPart = NextRoot->StrideSCEV;
829 CurrKind = Candidate::StrideDelta;
830 }
else if (
C.StrideSCEV == NextRoot->StrideSCEV &&
831 C.Index == NextRoot->Index) {
833 BasisPart = NextRoot->Base;
834 CurrKind = Candidate::BaseDelta;
838 assert(CandPart && BasisPart);
839 if (!isSimilar(
C, *NextRoot, CurrKind))
845 NewDelta = DeltaVal->getValue();
852 assert(NewKind != Candidate::InvalidDelta && NewDelta);
854 <<
" from path compression.\n");
855 return {Root, NewKind, NewDelta};
863void StraightLineStrengthReduce::sortCandidateInstructions() {
864 SortedCandidateInsts.clear();
870 DenseMap<Instruction *, int> InDegree;
871 for (
auto &KV : DependencyGraph) {
874 for (
auto *Child : KV.second) {
878 std::queue<Instruction *> WorkList;
879 DenseSet<Instruction *> Visited;
881 for (
auto &KV : DependencyGraph)
882 if (InDegree[KV.first] == 0)
883 WorkList.push(KV.first);
885 while (!WorkList.empty()) {
891 SortedCandidateInsts.push_back(
I);
893 for (
auto *
Next : DependencyGraph[
I]) {
894 auto &Degree = InDegree[
Next];
900 assert(SortedCandidateInsts.size() == DependencyGraph.size() &&
901 "Dependency graph should not have cycles");
904auto StraightLineStrengthReduce::pickRewriteCandidate(Instruction *
I)
const
907 auto It = RewriteCandidates.
find(
I);
908 if (It == RewriteCandidates.
end())
911 Candidate *BestC =
nullptr;
912 auto BestEfficiency = Candidate::Unknown;
913 for (Candidate *
C :
reverse(It->second))
915 auto Efficiency =
C->getRewriteEfficiency();
916 if (Efficiency > BestEfficiency) {
917 BestEfficiency = Efficiency;
928 return TTI->getGEPCost(
GEP->getSourceElementType(),
GEP->getPointerOperand(),
936 return Index->getBitWidth() <= 64 &&
937 TTI->isLegalAddressingMode(
Base->getType(),
nullptr, 0,
true,
941bool StraightLineStrengthReduce::isFoldable(
const Candidate &
C,
942 TargetTransformInfo *
TTI) {
943 if (
C.CandidateKind == Candidate::Add)
945 if (
C.CandidateKind == Candidate::GEP)
950void StraightLineStrengthReduce::allocateCandidatesAndFindBasis(
951 Candidate::Kind CT,
const SCEV *
B, ConstantInt *Idx,
Value *S,
956 Candidate
C(CT,
B, Idx, S,
I, getAndRecordSCEV(S));
967 if (!isFoldable(
C,
TTI) && !
C.isHighEfficiency()) {
968 setBasisAndDeltaFor(
C);
971 if (
auto Res = compressPath(
C,
C.Basis)) {
973 C.DeltaKind = Res.DeltaKind;
980 Candidates.push_back(
C);
981 RewriteCandidates[
C.Ins].push_back(&Candidates.back());
988 CandidateDict.add(Candidates.back());
992void StraightLineStrengthReduce::allocateCandidatesAndFindBasis(
994 switch (
I->getOpcode()) {
995 case Instruction::Add:
996 allocateCandidatesAndFindBasisForAdd(
I);
998 case Instruction::Mul:
999 allocateCandidatesAndFindBasisForMul(
I);
1001 case Instruction::GetElementPtr:
1007void StraightLineStrengthReduce::allocateCandidatesAndFindBasisForAdd(
1013 assert(
I->getNumOperands() == 2 &&
"isn't I an add?");
1015 allocateCandidatesAndFindBasisForAdd(
LHS,
RHS,
I);
1017 allocateCandidatesAndFindBasisForAdd(
RHS,
LHS,
I);
1020void StraightLineStrengthReduce::allocateCandidatesAndFindBasisForAdd(
1023 ConstantInt *Idx =
nullptr;
1026 allocateCandidatesAndFindBasis(Candidate::Add, SE->
getSCEV(
LHS), Idx, S,
I);
1031 allocateCandidatesAndFindBasis(Candidate::Add, SE->
getSCEV(
LHS), Idx, S,
I);
1035 allocateCandidatesAndFindBasis(Candidate::Add, SE->
getSCEV(
LHS), One,
RHS,
1050void StraightLineStrengthReduce::allocateCandidatesAndFindBasisForMul(
1053 ConstantInt *Idx =
nullptr;
1057 allocateCandidatesAndFindBasis(Candidate::Mul, SE->
getSCEV(
B), Idx,
RHS,
I);
1063 allocateCandidatesAndFindBasis(Candidate::Mul, SE->
getSCEV(
B), Idx,
RHS,
I);
1067 allocateCandidatesAndFindBasis(Candidate::Mul, SE->
getSCEV(
LHS), Zero,
RHS,
1072void StraightLineStrengthReduce::allocateCandidatesAndFindBasisForMul(
1079 assert(
I->getNumOperands() == 2 &&
"isn't I a mul?");
1081 allocateCandidatesAndFindBasisForMul(
LHS,
RHS,
I);
1084 allocateCandidatesAndFindBasisForMul(
RHS,
LHS,
I);
1088void StraightLineStrengthReduce::allocateCandidatesAndFindBasisForGEP(
1089 GetElementPtrInst *
GEP) {
1091 if (
GEP->getType()->isVectorTy())
1095 for (Use &Idx :
GEP->indices())
1099 for (
unsigned I = 1,
E =
GEP->getNumOperands();
I !=
E; ++
I, ++GTI) {
1103 SCEVUse OrigIndexExpr = IndexExprs[
I - 1];
1113 ConstantInt *ElementSizeIdx =
1116 DL->getIndexSizeInBits(
GEP->getAddressSpace())) {
1119 allocateCandidatesAndFindBasis(Candidate::GEP, BaseExpr, ElementSizeIdx,
1125 Value *TruncatedArrayIdx =
nullptr;
1128 DL->getIndexSizeInBits(
GEP->getAddressSpace())) {
1131 allocateCandidatesAndFindBasis(Candidate::GEP, BaseExpr, ElementSizeIdx,
1132 TruncatedArrayIdx,
GEP);
1135 IndexExprs[
I - 1] = OrigIndexExpr;
1139Value *StraightLineStrengthReduce::emitBump(
const Candidate &Basis,
1142 const DataLayout *
DL) {
1145 const APInt &ConstRHS = CR->getValue();
1146 IntegerType *DeltaType =
1150 ConstantInt::get(DeltaType, ConstRHS.
logBase2());
1155 ConstantInt::get(DeltaType, (-ConstRHS).logBase2());
1170 if (
C.DeltaKind == Candidate::IndexDelta) {
1181 if (IndexDelta == 1)
1187 IntegerType *DeltaType =
1194 assert(
C.DeltaKind == Candidate::StrideDelta ||
1195 C.DeltaKind == Candidate::BaseDelta);
1196 assert(
C.CandidateKind != Candidate::Mul);
1212 if (
C.DeltaKind == Candidate::StrideDelta) {
1215 if (
C.CandidateKind == Candidate::GEP) {
1217 Type *NewScalarIndexTy =
1218 DL->getIndexType(
GEP->getPointerOperandType()->getScalarType());
1221 if (!
C.Index->isOne()) {
1222 Value *ExtendedIndex =
1230void StraightLineStrengthReduce::rewriteCandidate(
const Candidate &
C) {
1234 const Candidate &Basis = *
C.Basis;
1235 assert(
C.Delta &&
C.CandidateKind == Basis.CandidateKind &&
1236 C.hasValidDelta(Basis));
1239 Value *Bump = emitBump(Basis,
C, Builder,
DL);
1240 Value *Reduced =
nullptr;
1244 Reduced = Basis.Ins;
1246 switch (
C.CandidateKind) {
1247 case Candidate::Add:
1248 case Candidate::Mul: {
1253 Reduced = Builder.
CreateSub(Basis.Ins, NegBump);
1267 Reduced = Builder.
CreateAdd(Basis.Ins, Bump);
1271 case Candidate::GEP: {
1274 Reduced = Builder.
CreatePtrAdd(Basis.Ins, Bump,
"", InBounds);
1282 C.Ins->replaceAllUsesWith(Reduced);
1283 DeadInstructions.push_back(
C.Ins);
1286bool StraightLineStrengthReduceLegacyPass::runOnFunction(Function &
F) {
1287 if (skipFunction(
F))
1290 auto *
TTI = &getAnalysis<TargetTransformInfoWrapperPass>().getTTI(
F);
1291 auto *DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
1292 auto *SE = &getAnalysis<ScalarEvolutionWrapperPass>().getSE();
1293 return StraightLineStrengthReduce(
DL, DT, SE,
TTI).runOnFunction(
F);
1296bool StraightLineStrengthReduce::runOnFunction(Function &
F) {
1301 for (
auto &
I : *(
Node->getBlock()))
1302 allocateCandidatesAndFindBasis(&
I);
1306 for (
auto &
C : Candidates) {
1307 DependencyGraph.try_emplace(
C.Ins);
1308 addDependency(
C,
C.Basis);
1310 sortCandidateInstructions();
1314 for (Instruction *
I :
reverse(SortedCandidateInsts))
1315 if (Candidate *
C = pickRewriteCandidate(
I))
1316 rewriteCandidate(*
C);
1318 for (
auto *DeadIns : DeadInstructions)
1321 if (DeadIns->getParent())
1324 bool Ret = !DeadInstructions.empty();
1325 DeadInstructions.clear();
1326 DependencyGraph.clear();
1327 RewriteCandidates.
clear();
1328 SortedCandidateInsts.clear();
1330 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.
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.
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()
SCEVUseT< const SCEV * > SCEVUse
SCEVPtrT getPointer() const