summaryrefslogtreecommitdiff
path: root/llvm/lib/Target
diff options
context:
space:
mode:
authorCraig Topper <craig.topper@sifive.com>2025-10-24 11:20:53 -0700
committerGitHub <noreply@github.com>2025-10-24 18:20:53 +0000
commit17abc16d7b76addee09d37dfd20247f0c890c3d8 (patch)
treebe3a2d987588501607504d3de6880b3330fe5fbf /llvm/lib/Target
parent1e84cb7de2e2e5d1b710521f55e75d4ff5e8fd0f (diff)
[RISCV] Support codegen for some scalar P extension instructions. (#164359)
This includes sext.b, sext.h, min/max, rev8, clz(w), and abs. Test cases copied from rv32zbb.ll and rv64zbb.ll and pruned to what was needed for P. Eventually we should merge these back into a single test file, but I wanted to keep P separated while it is experimental.
Diffstat (limited to 'llvm/lib/Target')
-rw-r--r--llvm/lib/Target/RISCV/RISCVFeatures.td3
-rw-r--r--llvm/lib/Target/RISCV/RISCVISelLowering.cpp35
-rw-r--r--llvm/lib/Target/RISCV/RISCVInstrInfoP.td8
-rw-r--r--llvm/lib/Target/RISCV/RISCVInstrInfoZb.td18
-rw-r--r--llvm/lib/Target/RISCV/RISCVSubtarget.h4
5 files changed, 54 insertions, 14 deletions
diff --git a/llvm/lib/Target/RISCV/RISCVFeatures.td b/llvm/lib/Target/RISCV/RISCVFeatures.td
index 9e6b7f0327eb..2754d789b989 100644
--- a/llvm/lib/Target/RISCV/RISCVFeatures.td
+++ b/llvm/lib/Target/RISCV/RISCVFeatures.td
@@ -1124,7 +1124,8 @@ def HasStdExtZbkbOrP
"'Base P' (Packed-SIMD)">;
def HasStdExtZbbOrZbkbOrP
- : Predicate<"Subtarget->HasStdExtZbbOrZbkb()|| Subtarget->hasStdExtP()">,
+ : Predicate<"Subtarget->hasStdExtZbb() || Subtarget->hasStdExtZbkb() || "
+ "Subtarget->hasStdExtP()">,
AssemblerPredicate<(any_of FeatureStdExtZbb, FeatureStdExtZbkb, FeatureStdExtP),
"'Zbb' (Basic Bit-Manipulation) or "
"'Zbkb' (Bitmanip instructions for Cryptography) or "
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 219e3f2c34a7..1c930acd9c4a 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -318,8 +318,9 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
setOperationAction(ISD::EH_DWARF_CFA, MVT::i32, Custom);
- if (!Subtarget.hasStdExtZbb() && !Subtarget.hasVendorXTHeadBb() &&
- !Subtarget.hasVendorXqcibm() && !Subtarget.hasVendorXAndesPerf() &&
+ if (!Subtarget.hasStdExtZbb() && !Subtarget.hasStdExtP() &&
+ !Subtarget.hasVendorXTHeadBb() && !Subtarget.hasVendorXqcibm() &&
+ !Subtarget.hasVendorXAndesPerf() &&
!(Subtarget.hasVendorXCValu() && !Subtarget.is64Bit()))
setOperationAction(ISD::SIGN_EXTEND_INREG, {MVT::i8, MVT::i16}, Expand);
@@ -392,7 +393,7 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
setOperationAction(ISD::BITREVERSE, MVT::i8, Custom);
}
- if (Subtarget.hasStdExtZbb() ||
+ if (Subtarget.hasStdExtZbb() || Subtarget.hasStdExtP() ||
(Subtarget.hasVendorXCValu() && !Subtarget.is64Bit())) {
setOperationAction({ISD::SMIN, ISD::SMAX, ISD::UMIN, ISD::UMAX}, XLenVT,
Legal);
@@ -403,6 +404,9 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
setOperationAction({ISD::CTTZ, ISD::CTTZ_ZERO_UNDEF}, MVT::i32, Custom);
} else {
setOperationAction(ISD::CTTZ, XLenVT, Expand);
+ // If have a CLZW, but not CTZW, custom promote i32.
+ if (Subtarget.hasStdExtP() && Subtarget.is64Bit())
+ setOperationAction({ISD::CTTZ, ISD::CTTZ_ZERO_UNDEF}, MVT::i32, Custom);
}
if (!Subtarget.hasCPOPLike()) {
@@ -419,13 +423,15 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
// We need the custom lowering to make sure that the resulting sequence
// for the 32bit case is efficient on 64bit targets.
// Use default promotion for i32 without Zbb.
- if (Subtarget.is64Bit() && Subtarget.hasStdExtZbb())
+ if (Subtarget.is64Bit() &&
+ (Subtarget.hasStdExtZbb() || Subtarget.hasStdExtP()))
setOperationAction({ISD::CTLZ, ISD::CTLZ_ZERO_UNDEF}, MVT::i32, Custom);
} else {
setOperationAction(ISD::CTLZ, XLenVT, Expand);
}
- if (Subtarget.hasVendorXCValu() && !Subtarget.is64Bit()) {
+ if (Subtarget.hasStdExtP() ||
+ (Subtarget.hasVendorXCValu() && !Subtarget.is64Bit())) {
setOperationAction(ISD::ABS, XLenVT, Legal);
} else if (Subtarget.hasShortForwardBranchOpt()) {
// We can use PseudoCCSUB to implement ABS.
@@ -14669,6 +14675,25 @@ void RISCVTargetLowering::ReplaceNodeResults(SDNode *N,
DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, N->getOperand(0));
bool IsCTZ =
N->getOpcode() == ISD::CTTZ || N->getOpcode() == ISD::CTTZ_ZERO_UNDEF;
+
+ // Without Zbb, lower as 32 - clzw(~X & (X-1))
+ if (IsCTZ && !Subtarget.hasStdExtZbb()) {
+ assert(Subtarget.hasStdExtP());
+
+ NewOp0 = DAG.getFreeze(NewOp0);
+ SDValue Not = DAG.getNOT(DL, NewOp0, MVT::i64);
+ SDValue Minus1 = DAG.getNode(ISD::SUB, DL, MVT::i64, NewOp0,
+ DAG.getConstant(1, DL, MVT::i64));
+ SDValue And = DAG.getNode(ISD::AND, DL, MVT::i64, Not, Minus1);
+ SDValue CLZW = DAG.getNode(RISCVISD::CLZW, DL, MVT::i64, And);
+ SDValue Sub = DAG.getNode(ISD::SUB, DL, MVT::i64,
+ DAG.getConstant(32, DL, MVT::i64), CLZW);
+ SDValue Res = DAG.getNode(ISD::SIGN_EXTEND_INREG, DL, MVT::i64, Sub,
+ DAG.getValueType(MVT::i32));
+ Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, Res));
+ return;
+ }
+
unsigned Opc = IsCTZ ? RISCVISD::CTZW : RISCVISD::CLZW;
SDValue Res = DAG.getNode(Opc, DL, MVT::i64, NewOp0);
Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, Res));
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoP.td b/llvm/lib/Target/RISCV/RISCVInstrInfoP.td
index 7d8a9192d984..cc085bb6c9fd 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoP.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoP.td
@@ -1455,3 +1455,11 @@ let Predicates = [HasStdExtP, IsRV32] in {
def PMAXU_DW : RVPPairBinaryExchanged_rr<0b1111, 0b01, "pmaxu.dw">;
def PMAXU_DB : RVPPairBinaryExchanged_rr<0b1111, 0b10, "pmaxu.db">;
} // Predicates = [HasStdExtP, IsRV32]
+
+
+//===----------------------------------------------------------------------===//
+// Codegen patterns
+//===----------------------------------------------------------------------===//
+
+let Predicates = [HasStdExtP] in
+def : PatGpr<abs, ABS>;
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoZb.td b/llvm/lib/Target/RISCV/RISCVInstrInfoZb.td
index 6b9a75f20dfc..5429c2a1a21b 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoZb.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoZb.td
@@ -599,14 +599,20 @@ def : PatGpr<riscv_zip, ZIP_RV32, i32>;
def : PatGpr<riscv_unzip, UNZIP_RV32, i32>;
} // Predicates = [HasStdExtZbkb, IsRV32]
-let Predicates = [HasStdExtZbb] in {
+let Predicates = [HasStdExtZbbOrP] in {
def : PatGpr<ctlz, CLZ>;
+}
+
+let Predicates = [HasStdExtZbb] in {
def : PatGpr<cttz, CTZ>;
def : PatGpr<ctpop, CPOP>;
} // Predicates = [HasStdExtZbb]
-let Predicates = [HasStdExtZbb, IsRV64] in {
+let Predicates = [HasStdExtZbbOrP, IsRV64] in {
def : PatGpr<riscv_clzw, CLZW>;
+}
+
+let Predicates = [HasStdExtZbb, IsRV64] in {
def : PatGpr<riscv_ctzw, CTZW>;
def : Pat<(i64 (ctpop (i64 (zexti32 (i64 GPR:$rs1))))), (CPOPW GPR:$rs1)>;
@@ -614,22 +620,22 @@ def : Pat<(i64 (riscv_negw_max GPR:$rs1)),
(MAX GPR:$rs1, (XLenVT (SUBW (XLenVT X0), GPR:$rs1)))>;
} // Predicates = [HasStdExtZbb, IsRV64]
-let Predicates = [HasStdExtZbb] in {
+let Predicates = [HasStdExtZbbOrP] in {
def : Pat<(XLenVT (sext_inreg GPR:$rs1, i8)), (SEXT_B GPR:$rs1)>;
def : Pat<(XLenVT (sext_inreg GPR:$rs1, i16)), (SEXT_H GPR:$rs1)>;
} // Predicates = [HasStdExtZbb]
-let Predicates = [HasStdExtZbb] in {
+let Predicates = [HasStdExtZbbOrP] in {
def : PatGprGpr<smin, MIN>;
def : PatGprGpr<smax, MAX>;
def : PatGprGpr<umin, MINU>;
def : PatGprGpr<umax, MAXU>;
} // Predicates = [HasStdExtZbb]
-let Predicates = [HasStdExtZbbOrZbkb, IsRV32] in
+let Predicates = [HasStdExtZbbOrZbkbOrP, IsRV32] in
def : PatGpr<bswap, REV8_RV32, i32>;
-let Predicates = [HasStdExtZbbOrZbkb, IsRV64] in
+let Predicates = [HasStdExtZbbOrZbkbOrP, IsRV64] in
def : PatGpr<bswap, REV8_RV64, i64>;
let Predicates = [HasStdExtZbkb] in {
diff --git a/llvm/lib/Target/RISCV/RISCVSubtarget.h b/llvm/lib/Target/RISCV/RISCVSubtarget.h
index 334db4bfb75d..4b4fc8f0d8e7 100644
--- a/llvm/lib/Target/RISCV/RISCVSubtarget.h
+++ b/llvm/lib/Target/RISCV/RISCVSubtarget.h
@@ -187,7 +187,7 @@ public:
}
bool hasCLZLike() const {
- return HasStdExtZbb || HasVendorXTHeadBb ||
+ return HasStdExtZbb || HasStdExtP || HasVendorXTHeadBb ||
(HasVendorXCVbitmanip && !IsRV64);
}
bool hasCTZLike() const {
@@ -197,7 +197,7 @@ public:
return HasStdExtZbb || (HasVendorXCVbitmanip && !IsRV64);
}
bool hasREV8Like() const {
- return HasStdExtZbb || HasStdExtZbkb || HasVendorXTHeadBb;
+ return HasStdExtZbb || HasStdExtZbkb || HasStdExtP || HasVendorXTHeadBb;
}
bool hasBEXTILike() const { return HasStdExtZbs || HasVendorXTHeadBs; }