DataAndControlFlowWithoutRuntimeCheck
};
+struct TailFoldingInfo {
+ TargetLibraryInfo *TLI;
+ LoopVectorizationLegality *LVL;
+ InterleavedAccessInfo *IAI;
+ TailFoldingInfo(TargetLibraryInfo *TLI, LoopVectorizationLegality *LVL,
+ InterleavedAccessInfo *IAI)
+ : TLI(TLI), LVL(LVL), IAI(IAI) {}
+};
+
class TargetTransformInfo;
typedef TargetTransformInfo TTI;
/// Query the target whether it would be prefered to create a predicated
/// vector loop, which can avoid the need to emit a scalar epilogue loop.
- bool preferPredicateOverEpilogue(Loop *L, LoopInfo *LI, ScalarEvolution &SE,
- AssumptionCache &AC, TargetLibraryInfo *TLI,
- DominatorTree *DT,
- LoopVectorizationLegality *LVL,
- InterleavedAccessInfo *IAI) const;
+ bool preferPredicateOverEpilogue(TailFoldingInfo *TFI) const;
/// Query the target what the preferred style of tail folding is.
/// \param IVUpdateMayOverflow Tells whether it is known if the IV update
AssumptionCache &AC,
TargetLibraryInfo *LibInfo,
HardwareLoopInfo &HWLoopInfo) = 0;
- virtual bool
- preferPredicateOverEpilogue(Loop *L, LoopInfo *LI, ScalarEvolution &SE,
- AssumptionCache &AC, TargetLibraryInfo *TLI,
- DominatorTree *DT, LoopVectorizationLegality *LVL,
- InterleavedAccessInfo *IAI) = 0;
+ virtual bool preferPredicateOverEpilogue(TailFoldingInfo *TFI) = 0;
virtual TailFoldingStyle
getPreferredTailFoldingStyle(bool IVUpdateMayOverflow = true) = 0;
virtual std::optional<Instruction *> instCombineIntrinsic(
HardwareLoopInfo &HWLoopInfo) override {
return Impl.isHardwareLoopProfitable(L, SE, AC, LibInfo, HWLoopInfo);
}
- bool preferPredicateOverEpilogue(Loop *L, LoopInfo *LI, ScalarEvolution &SE,
- AssumptionCache &AC, TargetLibraryInfo *TLI,
- DominatorTree *DT,
- LoopVectorizationLegality *LVL,
- InterleavedAccessInfo *IAI) override {
- return Impl.preferPredicateOverEpilogue(L, LI, SE, AC, TLI, DT, LVL, IAI);
+ bool preferPredicateOverEpilogue(TailFoldingInfo *TFI) override {
+ return Impl.preferPredicateOverEpilogue(TFI);
}
TailFoldingStyle
getPreferredTailFoldingStyle(bool IVUpdateMayOverflow = true) override {
return false;
}
- bool preferPredicateOverEpilogue(Loop *L, LoopInfo *LI, ScalarEvolution &SE,
- AssumptionCache &AC, TargetLibraryInfo *TLI,
- DominatorTree *DT,
- LoopVectorizationLegality *LVL,
- InterleavedAccessInfo *IAI) const {
- return false;
- }
+ bool preferPredicateOverEpilogue(TailFoldingInfo *TFI) const { return false; }
TailFoldingStyle
getPreferredTailFoldingStyle(bool IVUpdateMayOverflow = true) const {
return BaseT::isHardwareLoopProfitable(L, SE, AC, LibInfo, HWLoopInfo);
}
- bool preferPredicateOverEpilogue(Loop *L, LoopInfo *LI, ScalarEvolution &SE,
- AssumptionCache &AC, TargetLibraryInfo *TLI,
- DominatorTree *DT,
- LoopVectorizationLegality *LVL,
- InterleavedAccessInfo *IAI) {
- return BaseT::preferPredicateOverEpilogue(L, LI, SE, AC, TLI, DT, LVL, IAI);
+ bool preferPredicateOverEpilogue(TailFoldingInfo *TFI) {
+ return BaseT::preferPredicateOverEpilogue(TFI);
}
TailFoldingStyle
return &PSE;
}
+ Loop *getLoop() const { return TheLoop; }
+
+ LoopInfo *getLoopInfo() const { return LI; }
+
+ AssumptionCache *getAssumptionCache() const { return AC; }
+
+ ScalarEvolution *getScalarEvolution() const { return PSE.getSE(); }
+
+ DominatorTree *getDominatorTree() const { return DT; }
+
private:
/// Return true if the pre-header, exiting and latch blocks of \p Lp and all
/// its nested loops are considered legal for vectorization. These legal
}
bool TargetTransformInfo::preferPredicateOverEpilogue(
- Loop *L, LoopInfo *LI, ScalarEvolution &SE, AssumptionCache &AC,
- TargetLibraryInfo *TLI, DominatorTree *DT, LoopVectorizationLegality *LVL,
- InterleavedAccessInfo *IAI) const {
- return TTIImpl->preferPredicateOverEpilogue(L, LI, SE, AC, TLI, DT, LVL, IAI);
+ TailFoldingInfo *TFI) const {
+ return TTIImpl->preferPredicateOverEpilogue(TFI);
}
TailFoldingStyle TargetTransformInfo::getPreferredTailFoldingStyle(
return false;
}
-bool AArch64TTIImpl::preferPredicateOverEpilogue(
- Loop *L, LoopInfo *LI, ScalarEvolution &SE, AssumptionCache &AC,
- TargetLibraryInfo *TLI, DominatorTree *DT, LoopVectorizationLegality *LVL,
- InterleavedAccessInfo *IAI) {
+bool AArch64TTIImpl::preferPredicateOverEpilogue(TailFoldingInfo *TFI) {
if (!ST->hasSVE() || TailFoldingKindLoc == TailFoldingKind::TFDisabled)
return false;
// We don't currently support vectorisation with interleaving for SVE - with
// such loops we're better off not using tail-folding. This gives us a chance
// to fall back on fixed-width vectorisation using NEON's ld2/st2/etc.
- if (IAI->hasGroups())
+ if (TFI->IAI->hasGroups())
return false;
TailFoldingKind Required; // Defaults to 0.
- if (LVL->getReductionVars().size())
+ if (TFI->LVL->getReductionVars().size())
Required.add(TailFoldingKind::TFReductions);
- if (LVL->getFixedOrderRecurrences().size())
+ if (TFI->LVL->getFixedOrderRecurrences().size())
Required.add(TailFoldingKind::TFRecurrences);
// We call this to discover whether any load/store pointers in the loop have
// negative strides. This will require extra work to reverse the loop
// predicate, which may be expensive.
- if (containsDecreasingPointers(L, LVL->getPredicatedScalarEvolution()))
+ if (containsDecreasingPointers(TFI->LVL->getLoop(),
+ TFI->LVL->getPredicatedScalarEvolution()))
Required.add(TailFoldingKind::TFReverse);
if (!Required)
Required.add(TailFoldingKind::TFSimple);
return TailFoldingStyle::DataWithoutLaneMask;
}
- bool preferPredicateOverEpilogue(Loop *L, LoopInfo *LI, ScalarEvolution &SE,
- AssumptionCache &AC, TargetLibraryInfo *TLI,
- DominatorTree *DT,
- LoopVectorizationLegality *LVL,
- InterleavedAccessInfo *IAI);
+ bool preferPredicateOverEpilogue(TailFoldingInfo *TFI);
bool supportsScalableVectors() const { return ST->hasSVE(); }
return true;
}
-bool ARMTTIImpl::preferPredicateOverEpilogue(
- Loop *L, LoopInfo *LI, ScalarEvolution &SE, AssumptionCache &AC,
- TargetLibraryInfo *TLI, DominatorTree *DT, LoopVectorizationLegality *LVL,
- InterleavedAccessInfo *IAI) {
+bool ARMTTIImpl::preferPredicateOverEpilogue(TailFoldingInfo *TFI) {
if (!EnableTailPredication) {
LLVM_DEBUG(dbgs() << "Tail-predication not enabled.\n");
return false;
if (!ST->hasMVEIntegerOps())
return false;
+ LoopVectorizationLegality *LVL = TFI->LVL;
+ Loop *L = LVL->getLoop();
+
// For now, restrict this to single block loops.
if (L->getNumBlocks() > 1) {
LLVM_DEBUG(dbgs() << "preferPredicateOverEpilogue: not a single block "
assert(L->isInnermost() && "preferPredicateOverEpilogue: inner-loop expected");
+ LoopInfo *LI = LVL->getLoopInfo();
HardwareLoopInfo HWLoopInfo(L);
if (!HWLoopInfo.canAnalyze(*LI)) {
LLVM_DEBUG(dbgs() << "preferPredicateOverEpilogue: hardware-loop is not "
return false;
}
+ AssumptionCache *AC = LVL->getAssumptionCache();
+ ScalarEvolution *SE = LVL->getScalarEvolution();
+
// This checks if we have the low-overhead branch architecture
// extension, and if we will create a hardware-loop:
- if (!isHardwareLoopProfitable(L, SE, AC, TLI, HWLoopInfo)) {
+ if (!isHardwareLoopProfitable(L, *SE, *AC, TFI->TLI, HWLoopInfo)) {
LLVM_DEBUG(dbgs() << "preferPredicateOverEpilogue: hardware-loop is not "
"profitable.\n");
return false;
}
- if (!HWLoopInfo.isHardwareLoopCandidate(SE, *LI, *DT)) {
+ DominatorTree *DT = LVL->getDominatorTree();
+ if (!HWLoopInfo.isHardwareLoopCandidate(*SE, *LI, *DT)) {
LLVM_DEBUG(dbgs() << "preferPredicateOverEpilogue: hardware-loop is not "
"a candidate.\n");
return false;
}
- return canTailPredicateLoop(L, LI, SE, DL, LVL->getLAI());
+ return canTailPredicateLoop(L, LI, *SE, DL, LVL->getLAI());
}
TailFoldingStyle
AssumptionCache &AC,
TargetLibraryInfo *LibInfo,
HardwareLoopInfo &HWLoopInfo);
- bool preferPredicateOverEpilogue(Loop *L, LoopInfo *LI, ScalarEvolution &SE,
- AssumptionCache &AC, TargetLibraryInfo *TLI,
- DominatorTree *DT,
- LoopVectorizationLegality *LVL,
- InterleavedAccessInfo *IAI);
+ bool preferPredicateOverEpilogue(TailFoldingInfo *TFI);
void getUnrollingPreferences(Loop *L, ScalarEvolution &SE,
TTI::UnrollingPreferences &UP,
OptimizationRemarkEmitter *ORE);
static ScalarEpilogueLowering getScalarEpilogueLowering(
Function *F, Loop *L, LoopVectorizeHints &Hints, ProfileSummaryInfo *PSI,
BlockFrequencyInfo *BFI, TargetTransformInfo *TTI, TargetLibraryInfo *TLI,
- AssumptionCache *AC, LoopInfo *LI, ScalarEvolution *SE, DominatorTree *DT,
LoopVectorizationLegality &LVL, InterleavedAccessInfo *IAI) {
// 1) OptSize takes precedence over all other options, i.e. if this is set,
// don't look at hints or options, and don't request a scalar epilogue.
};
// 4) if the TTI hook indicates this is profitable, request predication.
- if (TTI->preferPredicateOverEpilogue(L, LI, *SE, *AC, TLI, DT, &LVL, IAI))
+ TailFoldingInfo TFI(TLI, &LVL, IAI);
+ if (TTI->preferPredicateOverEpilogue(&TFI))
return CM_ScalarEpilogueNotNeededUsePredicate;
return CM_ScalarEpilogueAllowed;
Function *F = L->getHeader()->getParent();
InterleavedAccessInfo IAI(PSE, L, DT, LI, LVL->getLAI());
- ScalarEpilogueLowering SEL = getScalarEpilogueLowering(
- F, L, Hints, PSI, BFI, TTI, TLI, AC, LI, PSE.getSE(), DT, *LVL, &IAI);
+ ScalarEpilogueLowering SEL =
+ getScalarEpilogueLowering(F, L, Hints, PSI, BFI, TTI, TLI, *LVL, &IAI);
LoopVectorizationCostModel CM(SEL, L, PSE, LI, LVL, *TTI, TLI, DB, AC, ORE, F,
&Hints, IAI);
// Check the function attributes and profiles to find out if this function
// should be optimized for size.
- ScalarEpilogueLowering SEL = getScalarEpilogueLowering(
- F, L, Hints, PSI, BFI, TTI, TLI, AC, LI, PSE.getSE(), DT, LVL, &IAI);
+ ScalarEpilogueLowering SEL =
+ getScalarEpilogueLowering(F, L, Hints, PSI, BFI, TTI, TLI, LVL, &IAI);
// Check the loop for a trip count threshold: vectorize loops with a tiny trip
// count by optimizing for size, to minimize overheads.