Skip to content

Commit 2b2b840

Browse files
committed
[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. riscv-non-isa/riscv-asm-manual#71 Reviewed By: reames Differential Revision: https://reviews.llvm.org/D144166
1 parent efe7c4b commit 2b2b840

4 files changed

Lines changed: 53 additions & 8 deletions

File tree

llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -564,7 +564,8 @@ struct RISCVOperand final : public MCParsedAsmOperand {
564564
RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
565565
int64_t Imm;
566566
bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
567-
return IsConstantImm && isInt<5>(Imm) && VK == RISCVMCExpr::VK_RISCV_None;
567+
return IsConstantImm && isInt<5>(fixImmediateForRV32(Imm, isRV64Imm())) &&
568+
VK == RISCVMCExpr::VK_RISCV_None;
568569
}
569570

570571
bool isSImm6() const {
@@ -573,7 +574,8 @@ struct RISCVOperand final : public MCParsedAsmOperand {
573574
RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
574575
int64_t Imm;
575576
bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
576-
return IsConstantImm && isInt<6>(Imm) && VK == RISCVMCExpr::VK_RISCV_None;
577+
return IsConstantImm && isInt<6>(fixImmediateForRV32(Imm, isRV64Imm())) &&
578+
VK == RISCVMCExpr::VK_RISCV_None;
577579
}
578580

579581
bool isSImm6NonZero() const {
@@ -582,7 +584,8 @@ struct RISCVOperand final : public MCParsedAsmOperand {
582584
RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
583585
int64_t Imm;
584586
bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
585-
return IsConstantImm && isInt<6>(Imm) && (Imm != 0) &&
587+
return IsConstantImm && Imm != 0 &&
588+
isInt<6>(fixImmediateForRV32(Imm, isRV64Imm())) &&
586589
VK == RISCVMCExpr::VK_RISCV_None;
587590
}
588591

@@ -659,6 +662,14 @@ struct RISCVOperand final : public MCParsedAsmOperand {
659662
VK == RISCVMCExpr::VK_RISCV_None;
660663
}
661664

665+
// If this a RV32 and the immediate is a uimm32, sign extend it to 32 bits.
666+
// This allows writing 'addi a0, a0, 0xffffffff'.
667+
static int64_t fixImmediateForRV32(int64_t Imm, bool IsRV64Imm) {
668+
if (IsRV64Imm || !isUInt<32>(Imm))
669+
return Imm;
670+
return SignExtend64<32>(Imm);
671+
}
672+
662673
bool isSImm12() const {
663674
RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
664675
int64_t Imm;
@@ -669,7 +680,7 @@ struct RISCVOperand final : public MCParsedAsmOperand {
669680
if (!IsConstantImm)
670681
IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK);
671682
else
672-
IsValid = isInt<12>(Imm);
683+
IsValid = isInt<12>(fixImmediateForRV32(Imm, isRV64Imm()));
673684
return IsValid && ((IsConstantImm && VK == RISCVMCExpr::VK_RISCV_None) ||
674685
VK == RISCVMCExpr::VK_RISCV_LO ||
675686
VK == RISCVMCExpr::VK_RISCV_PCREL_LO ||
@@ -757,7 +768,8 @@ struct RISCVOperand final : public MCParsedAsmOperand {
757768
RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
758769
int64_t Imm;
759770
bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
760-
return IsConstantImm && isInt<5>(Imm - 1) &&
771+
return IsConstantImm &&
772+
isInt<5>(fixImmediateForRV32(Imm, isRV64Imm()) - 1) &&
761773
VK == RISCVMCExpr::VK_RISCV_None;
762774
}
763775

@@ -909,14 +921,15 @@ struct RISCVOperand final : public MCParsedAsmOperand {
909921
return Op;
910922
}
911923

912-
static void addExpr(MCInst &Inst, const MCExpr *Expr) {
924+
static void addExpr(MCInst &Inst, const MCExpr *Expr, bool IsRV64Imm) {
913925
assert(Expr && "Expr shouldn't be null!");
914926
int64_t Imm = 0;
915927
RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
916928
bool IsConstant = evaluateConstantImm(Expr, Imm, VK);
917929

918930
if (IsConstant)
919-
Inst.addOperand(MCOperand::createImm(Imm));
931+
Inst.addOperand(
932+
MCOperand::createImm(fixImmediateForRV32(Imm, IsRV64Imm)));
920933
else
921934
Inst.addOperand(MCOperand::createExpr(Expr));
922935
}
@@ -929,7 +942,7 @@ struct RISCVOperand final : public MCParsedAsmOperand {
929942

930943
void addImmOperands(MCInst &Inst, unsigned N) const {
931944
assert(N == 1 && "Invalid number of operands!");
932-
addExpr(Inst, getImm());
945+
addExpr(Inst, getImm(), isRV64Imm());
933946
}
934947

935948
void addFenceArgOperands(MCInst &Inst, unsigned N) const {

llvm/test/MC/RISCV/rv32c-only-valid.s

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,8 @@
2121
# CHECK-NO-RV32: error: instruction requires the following: RV32I Base Instruction Set{{$}}
2222
# 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{{$}}
2323
c.jal 2046
24+
25+
# CHECK-OBJ: c.addi a1, -1
26+
# CHECK-ASM: c.addi a1, -1
27+
# CHECK-ASM: encoding: [0xfd,0x15]
28+
c.addi a1, 0xffffffff
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# RUN: llvm-mc %s -triple=riscv32 -riscv-no-aliases -show-encoding \
2+
# RUN: | FileCheck -check-prefixes=CHECK-ASM,CHECK-ASM-AND-OBJ %s
3+
# RUN: llvm-mc -filetype=obj -triple=riscv32 < %s \
4+
# RUN: | llvm-objdump -M no-aliases -d -r - \
5+
# RUN: | FileCheck -check-prefixes=CHECK-ASM-AND-OBJ %s
6+
7+
# CHECK-ASM-AND-OBJ: addi a0, a1, -1
8+
# CHECK-ASM: encoding: [0x13,0x85,0xf5,0xff]
9+
addi a0, a1, 4294967295 # 0xffffffff
10+
# CHECK-ASM-AND-OBJ: ori a2, a3, -2048
11+
# CHECK-ASM: encoding: [0x13,0xe6,0x06,0x80]
12+
ori a2, a3, 0xfffff800
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# RUN: llvm-mc -triple=riscv32 -show-encoding --mattr=+v %s \
2+
# RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST
3+
# RUN: llvm-mc -triple=riscv32 -filetype=obj --mattr=+v %s \
4+
# RUN: | llvm-objdump -d --mattr=+v - \
5+
# RUN: | FileCheck %s --check-prefix=CHECK-INST
6+
7+
# For rv32, allow 32 bit constants that contains a simm5 value.
8+
9+
vadd.vi v8, v4, 0xfffffff0
10+
# CHECK-INST: vadd.vi v8, v4, -16
11+
# CHECK-ENCODING: [0x57,0x34,0x48,0x02]
12+
13+
vmsltu.vi v8, v4, 0xfffffff1
14+
# CHECK-INST: vmsleu.vi v8, v4, -16
15+
# CHECK-ENCODING: [0x57,0x34,0x48,0x72]

0 commit comments

Comments
 (0)