132#define DEBUG_TYPE "loop-reduce"
148 return Opts.stress_ivchain;
158 static const unsigned UnknownAddressSpace =
159 std::numeric_limits<unsigned>::max();
161 Type *MemTy =
nullptr;
162 unsigned AddrSpace = UnknownAddressSpace;
164 MemAccessTy() =
default;
165 MemAccessTy(
Type *Ty,
unsigned AS) : MemTy(Ty), AddrSpace(AS) {}
168 return MemTy ==
Other.MemTy && AddrSpace ==
Other.AddrSpace;
173 static MemAccessTy getUnknown(LLVMContext &Ctx,
174 unsigned AS = UnknownAddressSpace) {
175 return MemAccessTy(Type::getVoidTy(Ctx), AS);
186 SmallBitVector UsedByIndices;
188 void print(raw_ostream &OS)
const;
195 constexpr Immediate(ScalarTy MinVal,
bool Scalable)
196 : FixedOrScalableQuantity(MinVal, Scalable) {}
198 constexpr Immediate(
const FixedOrScalableQuantity<Immediate, int64_t> &V)
199 : FixedOrScalableQuantity(
V) {}
202 constexpr Immediate() =
delete;
204 static constexpr Immediate getFixed(ScalarTy MinVal) {
205 return {MinVal,
false};
207 static constexpr Immediate getScalable(ScalarTy MinVal) {
208 return {MinVal,
true};
210 static constexpr Immediate
get(ScalarTy MinVal,
bool Scalable) {
211 return {MinVal, Scalable};
213 static constexpr Immediate getZero() {
return {0,
false}; }
214 static constexpr Immediate getFixedMin() {
215 return {std::numeric_limits<int64_t>::min(),
false};
217 static constexpr Immediate getFixedMax() {
218 return {std::numeric_limits<int64_t>::max(),
false};
220 static constexpr Immediate getScalableMin() {
221 return {std::numeric_limits<int64_t>::min(),
true};
223 static constexpr Immediate getScalableMax() {
224 return {std::numeric_limits<int64_t>::max(),
true};
227 constexpr bool isLessThanZero()
const {
return Quantity < 0; }
229 constexpr bool isGreaterThanZero()
const {
return Quantity > 0; }
231 constexpr bool isCompatibleImmediate(
const Immediate &
Imm)
const {
232 return isZero() ||
Imm.isZero() ||
Imm.Scalable == Scalable;
235 constexpr bool isMin()
const {
236 return Quantity == std::numeric_limits<ScalarTy>::min();
239 constexpr bool isMax()
const {
240 return Quantity == std::numeric_limits<ScalarTy>::max();
244 constexpr Immediate addUnsigned(
const Immediate &
RHS)
const {
245 assert(isCompatibleImmediate(
RHS) &&
"Incompatible Immediates");
247 return {
Value, Scalable ||
RHS.isScalable()};
250 constexpr Immediate subUnsigned(
const Immediate &
RHS)
const {
251 assert(isCompatibleImmediate(
RHS) &&
"Incompatible Immediates");
253 return {
Value, Scalable ||
RHS.isScalable()};
257 constexpr Immediate mulUnsigned(
const ScalarTy
RHS)
const {
259 return {
Value, Scalable};
263 const SCEV *getSCEV(ScalarEvolution &SE,
Type *Ty)
const {
270 const SCEV *getNegativeSCEV(ScalarEvolution &SE,
Type *Ty)
const {
277 const SCEV *getUnknownSCEV(ScalarEvolution &SE,
Type *Ty)
const {
292struct KeyOrderTargetImmediate {
293 bool operator()(
const Immediate &
LHS,
const Immediate &
RHS)
const {
294 if (
LHS.isScalable() && !
RHS.isScalable())
296 if (!
LHS.isScalable() &&
RHS.isScalable())
298 return LHS.getKnownMinValue() <
RHS.getKnownMinValue();
305struct KeyOrderSizeTAndImmediate {
306 bool operator()(
const std::pair<size_t, Immediate> &
LHS,
307 const std::pair<size_t, Immediate> &
RHS)
const {
308 size_t LSize =
LHS.first;
309 size_t RSize =
RHS.first;
311 return LSize < RSize;
312 return KeyOrderTargetImmediate()(
LHS.second,
RHS.second);
317#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
319 OS <<
"[NumUses=" << UsedByIndices.
count() <<
']';
331 using RegUsesTy = DenseMap<const SCEV *, RegSortData>;
333 RegUsesTy RegUsesMap;
337 void countRegister(
const SCEV *
Reg,
size_t LUIdx);
338 void dropRegister(
const SCEV *
Reg,
size_t LUIdx);
339 void swapAndDropUse(
size_t LUIdx,
size_t LastLUIdx);
341 bool isRegUsedByUsesOtherThan(
const SCEV *
Reg,
size_t LUIdx)
const;
343 const SmallBitVector &getUsedByIndices(
const SCEV *
Reg)
const;
359RegUseTracker::countRegister(
const SCEV *
Reg,
size_t LUIdx) {
360 std::pair<RegUsesTy::iterator, bool> Pair = RegUsesMap.try_emplace(
Reg);
361 RegSortData &RSD = Pair.first->second;
364 RSD.UsedByIndices.
resize(std::max(RSD.UsedByIndices.
size(), LUIdx + 1));
365 RSD.UsedByIndices.
set(LUIdx);
369RegUseTracker::dropRegister(
const SCEV *
Reg,
size_t LUIdx) {
370 RegUsesTy::iterator It = RegUsesMap.find(
Reg);
371 assert(It != RegUsesMap.end());
372 RegSortData &RSD = It->second;
374 RSD.UsedByIndices.
reset(LUIdx);
378RegUseTracker::swapAndDropUse(
size_t LUIdx,
size_t LastLUIdx) {
379 assert(LUIdx <= LastLUIdx);
383 for (
auto &Pair : RegUsesMap) {
384 SmallBitVector &UsedByIndices = Pair.second.UsedByIndices;
385 if (LUIdx < UsedByIndices.
size())
386 UsedByIndices[LUIdx] =
387 LastLUIdx < UsedByIndices.
size() ? UsedByIndices[LastLUIdx] :
false;
388 UsedByIndices.
resize(std::min(UsedByIndices.
size(), LastLUIdx));
393RegUseTracker::isRegUsedByUsesOtherThan(
const SCEV *
Reg,
size_t LUIdx)
const {
394 RegUsesTy::const_iterator
I = RegUsesMap.find(
Reg);
395 if (
I == RegUsesMap.end())
397 const SmallBitVector &UsedByIndices =
I->second.UsedByIndices;
399 if (i == -1)
return false;
400 if ((
size_t)i != LUIdx)
return true;
404const SmallBitVector &RegUseTracker::getUsedByIndices(
const SCEV *
Reg)
const {
405 RegUsesTy::const_iterator
I = RegUsesMap.find(
Reg);
406 assert(
I != RegUsesMap.end() &&
"Unknown register!");
407 return I->second.UsedByIndices;
410void RegUseTracker::clear() {
421 GlobalValue *BaseGV =
nullptr;
424 Immediate BaseOffset = Immediate::getZero();
427 bool HasBaseReg =
false;
450 const SCEV *ScaledReg =
nullptr;
455 Immediate UnfoldedOffset = Immediate::getZero();
459 void initialMatch(
const SCEV *S,
Loop *L, ScalarEvolution &SE);
463 void canonicalize(
const Loop &L);
467 bool hasZeroEnd()
const;
469 bool countsDownToZero()
const;
471 size_t getNumRegs()
const;
474 void deleteBaseReg(
const SCEV *&S);
476 bool referencesReg(
const SCEV *S)
const;
477 bool hasRegsUsedByUsesOtherThan(
size_t LUIdx,
478 const RegUseTracker &RegUses)
const;
480 void print(raw_ostream &OS)
const;
498 for (
const SCEV *S :
Add->operands())
504 const SCEV *Start, *Step;
519 if (
Mul->getOperand(0)->isAllOnesValue()) {
528 for (
const SCEV *S : MyGood)
530 for (
const SCEV *S : MyBad)
542void Formula::initialMatch(
const SCEV *S,
Loop *L, ScalarEvolution &SE) {
549 BaseRegs.push_back(Sum);
555 BaseRegs.push_back(Sum);
570bool Formula::isCanonical(
const Loop &L)
const {
571 assert((Scale == 0 || ScaledReg) &&
572 "ScaledReg must be non-null if Scale is non-zero");
575 return BaseRegs.size() <= 1;
580 if (Scale == 1 && BaseRegs.empty())
589 return none_of(BaseRegs, [&L](
const SCEV *S) {
600void Formula::canonicalize(
const Loop &L) {
604 if (BaseRegs.empty()) {
606 assert(ScaledReg &&
"Expected 1*reg => reg");
607 assert(Scale == 1 &&
"Expected 1*reg => reg");
608 BaseRegs.push_back(ScaledReg);
616 ScaledReg = BaseRegs.pop_back_val();
624 auto I =
find_if(BaseRegs, [&L](
const SCEV *S) {
627 if (
I != BaseRegs.end())
637bool Formula::unscale() {
641 BaseRegs.push_back(ScaledReg);
646bool Formula::hasZeroEnd()
const {
647 if (UnfoldedOffset || BaseOffset)
649 if (BaseRegs.size() != 1 || ScaledReg)
654bool Formula::countsDownToZero()
const {
657 assert(BaseRegs.size() == 1 &&
"hasZeroEnd should mean one BaseReg");
658 const APInt *StepInt;
666size_t Formula::getNumRegs()
const {
667 return !!ScaledReg + BaseRegs.size();
672Type *Formula::getType()
const {
673 return !BaseRegs.empty() ? BaseRegs.front()->getType() :
674 ScaledReg ? ScaledReg->
getType() :
680void Formula::deleteBaseReg(
const SCEV *&S) {
681 if (&S != &BaseRegs.back())
687bool Formula::referencesReg(
const SCEV *S)
const {
693bool Formula::hasRegsUsedByUsesOtherThan(
size_t LUIdx,
694 const RegUseTracker &RegUses)
const {
696 if (RegUses.isRegUsedByUsesOtherThan(ScaledReg, LUIdx))
698 for (
const SCEV *BaseReg : BaseRegs)
699 if (RegUses.isRegUsedByUsesOtherThan(BaseReg, LUIdx))
704#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
705void Formula::print(raw_ostream &OS)
const {
706 ListSeparator
Plus(
" + ");
711 if (BaseOffset.isNonZero())
712 OS <<
Plus << BaseOffset;
714 for (
const SCEV *BaseReg : BaseRegs)
717 if (HasBaseReg && BaseRegs.empty())
718 OS <<
Plus <<
"**error: HasBaseReg**";
719 else if (!HasBaseReg && !BaseRegs.empty())
720 OS <<
Plus <<
"**error: !HasBaseReg**";
723 OS <<
Plus << Scale <<
"*reg(";
730 if (UnfoldedOffset.isNonZero())
731 OS <<
Plus <<
"imm(" << UnfoldedOffset <<
')';
771 bool IgnoreSignificantBits =
false) {
786 if (
RA.isAllOnes()) {
787 if (
LHS->getType()->isPointerTy())
800 const APInt &LA =
C->getAPInt();
809 if ((IgnoreSignificantBits ||
isAddRecSExtable(AR, SE)) && AR->isAffine()) {
811 IgnoreSignificantBits);
812 if (!Step)
return nullptr;
814 IgnoreSignificantBits);
815 if (!Start)
return nullptr;
828 for (
const SCEV *S :
Add->operands()) {
830 if (!
Op)
return nullptr;
858 for (
const SCEV *S :
Mul->operands()) {
861 IgnoreSignificantBits)) {
882 bool PreferScalable) {
885 Immediate Result = Immediate::getZero();
894 C->getSignificantBits() <= 64) {
896 Result = Immediate::getFixed(
C->getSExtValue());
901 if (Opts.lsr_enable_vscale_immediates &&
902 (Result.isZero() || PreferScalable)) {
909 Result = Immediate::getScalable(
C->getSExtValue());
915 if (Result.isNonZero()) {
927 bool PreferScalable =
false) {
934 if (Result.isNonZero())
941 if (Result.isNonZero())
982 if (
SI->getPointerOperand() == OperandVal)
987 switch (
II->getIntrinsicID()) {
988 case Intrinsic::memset:
989 case Intrinsic::prefetch:
990 case Intrinsic::masked_load:
991 if (
II->getArgOperand(0) == OperandVal)
994 case Intrinsic::masked_store:
995 if (
II->getArgOperand(1) == OperandVal)
998 case Intrinsic::memmove:
999 case Intrinsic::memcpy:
1000 if (
II->getArgOperand(0) == OperandVal ||
1001 II->getArgOperand(1) == OperandVal)
1006 if (
TTI.getTgtMemIntrinsic(
II, IntrInfo)) {
1007 if (IntrInfo.
PtrVal == OperandVal)
1013 if (RMW->getPointerOperand() == OperandVal)
1016 if (CmpX->getPointerOperand() == OperandVal)
1025 MemAccessTy AccessTy = MemAccessTy::getUnknown(Inst->
getContext());
1029 AccessTy.MemTy = Ty;
1033 AccessTy.AddrSpace =
SI->getPointerAddressSpace();
1035 AccessTy.AddrSpace = LI->getPointerAddressSpace();
1037 AccessTy.AddrSpace = RMW->getPointerAddressSpace();
1039 AccessTy.AddrSpace = CmpX->getPointerAddressSpace();
1041 switch (
II->getIntrinsicID()) {
1042 case Intrinsic::prefetch:
1043 case Intrinsic::memset:
1044 AccessTy.AddrSpace =
II->getArgOperand(0)->getType()->getPointerAddressSpace();
1045 AccessTy.MemTy = OperandVal->
getType();
1047 case Intrinsic::memmove:
1048 case Intrinsic::memcpy:
1050 AccessTy.MemTy = OperandVal->
getType();
1052 case Intrinsic::masked_load:
1053 AccessTy.AddrSpace =
1054 II->getArgOperand(0)->getType()->getPointerAddressSpace();
1056 case Intrinsic::masked_store:
1057 AccessTy.AddrSpace =
1058 II->getArgOperand(1)->getType()->getPointerAddressSpace();
1062 if (
TTI.getTgtMemIntrinsic(
II, IntrInfo) && IntrInfo.
PtrVal) {
1118 if (!Processed.
insert(S).second)
1122 for (
const SCEV *S :
Add->operands()) {
1129 const SCEV *Op0, *Op1;
1138 Value *UVal = U->getValue();
1142 if (UI && UI->
getOpcode() == Instruction::Mul &&
1175 const LSRUse &LU,
const Formula &
F);
1179 const LSRUse &LU,
const Formula &
F,
1186 const ScalarOptions *Opts =
nullptr;
1187 const Loop *
L =
nullptr;
1188 ScalarEvolution *SE =
nullptr;
1189 const TargetTransformInfo *
TTI =
nullptr;
1190 TargetTransformInfo::LSRCost
C;
1195 Cost(
const ScalarOptions &Opts,
const Loop *L, ScalarEvolution &SE,
1197 : Opts(&Opts),
L(
L), SE(&SE),
TTI(&
TTI), AMK(AMK) {
1206 C.NumPrePostIndex = 0;
1216 return ((
C.Insns |
C.NumRegs |
C.AddRecCost |
C.NumIVMuls |
C.NumBaseAdds |
1217 C.ImmCost |
C.SetupCost |
C.ScaleCost |
C.NumPrePostIndex) !=
1219 ((
C.Insns &
C.NumRegs &
C.AddRecCost &
C.NumIVMuls &
C.NumBaseAdds &
1220 C.ImmCost &
C.SetupCost &
C.ScaleCost &
C.NumPrePostIndex) == ~0
u);
1226 return C.NumRegs == ~0
u;
1229 void RateFormula(
const Formula &
F, SmallPtrSetImpl<const SCEV *> &Regs,
1230 const DenseSet<const SCEV *> &VisitedRegs,
const LSRUse &LU,
1231 bool HardwareLoopProfitable,
1232 SmallPtrSetImpl<const SCEV *> *LoserRegs =
nullptr);
1234 void print(raw_ostream &OS)
const;
1238 void RateRegister(
const Formula &
F,
const SCEV *
Reg,
1239 SmallPtrSetImpl<const SCEV *> &Regs,
const LSRUse &LU,
1240 bool HardwareLoopProfitable);
1241 void RatePrimaryRegister(
const Formula &
F,
const SCEV *
Reg,
1242 SmallPtrSetImpl<const SCEV *> &Regs,
1243 const LSRUse &LU,
bool HardwareLoopProfitable,
1244 SmallPtrSetImpl<const SCEV *> *LoserRegs);
1255 Value *OperandValToReplace =
nullptr;
1265 Immediate
Offset = Immediate::getZero();
1267 LSRFixup() =
default;
1269 bool isUseFullyOutsideLoop(
const Loop *L)
const;
1271 void print(raw_ostream &OS)
const;
1281 DenseSet<SmallVector<const SCEV *, 4>> Uniquifier;
1294 using SCEVUseKindPair = PointerIntPair<const SCEV *, 2, KindType>;
1297 MemAccessTy AccessTy;
1303 Immediate MinOffset = Immediate::getFixedMax();
1304 Immediate MaxOffset = Immediate::getFixedMin();
1308 bool AllFixupsOutsideLoop =
true;
1313 bool AllFixupsUnconditional =
true;
1320 bool RigidFormula =
false;
1328 SmallPtrSet<const SCEV *, 4> Regs;
1330 LSRUse(KindType K, MemAccessTy AT) :
Kind(
K), AccessTy(AT) {}
1332 LSRFixup &getNewFixup() {
1333 Fixups.push_back(LSRFixup());
1337 void pushFixup(LSRFixup &f) {
1339 if (Immediate::isKnownGT(
f.Offset, MaxOffset))
1340 MaxOffset =
f.Offset;
1341 if (Immediate::isKnownLT(
f.Offset, MinOffset))
1342 MinOffset =
f.Offset;
1345 bool HasFormulaWithSameRegs(
const Formula &
F)
const;
1346 float getNotSelectedProbability(
const SCEV *
Reg)
const;
1347 bool InsertFormula(
const Formula &
F,
const Loop &L);
1348 void DeleteFormula(Formula &
F);
1349 void RecomputeRegs(
size_t LUIdx, RegUseTracker &Reguses);
1351 void print(raw_ostream &OS)
const;
1358 LSRUse::KindType Kind, MemAccessTy AccessTy,
1359 GlobalValue *BaseGV, Immediate BaseOffset,
1360 bool HasBaseReg, int64_t Scale,
1361 Instruction *Fixup =
nullptr);
1368 if (
TTI.getIntImmCost(
C->getAPInt(),
C->getType(),
1382 [&](
unsigned i,
const SCEV *
Reg) {
1383 return i + getSetupCost(Reg, Depth - 1, TTI);
1392void Cost::RateRegister(
const Formula &
F,
const SCEV *
Reg,
1393 SmallPtrSetImpl<const SCEV *> &Regs,
const LSRUse &LU,
1394 bool HardwareLoopProfitable) {
1399 if (AR->getLoop() != L) {
1406 if (!AR->getLoop()->contains(L)) {
1416 unsigned LoopCost = 1;
1425 F.BaseOffset.isFixed() &&
1426 *Step ==
F.BaseOffset.getFixedValue();
1431 if ((CanPreIndex || CanPostIndex) && LU.AllFixupsUnconditional) {
1432 ++
C.NumPrePostIndex;
1440 if (LU.Kind == LSRUse::ICmpZero &&
F.countsDownToZero() &&
1441 HardwareLoopProfitable)
1443 C.AddRecCost += LoopCost;
1447 const SCEV *StepReg = AR->getOperand(1);
1452 auto IsVScaleStep = [](
const SCEV *
Reg,
const TargetTransformInfo *
TTI) {
1458 if (!Regs.
count(StepReg) && !IsVScaleStep(StepReg,
TTI)) {
1459 RateRegister(
F, StepReg, Regs, LU, HardwareLoopProfitable);
1471 C.SetupCost = std::min<unsigned>(
C.SetupCost, 1 << 16);
1480void Cost::RatePrimaryRegister(
const Formula &
F,
const SCEV *
Reg,
1481 SmallPtrSetImpl<const SCEV *> &Regs,
1482 const LSRUse &LU,
bool HardwareLoopProfitable,
1483 SmallPtrSetImpl<const SCEV *> *LoserRegs) {
1484 if (LoserRegs && LoserRegs->
count(
Reg)) {
1489 RateRegister(
F,
Reg, Regs, LU, HardwareLoopProfitable);
1490 if (LoserRegs && isLoser())
1495void Cost::RateFormula(
const Formula &
F, SmallPtrSetImpl<const SCEV *> &Regs,
1496 const DenseSet<const SCEV *> &VisitedRegs,
1497 const LSRUse &LU,
bool HardwareLoopProfitable,
1498 SmallPtrSetImpl<const SCEV *> *LoserRegs) {
1501 assert(
F.isCanonical(*L) &&
"Cost is accurate only for canonical formula");
1503 unsigned PrevAddRecCost =
C.AddRecCost;
1504 unsigned PrevNumRegs =
C.NumRegs;
1505 unsigned PrevNumBaseAdds =
C.NumBaseAdds;
1506 if (
const SCEV *ScaledReg =
F.ScaledReg) {
1507 if (VisitedRegs.
count(ScaledReg)) {
1511 RatePrimaryRegister(
F, ScaledReg, Regs, LU, HardwareLoopProfitable,
1516 for (
const SCEV *BaseReg :
F.BaseRegs) {
1517 if (VisitedRegs.
count(BaseReg)) {
1521 RatePrimaryRegister(
F, BaseReg, Regs, LU, HardwareLoopProfitable,
1528 size_t NumBaseParts =
F.getNumRegs();
1529 if (NumBaseParts > 1)
1534 C.NumBaseAdds += (
F.UnfoldedOffset.isNonZero());
1540 for (
const LSRFixup &Fixup : LU.Fixups) {
1541 if (
Fixup.Offset.isCompatibleImmediate(
F.BaseOffset)) {
1542 Immediate
Offset =
Fixup.Offset.addUnsigned(
F.BaseOffset);
1546 else if (
Offset.isNonZero())
1548 APInt(64,
Offset.getKnownMinValue(),
true).getSignificantBits();
1552 if (LU.Kind == LSRUse::Address &&
Offset.isNonZero() &&
1563 if (!
valueOr(Opts->lsr_insns_cost,
true)) {
1573 if (
C.NumRegs > TTIRegNum) {
1576 if (PrevNumRegs > TTIRegNum)
1577 C.Insns += (
C.NumRegs - PrevNumRegs);
1579 C.Insns += (
C.NumRegs - TTIRegNum);
1592 if (LU.Kind == LSRUse::ICmpZero && !
F.hasZeroEnd() &&
1596 C.Insns += (
C.AddRecCost - PrevAddRecCost);
1599 if (LU.Kind != LSRUse::ICmpZero)
1600 C.Insns +=
C.NumBaseAdds - PrevNumBaseAdds;
1606 C.Insns = std::numeric_limits<unsigned>::max();
1607 C.NumRegs = std::numeric_limits<unsigned>::max();
1608 C.AddRecCost = std::numeric_limits<unsigned>::max();
1609 C.NumIVMuls = std::numeric_limits<unsigned>::max();
1610 C.NumBaseAdds = std::numeric_limits<unsigned>::max();
1611 C.ImmCost = std::numeric_limits<unsigned>::max();
1612 C.SetupCost = std::numeric_limits<unsigned>::max();
1613 C.ScaleCost = std::numeric_limits<unsigned>::max();
1614 C.NumPrePostIndex = std::numeric_limits<unsigned>::max();
1618bool Cost::isLess(
const Cost &
Other)
const {
1619 if (Opts->lsr_insns_cost == BoolOrDefault::True &&
C.Insns !=
Other.C.Insns)
1620 return C.Insns <
Other.C.Insns;
1624#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1626 if (
valueOr(Opts->lsr_insns_cost,
true))
1627 OS <<
C.Insns <<
" instruction" << (
C.Insns == 1 ?
" " :
"s ");
1628 OS <<
C.NumRegs <<
" reg" << (
C.NumRegs == 1 ?
"" :
"s");
1629 if (
C.AddRecCost != 0)
1630 OS <<
", with addrec cost " <<
C.AddRecCost;
1631 if (
C.NumIVMuls != 0)
1632 OS <<
", plus " <<
C.NumIVMuls <<
" IV mul"
1633 << (
C.NumIVMuls == 1 ?
"" :
"s");
1634 if (
C.NumBaseAdds != 0)
1635 OS <<
", plus " <<
C.NumBaseAdds <<
" base add"
1636 << (
C.NumBaseAdds == 1 ?
"" :
"s");
1637 if (
C.ScaleCost != 0)
1638 OS <<
", plus " <<
C.ScaleCost <<
" scale cost";
1640 OS <<
", plus " <<
C.ImmCost <<
" imm cost";
1641 if (
C.SetupCost != 0)
1642 OS <<
", plus " <<
C.SetupCost <<
" setup cost";
1643 if (
C.NumPrePostIndex != 0)
1644 OS <<
", plus " <<
C.NumPrePostIndex <<
" pre/post-index";
1653bool LSRFixup::isUseFullyOutsideLoop(
const Loop *L)
const {
1656 for (
unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i)
1657 if (PN->getIncomingValue(i) == OperandValToReplace &&
1658 L->contains(PN->getIncomingBlock(i)))
1663 return !
L->contains(UserInst);
1666#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1667void LSRFixup::print(raw_ostream &OS)
const {
1672 Store->getOperand(0)->printAsOperand(OS,
false);
1678 OS <<
", OperandValToReplace=";
1681 for (
const Loop *PIL : PostIncLoops) {
1682 OS <<
", PostIncLoop=";
1683 PIL->getHeader()->printAsOperand(OS,
false);
1687 OS <<
", Offset=" <<
Offset;
1697bool LSRUse::HasFormulaWithSameRegs(
const Formula &
F)
const {
1699 if (
F.ScaledReg)
Key.push_back(
F.ScaledReg);
1706float LSRUse::getNotSelectedProbability(
const SCEV *
Reg)
const {
1708 for (
const Formula &
F : Formulae)
1709 if (
F.referencesReg(
Reg))
1711 return ((
float)(Formulae.size() - FNum)) / Formulae.size();
1716bool LSRUse::InsertFormula(
const Formula &
F,
const Loop &L) {
1717 assert(
F.isCanonical(L) &&
"Invalid canonical representation");
1719 if (!Formulae.empty() && RigidFormula)
1723 if (
F.ScaledReg)
Key.push_back(
F.ScaledReg);
1731 assert((!
F.ScaledReg || !
F.ScaledReg->isZero()) &&
1732 "Zero allocated in a scaled register!");
1734 for (
const SCEV *BaseReg :
F.BaseRegs)
1735 assert(!
BaseReg->isZero() &&
"Zero allocated in a base register!");
1739 Formulae.push_back(
F);
1750void LSRUse::DeleteFormula(Formula &
F) {
1751 if (&
F != &Formulae.back())
1753 Formulae.pop_back();
1757void LSRUse::RecomputeRegs(
size_t LUIdx, RegUseTracker &RegUses) {
1759 SmallPtrSet<const SCEV *, 4> OldRegs = std::move(Regs);
1761 for (
const Formula &
F : Formulae) {
1762 if (
F.ScaledReg) Regs.
insert(
F.ScaledReg);
1767 for (
const SCEV *S : OldRegs)
1769 RegUses.dropRegister(S, LUIdx);
1772#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1773void LSRUse::print(raw_ostream &OS)
const {
1774 OS <<
"LSR Use: Kind=";
1776 case Basic: OS <<
"Basic";
break;
1777 case Special: OS <<
"Special";
break;
1778 case ICmpZero: OS <<
"ICmpZero";
break;
1780 OS <<
"Address of ";
1784 OS << *AccessTy.MemTy;
1787 OS <<
" in addrspace(" << AccessTy.AddrSpace <<
')';
1790 OS <<
", Offsets={";
1791 bool NeedComma =
false;
1792 for (
const LSRFixup &Fixup : Fixups) {
1793 if (NeedComma) OS <<
',';
1799 if (AllFixupsOutsideLoop)
1800 OS <<
", all-fixups-outside-loop";
1802 if (AllFixupsUnconditional)
1803 OS <<
", all-fixups-unconditional";
1812 LSRUse::KindType Kind, MemAccessTy AccessTy,
1814 bool HasBaseReg, int64_t Scale,
1817 case LSRUse::Address: {
1818 int64_t FixedOffset =
1819 BaseOffset.isScalable() ? 0 : BaseOffset.getFixedValue();
1820 int64_t ScalableOffset =
1821 BaseOffset.isScalable() ? BaseOffset.getKnownMinValue() : 0;
1822 return TTI.isLegalAddressingMode(AccessTy.MemTy, BaseGV, FixedOffset,
1823 HasBaseReg, Scale, AccessTy.AddrSpace,
1824 Fixup, ScalableOffset);
1826 case LSRUse::ICmpZero:
1833 if (Scale != 0 && HasBaseReg && BaseOffset.isNonZero())
1838 if (Scale != 0 && Scale != -1)
1843 if (BaseOffset.isNonZero()) {
1846 if (BaseOffset.isScalable())
1856 BaseOffset = BaseOffset.getFixed(-(
uint64_t)BaseOffset.getFixedValue());
1857 return TTI.isLegalICmpImmediate(BaseOffset.getFixedValue());
1865 return !BaseGV && Scale == 0 && BaseOffset.isZero();
1867 case LSRUse::Special:
1869 return !BaseGV && (Scale == 0 || Scale == -1) && BaseOffset.isZero();
1876 Immediate MinOffset, Immediate MaxOffset,
1877 LSRUse::KindType Kind, MemAccessTy AccessTy,
1879 bool HasBaseReg, int64_t Scale) {
1880 if (BaseOffset.isNonZero() &&
1881 (BaseOffset.isScalable() != MinOffset.isScalable() ||
1882 BaseOffset.isScalable() != MaxOffset.isScalable()))
1885 int64_t
Base = BaseOffset.getKnownMinValue();
1886 int64_t Min = MinOffset.getKnownMinValue();
1887 int64_t Max = MaxOffset.getKnownMinValue();
1890 MinOffset = Immediate::get((
uint64_t)
Base + Min, MinOffset.isScalable());
1893 MaxOffset = Immediate::get((
uint64_t)
Base + Max, MaxOffset.isScalable());
1896 HasBaseReg, Scale) &&
1902 Immediate MinOffset, Immediate MaxOffset,
1903 LSRUse::KindType Kind, MemAccessTy AccessTy,
1904 const Formula &
F,
const Loop &L) {
1912 assert((
F.isCanonical(L) ||
F.Scale != 0));
1914 F.BaseGV,
F.BaseOffset,
F.HasBaseReg,
F.Scale);
1919 Immediate MaxOffset, LSRUse::KindType Kind,
1921 Immediate BaseOffset,
bool HasBaseReg, int64_t Scale) {
1924 BaseOffset, HasBaseReg, Scale) ||
1929 BaseGV, BaseOffset,
true, 0));
1933 Immediate MaxOffset, LSRUse::KindType Kind,
1934 MemAccessTy AccessTy,
const Formula &
F) {
1935 return isLegalUse(
TTI, MinOffset, MaxOffset, Kind, AccessTy,
F.BaseGV,
1936 F.BaseOffset,
F.HasBaseReg,
F.Scale);
1942 return TTI.isLegalAddScalableImmediate(
Offset.getKnownMinValue());
1944 return TTI.isLegalAddImmediate(
Offset.getFixedValue());
1948 const LSRUse &LU,
const Formula &
F) {
1950 if (LU.Kind == LSRUse::Address &&
TTI.LSRWithInstrQueries()) {
1951 for (
const LSRFixup &Fixup : LU.Fixups)
1953 (
F.BaseOffset + Fixup.Offset),
F.HasBaseReg,
1954 F.Scale, Fixup.UserInst))
1960 LU.AccessTy,
F.BaseGV,
F.BaseOffset,
F.HasBaseReg,
1965 const LSRUse &LU,
const Formula &
F,
1974 return F.Scale != 1;
1977 case LSRUse::Address: {
1979 int64_t ScalableMin = 0, ScalableMax = 0, FixedMin = 0, FixedMax = 0;
1980 if (
F.BaseOffset.isScalable()) {
1981 ScalableMin = (
F.BaseOffset + LU.MinOffset).getKnownMinValue();
1982 ScalableMax = (
F.BaseOffset + LU.MaxOffset).getKnownMinValue();
1984 FixedMin = (
F.BaseOffset + LU.MinOffset).getFixedValue();
1985 FixedMax = (
F.BaseOffset + LU.MaxOffset).getFixedValue();
1989 F.HasBaseReg,
F.Scale, LU.AccessTy.AddrSpace);
1992 F.HasBaseReg,
F.Scale, LU.AccessTy.AddrSpace);
1995 "Legal addressing mode has an illegal cost!");
1996 return std::max(ScaleCostMinOffset, ScaleCostMaxOffset);
1998 case LSRUse::ICmpZero:
2000 case LSRUse::Special:
2011 LSRUse::KindType Kind, MemAccessTy AccessTy,
2015 if (BaseOffset.isZero() && !BaseGV)
2020 int64_t Scale = Kind == LSRUse::ICmpZero ? -1 : 1;
2024 if (!HasBaseReg && Scale == 1) {
2034 if (HasBaseReg && BaseOffset.isNonZero() && Kind != LSRUse::ICmpZero &&
2036 Opts.lsr_drop_scaled_reg_for_vscale)
2046 Immediate MaxOffset, LSRUse::KindType Kind,
2047 MemAccessTy AccessTy,
const SCEV *S,
2050 if (S->
isZero())
return true;
2063 if (BaseOffset.isZero() && !BaseGV)
2066 if (BaseOffset.isScalable())
2071 int64_t Scale = Kind == LSRUse::ICmpZero ? -1 : 1;
2074 BaseOffset, HasBaseReg, Scale);
2091 const SCEV *IncExpr;
2093 IVInc(Instruction *U,
Value *O,
const SCEV *
E)
2094 : UserInst(
U), IVOperand(
O), IncExpr(
E) {}
2101 const SCEV *ExprBase =
nullptr;
2103 IVChain() =
default;
2104 IVChain(
const IVInc &Head,
const SCEV *
Base)
2105 : Incs(1, Head), ExprBase(
Base) {}
2110 const_iterator
begin()
const {
2112 return std::next(Incs.
begin());
2114 const_iterator
end()
const {
2119 bool hasIncs()
const {
return Incs.
size() >= 2; }
2128 bool isProfitableIncrement(
const SCEV *OperExpr,
2129 const SCEV *IncExpr,
2137 SmallPtrSet<Instruction*, 4> FarUsers;
2138 SmallPtrSet<Instruction*, 4> NearUsers;
2143 const ScalarOptions &Opts;
2145 ScalarEvolution &SE;
2148 AssumptionCache &AC;
2149 TargetLibraryInfo &TLI;
2150 const TargetTransformInfo &
TTI;
2152 MemorySSAUpdater *MSSAU;
2156 bool HardwareLoopProfitable =
false;
2157 bool ShouldPreserveLCSSA =
false;
2171 SetVector<int64_t, SmallVector<int64_t, 8>, SmallSet<int64_t, 8>> Factors;
2178 SmallSetVector<Type *, 4> Types;
2184 RegUseTracker RegUses;
2189 static const unsigned MaxChains = 8;
2195 SmallPtrSet<Use*, MaxChains> IVIncSet;
2198 SmallVector<llvm::WeakVH, 2> ScalarEvolutionIVs;
2204 SmallSetVector<Instruction *, 4> InsertedNonLCSSAInsts;
2206 void OptimizeShadowIV();
2207 bool FindIVUserForCond(Instruction *
Cond, IVStrideUse *&CondUse);
2209 ICmpInst *OptimizeLoopTermCondToEquality(ICmpInst *
Cond,
2210 IVStrideUse *&CondUse,
2211 BasicBlock *ExitingBlock);
2212 void OptimizeLoopTermCond();
2214 void ChainInstruction(Instruction *UserInst, Instruction *IVOper,
2215 SmallVectorImpl<ChainUsers> &ChainUsersVec);
2216 void FinalizeChain(IVChain &Chain);
2217 void CollectChains();
2218 void GenerateIVChain(
const IVChain &Chain,
2219 SmallVectorImpl<WeakTrackingVH> &DeadInsts);
2221 void CollectInterestingTypesAndFactors();
2222 void CollectFixupsAndInitialFormulae();
2225 using UseMapTy = DenseMap<LSRUse::SCEVUseKindPair, size_t>;
2228 bool reconcileNewOffset(LSRUse &LU, Immediate NewOffset,
bool HasBaseReg,
2229 LSRUse::KindType Kind, MemAccessTy AccessTy);
2231 std::pair<size_t, Immediate> getUse(
const SCEV *&Expr, LSRUse::KindType Kind,
2232 MemAccessTy AccessTy);
2234 void DeleteUse(LSRUse &LU,
size_t LUIdx);
2236 LSRUse *FindUseWithSimilarFormula(
const Formula &
F,
const LSRUse &OrigLU);
2238 void InsertInitialFormula(
const SCEV *S, LSRUse &LU,
size_t LUIdx);
2239 void InsertSupplementalFormula(
const SCEV *S, LSRUse &LU,
size_t LUIdx);
2240 void CountRegisters(
const Formula &
F,
size_t LUIdx);
2241 bool InsertFormula(LSRUse &LU,
unsigned LUIdx,
const Formula &
F);
2242 bool IsFixupExecutedEachIncrement(
const LSRFixup &LF)
const;
2244 void CollectLoopInvariantFixupsAndFormulae();
2246 void GenerateReassociations(LSRUse &LU,
unsigned LUIdx, Formula
Base,
2247 unsigned Depth = 0);
2249 void GenerateReassociationsImpl(LSRUse &LU,
unsigned LUIdx,
2251 size_t Idx,
bool IsScaledReg =
false);
2252 void GenerateCombinations(LSRUse &LU,
unsigned LUIdx, Formula
Base);
2253 void GenerateSymbolicOffsetsImpl(LSRUse &LU,
unsigned LUIdx,
2254 const Formula &
Base,
size_t Idx,
2255 bool IsScaledReg =
false);
2256 void GenerateSymbolicOffsets(LSRUse &LU,
unsigned LUIdx, Formula
Base);
2257 void GenerateConstantOffsetsImpl(LSRUse &LU,
unsigned LUIdx,
2258 const Formula &
Base,
2259 const SmallVectorImpl<Immediate> &Worklist,
2260 size_t Idx,
bool IsScaledReg =
false);
2261 void GenerateConstantOffsets(LSRUse &LU,
unsigned LUIdx, Formula
Base);
2262 void GenerateICmpZeroScales(LSRUse &LU,
unsigned LUIdx, Formula
Base);
2263 void GenerateScales(LSRUse &LU,
unsigned LUIdx, Formula
Base);
2264 void GenerateTruncates(LSRUse &LU,
unsigned LUIdx, Formula
Base);
2265 void GenerateCrossUseConstantOffsets();
2266 void GenerateAllReuseFormulae();
2268 void FilterOutUndesirableDedicatedRegisters();
2270 size_t EstimateSearchSpaceComplexity()
const;
2271 void NarrowSearchSpaceByDetectingSupersets();
2272 void NarrowSearchSpaceByCollapsingUnrolledCode();
2273 void NarrowSearchSpaceByRefilteringUndesirableDedicatedRegisters();
2274 void NarrowSearchSpaceByFilterFormulaWithSameScaledReg();
2275 void NarrowSearchSpaceByFilterPostInc();
2276 void NarrowSearchSpaceByMergingUsesOutsideLoop();
2277 void NarrowSearchSpaceByDeletingCostlyFormulas();
2278 void NarrowSearchSpaceByPickingWinnerRegs();
2279 void NarrowSearchSpaceUsingHeuristics();
2281 void SolveRecurse(SmallVectorImpl<const Formula *> &Solution,
2283 SmallVectorImpl<const Formula *> &Workspace,
2284 const Cost &CurCost,
2285 const SmallPtrSet<const SCEV *, 16> &CurRegs,
2286 DenseSet<const SCEV *> &VisitedRegs)
const;
2287 void Solve(SmallVectorImpl<const Formula *> &Solution)
const;
2291 const SmallVectorImpl<Instruction *> &Inputs)
const;
2294 const LSRUse &LU)
const;
2296 Value *Expand(
const LSRUse &LU,
const LSRFixup &LF,
const Formula &
F,
2298 SmallVectorImpl<WeakTrackingVH> &DeadInsts)
const;
2299 void RewriteForPHI(PHINode *PN,
const LSRUse &LU,
const LSRFixup &LF,
2301 SmallVectorImpl<WeakTrackingVH> &DeadInsts);
2302 void Rewrite(
const LSRUse &LU,
const LSRFixup &LF,
const Formula &
F,
2303 SmallVectorImpl<WeakTrackingVH> &DeadInsts);
2304 void ImplementSolution(
const SmallVectorImpl<const Formula *> &Solution);
2311 LSRInstance(
const ScalarOptions &Opts,
Loop *L, IVUsers &IU,
2312 ScalarEvolution &SE, DominatorTree &DT, LoopInfo &LI,
2313 const TargetTransformInfo &
TTI, AssumptionCache &AC,
2314 TargetLibraryInfo &TLI, MemorySSAUpdater *MSSAU,
2315 bool PreserveLCSSA);
2317 bool getChanged()
const {
return Changed; }
2318 const SmallVectorImpl<WeakVH> &getScalarEvolutionIVs()
const {
2319 return ScalarEvolutionIVs;
2322 void print_factors_and_types(raw_ostream &OS)
const;
2323 void print_fixups(raw_ostream &OS)
const;
2324 void print_uses(raw_ostream &OS)
const;
2325 void print(raw_ostream &OS)
const;
2333void LSRInstance::OptimizeShadowIV() {
2343 Type *DestTy =
nullptr;
2344 bool IsSigned =
false;
2360 DestTy = UCast->getDestTy();
2364 DestTy = SCast->getDestTy();
2366 if (!DestTy)
continue;
2386 if (Mantissa == -1)
continue;
2390 unsigned Entry, Latch;
2400 if (!Init)
continue;
2401 Constant *NewInit = ConstantFP::get(DestTy, IsSigned ?
2405 BinaryOperator *Incr =
2407 if (!Incr)
continue;
2408 if (Incr->
getOpcode() != Instruction::Add
2409 && Incr->
getOpcode() != Instruction::Sub)
2413 ConstantInt *
C =
nullptr;
2425 if (!
C->getValue().isStrictlyPositive())
2433 Constant *CFP = ConstantFP::get(DestTy,
C->getZExtValue());
2435 Incr->
getOpcode() == Instruction::Add ? Instruction::FAdd
2436 : Instruction::FSub,
2453bool LSRInstance::FindIVUserForCond(Instruction *
Cond, IVStrideUse *&CondUse) {
2454 for (IVStrideUse &U : IU)
2455 if (
U.getUser() ==
Cond) {
2467ICmpInst *LSRInstance::OptimizeLoopTermCondToEquality(
2468 ICmpInst *
Cond, IVStrideUse *&CondUse, BasicBlock *ExitingBlock) {
2469 if (
Cond->isEquality() || ExitingBlock !=
L->getLoopLatch())
2473 if (!
IV || !
IV->getType()->isIntegerTy() ||
IV->getParent() !=
L->getHeader())
2481 if (!Step || Step->
isZero())
2484 const SCEV *ExitCount = SE.
getExitCount(L, ExitingBlock);
2492 const APInt &StepValue = Step->getAPInt();
2493 unsigned RecurrencePeriodLog2 =
2498 const auto *ExitValue =
2501 *
Cond, ExitValue->getAPInt() + StepValue))
2504 LLVM_DEBUG(
dbgs() <<
" Rewriting loop exit to compare " << *
IV <<
" against "
2505 << *ExitValue <<
'\n');
2508 bool TrueContinues =
L->contains(TermBr->getSuccessor(0));
2509 assert(TrueContinues !=
L->contains(TermBr->getSuccessor(1)) &&
2510 "Expected exactly one in-loop successor");
2512 auto Pred = TrueContinues ? ICmpInst::ICMP_NE : ICmpInst::ICMP_EQ;
2513 auto *NewCond =
new ICmpInst(TermBr->getIterator(), Pred,
IV,
2514 ExitValue->getValue(),
"lsr.exitcond");
2515 NewCond->setDebugLoc(
Cond->getDebugLoc());
2516 TermBr->setCondition(NewCond);
2518 if (
Cond->use_empty()) {
2520 Cond->eraseFromParent();
2522 CondUse = &IU.AddUser(NewCond,
IV);
2577Instruction *LSRInstance::OptimizeMax(ICmpInst *
Cond, IVStrideUse *&CondUse) {
2592 const SCEV *IterationCount = SE.
getAddExpr(One, BackedgeTakenCount);
2593 if (IterationCount != SE.
getSCEV(Sel))
return Cond;
2599 const SCEVNAryExpr *
Max =
nullptr;
2601 Pred = ICmpInst::ICMP_SLE;
2604 Pred = ICmpInst::ICMP_SLT;
2607 Pred = ICmpInst::ICMP_ULT;
2616 if (
Max->getNumOperands() != 2)
2619 const SCEV *MaxLHS =
Max->getOperand(0);
2620 const SCEV *MaxRHS =
Max->getOperand(1);
2625 (ICmpInst::isTrueWhenEqual(Pred) ? !MaxLHS->
isZero() : (MaxLHS != One)))
2636 "Loop condition operand is an addrec in a different loop!");
2640 Value *NewRHS =
nullptr;
2641 if (ICmpInst::isTrueWhenEqual(Pred)) {
2645 if (BO1->isOne() && SE.
getSCEV(BO->getOperand(0)) == MaxRHS)
2646 NewRHS = BO->getOperand(0);
2649 if (BO1->isOne() && SE.
getSCEV(BO->getOperand(0)) == MaxRHS)
2650 NewRHS = BO->getOperand(0);
2658 NewRHS = SU->getValue();
2670 ICmpInst *NewCond =
new ICmpInst(
Cond->getIterator(), Pred,
2671 Cond->getOperand(0), NewRHS,
"scmp");
2675 Cond->replaceAllUsesWith(NewCond);
2678 Cond->eraseFromParent();
2680 if (
Cmp->use_empty()) {
2682 Cmp->eraseFromParent();
2689LSRInstance::OptimizeLoopTermCond() {
2690 SmallPtrSet<Instruction *, 4> PostIncs;
2705 SmallVector<BasicBlock*, 8> ExitingBlocks;
2706 L->getExitingBlocks(ExitingBlocks);
2714 for (BasicBlock *ExitingBlock : ExitingBlocks) {
2736 IVStrideUse *CondUse =
nullptr;
2737 if (!FindIVUserForCond(
Cond, CondUse))
2747 Cond = OptimizeMax(Cmp, CondUse);
2752 if (!DT.
dominates(ExitingBlock, LatchBlock))
2756 Cond = OptimizeLoopTermCondToEquality(Cmp, CondUse, ExitingBlock);
2760 if (LatchBlock != ExitingBlock)
2761 for (
const IVStrideUse &UI : IU)
2764 if (&UI != CondUse &&
2768 const SCEV *
A = IU.getStride(*CondUse, L);
2769 const SCEV *
B = IU.getStride(UI, L);
2770 if (!
A || !
B)
continue;
2779 if (
const SCEVConstant *
D =
2781 const ConstantInt *
C =
D->getValue();
2783 if (
C->isOne() ||
C->isMinusOne())
2784 goto decline_post_inc;
2786 if (
C->getValue().getSignificantBits() >= 64 ||
2787 C->getValue().isMinSignedValue())
2788 goto decline_post_inc;
2791 MemAccessTy AccessTy =
2793 int64_t Scale =
C->getSExtValue();
2797 AccessTy.AddrSpace))
2798 goto decline_post_inc;
2803 AccessTy.AddrSpace))
2804 goto decline_post_inc;
2809 LLVM_DEBUG(
dbgs() <<
" Change loop exiting icmp to use postinc iv: "
2817 if (
Cond->hasOneUse()) {
2823 Cond->setName(
L->getHeader()->getName() +
".termcond");
2845 IVIncInsertPos =
L->getLoopLatch()->getTerminator();
2846 for (Instruction *Inst : PostIncs)
2852bool LSRInstance::reconcileNewOffset(LSRUse &LU, Immediate NewOffset,
2853 bool HasBaseReg, LSRUse::KindType Kind,
2854 MemAccessTy AccessTy) {
2855 Immediate NewMinOffset = LU.MinOffset;
2856 Immediate NewMaxOffset = LU.MaxOffset;
2857 MemAccessTy NewAccessTy = AccessTy;
2862 if (LU.Kind != Kind)
2868 if (Kind == LSRUse::Address) {
2869 if (AccessTy.MemTy != LU.AccessTy.MemTy) {
2870 NewAccessTy = MemAccessTy::getUnknown(AccessTy.MemTy->
getContext(),
2871 AccessTy.AddrSpace);
2876 if (Immediate::isKnownLT(NewOffset, LU.MinOffset)) {
2878 LU.MaxOffset - NewOffset, HasBaseReg))
2880 NewMinOffset = NewOffset;
2881 }
else if (Immediate::isKnownGT(NewOffset, LU.MaxOffset)) {
2883 NewOffset - LU.MinOffset, HasBaseReg))
2885 NewMaxOffset = NewOffset;
2891 if (NewAccessTy.MemTy && NewAccessTy.MemTy->
isVoidTy() &&
2892 (NewMinOffset.isScalable() || NewMaxOffset.isScalable()))
2896 LU.MinOffset = NewMinOffset;
2897 LU.MaxOffset = NewMaxOffset;
2898 LU.AccessTy = NewAccessTy;
2905std::pair<size_t, Immediate> LSRInstance::getUse(
const SCEV *&Expr,
2906 LSRUse::KindType Kind,
2907 MemAccessTy AccessTy) {
2908 const SCEV *
Copy = Expr;
2911 Opts, ExprUse, SE, AccessTy.MemTy && AccessTy.MemTy->
isScalableTy());
2918 Offset = Immediate::getFixed(0);
2921 std::pair<UseMapTy::iterator, bool>
P =
2922 UseMap.
try_emplace(LSRUse::SCEVUseKindPair(Expr, Kind));
2925 size_t LUIdx =
P.first->second;
2926 LSRUse &LU =
Uses[LUIdx];
2927 if (reconcileNewOffset(LU,
Offset,
true, Kind, AccessTy))
2929 return std::make_pair(LUIdx,
Offset);
2933 size_t LUIdx =
Uses.size();
2934 P.first->second = LUIdx;
2935 Uses.push_back(LSRUse(Kind, AccessTy));
2936 LSRUse &LU =
Uses[LUIdx];
2940 return std::make_pair(LUIdx,
Offset);
2944void LSRInstance::DeleteUse(LSRUse &LU,
size_t LUIdx) {
2945 if (&LU != &
Uses.back())
2950 RegUses.swapAndDropUse(LUIdx,
Uses.size());
2956LSRInstance::FindUseWithSimilarFormula(
const Formula &OrigF,
2957 const LSRUse &OrigLU) {
2959 for (LSRUse &LU :
Uses) {
2965 if (&LU != &OrigLU && LU.Kind != LSRUse::ICmpZero &&
2966 LU.Kind == OrigLU.Kind && OrigLU.AccessTy == LU.AccessTy &&
2967 LU.HasFormulaWithSameRegs(OrigF)) {
2969 for (
const Formula &
F : LU.Formulae) {
2972 if (
F.BaseRegs == OrigF.BaseRegs &&
2973 F.ScaledReg == OrigF.ScaledReg &&
2974 F.BaseGV == OrigF.BaseGV &&
2975 F.Scale == OrigF.Scale &&
2976 F.UnfoldedOffset == OrigF.UnfoldedOffset) {
2977 if (
F.BaseOffset.isZero())
2992void LSRInstance::CollectInterestingTypesAndFactors() {
2993 SmallSetVector<const SCEV *, 4> Strides;
2997 for (
const IVStrideUse &U : IU) {
2998 const SCEV *Expr = IU.getExpr(U);
3016 }
while (!Worklist.
empty());
3020 for (SmallSetVector<const SCEV *, 4>::const_iterator
3022 for (SmallSetVector<const SCEV *, 4>::const_iterator NewStrideIter =
3023 std::next(
I); NewStrideIter !=
E; ++NewStrideIter) {
3024 const SCEV *OldStride = *
I;
3025 const SCEV *NewStride = *NewStrideIter;
3035 if (
const SCEVConstant *Factor =
3038 if (Factor->getAPInt().getSignificantBits() <= 64 && !Factor->isZero())
3039 Factors.insert(Factor->getAPInt().getSExtValue());
3040 }
else if (
const SCEVConstant *Factor =
3044 if (Factor->getAPInt().getSignificantBits() <= 64 && !Factor->isZero())
3045 Factors.insert(Factor->getAPInt().getSExtValue());
3051 if (Types.size() == 1)
3063 for(; OI != OE; ++OI) {
3082 return Trunc->getOperand(0);
3115 if (SubExpr->getSCEVType() ==
scAddExpr)
3118 if (SubExpr->getSCEVType() !=
scMulExpr)
3134bool IVChain::isProfitableIncrement(
const SCEV *OperExpr,
3135 const SCEV *IncExpr,
3136 ScalarEvolution &SE) {
3145 SmallPtrSet<const SCEV*, 8> Processed;
3163 if (!Chain.hasIncs())
3166 if (!
Users.empty()) {
3167 LLVM_DEBUG(
dbgs() <<
"Chain: " << *Chain.Incs[0].UserInst <<
" users:\n";
3169 :
Users) {
dbgs() <<
" " << *Inst <<
"\n"; });
3172 assert(!Chain.Incs.empty() &&
"empty IV chains are not allowed");
3181 && SE.
getSCEV(Chain.tailUserInst()) == Chain.Incs[0].IncExpr) {
3184 const SCEV *LastIncExpr =
nullptr;
3185 unsigned NumConstIncrements = 0;
3186 unsigned NumVarIncrements = 0;
3187 unsigned NumReusedIncrements = 0;
3189 if (
TTI.isProfitableLSRChainElement(Chain.Incs[0].UserInst))
3192 for (
const IVInc &Inc : Chain) {
3193 if (
TTI.isProfitableLSRChainElement(Inc.UserInst))
3195 if (Inc.IncExpr->isZero())
3201 ++NumConstIncrements;
3205 if (Inc.IncExpr == LastIncExpr)
3206 ++NumReusedIncrements;
3210 LastIncExpr = Inc.IncExpr;
3215 if (NumConstIncrements > 1)
3222 cost += NumVarIncrements;
3226 cost -= NumReusedIncrements;
3228 LLVM_DEBUG(
dbgs() <<
"Chain: " << *Chain.Incs[0].UserInst <<
" Cost: " << cost
3235void LSRInstance::ChainInstruction(Instruction *UserInst, Instruction *IVOper,
3236 SmallVectorImpl<ChainUsers> &ChainUsersVec) {
3240 const SCEV *
const OperExpr = SE.
getSCEV(NextIV);
3241 const SCEV *
const OperExprBase =
getExprBase(OperExpr);
3245 unsigned ChainIdx = 0, NChains = IVChainVec.size();
3246 const SCEV *LastIncExpr =
nullptr;
3247 for (; ChainIdx < NChains; ++ChainIdx) {
3248 IVChain &Chain = IVChainVec[ChainIdx];
3266 const SCEV *PrevExpr = SE.
getSCEV(PrevIV);
3267 const SCEV *IncExpr = SE.
getMinusSCEV(OperExpr, PrevExpr);
3273 Chain.isProfitableIncrement(OperExpr, IncExpr, SE)) {
3274 LastIncExpr = IncExpr;
3280 if (ChainIdx == NChains) {
3287 LastIncExpr = OperExpr;
3294 IVChainVec.push_back(IVChain(IVInc(UserInst, IVOper, LastIncExpr),
3296 ChainUsersVec.
resize(NChains);
3297 LLVM_DEBUG(
dbgs() <<
"IV Chain#" << ChainIdx <<
" Head: (" << *UserInst
3298 <<
") IV=" << *LastIncExpr <<
"\n");
3300 LLVM_DEBUG(
dbgs() <<
"IV Chain#" << ChainIdx <<
" Inc: (" << *UserInst
3301 <<
") IV+" << *LastIncExpr <<
"\n");
3303 IVChainVec[ChainIdx].add(IVInc(UserInst, IVOper, LastIncExpr));
3305 IVChain &Chain = IVChainVec[ChainIdx];
3307 SmallPtrSet<Instruction*,4> &NearUsers = ChainUsersVec[ChainIdx].NearUsers;
3309 if (!LastIncExpr->
isZero()) {
3310 ChainUsersVec[ChainIdx].FarUsers.insert_range(NearUsers);
3319 for (User *U : IVOper->
users()) {
3325 IVChain::const_iterator IncIter = Chain.Incs.begin();
3326 IVChain::const_iterator IncEnd = Chain.Incs.end();
3327 for( ; IncIter != IncEnd; ++IncIter) {
3328 if (IncIter->UserInst == OtherUse)
3331 if (IncIter != IncEnd)
3336 && IU.isIVUserOrOperand(OtherUse)) {
3339 NearUsers.
insert(OtherUse);
3344 ChainUsersVec[ChainIdx].FarUsers.
erase(UserInst);
3369void LSRInstance::CollectChains() {
3373 SmallVector<BasicBlock *,8> LatchPath;
3376 Rung->
getBlock() != LoopHeader; Rung = Rung->getIDom()) {
3382 for (BasicBlock *BB :
reverse(LatchPath)) {
3383 for (Instruction &
I : *BB) {
3389 if (IU.isEphemeral(&
I))
3399 for (
unsigned ChainIdx = 0, NChains = IVChainVec.size();
3400 ChainIdx < NChains; ++ChainIdx) {
3401 ChainUsersVec[ChainIdx].NearUsers.
erase(&
I);
3404 SmallPtrSet<Instruction*, 4> UniqueOperands;
3407 while (IVOpIter != IVOpEnd) {
3409 if (UniqueOperands.
insert(IVOpInst).second)
3410 ChainInstruction(&
I, IVOpInst, ChainUsersVec);
3411 IVOpIter =
findIVOperand(std::next(IVOpIter), IVOpEnd, L, SE);
3416 for (PHINode &PN :
L->getHeader()->phis()) {
3423 ChainInstruction(&PN, IncV, ChainUsersVec);
3426 unsigned ChainIdx = 0;
3427 for (
unsigned UsersIdx = 0, NChains = IVChainVec.size();
3428 UsersIdx < NChains; ++UsersIdx) {
3431 ChainUsersVec[UsersIdx].FarUsers, SE,
TTI))
3434 if (ChainIdx != UsersIdx)
3435 IVChainVec[ChainIdx] = IVChainVec[UsersIdx];
3436 FinalizeChain(IVChainVec[ChainIdx]);
3439 IVChainVec.resize(ChainIdx);
3442void LSRInstance::FinalizeChain(IVChain &Chain) {
3443 assert(!Chain.Incs.empty() &&
"empty IV chains are not allowed");
3444 LLVM_DEBUG(
dbgs() <<
"Final Chain: " << *Chain.Incs[0].UserInst <<
"\n");
3446 for (
const IVInc &Inc : Chain) {
3448 auto UseI =
find(Inc.UserInst->operands(), Inc.IVOperand);
3449 assert(UseI != Inc.UserInst->op_end() &&
"cannot find IV operand");
3450 IVIncSet.insert(UseI);
3459 Immediate IncOffset = Immediate::getZero();
3468 C->getSignificantBits() > 64)
3470 IncOffset = Immediate::getScalable(
C->getSExtValue());
3478 nullptr, IncOffset,
false))
3486void LSRInstance::GenerateIVChain(
const IVChain &Chain,
3487 SmallVectorImpl<WeakTrackingVH> &DeadInsts) {
3490 const IVInc &Head = Chain.Incs[0];
3495 Value *IVSrc =
nullptr;
3496 while (IVOpIter != IVOpEnd) {
3507 if (SE.
getSCEV(*IVOpIter) == Head.IncExpr
3508 || SE.
getSCEV(IVSrc) == Head.IncExpr) {
3511 IVOpIter =
findIVOperand(std::next(IVOpIter), IVOpEnd, L, SE);
3513 if (IVOpIter == IVOpEnd) {
3515 LLVM_DEBUG(
dbgs() <<
"Concealed chain head: " << *Head.UserInst <<
"\n");
3518 assert(IVSrc &&
"Failed to find IV chain source");
3523 const SCEV *LeftOverExpr =
nullptr;
3524 const SCEV *Accum = SE.
getZero(IntTy);
3528 for (
const IVInc &Inc : Chain) {
3531 InsertPt =
L->getLoopLatch()->getTerminator();
3535 Value *IVOper = IVSrc;
3536 if (!Inc.IncExpr->isZero()) {
3541 LeftOverExpr = LeftOverExpr
3547 bool FoundBase =
false;
3548 for (
auto [MapScev, MapIVOper] :
reverse(Bases)) {
3549 const SCEV *Remainder = SE.
getMinusSCEV(Accum, MapScev);
3551 if (!Remainder->
isZero()) {
3553 Value *IncV =
Rewriter.expandCodeFor(Remainder, IntTy, InsertPt);
3554 const SCEV *IVOperExpr =
3556 IVOper =
Rewriter.expandCodeFor(IVOperExpr, IVTy, InsertPt);
3565 if (!FoundBase && LeftOverExpr && !LeftOverExpr->
isZero()) {
3568 Value *IncV =
Rewriter.expandCodeFor(LeftOverExpr, IntTy, InsertPt);
3571 IVOper =
Rewriter.expandCodeFor(IVOperExpr, IVTy, InsertPt);
3576 assert(IVTy == IVOper->
getType() &&
"inconsistent IV increment type");
3579 LeftOverExpr =
nullptr;
3583 if (IVTy != OperTy) {
3585 "cannot extend a chained IV");
3587 IVOper = Builder.CreateTruncOrBitCast(IVOper, OperTy,
"lsr.chain");
3589 Inc.UserInst->replaceUsesOfWith(Inc.IVOperand, IVOper);
3596 for (PHINode &Phi :
L->getHeader()->phis()) {
3600 Phi.getIncomingValueForBlock(
L->getLoopLatch()));
3603 Value *IVOper = IVSrc;
3605 if (IVTy != PostIncTy) {
3607 IRBuilder<> Builder(
L->getLoopLatch()->getTerminator());
3608 Builder.SetCurrentDebugLocation(PostIncV->
getDebugLoc());
3609 IVOper = Builder.CreatePointerCast(IVSrc, PostIncTy,
"lsr.chain");
3611 Phi.replaceUsesOfWith(PostIncV, IVOper);
3617void LSRInstance::CollectFixupsAndInitialFormulae() {
3618 CondBrInst *ExitBranch =
nullptr;
3619 bool SaveCmp =
TTI.
canSaveCmp(L, &ExitBranch, &SE, &LI, &DT, &AC, &TLI);
3622 SmallPtrSet<const SCEV *, 16> Regs;
3623 DenseSet<const SCEV *> VisitedRegs;
3624 DenseSet<size_t> VisitedLSRUse;
3626 for (
const IVStrideUse &U : IU) {
3631 assert(UseI != UserInst->
op_end() &&
"cannot find IV operand");
3632 if (IVIncSet.count(UseI)) {
3633 LLVM_DEBUG(
dbgs() <<
"Use is in profitable chain: " << **UseI <<
'\n');
3637 LSRUse::KindType
Kind = LSRUse::Basic;
3638 MemAccessTy AccessTy;
3640 Kind = LSRUse::Address;
3644 const SCEV *S = IU.getExpr(U);
3660 if (CI->isEquality()) {
3663 Value *
NV = CI->getOperand(1);
3664 if (NV ==
U.getOperandValToReplace()) {
3665 CI->setOperand(1, CI->getOperand(0));
3666 CI->setOperand(0, NV);
3667 NV = CI->getOperand(1);
3674 (!
NV->getType()->isPointerTy() ||
3681 Kind = LSRUse::ICmpZero;
3683 }
else if (
L->isLoopInvariant(NV) &&
3686 !
NV->getType()->isPointerTy()) {
3697 Kind = LSRUse::ICmpZero;
3704 for (
size_t i = 0, e = Factors.size(); i != e; ++i)
3705 if (Factors[i] != -1)
3706 Factors.insert(-(
uint64_t)Factors[i]);
3712 std::pair<size_t, Immediate>
P = getUse(S, Kind, AccessTy);
3713 size_t LUIdx =
P.first;
3715 LSRUse &LU =
Uses[LUIdx];
3718 LSRFixup &LF = LU.getNewFixup();
3719 LF.UserInst = UserInst;
3720 LF.OperandValToReplace =
U.getOperandValToReplace();
3721 LF.PostIncLoops = TmpPostIncLoops;
3723 LU.AllFixupsOutsideLoop &= LF.isUseFullyOutsideLoop(L);
3724 LU.AllFixupsUnconditional &= IsFixupExecutedEachIncrement(LF);
3727 if (!VisitedLSRUse.
count(LUIdx) && !LF.isUseFullyOutsideLoop(L)) {
3729 F.initialMatch(S, L, SE);
3730 BaselineCost.RateFormula(
F, Regs, VisitedRegs, LU,
3731 HardwareLoopProfitable);
3732 VisitedLSRUse.
insert(LUIdx);
3736 if (LU.Formulae.empty()) {
3737 InsertInitialFormula(S, LU, LUIdx);
3738 CountRegisters(LU.Formulae.back(), LUIdx);
3747void LSRInstance::InsertInitialFormula(
const SCEV *S, LSRUse &LU,
3751 LU.RigidFormula =
true;
3754 F.initialMatch(S, L, SE);
3755 bool Inserted = InsertFormula(LU, LUIdx,
F);
3756 assert(Inserted &&
"Initial formula already exists!"); (void)Inserted;
3762LSRInstance::InsertSupplementalFormula(
const SCEV *S,
3763 LSRUse &LU,
size_t LUIdx) {
3765 F.BaseRegs.push_back(S);
3766 F.HasBaseReg =
true;
3767 bool Inserted = InsertFormula(LU, LUIdx,
F);
3768 assert(Inserted &&
"Supplemental formula already exists!"); (void)Inserted;
3772void LSRInstance::CountRegisters(
const Formula &
F,
size_t LUIdx) {
3774 RegUses.countRegister(
F.ScaledReg, LUIdx);
3775 for (
const SCEV *BaseReg :
F.BaseRegs)
3776 RegUses.countRegister(BaseReg, LUIdx);
3781bool LSRInstance::InsertFormula(LSRUse &LU,
unsigned LUIdx,
const Formula &
F) {
3784 "Formula is illegal");
3786 if (!LU.InsertFormula(
F, *L))
3789 CountRegisters(
F, LUIdx);
3795bool LSRInstance::IsFixupExecutedEachIncrement(
const LSRFixup &LF)
const {
3807LSRInstance::CollectLoopInvariantFixupsAndFormulae() {
3809 SmallPtrSet<const SCEV *, 32> Visited;
3816 while (!Worklist.
empty()) {
3820 if (!Visited.
insert(S).second)
3831 const Value *
V = US->getValue();
3834 if (
L->contains(Inst))
continue;
3838 for (
const Use &U :
V->uses()) {
3848 if (UserInst->
getParent()->getParent() !=
L->getHeader()->getParent())
3870 bool HasIncompatibleEHPTerminatedBlock =
false;
3872 for (
unsigned int I = 0;
I < PhiNode->getNumIncomingValues();
I++) {
3873 if (PhiNode->getIncomingValue(
I) == ExpectedValue) {
3874 if (PhiNode->getIncomingBlock(
I)->getTerminator()->isEHPad()) {
3875 HasIncompatibleEHPTerminatedBlock =
true;
3880 if (HasIncompatibleEHPTerminatedBlock) {
3903 unsigned OtherIdx = !
U.getOperandNo();
3904 Value *OtherOp = ICI->getOperand(OtherIdx);
3914 std::pair<size_t, Immediate>
P =
3915 getUse(S, LSRUse::Basic, MemAccessTy());
3916 size_t LUIdx =
P.first;
3918 LSRUse &LU =
Uses[LUIdx];
3919 LSRFixup &LF = LU.getNewFixup();
3920 LF.UserInst =
const_cast<Instruction *
>(UserInst);
3921 LF.OperandValToReplace =
U;
3923 LU.AllFixupsOutsideLoop &= LF.isUseFullyOutsideLoop(L);
3924 LU.AllFixupsUnconditional &= IsFixupExecutedEachIncrement(LF);
3925 InsertSupplementalFormula(US, LU, LUIdx);
3926 CountRegisters(LU.Formulae.back(),
Uses.size() - 1);
3942 unsigned Depth = 0) {
3949 for (
const SCEV *S :
Add->operands()) {
3956 const SCEV *Start, *Step;
3961 if (Start->isZero())
3970 Remainder =
nullptr;
3972 if (Remainder != Start) {
3994 LSRUse &LU,
const SCEV *S,
const Loop *L,
3996 if (LU.Kind != LSRUse::Address ||
3997 !LU.AccessTy.getType()->isIntOrIntVectorTy())
4003 if (
TTI.isIndexedLoadLegal(
TTI.MIM_PostInc, S->
getType()) ||
4012void LSRInstance::GenerateReassociationsImpl(LSRUse &LU,
unsigned LUIdx,
4013 const Formula &
Base,
4014 unsigned Depth,
size_t Idx,
4024 const SCEV *Remainder =
CollectSubexprs(BaseReg,
nullptr, AddOps, L, SE);
4028 if (AddOps.
size() == 1)
4042 LU.AccessTy, *J,
Base.getNumRegs() > 1))
4047 InnerAddOps.append(std::next(J), std::as_const(AddOps).
end());
4051 if (InnerAddOps.size() == 1 &&
4053 LU.AccessTy, InnerAddOps[0],
Base.getNumRegs() > 1))
4056 const SCEV *InnerSum = SE.
getAddExpr(InnerAddOps);
4061 if (
F.UnfoldedOffset.isNonZero() &&
F.UnfoldedOffset.isScalable())
4070 Immediate::getFixed((
uint64_t)
F.UnfoldedOffset.getFixedValue() +
4073 F.ScaledReg =
nullptr;
4076 F.BaseRegs.erase(
F.BaseRegs.begin() + Idx);
4077 }
else if (IsScaledReg)
4078 F.ScaledReg = InnerSum;
4080 F.BaseRegs[
Idx] = InnerSum;
4088 Immediate::getFixed((
uint64_t)
F.UnfoldedOffset.getFixedValue() +
4091 F.BaseRegs.push_back(*J);
4096 if (InsertFormula(LU, LUIdx,
F))
4103 GenerateReassociations(LU, LUIdx, LU.Formulae.back(),
4109void LSRInstance::GenerateReassociations(LSRUse &LU,
unsigned LUIdx,
4111 assert(
Base.isCanonical(*L) &&
"Input must be in the canonical form");
4116 for (
size_t i = 0, e =
Base.BaseRegs.size(); i != e; ++i)
4117 GenerateReassociationsImpl(LU, LUIdx,
Base,
Depth, i);
4119 if (
Base.Scale == 1)
4120 GenerateReassociationsImpl(LU, LUIdx,
Base,
Depth,
4126void LSRInstance::GenerateCombinations(LSRUse &LU,
unsigned LUIdx,
4129 if (
Base.BaseRegs.size() + (
Base.Scale == 1) +
4130 (
Base.UnfoldedOffset.isNonZero()) <=
4138 Formula NewBase =
Base;
4139 NewBase.BaseRegs.clear();
4140 Type *CombinedIntegerType =
nullptr;
4141 for (
const SCEV *BaseReg :
Base.BaseRegs) {
4144 if (!CombinedIntegerType)
4146 Ops.push_back(BaseReg);
4149 NewBase.BaseRegs.push_back(BaseReg);
4153 if (
Ops.size() == 0)
4158 auto GenerateFormula = [&](
const SCEV *Sum) {
4159 Formula
F = NewBase;
4167 F.BaseRegs.push_back(Sum);
4169 (void)InsertFormula(LU, LUIdx,
F);
4173 if (
Ops.size() > 1) {
4180 if (NewBase.UnfoldedOffset.isNonZero() && NewBase.UnfoldedOffset.isFixed()) {
4181 assert(CombinedIntegerType &&
"Missing a type for the unfolded offset");
4183 NewBase.UnfoldedOffset.getFixedValue(),
true));
4184 NewBase.UnfoldedOffset = Immediate::getFixed(0);
4190void LSRInstance::GenerateSymbolicOffsetsImpl(LSRUse &LU,
unsigned LUIdx,
4191 const Formula &
Base,
size_t Idx,
4195 if (
G->isZero() || !GV)
4199 if (!
isLegalUse(
TTI, LU.MinOffset, LU.MaxOffset, LU.Kind, LU.AccessTy,
F))
4204 F.BaseRegs[
Idx] =
G;
4205 (void)InsertFormula(LU, LUIdx,
F);
4209void LSRInstance::GenerateSymbolicOffsets(LSRUse &LU,
unsigned LUIdx,
4212 if (
Base.BaseGV)
return;
4214 for (
size_t i = 0, e =
Base.BaseRegs.size(); i != e; ++i)
4215 GenerateSymbolicOffsetsImpl(LU, LUIdx,
Base, i);
4216 if (
Base.Scale == 1)
4217 GenerateSymbolicOffsetsImpl(LU, LUIdx,
Base, -1,
4222void LSRInstance::GenerateConstantOffsetsImpl(
4223 LSRUse &LU,
unsigned LUIdx,
const Formula &
Base,
4224 const SmallVectorImpl<Immediate> &Worklist,
size_t Idx,
bool IsScaledReg) {
4226 auto GenerateOffset = [&](
const SCEV *
G, Immediate
Offset) {
4228 if (!
Base.BaseOffset.isCompatibleImmediate(
Offset))
4230 F.BaseOffset =
Base.BaseOffset.subUnsigned(
Offset);
4232 if (
isLegalUse(
TTI, LU.MinOffset, LU.MaxOffset, LU.Kind, LU.AccessTy,
F)) {
4234 const SCEV *NewOffset =
Offset.getSCEV(SE,
G->getType());
4240 F.ScaledReg =
nullptr;
4242 F.deleteBaseReg(
F.BaseRegs[Idx]);
4244 }
else if (IsScaledReg)
4247 F.BaseRegs[
Idx] = NewG;
4249 (void)InsertFormula(LU, LUIdx,
F);
4264 const APInt *StepInt;
4269 for (Immediate
Offset : Worklist) {
4271 Offset = Immediate::getFixed(
Offset.getFixedValue() - Step);
4277 for (Immediate
Offset : Worklist)
4284 if (
G->isZero() ||
Imm.isZero() ||
4285 !
Base.BaseOffset.isCompatibleImmediate(
Imm))
4288 F.BaseOffset =
F.BaseOffset.addUnsigned(
Imm);
4289 if (!
isLegalUse(
TTI, LU.MinOffset, LU.MaxOffset, LU.Kind, LU.AccessTy,
F))
4294 F.BaseRegs[
Idx] =
G;
4299 (void)InsertFormula(LU, LUIdx,
F);
4303void LSRInstance::GenerateConstantOffsets(LSRUse &LU,
unsigned LUIdx,
4309 if (LU.MaxOffset != LU.MinOffset)
4312 for (
size_t i = 0, e =
Base.BaseRegs.size(); i != e; ++i)
4313 GenerateConstantOffsetsImpl(LU, LUIdx,
Base, Worklist, i);
4314 if (
Base.Scale == 1)
4315 GenerateConstantOffsetsImpl(LU, LUIdx,
Base, Worklist, -1,
4321void LSRInstance::GenerateICmpZeroScales(LSRUse &LU,
unsigned LUIdx,
4323 if (LU.Kind != LSRUse::ICmpZero)
return;
4331 if (LU.MinOffset != LU.MaxOffset)
return;
4334 if (
Base.ScaledReg &&
Base.ScaledReg->getType()->isPointerTy())
4336 for (
const SCEV *BaseReg :
Base.BaseRegs)
4337 if (
BaseReg->getType()->isPointerTy())
4339 assert(!
Base.BaseGV &&
"ICmpZero use is not legal!");
4342 for (int64_t Factor : Factors) {
4347 if (
Base.BaseOffset.isMin() && Factor == -1)
4350 if (
Base.BaseOffset.isNonZero() &&
Base.BaseOffset.isScalable())
4352 Immediate NewBaseOffset =
Base.BaseOffset.mulUnsigned(Factor);
4353 assert(Factor != 0 &&
"Zero factor not expected!");
4354 if (NewBaseOffset.getFixedValue() / Factor !=
4355 Base.BaseOffset.getFixedValue())
4363 Immediate
Offset = LU.MinOffset;
4364 if (
Offset.isMin() && Factor == -1)
4367 if (
Offset.getFixedValue() / Factor != LU.MinOffset.getFixedValue())
4375 F.BaseOffset = NewBaseOffset;
4382 F.BaseOffset =
F.BaseOffset.addUnsigned(
Offset).subUnsigned(LU.MinOffset);
4384 const SCEV *FactorS = SE.
getConstant(IntTy, Factor);
4387 for (
size_t i = 0, e =
F.BaseRegs.size(); i != e; ++i) {
4401 if (
F.UnfoldedOffset.isNonZero()) {
4402 if (
F.UnfoldedOffset.isMin() && Factor == -1)
4404 F.UnfoldedOffset =
F.UnfoldedOffset.mulUnsigned(Factor);
4405 if (
F.UnfoldedOffset.getFixedValue() / Factor !=
4406 Base.UnfoldedOffset.getFixedValue())
4410 IntTy,
F.UnfoldedOffset.getFixedValue()))
4415 (void)InsertFormula(LU, LUIdx,
F);
4422void LSRInstance::GenerateScales(LSRUse &LU,
unsigned LUIdx, Formula
Base) {
4429 if (
Base.Scale != 0 && !
Base.unscale())
4432 assert(
Base.Scale == 0 &&
"unscale did not did its job!");
4435 for (int64_t Factor : Factors) {
4436 Base.Scale = Factor;
4437 Base.HasBaseReg =
Base.BaseRegs.size() > 1;
4439 if (!
isLegalUse(
TTI, LU.MinOffset, LU.MaxOffset, LU.Kind, LU.AccessTy,
4443 if (LU.Kind == LSRUse::Basic &&
4444 isLegalUse(
TTI, LU.MinOffset, LU.MaxOffset, LSRUse::Special,
4445 LU.AccessTy,
Base) &&
4446 LU.AllFixupsOutsideLoop)
4447 LU.Kind = LSRUse::Special;
4453 if (LU.Kind == LSRUse::ICmpZero && !
Base.HasBaseReg &&
4454 Base.BaseOffset.isZero() && !
Base.BaseGV)
4457 for (
size_t i = 0, e =
Base.BaseRegs.size(); i != e; ++i) {
4459 if (AR && (AR->
getLoop() == L || LU.AllFixupsOutsideLoop)) {
4460 const SCEV *FactorS = SE.
getConstant(IntTy, Factor);
4465 if (
const SCEV *Quotient =
getExactSDiv(AR, FactorS, SE,
true))
4466 if (!Quotient->isZero()) {
4469 F.ScaledReg = Quotient;
4470 F.deleteBaseReg(
F.BaseRegs[i]);
4474 if (
F.Scale == 1 && (
F.BaseRegs.empty() ||
4475 (AR->
getLoop() != L && LU.AllFixupsOutsideLoop)))
4479 if (
F.Scale == 1 && LU.AllFixupsOutsideLoop)
4481 (void)InsertFormula(LU, LUIdx,
F);
4497 const SCEV *Result =
nullptr;
4498 for (
auto &L :
Loops) {
4502 if (!New || (Result && New != Result))
4507 assert(Result &&
"failed to create expression");
4512void LSRInstance::GenerateTruncates(LSRUse &LU,
unsigned LUIdx, Formula
Base) {
4514 if (
Base.BaseGV)
return;
4524 if (
Base.ScaledReg &&
Base.ScaledReg->getType()->isPointerTy())
4527 [](
const SCEV *S) { return S->getType()->isPointerTy(); }))
4531 for (
auto &LF : LU.Fixups)
4532 Loops.push_back(LF.PostIncLoops);
4534 for (
Type *SrcTy : Types) {
4543 const SCEV *NewScaledReg =
4545 if (!NewScaledReg || NewScaledReg->
isZero())
4547 F.ScaledReg = NewScaledReg;
4549 bool HasZeroBaseReg =
false;
4550 for (
const SCEV *&BaseReg :
F.BaseRegs) {
4551 const SCEV *NewBaseReg =
4553 if (!NewBaseReg || NewBaseReg->
isZero()) {
4554 HasZeroBaseReg =
true;
4564 if (!
F.hasRegsUsedByUsesOtherThan(LUIdx, RegUses))
4568 (void)InsertFormula(LU, LUIdx,
F);
4581 const SCEV *OrigReg;
4583 WorkItem(
size_t LI, Immediate
I,
const SCEV *R)
4584 : LUIdx(LI),
Imm(
I), OrigReg(
R) {}
4586 void print(raw_ostream &OS)
const;
4592#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
4593void WorkItem::print(raw_ostream &OS)
const {
4594 OS <<
"in formulae referencing " << *OrigReg <<
" in use " << LUIdx
4595 <<
" , add offset " <<
Imm;
4605void LSRInstance::GenerateCrossUseConstantOffsets() {
4607 using ImmMapTy = std::map<Immediate, const SCEV *, KeyOrderTargetImmediate>;
4609 DenseMap<const SCEV *, ImmMapTy>
Map;
4610 DenseMap<const SCEV *, SmallBitVector> UsedByIndicesMap;
4612 for (
const SCEV *Use : RegUses) {
4616 auto Pair =
Map.try_emplace(
Reg);
4619 Pair.first->second.insert(std::make_pair(
Imm, Use));
4620 UsedByIndicesMap[
Reg] |= RegUses.getUsedByIndices(Use);
4627 SmallSet<std::pair<size_t, Immediate>, 32, KeyOrderSizeTAndImmediate>
4629 for (
const SCEV *
Reg : Sequence) {
4630 const ImmMapTy &Imms =
Map.find(
Reg)->second;
4633 if (Imms.size() == 1)
4637 for (
const auto &Entry
4639 <<
' ' <<
Entry.first;
4643 for (ImmMapTy::const_iterator J = Imms.begin(), JE = Imms.end();
4645 const SCEV *OrigReg = J->second;
4647 Immediate JImm = J->first;
4648 const SmallBitVector &UsedByIndices = RegUses.getUsedByIndices(OrigReg);
4651 UsedByIndicesMap[
Reg].
count() == 1) {
4659 Immediate
First = Imms.begin()->first;
4660 Immediate
Last = std::prev(Imms.end())->first;
4661 if (!
First.isCompatibleImmediate(
Last)) {
4668 bool Scalable =
First.isScalable() ||
Last.isScalable();
4669 int64_t FI =
First.getKnownMinValue();
4670 int64_t LI =
Last.getKnownMinValue();
4673 int64_t Avg = (FI & LI) + ((FI ^ LI) >> 1);
4676 Avg = Avg + ((FI ^ LI) & ((
uint64_t)Avg >> 63));
4677 ImmMapTy::const_iterator OtherImms[] = {
4678 Imms.begin(), std::prev(Imms.end()),
4679 Imms.lower_bound(Immediate::get(Avg, Scalable))};
4680 for (
const auto &M : OtherImms) {
4681 if (M == J || M == JE)
continue;
4682 if (!JImm.isCompatibleImmediate(
M->first))
4686 Immediate
Imm = JImm.subUnsigned(
M->first);
4687 for (
unsigned LUIdx : UsedByIndices.
set_bits())
4689 if (UniqueItems.
insert(std::make_pair(LUIdx,
Imm)).second)
4697 UsedByIndicesMap.
clear();
4698 UniqueItems.
clear();
4701 for (
const WorkItem &WI : WorkItems) {
4702 size_t LUIdx = WI.LUIdx;
4703 LSRUse &LU =
Uses[LUIdx];
4704 Immediate
Imm = WI.Imm;
4705 const SCEV *OrigReg = WI.OrigReg;
4708 const SCEV *NegImmS =
Imm.getNegativeSCEV(SE, IntTy);
4712 for (
size_t L = 0, LE = LU.Formulae.size(); L != LE; ++L) {
4713 Formula
F = LU.Formulae[
L];
4720 if (
F.ScaledReg == OrigReg) {
4721 if (!
F.BaseOffset.isCompatibleImmediate(
Imm))
4723 Immediate
Offset =
F.BaseOffset.addUnsigned(
Imm.mulUnsigned(
F.Scale));
4725 const SCEV *S =
Offset.getNegativeSCEV(SE, IntTy);
4726 if (
F.referencesReg(S))
4729 NewF.BaseOffset =
Offset;
4730 if (!
isLegalUse(
TTI, LU.MinOffset, LU.MaxOffset, LU.Kind, LU.AccessTy,
4733 NewF.ScaledReg = SE.
getAddExpr(NegImmS, NewF.ScaledReg);
4742 if (NewF.BaseOffset.isNonZero() && NewF.BaseOffset.isScalable())
4744 if (
C->getValue()->isNegative() !=
4745 (NewF.BaseOffset.isLessThanZero()) &&
4746 (
C->getAPInt().abs() * APInt(
BitWidth,
F.Scale))
4747 .ule(std::abs(NewF.BaseOffset.getFixedValue())))
4752 NewF.canonicalize(*this->L);
4753 (void)InsertFormula(LU, LUIdx, NewF);
4756 for (
size_t N = 0, NE =
F.BaseRegs.size();
N != NE; ++
N) {
4758 if (BaseReg != OrigReg)
4761 if (!NewF.BaseOffset.isCompatibleImmediate(
Imm) ||
4762 !NewF.UnfoldedOffset.isCompatibleImmediate(
Imm) ||
4763 !NewF.BaseOffset.isCompatibleImmediate(NewF.UnfoldedOffset))
4765 NewF.BaseOffset = NewF.BaseOffset.addUnsigned(
Imm);
4767 LU.Kind, LU.AccessTy, NewF)) {
4771 Immediate NewUnfoldedOffset = NewF.UnfoldedOffset.addUnsigned(
Imm);
4775 NewF.UnfoldedOffset = NewUnfoldedOffset;
4777 NewF.BaseRegs[
N] = SE.
getAddExpr(NegImmS, BaseReg);
4782 for (
const SCEV *NewReg : NewF.BaseRegs)
4784 if (NewF.BaseOffset.isNonZero() && NewF.BaseOffset.isScalable())
4786 if ((
C->getAPInt() + NewF.BaseOffset.getFixedValue())
4788 .slt(std::abs(NewF.BaseOffset.getFixedValue())) &&
4789 (
C->getAPInt() + NewF.BaseOffset.getFixedValue())
4792 NewF.BaseOffset.getFixedValue()))
4797 NewF.canonicalize(*this->L);
4798 (void)InsertFormula(LU, LUIdx, NewF);
4809LSRInstance::GenerateAllReuseFormulae() {
4812 for (
size_t LUIdx = 0, NumUses =
Uses.size(); LUIdx != NumUses; ++LUIdx) {
4813 LSRUse &LU =
Uses[LUIdx];
4814 for (
size_t i = 0, f = LU.Formulae.size(); i != f; ++i)
4815 GenerateReassociations(LU, LUIdx, LU.Formulae[i]);
4816 for (
size_t i = 0, f = LU.Formulae.size(); i != f; ++i)
4817 GenerateCombinations(LU, LUIdx, LU.Formulae[i]);
4819 for (
size_t LUIdx = 0, NumUses =
Uses.size(); LUIdx != NumUses; ++LUIdx) {
4820 LSRUse &LU =
Uses[LUIdx];
4821 for (
size_t i = 0, f = LU.Formulae.size(); i != f; ++i)
4822 GenerateSymbolicOffsets(LU, LUIdx, LU.Formulae[i]);
4823 for (
size_t i = 0, f = LU.Formulae.size(); i != f; ++i)
4824 GenerateConstantOffsets(LU, LUIdx, LU.Formulae[i]);
4825 for (
size_t i = 0, f = LU.Formulae.size(); i != f; ++i)
4826 GenerateICmpZeroScales(LU, LUIdx, LU.Formulae[i]);
4827 for (
size_t i = 0, f = LU.Formulae.size(); i != f; ++i)
4828 GenerateScales(LU, LUIdx, LU.Formulae[i]);
4830 for (
size_t LUIdx = 0, NumUses =
Uses.size(); LUIdx != NumUses; ++LUIdx) {
4831 LSRUse &LU =
Uses[LUIdx];
4832 for (
size_t i = 0, f = LU.Formulae.size(); i != f; ++i)
4833 GenerateTruncates(LU, LUIdx, LU.Formulae[i]);
4836 GenerateCrossUseConstantOffsets();
4839 "After generating reuse formulae:\n";
4840 print_uses(
dbgs()));
4845void LSRInstance::FilterOutUndesirableDedicatedRegisters() {
4846 DenseSet<const SCEV *> VisitedRegs;
4847 SmallPtrSet<const SCEV *, 16> Regs;
4848 SmallPtrSet<const SCEV *, 16> LoserRegs;
4850 bool ChangedFormulae =
false;
4855 using BestFormulaeTy = DenseMap<SmallVector<const SCEV *, 4>,
size_t>;
4857 BestFormulaeTy BestFormulae;
4859 for (
size_t LUIdx = 0, NumUses =
Uses.size(); LUIdx != NumUses; ++LUIdx) {
4860 LSRUse &LU =
Uses[LUIdx];
4865 for (
size_t FIdx = 0, NumForms = LU.Formulae.size();
4866 FIdx != NumForms; ++FIdx) {
4867 Formula &
F = LU.Formulae[FIdx];
4876 Cost CostF(Opts, L, SE,
TTI, AMK);
4878 CostF.RateFormula(
F, Regs, VisitedRegs, LU, HardwareLoopProfitable,
4880 if (CostF.isLoser()) {
4892 for (
const SCEV *
Reg :
F.BaseRegs) {
4893 if (RegUses.isRegUsedByUsesOtherThan(
Reg, LUIdx))
4897 RegUses.isRegUsedByUsesOtherThan(
F.ScaledReg, LUIdx))
4898 Key.push_back(
F.ScaledReg);
4903 std::pair<BestFormulaeTy::const_iterator, bool>
P =
4904 BestFormulae.insert(std::make_pair(
Key, FIdx));
4908 Formula &Best = LU.Formulae[
P.first->second];
4910 Cost CostBest(Opts, L, SE,
TTI, AMK);
4912 CostBest.RateFormula(Best, Regs, VisitedRegs, LU,
4913 HardwareLoopProfitable);
4914 if (CostF.isLess(CostBest))
4918 " in favor of formula ";
4919 Best.print(
dbgs());
dbgs() <<
'\n');
4922 ChangedFormulae =
true;
4924 LU.DeleteFormula(
F);
4932 LU.RecomputeRegs(LUIdx, RegUses);
4935 BestFormulae.clear();
4940 "After filtering out undesirable candidates:\n";
4948size_t LSRInstance::EstimateSearchSpaceComplexity()
const {
4950 for (
const LSRUse &LU :
Uses) {
4951 size_t FSize = LU.Formulae.size();
4952 if (FSize >= Opts.lsr_complexity_limit) {
4953 Power = Opts.lsr_complexity_limit;
4957 if (Power >= Opts.lsr_complexity_limit)
4966void LSRInstance::NarrowSearchSpaceByDetectingSupersets() {
4967 if (EstimateSearchSpaceComplexity() >= Opts.lsr_complexity_limit) {
4970 LLVM_DEBUG(
dbgs() <<
"Narrowing the search space by eliminating formulae "
4971 "which use a superset of registers used by other "
4974 for (
size_t LUIdx = 0, NumUses =
Uses.size(); LUIdx != NumUses; ++LUIdx) {
4975 LSRUse &LU =
Uses[LUIdx];
4977 for (
size_t i = 0, e = LU.Formulae.size(); i != e; ++i) {
4978 Formula &
F = LU.Formulae[i];
4979 if (
F.BaseOffset.isNonZero() &&
F.BaseOffset.isScalable())
4985 I =
F.BaseRegs.begin(),
E =
F.BaseRegs.end();
I !=
E; ++
I) {
4991 Immediate::getFixed(NewF.BaseOffset.getFixedValue() +
4992 (
uint64_t)
C->getValue()->getSExtValue());
4993 NewF.BaseRegs.erase(NewF.BaseRegs.begin() +
4994 (
I -
F.BaseRegs.begin()));
4995 if (LU.HasFormulaWithSameRegs(NewF)) {
4998 LU.DeleteFormula(
F);
5009 NewF.BaseRegs.erase(NewF.BaseRegs.begin() +
5010 (
I -
F.BaseRegs.begin()));
5011 if (LU.HasFormulaWithSameRegs(NewF)) {
5014 LU.DeleteFormula(
F);
5025 LU.RecomputeRegs(LUIdx, RegUses);
5034void LSRInstance::NarrowSearchSpaceByCollapsingUnrolledCode() {
5035 if (EstimateSearchSpaceComplexity() < Opts.lsr_complexity_limit)
5039 dbgs() <<
"The search space is too complex.\n"
5040 "Narrowing the search space by assuming that uses separated "
5041 "by a constant offset will use the same registers.\n");
5045 for (
size_t LUIdx = 0, NumUses =
Uses.size(); LUIdx != NumUses; ++LUIdx) {
5046 LSRUse &LU =
Uses[LUIdx];
5047 for (
const Formula &
F : LU.Formulae) {
5048 if (
F.BaseOffset.isZero() || (
F.Scale != 0 &&
F.Scale != 1))
5050 assert((LU.Kind == LSRUse::Address || LU.Kind == LSRUse::ICmpZero) &&
5051 "Only address and cmp uses expected to have nonzero BaseOffset");
5053 LSRUse *LUThatHas = FindUseWithSimilarFormula(
F, LU);
5057 if (!reconcileNewOffset(*LUThatHas,
F.BaseOffset,
false,
5058 LU.Kind, LU.AccessTy))
5063 LUThatHas->AllFixupsOutsideLoop &= LU.AllFixupsOutsideLoop;
5064 LUThatHas->AllFixupsUnconditional &= LU.AllFixupsUnconditional;
5067 for (LSRFixup &Fixup : LU.Fixups) {
5068 Fixup.Offset +=
F.BaseOffset;
5069 LUThatHas->pushFixup(Fixup);
5074 Type *FixupType = LUThatHas->Fixups[0].OperandValToReplace->getType();
5075 for (LSRFixup &Fixup : LUThatHas->Fixups)
5076 assert(
Fixup.OperandValToReplace->getType() == FixupType &&
5077 "Expected all fixups to have the same type");
5082 for (
size_t i = 0, e = LUThatHas->Formulae.size(); i != e; ++i) {
5083 Formula &
F = LUThatHas->Formulae[i];
5084 if (!
isLegalUse(
TTI, LUThatHas->MinOffset, LUThatHas->MaxOffset,
5085 LUThatHas->Kind, LUThatHas->AccessTy,
F)) {
5087 LUThatHas->DeleteFormula(
F);
5095 LUThatHas->RecomputeRegs(LUThatHas - &
Uses.front(), RegUses);
5098 DeleteUse(LU, LUIdx);
5111void LSRInstance::NarrowSearchSpaceByRefilteringUndesirableDedicatedRegisters(){
5112 if (EstimateSearchSpaceComplexity() >= Opts.lsr_complexity_limit) {
5115 LLVM_DEBUG(
dbgs() <<
"Narrowing the search space by re-filtering out "
5116 "undesirable dedicated registers.\n");
5118 FilterOutUndesirableDedicatedRegisters();
5133void LSRInstance::NarrowSearchSpaceByFilterFormulaWithSameScaledReg() {
5134 if (EstimateSearchSpaceComplexity() < Opts.lsr_complexity_limit)
5138 dbgs() <<
"The search space is too complex.\n"
5139 "Narrowing the search space by choosing the best Formula "
5140 "from the Formulae with the same Scale and ScaledReg.\n");
5143 using BestFormulaeTy = DenseMap<std::pair<const SCEV *, int64_t>,
size_t>;
5145 BestFormulaeTy BestFormulae;
5147 bool ChangedFormulae =
false;
5149 DenseSet<const SCEV *> VisitedRegs;
5150 SmallPtrSet<const SCEV *, 16> Regs;
5152 for (
size_t LUIdx = 0, NumUses =
Uses.size(); LUIdx != NumUses; ++LUIdx) {
5153 LSRUse &LU =
Uses[LUIdx];
5158 auto IsBetterThan = [&](Formula &FA, Formula &FB) {
5163 size_t FARegNum = 0;
5164 for (
const SCEV *
Reg : FA.BaseRegs) {
5165 const SmallBitVector &UsedByIndices = RegUses.getUsedByIndices(
Reg);
5166 FARegNum += (NumUses - UsedByIndices.
count() + 1);
5168 size_t FBRegNum = 0;
5169 for (
const SCEV *
Reg : FB.BaseRegs) {
5170 const SmallBitVector &UsedByIndices = RegUses.getUsedByIndices(
Reg);
5171 FBRegNum += (NumUses - UsedByIndices.
count() + 1);
5173 if (FARegNum != FBRegNum)
5174 return FARegNum < FBRegNum;
5178 Cost CostFA(Opts, L, SE,
TTI, AMK);
5179 Cost CostFB(Opts, L, SE,
TTI, AMK);
5181 CostFA.RateFormula(FA, Regs, VisitedRegs, LU, HardwareLoopProfitable);
5183 CostFB.RateFormula(FB, Regs, VisitedRegs, LU, HardwareLoopProfitable);
5184 return CostFA.isLess(CostFB);
5188 for (
size_t FIdx = 0, NumForms = LU.Formulae.size(); FIdx != NumForms;
5190 Formula &
F = LU.Formulae[FIdx];
5193 auto P = BestFormulae.insert({{
F.ScaledReg,
F.Scale}, FIdx});
5197 Formula &Best = LU.Formulae[
P.first->second];
5198 if (IsBetterThan(
F, Best))
5202 " in favor of formula ";
5203 Best.print(
dbgs());
dbgs() <<
'\n');
5205 ChangedFormulae =
true;
5207 LU.DeleteFormula(
F);
5213 LU.RecomputeRegs(LUIdx, RegUses);
5216 BestFormulae.clear();
5221 "After filtering out undesirable candidates:\n";
5228void LSRInstance::NarrowSearchSpaceByFilterPostInc() {
5231 if (EstimateSearchSpaceComplexity() < Opts.lsr_complexity_limit)
5235 "Narrowing the search space by choosing the lowest "
5236 "register Formula for PostInc Uses.\n");
5238 for (
size_t LUIdx = 0, NumUses =
Uses.size(); LUIdx != NumUses; ++LUIdx) {
5239 LSRUse &LU =
Uses[LUIdx];
5241 if (LU.Kind != LSRUse::Address)
5247 size_t MinRegs = std::numeric_limits<size_t>::max();
5248 for (
const Formula &
F : LU.Formulae)
5249 MinRegs = std::min(
F.getNumRegs(), MinRegs);
5252 for (
size_t FIdx = 0, NumForms = LU.Formulae.size(); FIdx != NumForms;
5254 Formula &
F = LU.Formulae[FIdx];
5255 if (
F.getNumRegs() > MinRegs) {
5258 LU.DeleteFormula(
F);
5265 LU.RecomputeRegs(LUIdx, RegUses);
5267 if (EstimateSearchSpaceComplexity() < Opts.lsr_complexity_limit)
5274void LSRInstance::NarrowSearchSpaceByMergingUsesOutsideLoop() {
5275 if (EstimateSearchSpaceComplexity() < Opts.lsr_complexity_limit)
5279 dbgs() <<
"The search space is too complex.\n"
5280 "Narrowing the search space by merging uses with fixups "
5281 "entirely outside the loop with uses inside the loop.\n");
5283 for (
size_t LUIdx = 0, NumUses =
Uses.size(); LUIdx != NumUses; ++LUIdx) {
5284 LSRUse &LU =
Uses[LUIdx];
5287 if (!LU.AllFixupsOutsideLoop || LU.Formulae.empty() ||
5288 LU.Kind == LSRUse::ICmpZero)
5295 LSRUse *LUToMergeWith =
nullptr;
5296 const Formula &ThisF = LU.Formulae[0];
5297 for (LSRUse &OtherLU :
Uses) {
5299 if (OtherLU.AllFixupsOutsideLoop)
5303 if (OtherLU.Kind == LSRUse::ICmpZero)
5306 if (OtherLU.Formulae.empty())
5309 if (
any_of(OtherLU.Formulae, [&](
const Formula &
F) {
5310 return !isLegalUse(TTI, LU.MinOffset, LU.MaxOffset, OtherLU.Kind,
5311 OtherLU.AccessTy, F);
5318 const Formula &OtherF = OtherLU.Formulae[0];
5319 if (ThisF.BaseRegs == OtherF.BaseRegs &&
5320 ThisF.ScaledReg == OtherF.ScaledReg &&
5321 ThisF.BaseGV == OtherF.BaseGV && ThisF.Scale == OtherF.Scale &&
5322 ThisF.UnfoldedOffset == OtherF.UnfoldedOffset &&
5323 ThisF.BaseOffset == OtherF.BaseOffset) {
5324 LUToMergeWith = &OtherLU;
5335 for (LSRFixup &Fixup : LU.Fixups) {
5336 LUToMergeWith->pushFixup(Fixup);
5340 DeleteUse(LU, LUIdx);
5390void LSRInstance::NarrowSearchSpaceByDeletingCostlyFormulas() {
5391 if (EstimateSearchSpaceComplexity() < Opts.lsr_complexity_limit)
5399 SmallPtrSet<const SCEV *, 4> UniqRegs;
5403 DenseMap <const SCEV *, float> RegNumMap;
5404 for (
const SCEV *
Reg : RegUses) {
5408 for (
const LSRUse &LU :
Uses) {
5409 if (!LU.Regs.count(
Reg))
5411 float P = LU.getNotSelectedProbability(
Reg);
5417 RegNumMap.
insert(std::make_pair(
Reg, PNotSel));
5421 dbgs() <<
"Narrowing the search space by deleting costly formulas\n");
5424 for (
size_t LUIdx = 0, NumUses =
Uses.size(); LUIdx != NumUses; ++LUIdx) {
5425 LSRUse &LU =
Uses[LUIdx];
5427 if (LU.Formulae.size() < 2)
5432 float FMinRegNum = LU.Formulae[0].getNumRegs();
5433 float FMinARegNum = LU.Formulae[0].getNumRegs();
5435 for (
size_t i = 0, e = LU.Formulae.size(); i != e; ++i) {
5436 Formula &
F = LU.Formulae[i];
5439 for (
const SCEV *BaseReg :
F.BaseRegs) {
5440 if (UniqRegs.
count(BaseReg))
5442 FRegNum += RegNumMap[
BaseReg] / LU.getNotSelectedProbability(BaseReg);
5445 RegNumMap[
BaseReg] / LU.getNotSelectedProbability(BaseReg);
5447 if (
const SCEV *ScaledReg =
F.ScaledReg) {
5448 if (!UniqRegs.
count(ScaledReg)) {
5450 RegNumMap[ScaledReg] / LU.getNotSelectedProbability(ScaledReg);
5453 RegNumMap[ScaledReg] / LU.getNotSelectedProbability(ScaledReg);
5456 if (FMinRegNum > FRegNum ||
5457 (FMinRegNum == FRegNum && FMinARegNum > FARegNum)) {
5458 FMinRegNum = FRegNum;
5459 FMinARegNum = FARegNum;
5464 dbgs() <<
" with min reg num " << FMinRegNum <<
'\n');
5466 std::swap(LU.Formulae[MinIdx], LU.Formulae[0]);
5467 while (LU.Formulae.size() != 1) {
5470 LU.Formulae.pop_back();
5472 LU.RecomputeRegs(LUIdx, RegUses);
5473 assert(LU.Formulae.size() == 1 &&
"Should be exactly 1 min regs formula");
5474 Formula &
F = LU.Formulae[0];
5490 MemAccessTy AccessType) {
5500 return TTI.isLegalAddressingMode(
5501 AccessType.MemTy,
nullptr,
5502 Diff->getSExtValue(),
5503 true, 0, AccessType.AddrSpace) &&
5504 !
TTI.isLegalAddressingMode(
5505 AccessType.MemTy,
nullptr,
5506 -Diff->getSExtValue(),
5507 true, 0, AccessType.AddrSpace);
5513void LSRInstance::NarrowSearchSpaceByPickingWinnerRegs() {
5516 SmallPtrSet<const SCEV *, 4> Taken;
5517 while (EstimateSearchSpaceComplexity() >= Opts.lsr_complexity_limit) {
5524 const SCEV *Best =
nullptr;
5525 unsigned BestNum = 0;
5526 for (
const SCEV *
Reg : RegUses) {
5531 BestNum = RegUses.getUsedByIndices(
Reg).count();
5533 unsigned Count = RegUses.getUsedByIndices(
Reg).count();
5534 if (
Count > BestNum) {
5542 if (
Count == BestNum) {
5543 int LUIdx = RegUses.getUsedByIndices(
Reg).find_first();
5544 if (LUIdx >= 0 &&
Uses[LUIdx].Kind == LSRUse::Address &&
5546 Uses[LUIdx].AccessTy)) {
5553 assert(Best &&
"Failed to find best LSRUse candidate");
5555 LLVM_DEBUG(
dbgs() <<
"Narrowing the search space by assuming " << *Best
5556 <<
" will yield profitable reuse.\n");
5561 for (
size_t LUIdx = 0, NumUses =
Uses.size(); LUIdx != NumUses; ++LUIdx) {
5562 LSRUse &LU =
Uses[LUIdx];
5563 if (!LU.Regs.count(Best))
continue;
5566 for (
size_t i = 0, e = LU.Formulae.size(); i != e; ++i) {
5567 Formula &
F = LU.Formulae[i];
5568 if (!
F.referencesReg(Best)) {
5570 LU.DeleteFormula(
F);
5574 assert(e != 0 &&
"Use has no formulae left! Is Regs inconsistent?");
5580 LU.RecomputeRegs(LUIdx, RegUses);
5591void LSRInstance::NarrowSearchSpaceUsingHeuristics() {
5592 NarrowSearchSpaceByDetectingSupersets();
5593 NarrowSearchSpaceByCollapsingUnrolledCode();
5594 NarrowSearchSpaceByRefilteringUndesirableDedicatedRegisters();
5595 if (Opts.lsr_filter_same_scaled_reg)
5596 NarrowSearchSpaceByFilterFormulaWithSameScaledReg();
5597 NarrowSearchSpaceByFilterPostInc();
5598 NarrowSearchSpaceByMergingUsesOutsideLoop();
5599 if (Opts.lsr_exp_narrow)
5600 NarrowSearchSpaceByDeletingCostlyFormulas();
5602 NarrowSearchSpaceByPickingWinnerRegs();
5606void LSRInstance::SolveRecurse(SmallVectorImpl<const Formula *> &Solution,
5608 SmallVectorImpl<const Formula *> &Workspace,
5609 const Cost &CurCost,
5610 const SmallPtrSet<const SCEV *, 16> &CurRegs,
5611 DenseSet<const SCEV *> &VisitedRegs)
const {
5622 const LSRUse &LU =
Uses[Workspace.
size()];
5628 SmallSetVector<const SCEV *, 4> ReqRegs;
5629 for (
const SCEV *S : CurRegs)
5630 if (LU.Regs.count(S))
5633 SmallPtrSet<const SCEV *, 16> NewRegs;
5634 Cost NewCost(Opts, L, SE,
TTI, AMK);
5635 for (
const Formula &
F : LU.Formulae) {
5643 int NumReqRegsToFind = std::min(
F.getNumRegs(), ReqRegs.
size());
5644 for (
const SCEV *
Reg : ReqRegs) {
5645 if ((
F.ScaledReg &&
F.ScaledReg ==
Reg) ||
5648 if (NumReqRegsToFind == 0)
5652 if (NumReqRegsToFind != 0) {
5663 NewCost.RateFormula(
F, NewRegs, VisitedRegs, LU, HardwareLoopProfitable);
5664 if (NewCost.isLess(SolutionCost)) {
5666 if (Workspace.
size() !=
Uses.size()) {
5667 SolveRecurse(Solution, SolutionCost, Workspace, NewCost,
5668 NewRegs, VisitedRegs);
5669 if (
F.getNumRegs() == 1 && Workspace.
size() == 1)
5670 VisitedRegs.
insert(
F.ScaledReg ?
F.ScaledReg :
F.BaseRegs[0]);
5673 dbgs() <<
".\nRegs:\n";
5674 for (
const SCEV *S : NewRegs)
dbgs()
5675 <<
"- " << *S <<
"\n";
5678 SolutionCost = NewCost;
5679 Solution = Workspace;
5688void LSRInstance::Solve(SmallVectorImpl<const Formula *> &Solution)
const {
5690 Cost SolutionCost(Opts, L, SE,
TTI, AMK);
5691 SolutionCost.Lose();
5692 Cost CurCost(Opts, L, SE,
TTI, AMK);
5693 SmallPtrSet<const SCEV *, 16> CurRegs;
5694 DenseSet<const SCEV *> VisitedRegs;
5698 SolveRecurse(Solution, SolutionCost, Workspace, CurCost,
5699 CurRegs, VisitedRegs);
5700 if (Solution.
empty()) {
5707 "The chosen solution requires ";
5708 SolutionCost.print(
dbgs());
dbgs() <<
":\n";
5709 for (
size_t i = 0, e =
Uses.size(); i != e; ++i) {
5714 Solution[i]->print(
dbgs());
5720 const bool EnableDropUnprofitableSolution =
valueOr(
5723 if (BaselineCost.isLess(SolutionCost)) {
5724 if (!EnableDropUnprofitableSolution)
5726 dbgs() <<
"Baseline is more profitable than chosen solution, "
5727 "add option 'lsr-drop-solution' to drop LSR solution.\n");
5730 "solution, dropping LSR solution.\n";);
5741 const SmallVectorImpl<Instruction *> &Inputs)
5745 bool AllDominate =
true;
5752 for (Instruction *Inst : Inputs) {
5753 if (Inst == Tentative || !DT.
dominates(Inst, Tentative)) {
5754 AllDominate =
false;
5759 if (Tentative->
getParent() == Inst->getParent() &&
5760 (!BetterPos || !DT.
dominates(Inst, BetterPos)))
5770 const Loop *IPLoop = LI.getLoopFor(IP->getParent());
5771 unsigned IPLoopDepth = IPLoop ? IPLoop->
getLoopDepth() : 0;
5775 if (!Rung)
return IP;
5776 Rung = Rung->getIDom();
5777 if (!Rung)
return IP;
5778 IDom = Rung->getBlock();
5781 const Loop *IDomLoop = LI.getLoopFor(IDom);
5782 unsigned IDomDepth = IDomLoop ? IDomLoop->
getLoopDepth() : 0;
5783 if (IDomDepth <= IPLoopDepth &&
5784 (IDomDepth != IPLoopDepth || IDomLoop == IPLoop))
5801 SmallVector<Instruction *, 4> Inputs;
5804 if (LU.Kind == LSRUse::ICmpZero)
5805 if (Instruction *
I =
5808 if (LF.PostIncLoops.
count(L)) {
5809 if (LF.isUseFullyOutsideLoop(L))
5810 Inputs.
push_back(
L->getLoopLatch()->getTerminator());
5816 for (
const Loop *PIL : LF.PostIncLoops) {
5817 if (PIL == L)
continue;
5822 if (!ExitingBlocks.
empty()) {
5824 for (
unsigned i = 1, e = ExitingBlocks.
size(); i != e; ++i)
5831 "Insertion point must be a normal instruction");
5841 while (IP->isEHPad()) ++IP;
5846 while (
Rewriter.isInsertedInstruction(&*IP) && IP != LowestIP)
5854Value *LSRInstance::Expand(
const LSRUse &LU,
const LSRFixup &LF,
5856 SmallVectorImpl<WeakTrackingVH> &DeadInsts)
const {
5857 if (LU.RigidFormula)
5858 return LF.OperandValToReplace;
5862 IP = AdjustInsertPositionForExpand(IP, LF, LU);
5867 Rewriter.setPostInc(LF.PostIncLoops);
5872 Type *Ty =
F.getType();
5885 if (LU.Kind == LSRUse::ICmpZero && OpTy->
isPointerTy()) {
5894 for (
const SCEV *
Reg :
F.BaseRegs) {
5895 assert(!
Reg->isZero() &&
"Zero allocated in a base register!");
5903 Value *ICmpScaledV =
nullptr;
5905 const SCEV *ScaledS =
F.ScaledReg;
5911 if (LU.Kind == LSRUse::ICmpZero) {
5921 "The only scale supported by ICmpZero uses is -1!");
5922 ICmpScaledV =
Rewriter.expandCodeFor(ScaledS,
nullptr);
5930 if (!
Ops.empty() && LU.Kind == LSRUse::Address &&
5940 Ops.push_back(ScaledS);
5966 assert(
F.BaseOffset.isCompatibleImmediate(LF.Offset) &&
5967 "Expanding mismatched offsets\n");
5969 Immediate
Offset =
F.BaseOffset.addUnsigned(LF.Offset);
5970 if (
Offset.isNonZero()) {
5971 if (LU.Kind == LSRUse::ICmpZero) {
5987 Ops.push_back(
Offset.getUnknownSCEV(SE, IntTy));
5992 Immediate UnfoldedOffset =
F.UnfoldedOffset;
5993 if (UnfoldedOffset.isNonZero()) {
5995 Ops.push_back(UnfoldedOffset.getUnknownSCEV(SE, IntTy));
6009 if (LU.Kind == LSRUse::ICmpZero) {
6013 assert(!
F.BaseGV &&
"ICmp does not support folding a global value and "
6014 "a scale at the same time!");
6015 if (
F.Scale == -1) {
6016 if (ICmpScaledV->
getType() != OpTy) {
6026 assert((
F.Scale == 0 ||
F.Scale == 1) &&
6027 "ICmp does not support folding a global value and "
6028 "a scale at the same time!");
6034 if (
C->getType() != OpTy) {
6038 assert(
C &&
"Cast of ConstantInt should have folded");
6051void LSRInstance::RewriteForPHI(PHINode *PN,
const LSRUse &LU,
6052 const LSRFixup &LF,
const Formula &
F,
6053 SmallVectorImpl<WeakTrackingVH> &DeadInsts) {
6054 DenseMap<BasicBlock *, Value *>
Inserted;
6058 bool needUpdateFixups =
false;
6069 Loop *PNLoop = LI.getLoopFor(Parent);
6070 if (!PNLoop || Parent != PNLoop->
getHeader()) {
6074 CriticalEdgeSplittingOptions SplitOptions(&DT, &LI, MSSAU);
6076 SplitOptions.setMergeIdenticalEdges().setKeepOneInputPHIs();
6077 if (ShouldPreserveLCSSA)
6078 SplitOptions = SplitOptions.setPreserveLCSSA();
6082 DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Eager);
6084 MSSAU, ShouldPreserveLCSSA);
6094 if (
L->contains(BB) && !
L->contains(PN))
6102 needUpdateFixups =
true;
6107 std::pair<DenseMap<BasicBlock *, Value *>::iterator,
bool> Pair =
6120 LF.OperandValToReplace->
getType(),
"tmp",
6127 if (
L->contains(
I) && !
L->contains(BB))
6128 InsertedNonLCSSAInsts.insert(
I);
6131 Pair.first->second = FullV;
6138 if (needUpdateFixups) {
6139 for (LSRUse &LU :
Uses)
6140 for (LSRFixup &Fixup : LU.Fixups)
6144 if (
Fixup.UserInst == PN) {
6147 bool foundInOriginalPHI =
false;
6149 if (val ==
Fixup.OperandValToReplace) {
6150 foundInOriginalPHI =
true;
6155 if (foundInOriginalPHI)
6166 if (val ==
Fixup.OperandValToReplace)
6167 Fixup.UserInst = NewPN;
6177void LSRInstance::Rewrite(
const LSRUse &LU,
const LSRFixup &LF,
6179 SmallVectorImpl<WeakTrackingVH> &DeadInsts) {
6183 RewriteForPHI(PN, LU, LF,
F, DeadInsts);
6191 if (FullV->
getType() != OpTy &&
6192 !(LU.Kind == LSRUse::ICmpZero && OpTy->
isPointerTy())) {
6204 if (LU.Kind == LSRUse::ICmpZero)
6220 const LSRFixup &Fixup,
const LSRUse &LU,
6224 if (LU.Kind != LSRUse::Address)
6225 return IVIncInsertPos;
6229 Type *Ty =
I->getType();
6232 return IVIncInsertPos;
6239 return IVIncInsertPos;
6246void LSRInstance::ImplementSolution(
6247 const SmallVectorImpl<const Formula *> &Solution) {
6253 for (
const IVChain &Chain : IVChainVec) {
6259 for (
size_t LUIdx = 0, NumUses =
Uses.size(); LUIdx != NumUses; ++LUIdx)
6260 for (
const LSRFixup &Fixup :
Uses[LUIdx].Fixups) {
6263 Rewriter.setIVIncInsertPos(L, InsertPos);
6264 Rewrite(
Uses[LUIdx], Fixup, *Solution[LUIdx], DeadInsts);
6268 auto InsertedInsts = InsertedNonLCSSAInsts.takeVector();
6271 for (
const IVChain &Chain : IVChainVec) {
6272 GenerateIVChain(Chain, DeadInsts);
6276 for (
const WeakVH &
IV :
Rewriter.getInsertedIVs())
6294 for (PHINode &PN :
L->getHeader()->phis()) {
6295 BinaryOperator *BO =
nullptr;
6301 case Instruction::Sub:
6306 case Instruction::Add:
6323 [&](Use &U) {return DT.dominates(IVIncInsertPos, U);}))
6332LSRInstance::LSRInstance(
const ScalarOptions &Opts,
Loop *L, IVUsers &IU,
6333 ScalarEvolution &SE, DominatorTree &DT, LoopInfo &LI,
6334 const TargetTransformInfo &
TTI, AssumptionCache &AC,
6335 TargetLibraryInfo &TLI, MemorySSAUpdater *MSSAU,
6337 : Opts(Opts), IU(IU), SE(SE), DT(DT), LI(LI), AC(AC), TLI(TLI),
TTI(
TTI),
6338 L(
L), MSSAU(MSSAU), AMK(Opts.lsr_preferred_addressing_mode.value_or(
6339 TTI.getPreferredAddressingMode(
L, &SE))),
6340 Rewriter(SE,
"lsr", PreserveLCSSA), ShouldPreserveLCSSA(PreserveLCSSA),
6341 BaselineCost(Opts,
L, SE,
TTI, AMK) {
6343 if (!
L->isLoopSimplifyForm())
6351 unsigned NumUsers = 0;
6355 LLVM_DEBUG(
dbgs() <<
"LSR skipping loop, too many IV Users in " << U
6363 auto FirstNonPHI = PN->
getParent()->getFirstNonPHIIt();
6373 L->getHeader()->printAsOperand(
dbgs(),
false);
6379 HardwareLoopProfitable =
6380 TTI.isHardwareLoopProfitable(L, SE, AC, &TLI, HWLoopInfo);
6384#if LLVM_ENABLE_ABI_BREAKING_CHECKS
6387 Rewriter.disableCanonicalMode();
6388 Rewriter.enableLSRMode();
6392 OptimizeLoopTermCond();
6395 if (IU.empty())
return;
6398 if (!
L->isInnermost()) {
6411 CollectInterestingTypesAndFactors();
6412 CollectFixupsAndInitialFormulae();
6413 CollectLoopInvariantFixupsAndFormulae();
6419 print_uses(
dbgs()));
6421 BaselineCost.print(
dbgs());
dbgs() <<
"\n");
6425 GenerateAllReuseFormulae();
6427 FilterOutUndesirableDedicatedRegisters();
6428 NarrowSearchSpaceUsingHeuristics();
6438 if (Solution.
empty())
6443 for (
const LSRUse &LU :
Uses) {
6444 for (
const Formula &
F : LU.Formulae)
6446 F) &&
"Illegal formula generated!");
6451 ImplementSolution(Solution);
6454#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
6455void LSRInstance::print_factors_and_types(
raw_ostream &OS)
const {
6456 if (Factors.empty() &&
Types.empty())
return;
6458 OS <<
"LSR has identified the following interesting factors and types: ";
6461 for (int64_t Factor : Factors)
6462 OS <<
LS <<
'*' << Factor;
6464 for (
Type *Ty : Types)
6465 OS <<
LS <<
'(' << *Ty <<
')';
6469void LSRInstance::print_fixups(raw_ostream &OS)
const {
6470 OS <<
"LSR is examining the following fixup sites:\n";
6471 for (
const LSRUse &LU :
Uses)
6472 for (
const LSRFixup &LF : LU.Fixups) {
6479void LSRInstance::print_uses(raw_ostream &OS)
const {
6480 OS <<
"LSR is examining the following uses:\n";
6481 for (
const LSRUse &LU :
Uses) {
6485 for (
const Formula &
F : LU.Formulae) {
6493void LSRInstance::print(raw_ostream &OS)
const {
6494 print_factors_and_types(OS);
6506class LoopStrengthReduce :
public LoopPass {
6510 LoopStrengthReduce();
6513 bool runOnLoop(
Loop *L, LPPassManager &LPM)
override;
6514 void getAnalysisUsage(AnalysisUsage &AU)
const override;
6519LoopStrengthReduce::LoopStrengthReduce() : LoopPass(
ID) {
6523void LoopStrengthReduce::getAnalysisUsage(
AnalysisUsage &AU)
const {
6550ToDwarfOpIter(SmallVectorImpl<uint64_t> &Expr) {
6551 llvm::DIExpression::expr_op_iterator Begin =
6552 llvm::DIExpression::expr_op_iterator(Expr.
begin());
6553 llvm::DIExpression::expr_op_iterator
End =
6554 llvm::DIExpression::expr_op_iterator(Expr.
end());
6555 return {Begin,
End};
6558struct SCEVDbgValueBuilder {
6559 SCEVDbgValueBuilder() =
default;
6560 SCEVDbgValueBuilder(
const SCEVDbgValueBuilder &
Base) { clone(
Base); }
6562 void clone(
const SCEVDbgValueBuilder &
Base) {
6563 LocationOps =
Base.LocationOps;
6568 LocationOps.
clear();
6575 SmallVector<Value *, 2> LocationOps;
6585 unsigned ArgIndex = 0;
6586 if (It != LocationOps.
end()) {
6587 ArgIndex = std::distance(LocationOps.
begin(), It);
6589 ArgIndex = LocationOps.
size();
6595 void pushValue(
const SCEVUnknown *U) {
6600 bool pushConst(
const SCEVConstant *
C) {
6601 if (
C->getAPInt().getSignificantBits() > 64)
6603 Expr.
push_back(llvm::dwarf::DW_OP_consts);
6604 Expr.
push_back(
C->getAPInt().getSExtValue());
6611 return ToDwarfOpIter(Expr);
6616 bool pushArithmeticExpr(
const llvm::SCEVCommutativeExpr *CommExpr,
6619 "Expected arithmetic SCEV type");
6621 unsigned EmitOperator = 0;
6622 for (
const auto &
Op : CommExpr->
operands()) {
6625 if (EmitOperator >= 1)
6626 pushOperator(DwarfOp);
6633 bool pushCast(
const llvm::SCEVCastExpr *
C,
bool IsSigned) {
6634 const llvm::SCEV *Inner =
C->getOperand(0);
6635 const llvm::Type *
Type =
C->getType();
6637 bool Success = pushSCEV(Inner);
6639 IsSigned ? llvm::dwarf::DW_ATE_signed
6640 : llvm::dwarf::DW_ATE_unsigned};
6641 for (
const auto &
Op : CastOps)
6647 bool pushSCEV(
const llvm::SCEV *S) {
6650 Success &= pushConst(StartInt);
6655 pushLocation(
U->getValue());
6658 Success &= pushArithmeticExpr(MulRec, llvm::dwarf::DW_OP_mul);
6661 Success &= pushSCEV(UDiv->getLHS());
6662 Success &= pushSCEV(UDiv->getRHS());
6663 pushOperator(llvm::dwarf::DW_OP_div);
6669 "Unexpected cast type in SCEV.");
6673 Success &= pushArithmeticExpr(AddExpr, llvm::dwarf::DW_OP_plus);
6688 bool isIdentityFunction(
uint64_t Op,
const SCEV *S) {
6690 if (
C->getAPInt().getSignificantBits() > 64)
6692 int64_t
I =
C->getAPInt().getSExtValue();
6694 case llvm::dwarf::DW_OP_plus:
6695 case llvm::dwarf::DW_OP_minus:
6697 case llvm::dwarf::DW_OP_mul:
6698 case llvm::dwarf::DW_OP_div:
6711 bool SCEVToValueExpr(
const llvm::SCEVAddRecExpr &SAR, ScalarEvolution &SE) {
6717 if (!isIdentityFunction(llvm::dwarf::DW_OP_mul, Stride)) {
6718 if (!pushSCEV(Stride))
6720 pushOperator(llvm::dwarf::DW_OP_mul);
6722 if (!isIdentityFunction(llvm::dwarf::DW_OP_plus, Start)) {
6723 if (!pushSCEV(Start))
6725 pushOperator(llvm::dwarf::DW_OP_plus);
6731 void createOffsetExpr(int64_t
Offset,
Value *OffsetValue) {
6732 pushLocation(OffsetValue);
6735 dbgs() <<
"scev-salvage: Generated IV offset expression. Offset: "
6736 << std::to_string(
Offset) <<
"\n");
6742 bool createIterCountExpr(
const SCEV *S,
6743 const SCEVDbgValueBuilder &IterationCount,
6744 ScalarEvolution &SE) {
6753 LLVM_DEBUG(
dbgs() <<
"scev-salvage: Location to salvage SCEV: " << *S
6757 if (!Rec->isAffine())
6765 clone(IterationCount);
6766 if (!SCEVToValueExpr(*Rec, SE))
6777 bool SCEVToIterCountExpr(
const llvm::SCEVAddRecExpr &SAR,
6778 ScalarEvolution &SE) {
6784 if (!isIdentityFunction(llvm::dwarf::DW_OP_minus, Start)) {
6785 if (!pushSCEV(Start))
6787 pushOperator(llvm::dwarf::DW_OP_minus);
6789 if (!isIdentityFunction(llvm::dwarf::DW_OP_div, Stride)) {
6790 if (!pushSCEV(Stride))
6792 pushOperator(llvm::dwarf::DW_OP_div);
6800 void appendToVectors(SmallVectorImpl<uint64_t> &DestExpr,
6801 SmallVectorImpl<Value *> &DestLocations) {
6803 "Expected the locations vector to contain the IV");
6808 "Expected the location ops to contain the IV.");
6812 for (
const auto &
Op : LocationOps) {
6813 auto It =
find(DestLocations,
Op);
6814 if (It != DestLocations.
end()) {
6816 DestIndexMap.
push_back(std::distance(DestLocations.
begin(), It));
6824 for (
const auto &
Op : expr_ops()) {
6827 Op.appendToVector(DestExpr);
6834 uint64_t NewIndex = DestIndexMap[Arg.getIndex()];
6842struct DVIRecoveryRec {
6843 DVIRecoveryRec(DbgVariableRecord *DVR)
6844 : DbgRef(DVR), Expr(DVR->getExpression()), HadLocationArgList(
false) {}
6846 DbgVariableRecord *DbgRef;
6848 bool HadLocationArgList;
6854 for (
auto &RE : RecoveryExprs)
6856 RecoveryExprs.clear();
6859 ~DVIRecoveryRec() { clear(); }
6867 auto expr_ops = ToDwarfOpIter(Expr);
6869 for (
auto Op : expr_ops)
6878template <
typename T>
6882 "contain any DW_OP_llvm_arg operands.");
6888template <
typename T>
6893 "Expected expression that references DIArglist locations using "
6894 "DW_OP_llvm_arg operands.");
6896 for (
Value *V : Locations)
6913 if (NumLLVMArgs == 0) {
6920 "Lone LLVM_arg in a DIExpression should refer to location-op 0.");
6950 LLVM_DEBUG(
dbgs() <<
"scev-salvage: restore dbg.value to pre-LSR state\n"
6951 <<
"scev-salvage: post-LSR: " << *DbgVal <<
'\n');
6952 assert(DVIRec.Expr &&
"Expected an expression");
6957 if (!DVIRec.HadLocationArgList) {
6958 assert(DVIRec.LocationOps.size() == 1 &&
6959 "Unexpected number of location ops.");
6963 Value *CachedValue =
6968 for (
WeakVH VH : DVIRec.LocationOps) {
6976 LLVM_DEBUG(
dbgs() <<
"scev-salvage: pre-LSR: " << *DbgVal <<
'\n');
6981 const SCEV *SCEVInductionVar,
6982 SCEVDbgValueBuilder IterCountExpr) {
6996 LocationOpIndexMap.
assign(DVIRec.LocationOps.size(), -1);
6998 NewLocationOps.
push_back(LSRInductionVar);
7000 for (
unsigned i = 0; i < DVIRec.LocationOps.size(); i++) {
7001 WeakVH VH = DVIRec.LocationOps[i];
7007 LocationOpIndexMap[i] = NewLocationOps.
size() - 1;
7009 <<
" now at index " << LocationOpIndexMap[i] <<
"\n");
7017 LLVM_DEBUG(
dbgs() <<
"scev-salvage: SCEV for location at index: " << i
7018 <<
" refers to a location that is now undef or erased. "
7019 "Salvage abandoned.\n");
7023 LLVM_DEBUG(
dbgs() <<
"scev-salvage: salvaging location at index " << i
7024 <<
" with SCEV: " << *DVIRec.SCEVs[i] <<
"\n");
7026 DVIRec.RecoveryExprs[i] = std::make_unique<SCEVDbgValueBuilder>();
7027 SCEVDbgValueBuilder *SalvageExpr = DVIRec.RecoveryExprs[i].get();
7031 if (std::optional<APInt>
Offset =
7033 if (
Offset->getSignificantBits() <= 64)
7034 SalvageExpr->createOffsetExpr(
Offset->getSExtValue(), LSRInductionVar);
7037 }
else if (!SalvageExpr->createIterCountExpr(DVIRec.SCEVs[i], IterCountExpr,
7046 assert(DVIRec.RecoveryExprs.size() == 1 &&
7047 "Expected only a single recovery expression for an empty "
7049 assert(DVIRec.RecoveryExprs[0] &&
7050 "Expected a SCEVDbgSalvageBuilder for location 0");
7051 SCEVDbgValueBuilder *
B = DVIRec.RecoveryExprs[0].get();
7052 B->appendToVectors(
NewExpr, NewLocationOps);
7054 for (
const auto &
Op : DVIRec.Expr->
expr_ops()) {
7062 uint64_t LocationArgIndex = Arg.getIndex();
7063 SCEVDbgValueBuilder *DbgBuilder =
7064 DVIRec.RecoveryExprs[LocationArgIndex].get();
7070 assert(LocationOpIndexMap[LocationArgIndex] != -1 &&
7071 "Expected a positive index for the location-op position.");
7072 NewExpr.push_back(LocationOpIndexMap[LocationArgIndex]);
7076 DbgBuilder->appendToVectors(
NewExpr, NewLocationOps);
7080 LLVM_DEBUG(
dbgs() <<
"scev-salvage: Updated DVI: " << *DVIRec.DbgRef <<
"\n");
7088 SmallVector<std::unique_ptr<DVIRecoveryRec>, 2> &DVIToUpdate) {
7089 if (DVIToUpdate.empty())
7093 assert(SCEVInductionVar &&
7094 "Anticipated a SCEV for the post-LSR induction variable");
7098 if (!IVAddRec->isAffine())
7106 SCEVDbgValueBuilder IterCountExpr;
7107 IterCountExpr.pushLocation(LSRInductionVar);
7108 if (!IterCountExpr.SCEVToIterCountExpr(*IVAddRec, SE))
7111 LLVM_DEBUG(
dbgs() <<
"scev-salvage: IV SCEV: " << *SCEVInductionVar
7114 for (
auto &DVIRec : DVIToUpdate) {
7115 SalvageDVI(L, SE, LSRInductionVar, *DVIRec, SCEVInductionVar,
7126 SmallVector<std::unique_ptr<DVIRecoveryRec>, 2> &SalvageableDVISCEVs) {
7127 for (
const auto &
B : L->getBlocks()) {
7128 for (
auto &
I : *
B) {
7130 if (!DbgVal.isDbgValue() && !DbgVal.isDbgAssign())
7135 if (DbgVal.isKillLocation())
7140 const auto &HasTranslatableLocationOps =
7142 for (
const auto LocOp : DbgValToTranslate.location_ops()) {
7156 if (!HasTranslatableLocationOps(DbgVal))
7159 std::unique_ptr<DVIRecoveryRec> NewRec =
7160 std::make_unique<DVIRecoveryRec>(&DbgVal);
7164 NewRec->RecoveryExprs.resize(DbgVal.getNumVariableLocationOps());
7165 for (
const auto LocOp : DbgVal.location_ops()) {
7166 NewRec->SCEVs.push_back(SE.
getSCEV(LocOp));
7167 NewRec->LocationOps.push_back(LocOp);
7168 NewRec->HadLocationArgList = DbgVal.hasArgList();
7170 SalvageableDVISCEVs.push_back(std::move(NewRec));
7180 const LSRInstance &LSR) {
7182 auto IsSuitableIV = [&](
PHINode *
P) {
7193 for (
const WeakVH &
IV : LSR.getScalarEvolutionIVs()) {
7200 if (IsSuitableIV(
P))
7204 for (
PHINode &
P : L.getHeader()->phis()) {
7205 if (IsSuitableIV(&
P))
7224 std::unique_ptr<MemorySSAUpdater> MSSAU;
7226 MSSAU = std::make_unique<MemorySSAUpdater>(MSSA);
7229 const LSRInstance &Reducer = LSRInstance(Opts, L, IU, SE, DT, LI,
TTI, AC,
7230 TLI, MSSAU.get(), PreserveLCSSA);
7231 Changed |= Reducer.getChanged();
7235 if (Opts.enable_lsr_phielim && L->isLoopSimplifyForm()) {
7238#if LLVM_ENABLE_ABI_BREAKING_CHECKS
7241 unsigned numFolded = Rewriter.replaceCongruentIVs(L, &DT, DeadInsts, &
TTI);
7255 if (L->isRecursivelyLCSSAForm(DT, LI) && L->getExitBlock()) {
7269 if (SalvageableDVIRecords.
empty())
7275 for (
const auto &L : LI) {
7279 LLVM_DEBUG(
dbgs() <<
"scev-salvage: SCEV salvaging not possible. An IV "
7280 "could not be identified.\n");
7284 for (
auto &Rec : SalvageableDVIRecords)
7286 SalvageableDVIRecords.
clear();
7290bool LoopStrengthReduce::runOnLoop(
Loop *L, LPPassManager & ) {
7294 auto &IU = getAnalysis<IVUsersWrapperPass>().getIU();
7295 auto &SE = getAnalysis<ScalarEvolutionWrapperPass>().getSE();
7296 auto &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree();
7297 auto &LI = getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
7298 const auto &
TTI = getAnalysis<TargetTransformInfoWrapperPass>().getTTI(
7299 *
L->getHeader()->getParent());
7300 auto &AC = getAnalysis<AssumptionCacheTracker>().getAssumptionCache(
7301 *
L->getHeader()->getParent());
7302 auto &TLI = getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(
7303 *
L->getHeader()->getParent());
7304 auto *MSSAAnalysis = getAnalysisIfAvailable<MemorySSAWrapperPass>();
7307 MSSA = &MSSAAnalysis->getMSSA();
7326char LoopStrengthReduce::ID = 0;
7329 "Loop Strength Reduction",
false,
false)
for(const MachineOperand &MO :llvm::drop_begin(OldMI.operands(), Desc.getNumOperands()))
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
AArch64 Predicate As Counter Loop Rewrites
This file implements a class to represent arbitrary precision integral constant values and operations...
Function Alias Analysis false
static void print(raw_ostream &Out, object::Archive::Kind Kind, T Val)
static bool isAddressUse(const Use &U)
The use is the address of the function as a value.
static const Function * getParent(const Value *V)
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< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
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 defines the DenseMap class.
This file defines the DenseSet and SmallDenseSet classes.
This file contains constants used for implementing Dwarf debug support.
early cse Early CSE w MemorySSA
Module.h This file contains the declarations for the Module class.
This defines the Use class.
iv Induction Variable Users
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
static bool isZero(Value *V, const DataLayout &DL, DominatorTree *DT, AssumptionCache *AC)
This header provides classes for managing per-loop analyses.
static bool SalvageDVI(llvm::Loop *L, ScalarEvolution &SE, llvm::PHINode *LSRInductionVar, DVIRecoveryRec &DVIRec, const SCEV *SCEVInductionVar, SCEVDbgValueBuilder IterCountExpr)
static Value * getWideOperand(Value *Oper)
IVChain logic must consistently peek base TruncInst operands, so wrap it in a convenient helper.
static bool isAddSExtable(const SCEVAddExpr *A, ScalarEvolution &SE)
Return true if the given add can be sign-extended without changing its value.
static bool stressIVChain(const ScalarOptions &Opts)
static bool mayUsePostIncMode(const TargetTransformInfo &TTI, LSRUse &LU, const SCEV *S, const Loop *L, ScalarEvolution &SE)
Return true if the SCEV represents a value that may end up as a post-increment operation.
static void restorePreTransformState(DVIRecoveryRec &DVIRec)
Restore the DVI's pre-LSR arguments. Substitute undef for any erased values.
static bool containsAddRecDependentOnLoop(const SCEV *S, const Loop &L)
static User::op_iterator findIVOperand(User::op_iterator OI, User::op_iterator OE, Loop *L, ScalarEvolution &SE)
Helper for CollectChains that finds an IV operand (computed by an AddRec in this loop) within [OI,...
static bool isLegalUse(const TargetTransformInfo &TTI, Immediate MinOffset, Immediate MaxOffset, LSRUse::KindType Kind, MemAccessTy AccessTy, GlobalValue *BaseGV, Immediate BaseOffset, bool HasBaseReg, int64_t Scale)
Test whether we know how to expand the current formula.
static void DbgGatherSalvagableDVI(Loop *L, ScalarEvolution &SE, SmallVector< std::unique_ptr< DVIRecoveryRec >, 2 > &SalvageableDVISCEVs)
Identify and cache salvageable DVI locations and expressions along with the corresponding SCEV(s).
static bool isMulSExtable(const SCEVMulExpr *M, ScalarEvolution &SE)
Return true if the given mul can be sign-extended without changing its value.
static const unsigned MaxSCEVSalvageExpressionSize
Limit the size of expression that SCEV-based salvaging will attempt to translate into a DIExpression.
static bool isExistingPhi(const SCEVAddRecExpr *AR, ScalarEvolution &SE)
Return true if this AddRec is already a phi in its loop.
static InstructionCost getScalingFactorCost(const TargetTransformInfo &TTI, const LSRUse &LU, const Formula &F, const Loop &L)
static void DoInitialMatch(const SCEV *S, Loop *L, SmallVectorImpl< SCEVUse > &Good, SmallVectorImpl< SCEVUse > &Bad, ScalarEvolution &SE)
Recursion helper for initialMatch.
static void updateDVIWithLocation(T &DbgVal, Value *Location, SmallVectorImpl< uint64_t > &Ops)
Overwrites DVI with the location and Ops as the DIExpression.
static bool ReduceLoopStrength(Loop *L, IVUsers &IU, ScalarEvolution &SE, DominatorTree &DT, LoopInfo &LI, const TargetTransformInfo &TTI, AssumptionCache &AC, TargetLibraryInfo &TLI, MemorySSA *MSSA, bool PreserveLCSSA)
static bool isLegalAddImmediate(const TargetTransformInfo &TTI, Immediate Offset)
static Instruction * getFixupInsertPos(const TargetTransformInfo &TTI, const LSRFixup &Fixup, const LSRUse &LU, Instruction *IVIncInsertPos, DominatorTree &DT)
static const SCEV * getExprBase(const SCEV *S)
Return an approximation of this SCEV expression's "base", or NULL for any constant.
static llvm::PHINode * GetInductionVariable(const Loop &L, ScalarEvolution &SE, const LSRInstance &LSR)
Ideally pick the PHI IV inserted by ScalarEvolutionExpander.
static bool IsSimplerBaseSCEVForTarget(const TargetTransformInfo &TTI, ScalarEvolution &SE, const SCEV *Best, const SCEV *Reg, MemAccessTy AccessType)
static const unsigned MaxIVUsers
MaxIVUsers is an arbitrary threshold that provides an early opportunity for bail out.
static Immediate extractImmediate(const ScalarOptions &Opts, SCEVUse &S, ScalarEvolution &SE, bool PreferScalable=false)
If S involves the addition of a constant integer value, return that integer value,...
static bool isHighCostExpansion(const SCEV *S, SmallPtrSetImpl< const SCEV * > &Processed, ScalarEvolution &SE)
Check if expanding this expression is likely to incur significant cost.
static Value * getValueOrPoison(WeakVH &VH, LLVMContext &C)
Cached location ops may be erased during LSR, in which case a poison is required when restoring from ...
static MemAccessTy getAccessType(const TargetTransformInfo &TTI, Instruction *Inst, Value *OperandVal)
Return the type of the memory being accessed.
static unsigned numLLVMArgOps(SmallVectorImpl< uint64_t > &Expr)
Returns the total number of DW_OP_llvm_arg operands in the expression.
static bool isAlwaysFoldable(const ScalarOptions &Opts, const TargetTransformInfo &TTI, LSRUse::KindType Kind, MemAccessTy AccessTy, GlobalValue *BaseGV, Immediate BaseOffset, bool HasBaseReg)
static void DbgRewriteSalvageableDVIs(llvm::Loop *L, ScalarEvolution &SE, llvm::PHINode *LSRInductionVar, SmallVector< std::unique_ptr< DVIRecoveryRec >, 2 > &DVIToUpdate)
Obtain an expression for the iteration count, then attempt to salvage the dbg.value intrinsics.
static void UpdateDbgValue(DVIRecoveryRec &DVIRec, SmallVectorImpl< Value * > &NewLocationOps, SmallVectorImpl< uint64_t > &NewExpr)
Write the new expression and new location ops for the dbg.value.
static bool isAddRecSExtable(const SCEVAddRecExpr *AR, ScalarEvolution &SE)
Return true if the given addrec can be sign-extended without changing its value.
static bool isAMCompletelyFolded(const TargetTransformInfo &TTI, const LSRUse &LU, const Formula &F)
Check if the addressing mode defined by F is completely folded in LU at isel time.
static Immediate extractImmediateOperand(const ScalarOptions &Opts, MutableArrayRef< SCEVUse > Ops, ScalarEvolution &SE, bool PreferScalable)
Extracts an immediate operand from Ops and replaces the operand with zero.
static void updateDVIWithLocations(T &DbgVal, SmallVectorImpl< Value * > &Locations, SmallVectorImpl< uint64_t > &Ops)
Overwrite DVI with locations placed into a DIArglist.
static bool canFoldIVIncExpr(const ScalarOptions &Opts, const SCEV *IncExpr, Instruction *UserInst, Value *Operand, const TargetTransformInfo &TTI)
Return true if the IVInc can be folded into an addressing mode.
static GlobalValue * ExtractSymbol(SCEVUse &S, ScalarEvolution &SE)
If S involves the addition of a GlobalValue address, return that symbol, and mutate S to point to a n...
static bool isProfitableChain(IVChain &Chain, SmallPtrSetImpl< Instruction * > &Users, ScalarEvolution &SE, const TargetTransformInfo &TTI)
Return true if the number of registers needed for the chain is estimated to be less than the number r...
static const SCEV * CollectSubexprs(const SCEV *S, const SCEVConstant *C, SmallVectorImpl< const SCEV * > &Ops, const Loop *L, ScalarEvolution &SE, unsigned Depth=0)
Split S into subexpressions which can be pulled out into separate registers.
static const SCEV * getExactSDiv(const SCEV *LHS, const SCEV *RHS, ScalarEvolution &SE, bool IgnoreSignificantBits=false)
Return an expression for LHS /s RHS, if it can be determined and if the remainder is known to be zero...
static const SCEV * getAnyExtendConsideringPostIncUses(ArrayRef< PostIncLoopSet > Loops, const SCEV *Expr, Type *ToTy, ScalarEvolution &SE)
Extend/Truncate Expr to ToTy considering post-inc uses in Loops.
static unsigned getSetupCost(const SCEV *Reg, unsigned Depth, const TargetTransformInfo &TTI)
This file exposes an interface to building/using memory SSA to walk memory instructions using a use/d...
uint64_t IntrinsicInst * II
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
This file defines the PointerIntPair class.
SmallVector< MachineOperand, 4 > Cond
Remove Loads Into Fake Uses
static bool isValid(const char C)
Returns true if C is a valid mangled character: <0-9a-zA-Z_>.
SI optimize exec mask operations pre RA
This file implements a set that has insertion order iteration characteristics.
This file implements the SmallBitVector class.
This file defines the SmallPtrSet class.
This file defines the SmallSet 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...
static SymbolRef::Type getType(const Symbol *Sym)
virt reg Virtual Register Rewriter
static const uint32_t IV[8]
Class for arbitrary precision integers.
uint64_t getZExtValue() const
Get zero extended value.
bool isZero() const
Determine if this value is zero, i.e. all bits are clear.
unsigned getBitWidth() const
Return the number of bits in the APInt.
bool isNegative() const
Determine sign of this APInt.
LLVM_ABI APInt sdiv(const APInt &RHS) const
Signed division function for APInt.
unsigned countr_zero() const
Count the number of trailing zero bits.
unsigned getSignificantBits() const
Get the minimum bit size for this signed APInt.
LLVM_ABI APInt srem(const APInt &RHS) const
Function for signed remainder operation.
bool isIntN(unsigned N) const
Check if this APInt has an N-bits unsigned integer value.
int64_t getSExtValue() const
Get sign extended value.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Represent the analysis usage information of a pass.
LLVM_ABI AnalysisUsage & addRequiredID(const void *ID)
AnalysisUsage & addPreservedID(const void *ID)
AnalysisUsage & addRequired()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
A cache of @llvm.assume calls within a function.
An instruction that atomically checks whether a specified value is in a memory location,...
an instruction that atomically reads a memory location, combines it with another value,...
LLVM Basic Block Representation.
iterator_range< const_phi_iterator > phis() const
Returns a range that iterates over the phis in the basic block.
InstListType::iterator iterator
Instruction iterators...
void moveBefore(BasicBlock *MovePos)
Unlink this basic block from its current function and insert it into the function that MovePos lives ...
LLVM_ABI bool isLandingPad() const
Return true if this basic block is a landing pad.
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction; assumes that the block is well-formed.
BinaryOps getOpcode() const
static LLVM_ABI BinaryOperator * Create(BinaryOps Op, Value *S1, Value *S2, const Twine &Name=Twine(), InsertPosition InsertBefore=nullptr)
Construct a binary instruction, given the opcode and the two operands.
static LLVM_ABI Instruction::CastOps getCastOpcode(const Value *Val, bool SrcIsSigned, Type *Ty, bool DstIsSigned)
Returns the opcode necessary to cast Val into Ty using usual casting rules.
static LLVM_ABI CastInst * Create(Instruction::CastOps, Value *S, Type *Ty, const Twine &Name="", InsertPosition InsertBefore=nullptr)
Provides a way to construct any of the CastInst subclasses using an opcode instead of the subclass's ...
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
Predicate getInversePredicate() const
For example, EQ -> NE, UGT -> ULE, SLT -> SGE, OEQ -> UNE, UGT -> OLE, OLT -> UGE,...
Value * getCondition() const
static LLVM_ABI bool isValueValidForType(Type *Ty, uint64_t V)
This static method returns true if the type Ty is big enough to represent the value V.
static ConstantInt * getSigned(IntegerType *Ty, int64_t V, bool ImplicitTrunc=false)
Return a ConstantInt with the specified value for the specified type.
int64_t getSExtValue() const
Return the constant as a 64-bit integer value after it has been sign extended as appropriate for the ...
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
static LLVM_ABI Constant * getAllOnesValue(Type *Ty)
static LLVM_ABI DIArgList * get(LLVMContext &Context, ArrayRef< ValueAsMetadata * > Args)
iterator_range< expr_op_iterator > expr_ops() const
static LLVM_ABI DIExpression * append(const DIExpression *Expr, ArrayRef< uint64_t > Ops)
Append the opcodes Ops to DIExpr.
unsigned getNumElements() const
static LLVM_ABI void appendOffset(SmallVectorImpl< uint64_t > &Ops, int64_t Offset)
Append Ops with operations to apply the Offset.
LLVM_ABI bool isComplex() const
Return whether the location is computed on the expression stack, meaning it cannot be a simple regist...
LLVM_ABI LLVMContext & getContext()
Record of a variable value-assignment, aka a non instruction representation of the dbg....
LLVM_ABI bool isKillLocation() const
void setRawLocation(Metadata *NewLocation)
Use of this should generally be avoided; instead, replaceVariableLocationOp and addVariableLocationOp...
void setExpression(DIExpression *NewExpr)
DIExpression * getExpression() const
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
DomTreeNodeBase< NodeT > * getNode(const NodeT *BB) const
getNode - return the (Post)DominatorTree node for the specified basic block.
bool properlyDominates(const DomTreeNodeBase< NodeT > *A, const DomTreeNodeBase< NodeT > *B) const
properlyDominates - Returns true iff A dominates B and A != B.
Legacy analysis pass which computes a DominatorTree.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
LLVM_ABI Instruction * findNearestCommonDominator(Instruction *I1, Instruction *I2) const
Find the nearest instruction I that dominates both I1 and I2, in the sense that a result produced bef...
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.
PointerType * getType() const
Global values are always pointers.
IVStrideUse - Keep track of one use of a strided induction variable.
void transformToPostInc(const Loop *L)
transformToPostInc - Transform the expression to post-inc form for the given loop.
Value * getOperandValToReplace() const
getOperandValToReplace - Return the Value of the operand in the user instruction that this IVStrideUs...
void setUser(Instruction *NewUser)
setUser - Assign a new user instruction for this use.
Analysis pass that exposes the IVUsers for a loop.
ilist< IVStrideUse >::const_iterator const_iterator
LLVM_ABI void print(raw_ostream &OS) const
CostType getValue() const
This function is intended to be used as sparingly as possible, since the class provides the full rang...
LLVM_ABI bool isLifetimeStartOrEnd() const LLVM_READONLY
Return true if the instruction is a llvm.lifetime.start or llvm.lifetime.end marker.
LLVM_ABI unsigned getNumSuccessors() const LLVM_READONLY
Return the number of successors that this instruction has.
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
LLVM_ABI void moveBefore(InstListType::iterator InsertPos)
Unlink this instruction from its current basic block and insert it into the basic block that MovePos ...
bool isEHPad() const
Return true if the instruction is a variety of EH-block.
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
LLVM_ABI Type * getAccessType() const LLVM_READONLY
Return the type this instruction accesses in memory, if any.
iterator_range< user_iterator > users()
const char * getOpcodeName() const
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
void setDebugLoc(DebugLoc Loc)
Set the debug location information for this instruction.
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this instruction belongs to.
static LLVM_ABI IntegerType * get(LLVMContext &C, unsigned NumBits)
This static method is the primary way of constructing an IntegerType.
A wrapper class for inspecting calls to intrinsic functions.
This is an important class for using LLVM in a threaded context.
This class provides an interface for updating the loop pass manager based on mutations to the loop ne...
An instruction for reading from memory.
void getExitingBlocks(SmallVectorImpl< BlockT * > &ExitingBlocks) const
Return all blocks inside the loop that have successors outside of the loop.
BlockT * getHeader() const
unsigned getLoopDepth() const
Return the nesting level of this loop.
The legacy pass manager's analysis pass to compute loop information.
LLVM_ABI PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM, LoopStandardAnalysisResults &AR, LPMUpdater &U)
Represents a single loop in the control flow graph.
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
An analysis that produces MemorySSA for a function.
Encapsulates MemorySSA, including all data associated with memory accesses.
Represent a mutable reference to an array (0 or more elements consecutively in memory),...
void addIncoming(Value *V, BasicBlock *BB)
Add an incoming value to the end of the PHI list.
iterator_range< const_block_iterator > blocks() const
op_range incoming_values()
void setIncomingValue(unsigned i, Value *V)
BasicBlock * getIncomingBlock(unsigned i) const
Return incoming basic block number i.
Value * getIncomingValue(unsigned i) const
Return incoming value number x.
static unsigned getIncomingValueNumForOperand(unsigned i)
int getBasicBlockIndex(const BasicBlock *BB) const
Return the first index of the specified basic block in the value list for this PHI.
unsigned getNumIncomingValues() const
Return the number of incoming edges.
static PHINode * Create(Type *Ty, unsigned NumReservedValues, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
Constructors - NumReservedValues is a hint for the number of incoming edges that this phi node will h...
static LLVM_ABI PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
Pass interface - Implemented by all 'passes'.
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
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.
This node represents an addition of some number of SCEVs.
This node represents a polynomial recurrence on the trip count of the specified loop.
LLVM_ABI const SCEV * evaluateAtIteration(const SCEV *It, ScalarEvolution &SE) const
Return the value of this chain of recurrences at the specified iteration number.
bool isAffine() const
Return true if this represents an expression A + B*x where A and B are loop invariant values.
const Loop * getLoop() const
SCEVUse getStepRecurrence(ScalarEvolution &SE) const
Constructs and returns the recurrence indicating how much this expression steps by.
This class represents a constant integer value.
ConstantInt * getValue() const
const APInt & getAPInt() const
This class uses information about analyze scalars to rewrite expressions in canonical form.
This node represents multiplication of some number of SCEVs.
bool hasNoUnsignedWrap() const
ArrayRef< SCEVUse > operands() const
bool hasNoSignedWrap() const
This means that we are dealing with an entirely unknown SCEV value, and only represent it as its LLVM...
This class represents an analyzed expression in the program.
unsigned short getExpressionSize() const
LLVM_ABI bool isZero() const
Return true if the expression is a constant zero.
LLVM_ABI ArrayRef< SCEVUse > operands() const
Return operands of this SCEV expression.
Type * getType() const
Return the LLVM type of this SCEV expression.
static constexpr auto FlagNone
SCEVTypes getSCEVType() const
The main scalar evolution driver.
LLVM_ABI const SCEV * getBackedgeTakenCount(const Loop *L, ExitCountKind Kind=Exact)
If the specified loop has a predictable backedge-taken count, return it, otherwise return a SCEVCould...
const SCEV * getZero(Type *Ty)
Return a SCEV for the constant 0 of a specific type.
LLVM_ABI const SCEV * getMinusSCEV(SCEVUse LHS, SCEVUse RHS, SCEVFlags Flags=SCEV::FlagNone, unsigned Depth=0)
Return LHS-RHS.
LLVM_ABI uint64_t getTypeSizeInBits(Type *Ty) const
Return the size in bits of the specified type, for which isSCEVable must return true.
LLVM_ABI const SCEV * getConstant(ConstantInt *V)
LLVM_ABI const SCEV * getSCEV(Value *V)
Return a SCEV expression for the full generality of the specified expression.
LLVM_ABI const SCEV * getNoopOrSignExtend(const SCEV *V, Type *Ty)
Return a SCEV corresponding to a conversion of the input value to the specified type.
LLVM_ABI SCEVUse getAddRecExpr(SCEVUse Start, SCEVUse Step, const Loop *L, SCEVFlagsPair Flags)
Get an add recurrence expression for the specified loop.
LLVM_ABI bool isLoopInvariant(const SCEV *S, const Loop *L)
Return true if the value of the given SCEV is unchanging in the specified loop.
LLVM_ABI SCEVUse getAddExpr(SmallVectorImpl< SCEVUse > &Ops, SCEVFlagsPair Flags={}, unsigned Depth=0)
Get a canonical add expression, or something simpler if possible.
LLVM_ABI bool isSCEVable(Type *Ty) const
Test if values of the given type are analyzable within the SCEV framework.
LLVM_ABI Type * getEffectiveSCEVType(Type *Ty) const
Return a type with the same bitwidth as the given type and which represents how SCEV will treat the g...
LLVM_ABI const SCEV * getAnyExtendExpr(SCEVUse Op, Type *Ty)
getAnyExtendExpr - Return a SCEV for the given operand extended with unspecified bits out to the give...
LLVM_ABI const SCEV * getSignExtendExpr(SCEVUse Op, Type *Ty, unsigned Depth=0)
LLVM_ABI bool containsUndefs(const SCEV *S) const
Return true if the SCEV expression contains an undef value.
LLVM_ABI const SCEV * getExitCount(const Loop *L, const BasicBlock *ExitingBlock, ExitCountKind Kind=Exact)
Return the number of times the backedge executes before the given exit would be taken; if not exactly...
LLVM_ABI const SCEV * getVScale(Type *Ty)
LLVM_ABI SCEVUse getMulExpr(SmallVectorImpl< SCEVUse > &Ops, SCEVFlagsPair Flags={}, unsigned Depth=0)
Get a canonical multiply expression, or something simpler if possible.
LLVM_ABI bool hasComputableLoopEvolution(const SCEV *S, const Loop *L)
Return true if the given SCEV changes value in a known way in the specified loop.
LLVM_ABI const SCEV * getPointerBase(const SCEV *V)
Transitively follow the chain of pointer-type operands until reaching a SCEV that does not have a sin...
APInt getUnsignedRangeMax(const SCEV *S)
Determine the max of the unsigned range for a particular SCEV.
LLVM_ABI const SCEV * getUnknown(Value *V)
LLVM_ABI std::optional< APInt > computeConstantDifference(const SCEV *LHS, const SCEV *RHS)
Compute LHS - RHS and returns the result as an APInt if it is a constant, and std::nullopt if it isn'...
LLVM_ABI bool properlyDominates(const SCEV *S, const BasicBlock *BB)
Return true if elements that makes up the given SCEV properly dominate the specified basic block.
LLVM_ABI bool containsErasedValue(const SCEV *S) const
Return true if the SCEV expression contains a Value that has been optimised out and is now a nullptr.
LLVMContext & getContext() const
size_type size() const
Determine the number of elements in the SetVector.
iterator end()
Get an iterator to the end of the SetVector.
iterator begin()
Get an iterator to the beginning of the SetVector.
bool insert(const value_type &X)
Insert a new element into the SetVector.
int find_first() const
Returns the index of the first set bit, -1 if none of the bits are set.
iterator_range< const_set_bits_iterator > set_bits() const
int find_next(unsigned Prev) const
Returns the index of the next set bit following the "Prev" bit.
size_type size() const
Returns the number of bits in this bitvector.
void resize(unsigned N, bool t=false)
Grow or shrink the bitvector.
size_type count() const
Returns the number of bits which are set.
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
void insert_range(Range &&R)
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void assign(size_type NumElts, ValueParamT Elt)
reference emplace_back(ArgTypes &&... Args)
void reserve(size_type N)
iterator erase(const_iterator CI)
typename SuperClass::const_iterator const_iterator
typename SuperClass::iterator iterator
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
static StackOffset get(int64_t Fixed, int64_t Scalable)
An instruction for storing to memory.
Provides information about what library functions are available for the current target.
This class represents a truncation of integer types.
The instances of the Type class are immutable: once they are created, they are never changed.
bool isPointerTy() const
True if this is an instance of PointerType.
LLVM_ABI unsigned getPointerAddressSpace() const
Get the address space of this pointer or pointer vector type.
static LLVM_ABI IntegerType * getInt8Ty(LLVMContext &C)
LLVMContext & getContext() const
Return the LLVMContext in which this type was uniqued.
LLVM_ABI bool isScalableTy() const
Return true if this is a type whose size is a known multiple of vscale.
LLVM_ABI int getFPMantissaWidth() const
Return the width of the mantissa of this type.
bool isVoidTy() const
Return true if this is 'void'.
void setOperand(unsigned i, Value *Val)
LLVM_ABI bool replaceUsesOfWith(Value *From, Value *To)
Replace uses of one Value with another.
Value * getOperand(unsigned i) const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
bool hasOneUse() const
Return true if there is exactly one use of this value.
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
LLVMContext & getContext() const
All values hold a context through their type.
iterator_range< user_iterator > users()
LLVM_ABI void printAsOperand(raw_ostream &O, bool PrintType=true, const Module *M=nullptr) const
Print the name of this Value out to the specified raw_ostream.
iterator_range< use_iterator > uses()
A nullable Value handle that is nullable.
std::pair< iterator, bool > insert(const ValueT &V)
size_type count(const_arg_type_t< ValueT > V) const
Return 1 if the specified key is in the set, 0 otherwise.
const ParentTy * getParent() const
self_iterator getIterator()
This class implements an extremely fast bulk output stream that can only output to a stream.
This provides a very simple, boring adaptor for a begin and end iterator into a range type.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ BasicBlock
Various leaf nodes.
bind_cst_ty m_scev_APInt(const APInt *&C)
Match an SCEV constant and bind it to an APInt.
match_bind< const SCEVMulExpr > m_scev_Mul(const SCEVMulExpr *&V)
bool match(const SCEV *S, const Pattern &P)
SCEVAffineAddRec_match< Op0_t, Op1_t, match_isa< const Loop > > m_scev_AffineAddRec(const Op0_t &Op0, const Op1_t &Op1)
cst_pred_ty< is_specific_cst > m_scev_SpecificInt(uint64_t V)
Match an SCEV constant with a plain unsigned integer.
@ DW_OP_LLVM_arg
Only used in LLVM metadata.
@ DW_OP_LLVM_convert
Only used in LLVM metadata.
Sequence
A sequence of states that a pointer may go through in which an objc_retain and objc_release are actua...
DiagnosticInfoOptimizationBase::Argument NV
NodeAddr< PhiNode * > Phi
NodeAddr< UseNode * > Use
friend class Instruction
Iterator for Instructions in a `BasicBlock.
LLVM_ABI iterator begin() const
BaseReg
Stack frame base register. Bit 0 of FREInfo.Info.
unsigned KindType
For isa, dyn_cast, etc operations on TelemetryInfo.
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
auto find(R &&Range, const T &Val)
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Printable print(const GCNRegPressure &RP, const GCNSubtarget *ST=nullptr, unsigned DynamicVGPRBlockSize=0)
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI void salvageDebugInfo(const MachineRegisterInfo &MRI, MachineInstr &MI)
Assuming the instruction MI is going to be deleted, attempt to salvage debug users of MI by writing t...
@ Store
The extracted value is stored (ExtractElement only).
bool operator!=(uint64_t V1, const APInt &V2)
LLVM_ABI bool DeleteDeadPHIs(BasicBlock *BB, const TargetLibraryInfo *TLI=nullptr, MemorySSAUpdater *MSSAU=nullptr, SmallPtrSetImpl< PHINode * > *KnownNonDeadPHIs=nullptr)
Examine each PHI in the given block and delete it if it is dead.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
const ScalarOptions & getScalarOptions(const LLVMContext &C)
LLVM_ABI char & LoopSimplifyID
bool isa_and_nonnull(const Y &Val)
bool operator==(const AddressRangeValuePair &LHS, const AddressRangeValuePair &RHS)
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
DomTreeNodeBase< BasicBlock > DomTreeNode
AnalysisManager< Loop, LoopStandardAnalysisResults & > LoopAnalysisManager
The loop analysis manager.
LLVM_ABI bool matchSimpleRecurrence(const PHINode *P, BinaryOperator *&BO, Value *&Start, Value *&Step)
Attempt to match a simple first order recurrence cycle of the form: iv = phi Ty [Start,...
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.
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
LLVM_ABI void initializeLoopStrengthReducePass(PassRegistry &)
auto reverse(ContainerTy &&C)
LLVM_ABI const SCEV * denormalizeForPostIncUse(const SCEV *S, const PostIncLoopSet &Loops, ScalarEvolution &SE)
Denormalize S to be post-increment for all loops present in Loops.
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
void sort(IteratorTy Start, IteratorTy End)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
bool none_of(R &&Range, UnaryPredicate P)
Provide wrappers to std::none_of which take ranges instead of having to pass begin/end explicitly.
IRBuilder(LLVMContext &, FolderTy, InserterTy) -> IRBuilder< FolderTy, InserterTy >
LLVM_ABI Constant * ConstantFoldCastOperand(unsigned Opcode, Constant *C, Type *DestTy, const DataLayout &DL)
Attempt to constant fold a cast with the specified operand.
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...
LLVM_ABI void SplitLandingPadPredecessors(BasicBlock *OrigBB, ArrayRef< BasicBlock * > Preds, const char *Suffix, const char *Suffix2, SmallVectorImpl< BasicBlock * > &NewBBs, DomTreeUpdater *DTU=nullptr, LoopInfo *LI=nullptr, MemorySSAUpdater *MSSAU=nullptr, bool PreserveLCSSA=false)
This method transforms the landing pad, OrigBB, by introducing two new basic blocks into the function...
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
LLVM_ABI const SCEV * normalizeForPostIncUse(const SCEV *S, const PostIncLoopSet &Loops, ScalarEvolution &SE, bool CheckInvertible=true)
Normalize S to be post-increment for all loops present in Loops.
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
iterator_range(Container &&) -> iterator_range< llvm::detail::IterOfRange< Container > >
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
auto count(R &&Range, const E &Element)
Wrapper function around std::count to count the number of times an element Element occurs in the give...
DWARFExpression::Operation Op
LLVM_ABI Pass * createLoopStrengthReducePass()
LLVM_ABI BasicBlock * SplitCriticalEdge(Instruction *TI, unsigned SuccNum, const CriticalEdgeSplittingOptions &Options=CriticalEdgeSplittingOptions(), const Twine &BBName="")
If this edge is a critical edge, insert a new node to split the critical edge.
LLVM_ABI bool RecursivelyDeleteTriviallyDeadInstructionsPermissive(SmallVectorImpl< WeakTrackingVH > &DeadInsts, const TargetLibraryInfo *TLI=nullptr, MemorySSAUpdater *MSSAU=nullptr, std::function< void(Value *)> AboutToDeleteCallback=std::function< void(Value *)>())
Same functionality as RecursivelyDeleteTriviallyDeadInstructions, but allow instructions that are not...
constexpr unsigned BitWidth
LLVM_ABI bool formLCSSAForInstructions(SmallVectorImpl< Instruction * > &Worklist, const DominatorTree &DT, const LoopInfo &LI, ScalarEvolution *SE, SmallVectorImpl< PHINode * > *PHIsToRemove=nullptr, SmallVectorImpl< PHINode * > *InsertedPHIs=nullptr)
Ensures LCSSA form for every instruction from the Worklist in the scope of innermost containing loop.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI PreservedAnalyses getLoopPassPreservedAnalyses()
Returns the minimum set of Analyses that all loop passes must preserve.
SmallPtrSet< const Loop *, 2 > PostIncLoopSet
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI int rewriteLoopExitValues(Loop *L, LoopInfo *LI, TargetLibraryInfo *TLI, ScalarEvolution *SE, const TargetTransformInfo *TTI, SCEVExpander &Rewriter, DominatorTree *DT, ReplaceExitVal ReplaceExitValue, SmallVector< WeakTrackingVH, 16 > &DeadInsts)
If the final value of any expressions that are recurrent in the loop can be computed,...
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
constexpr bool valueOr(BoolOrDefault X, bool Default)
@ End
Run the machine verifier once, at the end of the pipeline.
static auto filterDbgVars(iterator_range< simple_ilist< DbgRecord >::iterator > R)
Filter the DbgRecord range to DbgVariableRecord types only and downcast.
SCEVUseT< const SCEV * > SCEVUse
bool SCEVExprContains(const SCEV *Root, PredTy Pred)
Return true if any node in Root satisfies the predicate Pred.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Attributes of a target dependent hardware loop.
The adaptor from a function pass to a loop pass computes these analyses and makes them available to t...
TargetTransformInfo & TTI
Information about a load/store intrinsic defined by the target.
Value * PtrVal
This is the pointer that the intrinsic is loading from or storing to.
SCEVPtrT getPointer() const