[llvm] [RISCV] Accept c.slli/c.srli/c.srli with a 0 immediate as hints. (PR #150689)
Craig Topper via llvm-commits
llvm-commits at lists.llvm.org
Fri Jul 25 23:19:26 PDT 2025
https://github.com/topperc updated https://github.com/llvm/llvm-project/pull/150689
>From fb7c6b790c7a56c8c7db3ae8f348907bed58aa8d Mon Sep 17 00:00:00 2001
From: Craig Topper <craig.topper at sifive.com>
Date: Fri, 25 Jul 2025 12:49:24 -0700
Subject: [PATCH] [RISCV] Accept c.slli/c.srli/c.srli with a 0 immediate as
hints.
These encodings were previously assigned to c.slli64/srli64/srai64,
and designated as hints for RV32 and RV64. Those mnemonics no longer
appear in the ISA manual after RV128 was removed. The spec now
indicates that an immediate of 0 is a hint.
This patch updates the assembler to accept this. I've left the old
spelling for backwards compatibility but we disassemble a shift with
a zero immediate.
There's some diagnostic message issues here, but those should hopefully
go away if I'm able to merge all the C_*_HINT instructions.
---
.../RISCV/Disassembler/RISCVDisassembler.cpp | 32 ++++++++++
llvm/lib/Target/RISCV/RISCVInstrInfoC.td | 21 ++++--
llvm/test/MC/Disassembler/RISCV/c_slli.txt | 64 +++++++++----------
llvm/test/MC/RISCV/rv32c-invalid.s | 3 +-
llvm/test/MC/RISCV/rv64c-invalid.s | 3 +-
llvm/test/MC/RISCV/rvc-hints-invalid.s | 7 +-
llvm/test/MC/RISCV/rvc-hints-valid.s | 24 +++++--
7 files changed, 103 insertions(+), 51 deletions(-)
diff --git a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
index fa7bcfa0e8132..3e5ecd3447d7c 100644
--- a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
+++ b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
@@ -540,6 +540,14 @@ static DecodeStatus decodeRVCInstrRdRs1ImmZero(MCInst &Inst, uint32_t Insn,
uint64_t Address,
const MCDisassembler *Decoder);
+static DecodeStatus decodeRVCInstrShiftLeftHint(MCInst &Inst, uint32_t Insn,
+ uint64_t Address,
+ const MCDisassembler *Decoder);
+
+static DecodeStatus decodeRVCInstrShiftRightHint(MCInst &Inst, uint32_t Insn,
+ uint64_t Address,
+ const MCDisassembler *Decoder);
+
static DecodeStatus decodeRVCInstrRdSImm6(MCInst &Inst, uint32_t Insn,
uint64_t Address,
const MCDisassembler *Decoder);
@@ -591,6 +599,30 @@ static DecodeStatus decodeRVCInstrRdRs1ImmZero(MCInst &Inst, uint32_t Insn,
return S;
}
+static DecodeStatus decodeRVCInstrShiftLeftHint(MCInst &Inst, uint32_t Insn,
+ uint64_t Address,
+ const MCDisassembler *Decoder) {
+ DecodeStatus S = MCDisassembler::Success;
+ uint32_t Rd = fieldFromInstruction(Insn, 7, 5);
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rd, Address, Decoder)))
+ return MCDisassembler::Fail;
+ Inst.addOperand(Inst.getOperand(0));
+ Inst.addOperand(MCOperand::createImm(0));
+ return S;
+}
+
+static DecodeStatus
+decodeRVCInstrShiftRightHint(MCInst &Inst, uint32_t Insn, uint64_t Address,
+ const MCDisassembler *Decoder) {
+ DecodeStatus S = MCDisassembler::Success;
+ uint32_t Rd = fieldFromInstruction(Insn, 7, 3);
+ if (!Check(S, DecodeGPRCRegisterClass(Inst, Rd, Address, Decoder)))
+ return MCDisassembler::Fail;
+ Inst.addOperand(Inst.getOperand(0));
+ Inst.addOperand(MCOperand::createImm(0));
+ return S;
+}
+
static DecodeStatus decodeCSSPushPopchk(MCInst &Inst, uint32_t Insn,
uint64_t Address,
const MCDisassembler *Decoder) {
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoC.td b/llvm/lib/Target/RISCV/RISCVInstrInfoC.td
index 8252a9b170eb3..1b4abf1caf7a9 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoC.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoC.td
@@ -664,31 +664,35 @@ def C_SLLI_HINT : RVInst16CI<0b000, 0b10, (outs GPRX0:$rd_wb),
let DecoderMethod = "decodeRVCInstrRdRs1UImmLog2XLenNonZero";
}
-def C_SLLI64_HINT : RVInst16CI<0b000, 0b10, (outs GPR:$rd_wb), (ins GPR:$rd),
- "c.slli64", "$rd">,
+def C_SLLI64_HINT : RVInst16CI<0b000, 0b10, (outs GPR:$rd_wb),
+ (ins GPR:$rd, immzero:$imm),
+ "c.slli", "$rd, $imm">,
Sched<[WriteShiftImm, ReadShiftImm]> {
let Constraints = "$rd = $rd_wb";
let imm = 0;
+ let DecoderMethod = "decodeRVCInstrShiftLeftHint";
}
def C_SRLI64_HINT : RVInst16CB<0b100, 0b01, (outs GPRC:$rd),
- (ins GPRC:$rs1),
- "c.srli64", "$rs1">,
+ (ins GPRC:$rs1, immzero:$imm),
+ "c.srli", "$rs1, $imm">,
Sched<[WriteShiftImm, ReadShiftImm]> {
let Constraints = "$rs1 = $rd";
let Inst{6-2} = 0;
let Inst{11-10} = 0b00;
let Inst{12} = 0;
+ let DecoderMethod = "decodeRVCInstrShiftRightHint";
}
def C_SRAI64_HINT : RVInst16CB<0b100, 0b01, (outs GPRC:$rd),
- (ins GPRC:$rs1),
- "c.srai64", "$rs1">,
+ (ins GPRC:$rs1, immzero:$imm),
+ "c.srai", "$rs1, $imm">,
Sched<[WriteShiftImm, ReadShiftImm]> {
let Constraints = "$rs1 = $rd";
let Inst{6-2} = 0;
let Inst{11-10} = 0b01;
let Inst{12} = 0;
+ let DecoderMethod = "decodeRVCInstrShiftRightHint";
}
} // Predicates = [HasStdExtZca], hasSideEffects = 0, mayLoad = 0,
@@ -701,6 +705,11 @@ def C_SRAI64_HINT : RVInst16CB<0b100, 0b01, (outs GPRC:$rd),
let Predicates = [HasStdExtZca] in {
// Just a different syntax for the c.nop hint: c.addi x0, simm6 vs c.nop simm6.
def : InstAlias<"c.addi x0, $imm", (C_NOP_HINT simm6nonzero:$imm), 0>;
+
+// Legacy aliases.
+def : InstAlias<"c.slli64 $rd", (C_SLLI64_HINT GPR:$rd, 0), 0>;
+def : InstAlias<"c.srli64 $rs1", (C_SRLI64_HINT GPRC:$rs1, 0), 0>;
+def : InstAlias<"c.srai64 $rs1", (C_SRAI64_HINT GPRC:$rs1, 0), 0>;
}
let Predicates = [HasStdExtC, HasStdExtZihintntl] in {
diff --git a/llvm/test/MC/Disassembler/RISCV/c_slli.txt b/llvm/test/MC/Disassembler/RISCV/c_slli.txt
index 25204555d84e0..d8d65efb09f3d 100644
--- a/llvm/test/MC/Disassembler/RISCV/c_slli.txt
+++ b/llvm/test/MC/Disassembler/RISCV/c_slli.txt
@@ -14,7 +14,7 @@
# RUN: -M no-aliases --show-encoding < %s 2>&1 | \
# RUN: FileCheck --check-prefix=NOHINTS %s
-# GOOD: c.slli64 zero
+# GOOD: c.slli zero, 0
# NOHINTS: invalid instruction encoding
0x02 0x00
@@ -302,7 +302,7 @@
# NOHINTS: invalid instruction encoding
0x7E 0x10
-# GOOD: c.slli64 ra
+# GOOD: c.slli ra, 0
0x82 0x00
# GOOD: c.slli ra, 1
@@ -526,7 +526,7 @@
# GOOD64: c.slli ra, 63
0xFE 0x10
-# GOOD: c.slli64 sp
+# GOOD: c.slli sp, 0
0x02 0x01
# GOOD: c.slli sp, 1
@@ -750,7 +750,7 @@
# GOOD64: c.slli sp, 63
0x7E 0x11
-# GOOD: c.slli64 gp
+# GOOD: c.slli gp, 0
0x82 0x01
# GOOD: c.slli gp, 1
@@ -974,7 +974,7 @@
# GOOD64: c.slli gp, 63
0xFE 0x11
-# GOOD: c.slli64 tp
+# GOOD: c.slli tp, 0
0x02 0x02
# GOOD: c.slli tp, 1
@@ -1198,7 +1198,7 @@
# GOOD64: c.slli tp, 63
0x7E 0x12
-# GOOD: c.slli64 t0
+# GOOD: c.slli t0, 0
0x82 0x02
# GOOD: c.slli t0, 1
@@ -1422,7 +1422,7 @@
# GOOD64: c.slli t0, 63
0xFE 0x12
-# GOOD: c.slli64 t1
+# GOOD: c.slli t1, 0
0x02 0x03
# GOOD: c.slli t1, 1
@@ -1646,7 +1646,7 @@
# GOOD64: c.slli t1, 63
0x7E 0x13
-# GOOD: c.slli64 t2
+# GOOD: c.slli t2, 0
0x82 0x03
# GOOD: c.slli t2, 1
@@ -1870,7 +1870,7 @@
# GOOD64: c.slli t2, 63
0xFE 0x13
-# GOOD: c.slli64 s0
+# GOOD: c.slli s0, 0
0x02 0x04
# GOOD: c.slli s0, 1
@@ -2094,7 +2094,7 @@
# GOOD64: c.slli s0, 63
0x7E 0x14
-# GOOD: c.slli64 s1
+# GOOD: c.slli s1, 0
0x82 0x04
# GOOD: c.slli s1, 1
@@ -2318,7 +2318,7 @@
# GOOD64: c.slli s1, 63
0xFE 0x14
-# GOOD: c.slli64 a0
+# GOOD: c.slli a0, 0
0x02 0x05
# GOOD: c.slli a0, 1
@@ -2542,7 +2542,7 @@
# GOOD64: c.slli a0, 63
0x7E 0x15
-# GOOD: c.slli64 a1
+# GOOD: c.slli a1, 0
0x82 0x05
# GOOD: c.slli a1, 1
@@ -2766,7 +2766,7 @@
# GOOD64: c.slli a1, 63
0xFE 0x15
-# GOOD: c.slli64 a2
+# GOOD: c.slli a2, 0
0x02 0x06
# GOOD: c.slli a2, 1
@@ -2990,7 +2990,7 @@
# GOOD64: c.slli a2, 63
0x7E 0x16
-# GOOD: c.slli64 a3
+# GOOD: c.slli a3, 0
0x82 0x06
# GOOD: c.slli a3, 1
@@ -3214,7 +3214,7 @@
# GOOD64: c.slli a3, 63
0xFE 0x16
-# GOOD: c.slli64 a4
+# GOOD: c.slli a4, 0
0x02 0x07
# GOOD: c.slli a4, 1
@@ -3438,7 +3438,7 @@
# GOOD64: c.slli a4, 63
0x7E 0x17
-# GOOD: c.slli64 a5
+# GOOD: c.slli a5, 0
0x82 0x07
# GOOD: c.slli a5, 1
@@ -3662,7 +3662,7 @@
# GOOD64: c.slli a5, 63
0xFE 0x17
-# GOOD: c.slli64 a6
+# GOOD: c.slli a6, 0
0x02 0x08
# GOOD: c.slli a6, 1
@@ -3886,7 +3886,7 @@
# GOOD64: c.slli a6, 63
0x7E 0x18
-# GOOD: c.slli64 a7
+# GOOD: c.slli a7, 0
0x82 0x08
# GOOD: c.slli a7, 1
@@ -4110,7 +4110,7 @@
# GOOD64: c.slli a7, 63
0xFE 0x18
-# GOOD: c.slli64 s2
+# GOOD: c.slli s2, 0
0x02 0x09
# GOOD: c.slli s2, 1
@@ -4334,7 +4334,7 @@
# GOOD64: c.slli s2, 63
0x7E 0x19
-# GOOD: c.slli64 s3
+# GOOD: c.slli s3, 0
0x82 0x09
# GOOD: c.slli s3, 1
@@ -4558,7 +4558,7 @@
# GOOD64: c.slli s3, 63
0xFE 0x19
-# GOOD: c.slli64 s4
+# GOOD: c.slli s4, 0
0x02 0x0A
# GOOD: c.slli s4, 1
@@ -4782,7 +4782,7 @@
# GOOD64: c.slli s4, 63
0x7E 0x1A
-# GOOD: c.slli64 s5
+# GOOD: c.slli s5, 0
0x82 0x0A
# GOOD: c.slli s5, 1
@@ -5006,7 +5006,7 @@
# GOOD64: c.slli s5, 63
0xFE 0x1A
-# GOOD: c.slli64 s6
+# GOOD: c.slli s6, 0
0x02 0x0B
# GOOD: c.slli s6, 1
@@ -5230,7 +5230,7 @@
# GOOD64: c.slli s6, 63
0x7E 0x1B
-# GOOD: c.slli64 s7
+# GOOD: c.slli s7, 0
0x82 0x0B
# GOOD: c.slli s7, 1
@@ -5454,7 +5454,7 @@
# GOOD64: c.slli s7, 63
0xFE 0x1B
-# GOOD: c.slli64 s8
+# GOOD: c.slli s8, 0
0x02 0x0C
# GOOD: c.slli s8, 1
@@ -5678,7 +5678,7 @@
# GOOD64: c.slli s8, 63
0x7E 0x1C
-# GOOD: c.slli64 s9
+# GOOD: c.slli s9, 0
0x82 0x0C
# GOOD: c.slli s9, 1
@@ -5902,7 +5902,7 @@
# GOOD64: c.slli s9, 63
0xFE 0x1C
-# GOOD: c.slli64 s10
+# GOOD: c.slli s10, 0
0x02 0x0D
# GOOD: c.slli s10, 1
@@ -6126,7 +6126,7 @@
# GOOD64: c.slli s10, 63
0x7E 0x1D
-# GOOD: c.slli64 s11
+# GOOD: c.slli s11, 0
0x82 0x0D
# GOOD: c.slli s11, 1
@@ -6350,7 +6350,7 @@
# GOOD64: c.slli s11, 63
0xFE 0x1D
-# GOOD: c.slli64 t3
+# GOOD: c.slli t3, 0
0x02 0x0E
# GOOD: c.slli t3, 1
@@ -6574,7 +6574,7 @@
# GOOD64: c.slli t3, 63
0x7E 0x1E
-# GOOD: c.slli64 t4
+# GOOD: c.slli t4, 0
0x82 0x0E
# GOOD: c.slli t4, 1
@@ -6798,7 +6798,7 @@
# GOOD64: c.slli t4, 63
0xFE 0x1E
-# GOOD: c.slli64 t5
+# GOOD: c.slli t5, 0
0x02 0x0F
# GOOD: c.slli t5, 1
@@ -7022,7 +7022,7 @@
# GOOD64: c.slli t5, 63
0x7E 0x1F
-# GOOD: c.slli64 t6
+# GOOD: c.slli t6, 0
0x82 0x0F
# GOOD: c.slli t6, 1
diff --git a/llvm/test/MC/RISCV/rv32c-invalid.s b/llvm/test/MC/RISCV/rv32c-invalid.s
index 413573af1c5e6..2a111340475c4 100644
--- a/llvm/test/MC/RISCV/rv32c-invalid.s
+++ b/llvm/test/MC/RISCV/rv32c-invalid.s
@@ -36,9 +36,8 @@ c.addi16sp t0, 16 # CHECK: :[[@LINE]]:13: error: register must be sp (x2)
# Out of range immediates
## uimmlog2xlennonzero
-c.slli t0, 64 # CHECK: :[[@LINE]]:12: error: immediate must be an integer in the range [1, 31]
+c.slli t0, 64 # CHECK: :[[@LINE]]:12: error: immediate must be zero
c.srli a0, 32 # CHECK: :[[@LINE]]:12: error: immediate must be an integer in the range [1, 31]
-c.srai a0, 0 # CHECK: :[[@LINE]]:12: error: immediate must be an integer in the range [1, 31]
## simm6
c.li t0, 128 # CHECK: :[[@LINE]]:10: error: immediate must be an integer in the range [-32, 31]
diff --git a/llvm/test/MC/RISCV/rv64c-invalid.s b/llvm/test/MC/RISCV/rv64c-invalid.s
index 9b0a3244f3aac..9be90cccd6941 100644
--- a/llvm/test/MC/RISCV/rv64c-invalid.s
+++ b/llvm/test/MC/RISCV/rv64c-invalid.s
@@ -14,9 +14,8 @@ c.ldsp zero, 4(sp) # CHECK: :[[@LINE]]:9: error: register must be a GPR excludi
# Out of range immediates
## uimmlog2xlennonzero
-c.slli t0, 64 # CHECK: :[[@LINE]]:12: error: immediate must be an integer in the range [1, 63]
+c.slli t0, 64 # CHECK: :[[@LINE]]:12: error: immediate must be zero
c.srli a0, -1 # CHECK: :[[@LINE]]:12: error: immediate must be an integer in the range [1, 63]
-c.srai a0, 0 # CHECK: :[[@LINE]]:12: error: immediate must be an integer in the range [1, 63]
## simm6
c.addiw t0, -33 # CHECK: :[[@LINE]]:13: error: immediate must be an integer in the range [-32, 31]
diff --git a/llvm/test/MC/RISCV/rvc-hints-invalid.s b/llvm/test/MC/RISCV/rvc-hints-invalid.s
index 2a7a6addd31ab..68772dbc1d864 100644
--- a/llvm/test/MC/RISCV/rvc-hints-invalid.s
+++ b/llvm/test/MC/RISCV/rvc-hints-invalid.s
@@ -1,7 +1,7 @@
# RUN: not llvm-mc -triple=riscv32 -mattr=+c < %s 2>&1 \
# RUN: | FileCheck -check-prefixes=CHECK,CHECK-RV32 %s
# RUN: not llvm-mc -triple=riscv64 -mattr=+c < %s 2>&1 \
-# RUN: | FileCheck -check-prefixes=CHECK,CHECK-RV64 %s
+# RUN: | FileCheck -check-prefixes=CHECK %s
c.nop 0 # CHECK: :[[@LINE]]:7: error: immediate must be non-zero in the range [-32, 31]
@@ -15,10 +15,7 @@ c.mv x0, x0 # CHECK: :[[@LINE]]:10: error: register must be a GPR excluding zero
c.add x0, x0 # CHECK: :[[@LINE]]:11: error: register must be a GPR excluding zero (x0)
-c.slli x0, 0 # CHECK-RV32: :[[@LINE]]:12: error: immediate must be an integer in the range [1, 31]
-c.slli x0, 32 # CHECK-RV32: :[[@LINE]]:12: error: immediate must be an integer in the range [1, 31]
-
-c.slli x0, 0 # CHECK-RV64: :[[@LINE]]:12: error: immediate must be an integer in the range [1, 63]
+c.slli x0, 32 # CHECK-RV32: :[[@LINE]]:12: error: immediate must be zero
c.srli64 x30 # CHECK: :[[@LINE]]:10: error: invalid operand for instruction
diff --git a/llvm/test/MC/RISCV/rvc-hints-valid.s b/llvm/test/MC/RISCV/rvc-hints-valid.s
index 5dc86d17dcc63..7fba8647a3b97 100644
--- a/llvm/test/MC/RISCV/rvc-hints-valid.s
+++ b/llvm/test/MC/RISCV/rvc-hints-valid.s
@@ -48,18 +48,34 @@ c.add x0, a0
# CHECK-ASM: encoding: [0x06,0x00]
c.slli x0, 1
-# CHECK-ASM-AND-OBJ: c.slli64 zero
+# CHECK-ASM-AND-OBJ: c.slli zero, 0
# CHECK-ASM: encoding: [0x02,0x00]
c.slli64 x0
-# CHECK-ASM-AND-OBJ: c.slli64 a0
+# CHECK-ASM-AND-OBJ: c.slli zero, 0
+# CHECK-ASM: encoding: [0x02,0x00]
+c.slli x0, 0
+
+# CHECK-ASM-AND-OBJ: c.slli a0, 0
# CHECK-ASM: encoding: [0x02,0x05]
c.slli64 a0
-# CHECK-ASM-AND-OBJ: c.srli64 a1
+# CHECK-ASM-AND-OBJ: c.slli a0, 0
+# CHECK-ASM: encoding: [0x02,0x05]
+c.slli a0, 0
+
+# CHECK-ASM-AND-OBJ: c.srli a1, 0
# CHECK-ASM: encoding: [0x81,0x81]
c.srli64 a1
-# CHECK-ASM-AND-OBJ: c.srai64 a0
+# CHECK-ASM-AND-OBJ: c.srli a1, 0
+# CHECK-ASM: encoding: [0x81,0x81]
+c.srli a1, 0
+
+# CHECK-ASM-AND-OBJ: c.srai a0, 0
# CHECK-ASM: encoding: [0x01,0x85]
c.srai64 a0
+
+# CHECK-ASM-AND-OBJ: c.srai a0, 0
+# CHECK-ASM: encoding: [0x01,0x85]
+c.srai a0, 0
More information about the llvm-commits
mailing list