[TTI] Remove Args argument from getOperandsScalarizationOverhead (NFC). (#154126)

Remove the ArrayRef<const Value*> Args operand from
getOperandsScalarizationOverhead and require that the callers
de-duplicate arguments and filter constant operands.

Removing the Value * based Args argument enables callers where no Value
* operands are available to use the function in a follow-up: computing
the scalarization cost directly for a VPlan recipe.

It also allows more accurate cost-estimates in the future: for example,
when vectorizing a loop, we could also skip operands that are live-ins,
as those also do not require scalarization.

PR: https://github.com/llvm/llvm-project/pull/154126
This commit is contained in:
Florian Hahn 2025-08-20 21:09:08 +01:00 committed by GitHub
parent 4875553f4c
commit 4e6c88be7c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 45 additions and 32 deletions

View File

@ -961,12 +961,10 @@ public:
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

View File

@ -459,8 +459,7 @@ public:
}
virtual InstructionCost
getOperandsScalarizationOverhead(ArrayRef<const Value *> Args,
ArrayRef<Type *> Tys,
getOperandsScalarizationOverhead(ArrayRef<Type *> Tys,
TTI::TargetCostKind CostKind) const {
return 0;
}

View File

@ -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"
@ -347,6 +348,21 @@ private:
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) {}
@ -935,29 +951,21 @@ public:
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;
@ -974,7 +982,8 @@ public:
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.
@ -2170,8 +2179,9 @@ public:
/*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,

View File

@ -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 {

View File

@ -1697,8 +1697,16 @@ private:
/// Returns a range containing only operands needing to be extracted.
SmallVector<Value *, 4> filterExtractingOperands(Instruction::op_range Ops,
ElementCount VF) const {
return SmallVector<Value *, 4>(make_filter_range(
Ops, [this, VF](Value *V) { return this->needsExtract(V, VF); }));
SmallPtrSet<const Value *, 4> UniqueOperands;
SmallVector<Value *, 4> Res;
for (Value *Op : Ops) {
if (isa<Constant>(Op) || !UniqueOperands.insert(Op).second ||
!needsExtract(Op, VF))
continue;
Res.push_back(Op);
}
return Res;
}
public:
@ -5610,8 +5618,7 @@ LoopVectorizationCostModel::getScalarizationOverhead(Instruction *I,
SmallVector<Type *> Tys;
for (auto *V : filterExtractingOperands(Ops, VF))
Tys.push_back(maybeVectorizeType(V->getType(), VF));
return Cost + TTI.getOperandsScalarizationOverhead(
filterExtractingOperands(Ops, VF), Tys, CostKind);
return Cost + TTI.getOperandsScalarizationOverhead(Tys, CostKind);
}
void LoopVectorizationCostModel::setCostBasedWideningDecision(ElementCount VF) {