[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:
parent
4875553f4c
commit
4e6c88be7c
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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 {
|
||||
|
@ -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) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user