Skip to content

Commit b52fa94

Browse files
authored
[Analysis] Add cost model for experimental.cttz.elts intrinsic (#90720)
In PR #88385 I've added support for auto-vectorisation of some early exit loops, which requires using the experimental.cttz.elts to calculate final indices in the early exit block. We need a more accurate cost model for this intrinsic to better reflect the cost of work required in the early exit block. I've tried to accurately represent the expansion code for the intrinsic when the target does not have efficient lowering for it. It's quite tricky to model because you need to first figure out what types will actually be used in the expansion. The type used can have a significant effect on the cost if you end up using illegal vector types. Tests added here: Analysis/CostModel/AArch64/cttz_elts.ll Analysis/CostModel/RISCV/cttz_elts.ll
1 parent febd89c commit b52fa94

File tree

6 files changed

+437
-12
lines changed

6 files changed

+437
-12
lines changed

llvm/include/llvm/CodeGen/BasicTTIImpl.h

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "llvm/Analysis/OptimizationRemarkEmitter.h"
2626
#include "llvm/Analysis/TargetTransformInfo.h"
2727
#include "llvm/Analysis/TargetTransformInfoImpl.h"
28+
#include "llvm/Analysis/ValueTracking.h"
2829
#include "llvm/CodeGen/ISDOpcodes.h"
2930
#include "llvm/CodeGen/TargetLowering.h"
3031
#include "llvm/CodeGen/TargetSubtargetInfo.h"
@@ -1758,6 +1759,53 @@ class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase<T> {
17581759
CmpInst::ICMP_ULT, CostKind);
17591760
return Cost;
17601761
}
1762+
case Intrinsic::experimental_cttz_elts: {
1763+
EVT ArgType = getTLI()->getValueType(DL, ICA.getArgTypes()[0], true);
1764+
1765+
// If we're not expanding the intrinsic then we assume this is cheap
1766+
// to implement.
1767+
if (!getTLI()->shouldExpandCttzElements(ArgType))
1768+
return getTypeLegalizationCost(RetTy).first;
1769+
1770+
// TODO: The costs below reflect the expansion code in
1771+
// SelectionDAGBuilder, but we may want to sacrifice some accuracy in
1772+
// favour of compile time.
1773+
1774+
// Find the smallest "sensible" element type to use for the expansion.
1775+
bool ZeroIsPoison = !cast<ConstantInt>(Args[1])->isZero();
1776+
ConstantRange VScaleRange(APInt(64, 1), APInt::getZero(64));
1777+
if (isa<ScalableVectorType>(ICA.getArgTypes()[0]) && I && I->getCaller())
1778+
VScaleRange = getVScaleRange(I->getCaller(), 64);
1779+
1780+
unsigned EltWidth = getTLI()->getBitWidthForCttzElements(
1781+
RetTy, ArgType.getVectorElementCount(), ZeroIsPoison, &VScaleRange);
1782+
Type *NewEltTy = IntegerType::getIntNTy(RetTy->getContext(), EltWidth);
1783+
1784+
// Create the new vector type & get the vector length
1785+
Type *NewVecTy = VectorType::get(
1786+
NewEltTy, cast<VectorType>(Args[0]->getType())->getElementCount());
1787+
1788+
IntrinsicCostAttributes StepVecAttrs(Intrinsic::experimental_stepvector,
1789+
NewVecTy, {}, FMF);
1790+
InstructionCost Cost =
1791+
thisT()->getIntrinsicInstrCost(StepVecAttrs, CostKind);
1792+
1793+
Cost +=
1794+
thisT()->getArithmeticInstrCost(Instruction::Sub, NewVecTy, CostKind);
1795+
Cost += thisT()->getCastInstrCost(Instruction::SExt, NewVecTy,
1796+
Args[0]->getType(),
1797+
TTI::CastContextHint::None, CostKind);
1798+
Cost +=
1799+
thisT()->getArithmeticInstrCost(Instruction::And, NewVecTy, CostKind);
1800+
1801+
IntrinsicCostAttributes ReducAttrs(Intrinsic::vector_reduce_umax,
1802+
NewEltTy, NewVecTy, FMF, I, 1);
1803+
Cost += thisT()->getTypeBasedIntrinsicInstrCost(ReducAttrs, CostKind);
1804+
Cost +=
1805+
thisT()->getArithmeticInstrCost(Instruction::Sub, NewEltTy, CostKind);
1806+
1807+
return Cost;
1808+
}
17611809
}
17621810

17631811
// VP Intrinsics should have the same cost as their non-vp counterpart.

llvm/include/llvm/CodeGen/TargetLowering.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,12 @@ class TargetLoweringBase {
470470
/// expanded using generic code in SelectionDAGBuilder.
471471
virtual bool shouldExpandCttzElements(EVT VT) const { return true; }
472472

473+
/// Return the minimum number of bits required to hold the maximum possible
474+
/// number of trailing zero vector elements.
475+
unsigned getBitWidthForCttzElements(Type *RetTy, ElementCount EC,
476+
bool ZeroIsPoison,
477+
const ConstantRange *VScaleRange) const;
478+
473479
// Return true if op(vecreduce(x), vecreduce(y)) should be reassociated to
474480
// vecreduce(op(x, y)) for the reduction opcode RedOpc.
475481
virtual bool shouldReassociateReduction(unsigned RedOpc, EVT VT) const {

llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7861,20 +7861,15 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I,
78617861
Op = DAG.getSetCC(DL, OpVT, Op, AllZero, ISD::SETNE);
78627862
}
78637863

7864-
// Find the smallest "sensible" element type to use for the expansion.
7865-
ConstantRange CR(
7866-
APInt(64, OpVT.getVectorElementCount().getKnownMinValue()));
7867-
if (OpVT.isScalableVT())
7868-
CR = CR.umul_sat(getVScaleRange(I.getCaller(), 64));
7869-
78707864
// If the zero-is-poison flag is set, we can assume the upper limit
78717865
// of the result is VF-1.
7872-
if (!cast<ConstantSDNode>(getValue(I.getOperand(1)))->isZero())
7873-
CR = CR.subtract(APInt(64, 1));
7874-
7875-
unsigned EltWidth = I.getType()->getScalarSizeInBits();
7876-
EltWidth = std::min(EltWidth, (unsigned)CR.getActiveBits());
7877-
EltWidth = std::max(llvm::bit_ceil(EltWidth), (unsigned)8);
7866+
bool ZeroIsPoison =
7867+
!cast<ConstantSDNode>(getValue(I.getOperand(1)))->isZero();
7868+
ConstantRange VScaleRange(1, true); // Dummy value.
7869+
if (isa<ScalableVectorType>(I.getOperand(0)->getType()))
7870+
VScaleRange = getVScaleRange(I.getCaller(), 64);
7871+
unsigned EltWidth = TLI.getBitWidthForCttzElements(
7872+
I.getType(), OpVT.getVectorElementCount(), ZeroIsPoison, &VScaleRange);
78787873

78797874
MVT NewEltTy = MVT::getIntegerVT(EltWidth);
78807875

llvm/lib/CodeGen/TargetLoweringBase.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1048,6 +1048,24 @@ bool TargetLoweringBase::isFreeAddrSpaceCast(unsigned SrcAS,
10481048
return TM.isNoopAddrSpaceCast(SrcAS, DestAS);
10491049
}
10501050

1051+
unsigned TargetLoweringBase::getBitWidthForCttzElements(
1052+
Type *RetTy, ElementCount EC, bool ZeroIsPoison,
1053+
const ConstantRange *VScaleRange) const {
1054+
// Find the smallest "sensible" element type to use for the expansion.
1055+
ConstantRange CR(APInt(64, EC.getKnownMinValue()));
1056+
if (EC.isScalable())
1057+
CR = CR.umul_sat(*VScaleRange);
1058+
1059+
if (ZeroIsPoison)
1060+
CR = CR.subtract(APInt(64, 1));
1061+
1062+
unsigned EltWidth = RetTy->getScalarSizeInBits();
1063+
EltWidth = std::min(EltWidth, (unsigned)CR.getActiveBits());
1064+
EltWidth = std::max(llvm::bit_ceil(EltWidth), (unsigned)8);
1065+
1066+
return EltWidth;
1067+
}
1068+
10511069
void TargetLoweringBase::setJumpIsExpensive(bool isExpensive) {
10521070
// If the command-line option was specified, ignore this request.
10531071
if (!JumpIsExpensiveOverride.getNumOccurrences())

0 commit comments

Comments
 (0)