From fb7c6b790c7a56c8c7db3ae8f348907bed58aa8d Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Fri, 25 Jul 2025 12:49:24 -0700 Subject: [PATCH 1/3] [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 From 1ce96bdcbe78f3bfc1f0a32ab7c0d7434e66d726 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Fri, 25 Jul 2025 23:28:20 -0700 Subject: [PATCH 2/3] Fix test comment --- llvm/test/MC/RISCV/rv64c-invalid.s | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/test/MC/RISCV/rv64c-invalid.s b/llvm/test/MC/RISCV/rv64c-invalid.s index c3258dcdc805d..404e02cf50437 100644 --- a/llvm/test/MC/RISCV/rv64c-invalid.s +++ b/llvm/test/MC/RISCV/rv64c-invalid.s @@ -13,7 +13,7 @@ c.ldsp zero, 4(sp) # CHECK: :[[@LINE]]:9: error: register must be a GPR excludi # Out of range immediates -## uimmlog2xlennonzero +## uimmlog2xlen c.slli t0, 64 # CHECK: :[[@LINE]]:12: error: immediate must be an integer in the range [0, 63] c.srli a0, -1 # CHECK: :[[@LINE]]:12: error: immediate must be an integer in the range [0, 63] From 932d03f43ac0a3c6ce85ffb56c99612b0e5bc728 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Fri, 25 Jul 2025 23:30:07 -0700 Subject: [PATCH 3/3] Fix test comment --- llvm/test/MC/RISCV/rv32c-invalid.s | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/test/MC/RISCV/rv32c-invalid.s b/llvm/test/MC/RISCV/rv32c-invalid.s index 5e6c46799590b..5214747e63b86 100644 --- a/llvm/test/MC/RISCV/rv32c-invalid.s +++ b/llvm/test/MC/RISCV/rv32c-invalid.s @@ -35,7 +35,7 @@ c.addi16sp t0, 16 # CHECK: :[[@LINE]]:13: error: register must be sp (x2) # Out of range immediates -## uimmlog2xlennonzero +## uimmlog2xlenn c.slli t0, 64 # CHECK: :[[@LINE]]:12: error: immediate must be an integer in the range [0, 31] c.srli a0, 32 # CHECK: :[[@LINE]]:12: error: immediate must be an integer in the range [0, 31]