[llvm] [TTI][RISCV][SLP] Add IdentityConstantValue option to OperandValueKind for use by SLP and RISCV (PR #228630)
Ryan Buchner via llvm-commits
llvm-commits at lists.llvm.org
Fri Oct 2 18:28:10 PDT 2026
https://github.com/bababuck created https://github.com/llvm/llvm-project/pull/228630
SLP uses this now when generating `OperandValueInfo` for operands.
RISCV can cost for a `vid_v` instruction rather than a constant pool load for such cases, matching final codegen.
Assisted By: Codex
>From 09e79b7a3a0fcf7cdbf66661e1c47299d2f6c1f4 Mon Sep 17 00:00:00 2001
From: bababuck <buchner.ryan at gmail.com>
Date: Fri, 2 Oct 2026 14:48:13 -0700
Subject: [PATCH] [TTI][RISCV][SLP] Add IdentityConstantValue option to
OperandValueKind
SLP uses this now when generating OperandValueInfo for operands.
RISCV can cost for a vid_v instruction rather than a constatn pool load for such cases.
---
.../llvm/Analysis/TargetTransformInfo.h | 6 ++++-
.../Target/RISCV/RISCVTargetTransformInfo.cpp | 17 +++++++++++++
.../Target/RISCV/RISCVTargetTransformInfo.h | 9 +++++++
.../Transforms/Vectorize/SLPVectorizer.cpp | 6 +++++
.../SLPVectorizer/RISCV/load-store.ll | 8 +-----
.../RISCV/reordered-buildvector-scalars.ll | 25 ++++++++++---------
6 files changed, 51 insertions(+), 20 deletions(-)
diff --git a/llvm/include/llvm/Analysis/TargetTransformInfo.h b/llvm/include/llvm/Analysis/TargetTransformInfo.h
index a33e6f62e941ed..ecbb68297f728d 100644
--- a/llvm/include/llvm/Analysis/TargetTransformInfo.h
+++ b/llvm/include/llvm/Analysis/TargetTransformInfo.h
@@ -1324,6 +1324,7 @@ class TargetTransformInfo {
OK_AnyValue, // Operand can have any value.
OK_UniformValue, // Operand is uniform (splat of a value).
OK_UniformConstantValue, // Operand is uniform constant.
+ OK_IdentityConstantValue, // Operand is the identity vector (0, 1, ...)
OK_NonUniformConstantValue // Operand is a non uniform constant value.
};
@@ -1342,11 +1343,14 @@ class TargetTransformInfo {
OperandValueProperties Properties = OP_None;
bool isConstant() const {
- return Kind == OK_UniformConstantValue || Kind == OK_NonUniformConstantValue;
+ return Kind == OK_UniformConstantValue ||
+ Kind == OK_NonUniformConstantValue ||
+ Kind == OK_IdentityConstantValue;
}
bool isUniform() const {
return Kind == OK_UniformConstantValue || Kind == OK_UniformValue;
}
+ bool isIdentityConstant() const { return Kind == OK_IdentityConstantValue; }
bool isPowerOf2() const {
return Properties == OP_PowerOf2;
}
diff --git a/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp b/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp
index 69554ca2b81555..f57dc104f68bc5 100644
--- a/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp
+++ b/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp
@@ -50,6 +50,14 @@ static cl::opt<unsigned>
static cl::opt<bool> EnableOrLikeSelectOpt("enable-riscv-or-like-select",
cl::init(true), cl::Hidden);
+InstructionCost
+RISCVTTIImpl::getRISCVInstructionCost(ArrayRef<unsigned> OpCodes, Type *Tp,
+ TTI::TargetCostKind CostKind) const {
+ std::pair<InstructionCost, MVT> LT = getTypeLegalizationCost(Tp);
+ // Note: Asuming all vdot4a* variants are equal cost
+ return LT.first * getRISCVInstructionCost(OpCodes, LT.second, CostKind);
+}
+
InstructionCost
RISCVTTIImpl::getRISCVInstructionCost(ArrayRef<unsigned> OpCodes, MVT VT,
TTI::TargetCostKind CostKind) const {
@@ -2517,6 +2525,9 @@ RISCVTTIImpl::getStoreImmCost(Type *Ty, TTI::OperandValueInfo OpInfo,
// with how we treat scalar constants themselves just above.
return 1;
+ if (OpInfo.isIdentityConstant())
+ return getRISCVInstructionCost(RISCV::VID_V, Ty, CostKind);
+
return getConstantPoolLoadCost(Ty, CostKind);
}
@@ -2591,6 +2602,9 @@ InstructionCost RISCVTTIImpl::getCmpSelInstrCost(
// constants in GPRs.
return 0;
+ if (OpInfo.isIdentityConstant())
+ return getRISCVInstructionCost(RISCV::VID_V, ValTy, CostKind);
+
return getConstantPoolLoadCost(ValTy, CostKind);
};
@@ -3032,6 +3046,9 @@ InstructionCost RISCVTTIImpl::getArithmeticInstrCost(
// scalar constants in GPRs.
return 0;
+ if (OpInfo.isIdentityConstant())
+ return getRISCVInstructionCost(RISCV::VID_V, Ty, CostKind);
+
return getConstantPoolLoadCost(Ty, CostKind);
};
diff --git a/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.h b/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.h
index 2d179479565b5d..ac90956df3ab83 100644
--- a/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.h
+++ b/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.h
@@ -58,6 +58,15 @@ class RISCVTTIImpl final : public BasicTTIImplBase<RISCVTTIImpl> {
InstructionCost getRISCVInstructionCost(ArrayRef<unsigned> OpCodes, MVT VT,
TTI::TargetCostKind CostKind) const;
+ /// This function calculates the costs for one or more RVV opcodes based
+ /// on the type and the cost kind.
+ /// \param Opcodes A list of opcodes of the RVV instruction to evaluate.
+ /// \param Tp The Type associated with the RVV instructions. Will be legalized
+ /// and the result multiplied by the legalization cost;
+ /// \param CostKind The type of cost to compute.
+ InstructionCost getRISCVInstructionCost(ArrayRef<unsigned> OpCodes, Type *Tp,
+ TTI::TargetCostKind CostKind) const;
+
// Return the cost of generating a PC relative address
InstructionCost
getStaticDataAddrGenerationCost(const TTI::TargetCostKind CostKind) const;
diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
index 601791da524006..10884ce95cb3e9 100644
--- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
+++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
@@ -13671,10 +13671,16 @@ TTI::OperandValueInfo BoUpSLP::getOperandInfo(ArrayRef<Value *> Ops) const {
return CI->getValue().isNegatedPowerOf2();
return false;
});
+ const bool IsIdentity = all_of(enumerate(Ops), [&](const auto &Data) {
+ auto *CI = llvm::dyn_cast<llvm::ConstantInt>(Data.value());
+ return CI && CI->getLimitedValue() == Data.index();
+ });
TTI::OperandValueKind VK = TTI::OK_AnyValue;
if (IsConstant && IsUniform)
VK = TTI::OK_UniformConstantValue;
+ else if (IsIdentity)
+ VK = TTI::OK_IdentityConstantValue;
else if (IsConstant)
VK = TTI::OK_NonUniformConstantValue;
else if (IsUniform)
diff --git a/llvm/test/Transforms/SLPVectorizer/RISCV/load-store.ll b/llvm/test/Transforms/SLPVectorizer/RISCV/load-store.ll
index 604695cb05b3a5..5b4622dc051508 100644
--- a/llvm/test/Transforms/SLPVectorizer/RISCV/load-store.ll
+++ b/llvm/test/Transforms/SLPVectorizer/RISCV/load-store.ll
@@ -148,13 +148,7 @@ entry:
define void @store_stepvector_i32(ptr %dest) {
; CHECK-LABEL: @store_stepvector_i32(
; CHECK-NEXT: entry:
-; CHECK-NEXT: store i32 0, ptr [[DEST:%.*]], align 4
-; CHECK-NEXT: [[INC1:%.*]] = getelementptr inbounds i32, ptr [[DEST]], i64 1
-; CHECK-NEXT: store i32 1, ptr [[INC1]], align 2
-; CHECK-NEXT: [[INC2:%.*]] = getelementptr inbounds i32, ptr [[DEST]], i64 2
-; CHECK-NEXT: store i32 2, ptr [[INC2]], align 2
-; CHECK-NEXT: [[INC3:%.*]] = getelementptr inbounds i32, ptr [[DEST]], i64 3
-; CHECK-NEXT: store i32 3, ptr [[INC3]], align 2
+; CHECK-NEXT: store <4 x i32> <i32 0, i32 1, i32 2, i32 3>, ptr [[DEST:%.*]], align 4
; CHECK-NEXT: ret void
;
entry:
diff --git a/llvm/test/Transforms/SLPVectorizer/RISCV/reordered-buildvector-scalars.ll b/llvm/test/Transforms/SLPVectorizer/RISCV/reordered-buildvector-scalars.ll
index 2d6ef587f764ff..91881a816463a5 100644
--- a/llvm/test/Transforms/SLPVectorizer/RISCV/reordered-buildvector-scalars.ll
+++ b/llvm/test/Transforms/SLPVectorizer/RISCV/reordered-buildvector-scalars.ll
@@ -12,22 +12,27 @@ define fastcc i32 @test(i32 %0, i32 %add111.i.i, <4 x i32> %PredPel.i.sroa.86.72
; CHECK-SAME: i32 [[TMP0:%.*]], i32 [[ADD111_I_I:%.*]], <4 x i32> [[PREDPEL_I_SROA_86_72_VEC_EXTRACT:%.*]], <4 x i32> [[TMP1:%.*]]) #[[ATTR0:[0-9]+]] {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[MUL1445_I:%.*]] = shl i32 [[TMP0]], 1
+; CHECK-NEXT: [[PREDPEL_I_SROA_7_4_VEC_EXTRACT446:%.*]] = extractelement <4 x i32> [[TMP1]], i64 0
; CHECK-NEXT: [[ADD2235_I17:%.*]] = or i32 [[TMP0]], 1
; CHECK-NEXT: [[ADD1392_I:%.*]] = add i32 [[TMP0]], 1
-; CHECK-NEXT: [[TMP2:%.*]] = insertelement <3 x i32> poison, i32 [[ADD111_I_I]], i64 0
-; CHECK-NEXT: [[TMP3:%.*]] = insertelement <3 x i32> poison, i32 [[TMP0]], i64 0
-; CHECK-NEXT: [[TMP6:%.*]] = shufflevector <3 x i32> [[TMP3]], <3 x i32> poison, <3 x i32> zeroinitializer
-; CHECK-NEXT: [[LOOPARRAY_SROA_24_0_I_I3:%.*]] = ashr i32 [[TMP0]], 1
+; CHECK-NEXT: [[TMP2:%.*]] = insertelement <2 x i32> poison, i32 [[TMP0]], i64 0
+; CHECK-NEXT: [[TMP3:%.*]] = shufflevector <2 x i32> [[TMP2]], <2 x i32> poison, <2 x i32> zeroinitializer
+; CHECK-NEXT: [[TMP4:%.*]] = add <2 x i32> [[TMP3]], <i32 0, i32 1>
+; CHECK-NEXT: [[TMP20:%.*]] = shufflevector <2 x i32> [[TMP4]], <2 x i32> poison, <4 x i32> <i32 0, i32 1, i32 0, i32 0>
; CHECK-NEXT: [[SHR143_5_I_I9:%.*]] = ashr i32 [[TMP0]], 1
-; CHECK-NEXT: [[ADD1392_I1:%.*]] = add i32 [[TMP0]], 1
-; CHECK-NEXT: [[TMP5:%.*]] = insertelement <3 x i32> [[TMP2]], i32 [[LOOPARRAY_SROA_24_0_I_I3]], i64 1
+; CHECK-NEXT: [[TMP32:%.*]] = ashr <4 x i32> [[TMP20]], <i32 1, i32 0, i32 0, i32 1>
+; CHECK-NEXT: [[TMP21:%.*]] = insertelement <3 x i32> poison, i32 [[ADD111_I_I]], i64 0
+; CHECK-NEXT: [[TMP31:%.*]] = shufflevector <4 x i32> [[TMP32]], <4 x i32> poison, <3 x i32> <i32 0, i32 poison, i32 poison>
+; CHECK-NEXT: [[TMP33:%.*]] = shufflevector <3 x i32> [[TMP21]], <3 x i32> poison, <4 x i32> <i32 0, i32 1, i32 2, i32 poison>
+; CHECK-NEXT: [[TMP5:%.*]] = shufflevector <4 x i32> [[TMP33]], <4 x i32> [[TMP32]], <3 x i32> <i32 0, i32 4, i32 poison>
; CHECK-NEXT: [[TMP30:%.*]] = insertelement <3 x i32> [[TMP5]], i32 [[ADD1392_I]], i64 2
+; CHECK-NEXT: [[TMP6:%.*]] = shufflevector <2 x i32> [[TMP3]], <2 x i32> poison, <3 x i32> zeroinitializer
; CHECK-NEXT: [[TMP7:%.*]] = or <3 x i32> [[TMP30]], [[TMP6]]
-; CHECK-NEXT: [[TMP8:%.*]] = shufflevector <4 x i32> [[PREDPEL_I_SROA_86_72_VEC_EXTRACT]], <4 x i32> [[TMP1]], <8 x i32> <i32 0, i32 poison, i32 poison, i32 4, i32 poison, i32 poison, i32 poison, i32 poison>
+; CHECK-NEXT: [[TMP8:%.*]] = shufflevector <4 x i32> [[PREDPEL_I_SROA_86_72_VEC_EXTRACT]], <4 x i32> [[TMP32]], <8 x i32> <i32 0, i32 poison, i32 4, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison>
; CHECK-NEXT: [[TMP9:%.*]] = insertelement <8 x i32> [[TMP8]], i32 [[TMP0]], i64 4
; CHECK-NEXT: [[TMP10:%.*]] = insertelement <8 x i32> [[TMP9]], i32 [[ADD111_I_I]], i64 6
; CHECK-NEXT: [[TMP11:%.*]] = insertelement <8 x i32> [[TMP10]], i32 [[ADD2235_I17]], i64 1
-; CHECK-NEXT: [[TMP12:%.*]] = insertelement <8 x i32> [[TMP11]], i32 [[LOOPARRAY_SROA_24_0_I_I3]], i64 2
+; CHECK-NEXT: [[TMP12:%.*]] = insertelement <8 x i32> [[TMP11]], i32 [[PREDPEL_I_SROA_7_4_VEC_EXTRACT446]], i64 3
; CHECK-NEXT: [[TMP13:%.*]] = insertelement <8 x i32> [[TMP12]], i32 [[MUL1445_I]], i64 5
; CHECK-NEXT: [[TMP14:%.*]] = insertelement <8 x i32> [[TMP13]], i32 [[SHR143_5_I_I9]], i64 7
; CHECK-NEXT: [[TMP15:%.*]] = add <8 x i32> [[TMP14]], <i32 1, i32 1, i32 1, i32 1, i32 1, i32 2, i32 1, i32 1>
@@ -35,10 +40,6 @@ define fastcc i32 @test(i32 %0, i32 %add111.i.i, <4 x i32> %PredPel.i.sroa.86.72
; CHECK-NEXT: [[TMP17:%.*]] = shufflevector <3 x i32> [[TMP7]], <3 x i32> poison, <11 x i32> <i32 0, i32 1, i32 2, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison>
; CHECK-NEXT: [[TMP18:%.*]] = shufflevector <11 x i32> [[TMP16]], <11 x i32> [[TMP17]], <11 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 11, i32 12, i32 13>
; CHECK-NEXT: [[TMP19:%.*]] = lshr <11 x i32> [[TMP18]], <i32 1, i32 1, i32 1, i32 1, i32 1, i32 2, i32 1, i32 1, i32 1, i32 1, i32 1>
-; CHECK-NEXT: [[TMP20:%.*]] = insertelement <4 x i32> poison, i32 [[TMP0]], i64 2
-; CHECK-NEXT: [[TMP21:%.*]] = insertelement <4 x i32> [[TMP20]], i32 [[LOOPARRAY_SROA_24_0_I_I3]], i64 0
-; CHECK-NEXT: [[TMP31:%.*]] = insertelement <4 x i32> [[TMP21]], i32 [[ADD1392_I1]], i64 1
-; CHECK-NEXT: [[TMP32:%.*]] = insertelement <4 x i32> [[TMP31]], i32 [[SHR143_5_I_I9]], i64 3
; CHECK-NEXT: [[TMP22:%.*]] = or <4 x i32> [[TMP32]], splat (i32 1)
; CHECK-NEXT: [[TMP23:%.*]] = shufflevector <3 x i32> [[TMP6]], <3 x i32> poison, <4 x i32> zeroinitializer
; CHECK-NEXT: [[TMP24:%.*]] = add <4 x i32> [[TMP22]], [[TMP23]]
More information about the llvm-commits
mailing list