[llvm] 2b2b840 - [RISCV] For rv32, accept constants like 0xfffff800 as a valid simm12.

Craig Topper via llvm-commits llvm-commits at lists.llvm.org
Fri Feb 17 10:53:53 PST 2023


Author: Craig Topper
Date: 2023-02-17T10:53:44-08:00
New Revision: 2b2b8409e6848361577be404bd0ae47a097f0e0c

URL: https://github.com/llvm/llvm-project/commit/2b2b8409e6848361577be404bd0ae47a097f0e0c
DIFF: https://github.com/llvm/llvm-project/commit/2b2b8409e6848361577be404bd0ae47a097f0e0c.diff

LOG: [RISCV] For rv32, accept constants like 0xfffff800 as a valid simm12.

Internally we store constants in int64_t after parsing, but this is
kind of an implementation detail. If we only supported rv32, we might
have chosen int32_t.

For rv32, I think it makes sense to accept the constants that we
would accept if int32_t was the internal type. In fact we already
do this for the `li` alias. This patch extends this to sign
extended constants for other instructions.

This matches the GNU assembler. The difference between LLVM and gcc
was previously noted here. https://github.com/riscv-non-isa/riscv-asm-manual/pull/71

Reviewed By: reames

Differential Revision: https://reviews.llvm.org/D144166

Added: 
    llvm/test/MC/RISCV/rv32i-only-valid.s
    llvm/test/MC/RISCV/rvv/rv32-immediate.s

Modified: 
    llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
    llvm/test/MC/RISCV/rv32c-only-valid.s

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
index 1ff6188e74a01..d7529a7cfabe1 100644
--- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
+++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
@@ -564,7 +564,8 @@ struct RISCVOperand final : public MCParsedAsmOperand {
     RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
     int64_t Imm;
     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
-    return IsConstantImm && isInt<5>(Imm) && VK == RISCVMCExpr::VK_RISCV_None;
+    return IsConstantImm && isInt<5>(fixImmediateForRV32(Imm, isRV64Imm())) &&
+           VK == RISCVMCExpr::VK_RISCV_None;
   }
 
   bool isSImm6() const {
@@ -573,7 +574,8 @@ struct RISCVOperand final : public MCParsedAsmOperand {
     RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
     int64_t Imm;
     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
-    return IsConstantImm && isInt<6>(Imm) && VK == RISCVMCExpr::VK_RISCV_None;
+    return IsConstantImm && isInt<6>(fixImmediateForRV32(Imm, isRV64Imm())) &&
+           VK == RISCVMCExpr::VK_RISCV_None;
   }
 
   bool isSImm6NonZero() const {
@@ -582,7 +584,8 @@ struct RISCVOperand final : public MCParsedAsmOperand {
     RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
     int64_t Imm;
     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
-    return IsConstantImm && isInt<6>(Imm) && (Imm != 0) &&
+    return IsConstantImm && Imm != 0 &&
+           isInt<6>(fixImmediateForRV32(Imm, isRV64Imm())) &&
            VK == RISCVMCExpr::VK_RISCV_None;
   }
 
@@ -659,6 +662,14 @@ struct RISCVOperand final : public MCParsedAsmOperand {
            VK == RISCVMCExpr::VK_RISCV_None;
   }
 
+  // If this a RV32 and the immediate is a uimm32, sign extend it to 32 bits.
+  // This allows writing 'addi a0, a0, 0xffffffff'.
+  static int64_t fixImmediateForRV32(int64_t Imm, bool IsRV64Imm) {
+    if (IsRV64Imm || !isUInt<32>(Imm))
+      return Imm;
+    return SignExtend64<32>(Imm);
+  }
+
   bool isSImm12() const {
     RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
     int64_t Imm;
@@ -669,7 +680,7 @@ struct RISCVOperand final : public MCParsedAsmOperand {
     if (!IsConstantImm)
       IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK);
     else
-      IsValid = isInt<12>(Imm);
+      IsValid = isInt<12>(fixImmediateForRV32(Imm, isRV64Imm()));
     return IsValid && ((IsConstantImm && VK == RISCVMCExpr::VK_RISCV_None) ||
                        VK == RISCVMCExpr::VK_RISCV_LO ||
                        VK == RISCVMCExpr::VK_RISCV_PCREL_LO ||
@@ -757,7 +768,8 @@ struct RISCVOperand final : public MCParsedAsmOperand {
     RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
     int64_t Imm;
     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
-    return IsConstantImm && isInt<5>(Imm - 1) &&
+    return IsConstantImm &&
+           isInt<5>(fixImmediateForRV32(Imm, isRV64Imm()) - 1) &&
            VK == RISCVMCExpr::VK_RISCV_None;
   }
 
@@ -909,14 +921,15 @@ struct RISCVOperand final : public MCParsedAsmOperand {
     return Op;
   }
 
-  static void addExpr(MCInst &Inst, const MCExpr *Expr) {
+  static void addExpr(MCInst &Inst, const MCExpr *Expr, bool IsRV64Imm) {
     assert(Expr && "Expr shouldn't be null!");
     int64_t Imm = 0;
     RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
     bool IsConstant = evaluateConstantImm(Expr, Imm, VK);
 
     if (IsConstant)
-      Inst.addOperand(MCOperand::createImm(Imm));
+      Inst.addOperand(
+          MCOperand::createImm(fixImmediateForRV32(Imm, IsRV64Imm)));
     else
       Inst.addOperand(MCOperand::createExpr(Expr));
   }
@@ -929,7 +942,7 @@ struct RISCVOperand final : public MCParsedAsmOperand {
 
   void addImmOperands(MCInst &Inst, unsigned N) const {
     assert(N == 1 && "Invalid number of operands!");
-    addExpr(Inst, getImm());
+    addExpr(Inst, getImm(), isRV64Imm());
   }
 
   void addFenceArgOperands(MCInst &Inst, unsigned N) const {

diff  --git a/llvm/test/MC/RISCV/rv32c-only-valid.s b/llvm/test/MC/RISCV/rv32c-only-valid.s
index 9409cd83eb1b0..1110deab1fa78 100644
--- a/llvm/test/MC/RISCV/rv32c-only-valid.s
+++ b/llvm/test/MC/RISCV/rv32c-only-valid.s
@@ -21,3 +21,8 @@
 # CHECK-NO-RV32: error: instruction requires the following: RV32I Base Instruction Set{{$}}
 # CHECK-NO-RV32-AND-EXT: error: instruction requires the following: 'C' (Compressed Instructions) or 'Zca' (part of the C extension, excluding compressed floating point loads/stores), RV32I Base Instruction Set{{$}}
 c.jal 2046
+
+# CHECK-OBJ: c.addi a1, -1
+# CHECK-ASM: c.addi a1, -1
+# CHECK-ASM: encoding: [0xfd,0x15]
+c.addi a1, 0xffffffff

diff  --git a/llvm/test/MC/RISCV/rv32i-only-valid.s b/llvm/test/MC/RISCV/rv32i-only-valid.s
new file mode 100644
index 0000000000000..1e95f52750b64
--- /dev/null
+++ b/llvm/test/MC/RISCV/rv32i-only-valid.s
@@ -0,0 +1,12 @@
+# RUN: llvm-mc %s -triple=riscv32 -riscv-no-aliases -show-encoding \
+# RUN:     | FileCheck -check-prefixes=CHECK-ASM,CHECK-ASM-AND-OBJ %s
+# RUN: llvm-mc -filetype=obj -triple=riscv32 < %s \
+# RUN:     | llvm-objdump -M no-aliases -d -r - \
+# RUN:     | FileCheck -check-prefixes=CHECK-ASM-AND-OBJ %s
+
+# CHECK-ASM-AND-OBJ: addi a0, a1, -1
+# CHECK-ASM: encoding: [0x13,0x85,0xf5,0xff]
+addi a0, a1, 4294967295 # 0xffffffff
+# CHECK-ASM-AND-OBJ: ori a2, a3, -2048
+# CHECK-ASM: encoding: [0x13,0xe6,0x06,0x80]
+ori a2, a3, 0xfffff800

diff  --git a/llvm/test/MC/RISCV/rvv/rv32-immediate.s b/llvm/test/MC/RISCV/rvv/rv32-immediate.s
new file mode 100644
index 0000000000000..44df34f2f21d4
--- /dev/null
+++ b/llvm/test/MC/RISCV/rvv/rv32-immediate.s
@@ -0,0 +1,15 @@
+# RUN: llvm-mc -triple=riscv32 -show-encoding --mattr=+v %s \
+# RUN:        | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST
+# RUN: llvm-mc -triple=riscv32 -filetype=obj --mattr=+v %s \
+# RUN:        | llvm-objdump -d --mattr=+v - \
+# RUN:        | FileCheck %s --check-prefix=CHECK-INST
+
+# For rv32, allow 32 bit constants that contains a simm5 value.
+
+vadd.vi v8, v4, 0xfffffff0
+# CHECK-INST: vadd.vi v8, v4, -16
+# CHECK-ENCODING: [0x57,0x34,0x48,0x02]
+
+vmsltu.vi v8, v4, 0xfffffff1
+# CHECK-INST: vmsleu.vi v8, v4, -16
+# CHECK-ENCODING: [0x57,0x34,0x48,0x72]


        


More information about the llvm-commits mailing list