Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
b826b60
[VPlan] Compute cost single-scalar calls in computeCost. (NFC)
fhahn Aug 18, 2025
7adf2b4
[VPlan] Factor out logic to common compute costs to helper (NFCI). (#…
fhahn Aug 20, 2025
74519ed
[LV] Use MapVector for InstsToScalarize for deterministic iter order …
fhahn Aug 1, 2025
246b46c
[LV] Use MapVector for ScalarCostsTy for deterministic iter order (NFC)
fhahn Aug 4, 2025
6fddb71
[VPlan] Return invalid cost if any skeleton block has invalid costs. …
fhahn Aug 7, 2025
f0b2026
[TTI] Remove Args argument from getOperandsScalarizationOverhead (NFC…
fhahn Aug 20, 2025
c7069ab
[VPlan] Compute cost of replicating calls in VPlan. (NFCI) (#154291)
fhahn Aug 26, 2025
dde0c0e
[VPlan] Move logic to compute cost for intrinsic to helper (NFC).
fhahn Aug 27, 2025
a20edc7
[VPlan] Compute cost of intrinsics directly for VPReplicateRecipe (NF…
fhahn Aug 27, 2025
9d992f2
[LV] Correctly cost chains of replicating calls in legacy CM.
fhahn Aug 31, 2025
5137036
[LV] Don't consider second op as invariant in getDivRemSpeculationCost.
fhahn Sep 6, 2025
6c8e178
[VPlan] Move logic to compute scalarization overhead to cost helper(NFC)
fhahn Sep 13, 2025
ccd9f3e
[LV] Add scalar load/stores to VPReplicateRecipe::computeCost (#153218)
david-arm Sep 5, 2025
caef924
Reapply "[VPlan] Compute cost of scalar (U|S)Div, (U|S)Rem in compute…
fhahn Sep 14, 2025
65d1d76
[VPlan] Return non-option cost from getCostForRecipeWithOpcode (NFC).
fhahn Sep 14, 2025
8eb41eb
[VPlan] Handle predicated UDiv in VPReplicateRecipe::computeCost.
fhahn Sep 15, 2025
02ae53f
[LV] Also handle non-uniform scalarized loads when processing AddrDefs.
fhahn Sep 21, 2025
88b3703
[LV] Skip select cost for invariant divisors in legacy cost model.
fhahn Sep 21, 2025
16c0f7b
[LV] Set correct costs for interleave group members.
fhahn Sep 21, 2025
0335aef
[LV] Check for hoisted safe-div selects in planContainsAdditionalSimp.
fhahn Sep 23, 2025
e637b8d
[LV] Re-compute cost of scalarized load users.
fhahn Oct 1, 2025
a3bbee2
[VPlan] Materialize Build(Struct)Vectors for VPReplicateRecipes. (NFC…
fhahn Aug 18, 2025
80d8bee
[VPlan] Handle stores to single-scalar addr in narrowToSingleScalars.
fhahn Sep 10, 2025
422130e
[SCEV] Add tests for UDiv canonicalization of AddRecs that may wrap.
fhahn Nov 25, 2025
980898d
[SCEV] Add UDiv canonicalization tests with nested AddRecs.
fhahn Dec 2, 2025
4da5629
[SCEV] Allow udiv canonicalization of potentially-wrapping AddRecs (#…
fhahn Dec 2, 2025
de924ba
[LV] Always add uniform pointers to uniforms list.
fhahn Sep 18, 2025
1da20e6
Reapply "[VPlan] Compute cost of more replicating loads/stores in ::c…
fhahn Oct 6, 2025
37af84e
[SCEV] Expose getGEPExpr without needing to pass GEPOperator* (NFC) (…
fhahn Oct 22, 2025
add4b91
[VPlan] Extend getSCEVForVPV, use to compute VPReplicateRecipe cost. …
fhahn Oct 30, 2025
8f44611
[LV] Stop using the legacy cost model for udiv + friends (#152707)
david-arm Aug 26, 2025
751f98f
[VPlan] Introduce m_Cmp; match more compares (#154771)
artagnon Aug 24, 2025
8cd7527
[VPlan] Use predicate in VPInstruction::computeCost for selects. (#17…
fhahn Dec 3, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions llvm/include/llvm/Analysis/ScalarEvolution.h
Original file line number Diff line number Diff line change
Expand Up @@ -636,8 +636,12 @@ class ScalarEvolution {
/// \p GEP The GEP. The indices contained in the GEP itself are ignored,
/// instead we use IndexExprs.
/// \p IndexExprs The expressions for the indices.
LLVM_ABI const SCEV *
getGEPExpr(GEPOperator *GEP, const SmallVectorImpl<const SCEV *> &IndexExprs);
LLVM_ABI const SCEV *getGEPExpr(GEPOperator *GEP,
ArrayRef<const SCEV *> IndexExprs);
LLVM_ABI const SCEV *getGEPExpr(const SCEV *BaseExpr,
ArrayRef<const SCEV *> IndexExprs,
Type *SrcElementTy,
GEPNoWrapFlags NW = GEPNoWrapFlags::none());
LLVM_ABI const SCEV *getAbsExpr(const SCEV *Op, bool IsNSW);
LLVM_ABI const SCEV *getMinMaxExpr(SCEVTypes Kind,
SmallVectorImpl<const SCEV *> &Operands);
Expand Down
8 changes: 3 additions & 5 deletions llvm/include/llvm/Analysis/TargetTransformInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -961,12 +961,10 @@ class TargetTransformInfo {
TTI::TargetCostKind CostKind, bool ForPoisonSrc = true,
ArrayRef<Value *> VL = {}) const;

/// Estimate the overhead of scalarizing an instructions unique
/// non-constant operands. The (potentially vector) types to use for each of
/// argument are passes via Tys.
/// Estimate the overhead of scalarizing operands with the given types. The
/// (potentially vector) types to use for each of argument are passes via Tys.
LLVM_ABI InstructionCost getOperandsScalarizationOverhead(
ArrayRef<const Value *> Args, ArrayRef<Type *> Tys,
TTI::TargetCostKind CostKind) const;
ArrayRef<Type *> Tys, TTI::TargetCostKind CostKind) const;

/// If target has efficient vector element load/store instructions, it can
/// return true here so that insertion/extraction costs are not added to
Expand Down
3 changes: 1 addition & 2 deletions llvm/include/llvm/Analysis/TargetTransformInfoImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -459,8 +459,7 @@ class TargetTransformInfoImplBase {
}

virtual InstructionCost
getOperandsScalarizationOverhead(ArrayRef<const Value *> Args,
ArrayRef<Type *> Tys,
getOperandsScalarizationOverhead(ArrayRef<Type *> Tys,
TTI::TargetCostKind CostKind) const {
return 0;
}
Expand Down
46 changes: 28 additions & 18 deletions llvm/include/llvm/CodeGen/BasicTTIImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

#include "llvm/ADT/APInt.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Analysis/LoopInfo.h"
Expand Down Expand Up @@ -347,6 +348,21 @@ class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase<T> {
return Cost;
}

/// Filter out constant and duplicated entries in \p Ops and return a vector
/// containing the types from \p Tys corresponding to the remaining operands.
static SmallVector<Type *, 4>
filterConstantAndDuplicatedOperands(ArrayRef<const Value *> Ops,
ArrayRef<Type *> Tys) {
SmallPtrSet<const Value *, 4> UniqueOperands;
SmallVector<Type *, 4> FilteredTys;
for (const auto &[Op, Ty] : zip_equal(Ops, Tys)) {
if (isa<Constant>(Op) || !UniqueOperands.insert(Op).second)
continue;
FilteredTys.push_back(Ty);
}
return FilteredTys;
}

protected:
explicit BasicTTIImplBase(const TargetMachine *TM, const DataLayout &DL)
: BaseT(DL) {}
Expand Down Expand Up @@ -935,29 +951,21 @@ class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase<T> {
CostKind);
}

/// Estimate the overhead of scalarizing an instructions unique
/// non-constant operands. The (potentially vector) types to use for each of
/// Estimate the overhead of scalarizing an instruction's
/// operands. The (potentially vector) types to use for each of
/// argument are passes via Tys.
InstructionCost getOperandsScalarizationOverhead(
ArrayRef<const Value *> Args, ArrayRef<Type *> Tys,
TTI::TargetCostKind CostKind) const override {
assert(Args.size() == Tys.size() && "Expected matching Args and Tys");

ArrayRef<Type *> Tys, TTI::TargetCostKind CostKind) const override {
InstructionCost Cost = 0;
SmallPtrSet<const Value*, 4> UniqueOperands;
for (int I = 0, E = Args.size(); I != E; I++) {
for (Type *Ty : Tys) {
// Disregard things like metadata arguments.
const Value *A = Args[I];
Type *Ty = Tys[I];
if (!Ty->isIntOrIntVectorTy() && !Ty->isFPOrFPVectorTy() &&
!Ty->isPtrOrPtrVectorTy())
continue;

if (!isa<Constant>(A) && UniqueOperands.insert(A).second) {
if (auto *VecTy = dyn_cast<VectorType>(Ty))
Cost += getScalarizationOverhead(VecTy, /*Insert*/ false,
/*Extract*/ true, CostKind);
}
if (auto *VecTy = dyn_cast<VectorType>(Ty))
Cost += getScalarizationOverhead(VecTy, /*Insert*/ false,
/*Extract*/ true, CostKind);
}

return Cost;
Expand All @@ -974,7 +982,8 @@ class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase<T> {
InstructionCost Cost = getScalarizationOverhead(
RetTy, /*Insert*/ true, /*Extract*/ false, CostKind);
if (!Args.empty())
Cost += getOperandsScalarizationOverhead(Args, Tys, CostKind);
Cost += getOperandsScalarizationOverhead(
filterConstantAndDuplicatedOperands(Args, Tys), CostKind);
else
// When no information on arguments is provided, we add the cost
// associated with one argument as a heuristic.
Expand Down Expand Up @@ -2158,8 +2167,9 @@ class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase<T> {
/*Insert=*/true, /*Extract=*/false, CostKind);
}
}
ScalarizationCost +=
getOperandsScalarizationOverhead(Args, ICA.getArgTypes(), CostKind);
ScalarizationCost += getOperandsScalarizationOverhead(
filterConstantAndDuplicatedOperands(Args, ICA.getArgTypes()),
CostKind);
}

IntrinsicCostAttributes Attrs(IID, RetTy, ICA.getArgTypes(), FMF, I,
Expand Down
43 changes: 28 additions & 15 deletions llvm/lib/Analysis/ScalarEvolution.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3493,17 +3493,25 @@ const SCEV *ScalarEvolution::getUDivExpr(const SCEV *LHS,
/// {X,+,N}/C => {Y,+,N}/C where Y=X-(X%N). Safe when C%N=0.
// We can currently only fold X%N if X is constant.
const SCEVConstant *StartC = dyn_cast<SCEVConstant>(AR->getStart());
if (StartC && !DivInt.urem(StepInt) &&
getZeroExtendExpr(AR, ExtTy) ==
getAddRecExpr(getZeroExtendExpr(AR->getStart(), ExtTy),
getZeroExtendExpr(Step, ExtTy),
AR->getLoop(), SCEV::FlagAnyWrap)) {
if (StartC && !DivInt.urem(StepInt)) {
const APInt &StartInt = StartC->getAPInt();
const APInt &StartRem = StartInt.urem(StepInt);
if (StartRem != 0) {
const SCEV *NewLHS =
getAddRecExpr(getConstant(StartInt - StartRem), Step,
AR->getLoop(), SCEV::FlagNW);
bool NoWrap =
getZeroExtendExpr(AR, ExtTy) ==
getAddRecExpr(getZeroExtendExpr(AR->getStart(), ExtTy),
getZeroExtendExpr(Step, ExtTy), AR->getLoop(),
SCEV::FlagAnyWrap);

// With N <= C and both N, C as powers-of-2, the transformation
// {X,+,N}/C => {(X - X%N),+,N}/C preserves division results even
// if wrapping occurs, as the division results remain equivalent for
// all offsets in [[(X - X%N), X).
bool CanFoldWithWrap = StepInt.ule(DivInt) && // N <= C
StepInt.isPowerOf2() && DivInt.isPowerOf2();
if (StartRem != 0 && (NoWrap || CanFoldWithWrap)) {
const SCEV *NewLHS = getAddRecExpr(
getConstant(StartInt - StartRem), Step, AR->getLoop(),
NoWrap ? SCEV::FlagNW : SCEV::FlagAnyWrap);
if (LHS != NewLHS) {
LHS = NewLHS;

Expand Down Expand Up @@ -3770,13 +3778,11 @@ ScalarEvolution::getAddRecExpr(SmallVectorImpl<const SCEV *> &Operands,
return getOrCreateAddRecExpr(Operands, L, Flags);
}

const SCEV *
ScalarEvolution::getGEPExpr(GEPOperator *GEP,
const SmallVectorImpl<const SCEV *> &IndexExprs) {
const SCEV *ScalarEvolution::getGEPExpr(GEPOperator *GEP,
ArrayRef<const SCEV *> IndexExprs) {
const SCEV *BaseExpr = getSCEV(GEP->getPointerOperand());
// getSCEV(Base)->getType() has the same address space as Base->getType()
// because SCEV::getType() preserves the address space.
Type *IntIdxTy = getEffectiveSCEVType(BaseExpr->getType());
GEPNoWrapFlags NW = GEP->getNoWrapFlags();
if (NW != GEPNoWrapFlags::none()) {
// We'd like to propagate flags from the IR to the corresponding SCEV nodes,
Expand All @@ -3789,13 +3795,20 @@ ScalarEvolution::getGEPExpr(GEPOperator *GEP,
NW = GEPNoWrapFlags::none();
}

return getGEPExpr(BaseExpr, IndexExprs, GEP->getSourceElementType(), NW);
}

const SCEV *ScalarEvolution::getGEPExpr(const SCEV *BaseExpr,
ArrayRef<const SCEV *> IndexExprs,
Type *SrcElementTy, GEPNoWrapFlags NW) {
SCEV::NoWrapFlags OffsetWrap = SCEV::FlagAnyWrap;
if (NW.hasNoUnsignedSignedWrap())
OffsetWrap = setFlags(OffsetWrap, SCEV::FlagNSW);
if (NW.hasNoUnsignedWrap())
OffsetWrap = setFlags(OffsetWrap, SCEV::FlagNUW);

Type *CurTy = GEP->getType();
Type *CurTy = BaseExpr->getType();
Type *IntIdxTy = getEffectiveSCEVType(BaseExpr->getType());
bool FirstIter = true;
SmallVector<const SCEV *, 4> Offsets;
for (const SCEV *IndexExpr : IndexExprs) {
Expand All @@ -3814,7 +3827,7 @@ ScalarEvolution::getGEPExpr(GEPOperator *GEP,
if (FirstIter) {
assert(isa<PointerType>(CurTy) &&
"The first index of a GEP indexes a pointer");
CurTy = GEP->getSourceElementType();
CurTy = SrcElementTy;
FirstIter = false;
} else {
CurTy = GetElementPtrInst::getTypeAtIndex(CurTy, (uint64_t)0);
Expand Down
5 changes: 2 additions & 3 deletions llvm/lib/Analysis/TargetTransformInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -637,9 +637,8 @@ InstructionCost TargetTransformInfo::getScalarizationOverhead(
}

InstructionCost TargetTransformInfo::getOperandsScalarizationOverhead(
ArrayRef<const Value *> Args, ArrayRef<Type *> Tys,
TTI::TargetCostKind CostKind) const {
return TTIImpl->getOperandsScalarizationOverhead(Args, Tys, CostKind);
ArrayRef<Type *> Tys, TTI::TargetCostKind CostKind) const {
return TTIImpl->getOperandsScalarizationOverhead(Tys, CostKind);
}

bool TargetTransformInfo::supportsEfficientVectorElementLoadStore() const {
Expand Down
Loading