[llvm] d045f1d - [RISCV] Allow LI with symbol difference as constant
Job Noorman via llvm-commits
llvm-commits at lists.llvm.org
Wed May 17 02:35:39 PDT 2023
Author: Job Noorman
Date: 2023-05-17T11:35:20+02:00
New Revision: d045f1d393317962251ba6dc58e3f8edc7e2fd99
URL: https://github.com/llvm/llvm-project/commit/d045f1d393317962251ba6dc58e3f8edc7e2fd99
DIFF: https://github.com/llvm/llvm-project/commit/d045f1d393317962251ba6dc58e3f8edc7e2fd99.diff
LOG: [RISCV] Allow LI with symbol difference as constant
This patch lets the assembler accept code like the following:
.Lbuf: ...
.set .Lbuf_len, . - .Lbuf
li a0, .Lbuf_len
It works by translating such instances of LI into an ADDI and inserting
the correct constant value via a new fixup.
Note that this means that the constant value is restricted to 12 bits
since we cannot insert new instructions during the relaxation stage.
Binutils seems to have the same restriction though.
This patch also fixes a small issue where the SMLoc of an LI wasn't
propagated when translated to ADDI. While this is technically unrelated
to the main functionality of this patch, it improves error messages
related to the new use of LI.
This patch does _not_ allow I-type instructions to take such symbolic
constants as well. While technically possible (and allowed by binutils),
it's probably better to implement this in another patch.
Fixes #57461
Reviewed By: asb
Differential Revision: https://reviews.llvm.org/D135960
Added:
Modified:
llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp
llvm/lib/Target/RISCV/MCTargetDesc/RISCVFixupKinds.h
llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
llvm/test/MC/RISCV/fixups-invalid.s
llvm/test/MC/RISCV/rv32i-aliases-valid.s
llvm/test/MC/RISCV/rv64i-aliases-valid.s
Removed:
################################################################################
diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
index 9d45b7299a6e8..4c1bd2a6e6ff1 100644
--- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
+++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
@@ -246,6 +246,7 @@ class RISCVAsmParser : public MCTargetAsmParser {
static bool classifySymbolRef(const MCExpr *Expr,
RISCVMCExpr::VariantKind &Kind);
+ static bool isSymbolDiff(const MCExpr *Expr);
RISCVAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
const MCInstrInfo &MII, const MCTargetOptions &Options)
@@ -562,8 +563,12 @@ struct RISCVOperand final : public MCParsedAsmOperand {
return true;
// Given only Imm, ensuring that the actually specified constant is either
// a signed or unsigned 64-bit number is unfortunately impossible.
- return IsConstantImm && VK == RISCVMCExpr::VK_RISCV_None &&
- (isRV64Imm() || (isInt<32>(Imm) || isUInt<32>(Imm)));
+ if (IsConstantImm) {
+ return VK == RISCVMCExpr::VK_RISCV_None &&
+ (isRV64Imm() || (isInt<32>(Imm) || isUInt<32>(Imm)));
+ }
+
+ return RISCVAsmParser::isSymbolDiff(getImm());
}
bool isUImmLog2XLen() const {
@@ -2547,6 +2552,16 @@ bool RISCVAsmParser::classifySymbolRef(const MCExpr *Expr,
return false;
}
+bool RISCVAsmParser::isSymbolDiff(const MCExpr *Expr) {
+ MCValue Res;
+ MCFixup Fixup;
+ if (Expr->evaluateAsRelocatable(Res, nullptr, &Fixup)) {
+ return Res.getRefKind() == RISCVMCExpr::VK_RISCV_None && Res.getSymA() &&
+ Res.getSymB();
+ }
+ return false;
+}
+
bool RISCVAsmParser::ParseDirective(AsmToken DirectiveID) {
// This returns false if this function recognizes the directive
// regardless of whether it is successfully handles or reports an
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp
index 8ec2ae918335c..68dfb6852631c 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp
@@ -53,6 +53,7 @@ RISCVAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
// name offset bits flags
{"fixup_riscv_hi20", 12, 20, 0},
{"fixup_riscv_lo12_i", 20, 12, 0},
+ {"fixup_riscv_12_i", 20, 12, 0},
{"fixup_riscv_lo12_s", 0, 32, 0},
{"fixup_riscv_pcrel_hi20", 12, 20,
MCFixupKindInfo::FKF_IsPCRel | MCFixupKindInfo::FKF_IsTarget},
@@ -421,6 +422,12 @@ static uint64_t adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
case RISCV::fixup_riscv_pcrel_lo12_i:
case RISCV::fixup_riscv_tprel_lo12_i:
return Value & 0xfff;
+ case RISCV::fixup_riscv_12_i:
+ if (!isInt<12>(Value)) {
+ Ctx.reportError(Fixup.getLoc(),
+ "operand must be a constant 12-bit integer");
+ }
+ return Value & 0xfff;
case RISCV::fixup_riscv_lo12_s:
case RISCV::fixup_riscv_pcrel_lo12_s:
case RISCV::fixup_riscv_tprel_lo12_s:
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVFixupKinds.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVFixupKinds.h
index d254f3a06e264..5727aab3cd4ca 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVFixupKinds.h
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVFixupKinds.h
@@ -20,6 +20,8 @@ enum Fixups {
fixup_riscv_hi20 = FirstTargetFixupKind,
// 12-bit fixup corresponding to %lo(foo) for instructions like addi
fixup_riscv_lo12_i,
+ // 12-bit fixup corresponding to foo-bar for instructions like addi
+ fixup_riscv_12_i,
// 12-bit fixup corresponding to %lo(foo) for the S-type store instructions
fixup_riscv_lo12_s,
// 20-bit fixup corresponding to %pcrel_hi(foo) for instructions like auipc
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
index 831c1e788dd45..9de4178e7bdef 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
@@ -448,6 +448,8 @@ unsigned RISCVMCCodeEmitter::getImmOpValue(const MCInst &MI, unsigned OpNo,
FixupKind = RISCV::fixup_riscv_rvc_jump;
} else if (MIFrm == RISCVII::InstFormatCB) {
FixupKind = RISCV::fixup_riscv_rvc_branch;
+ } else if (MIFrm == RISCVII::InstFormatI) {
+ FixupKind = RISCV::fixup_riscv_12_i;
}
}
diff --git a/llvm/test/MC/RISCV/fixups-invalid.s b/llvm/test/MC/RISCV/fixups-invalid.s
index 55ced21e1c9d3..44313e0164e36 100644
--- a/llvm/test/MC/RISCV/fixups-invalid.s
+++ b/llvm/test/MC/RISCV/fixups-invalid.s
@@ -5,3 +5,11 @@
.byte foo # CHECK: [[@LINE]]:7: error: 1-byte data relocations not supported
.2byte foo # CHECK: [[@LINE]]:8: error: 2-byte data relocations not supported
+
+# Test that using li with a symbol
diff erence constant rejects values that
+# cannot fit in a signed 12-bit integer.
+.Lbuf: .skip (1 << 11)
+.Lbuf_end:
+.equ CONST, .Lbuf_end - .Lbuf
+# CHECK: error: operand must be a constant 12-bit integer
+li a0, CONST
diff --git a/llvm/test/MC/RISCV/rv32i-aliases-valid.s b/llvm/test/MC/RISCV/rv32i-aliases-valid.s
index fb4004d9fe75b..c0e4be1f2d0ac 100644
--- a/llvm/test/MC/RISCV/rv32i-aliases-valid.s
+++ b/llvm/test/MC/RISCV/rv32i-aliases-valid.s
@@ -1,7 +1,7 @@
# RUN: llvm-mc %s -triple=riscv32 -riscv-no-aliases \
-# RUN: | FileCheck -check-prefixes=CHECK-EXPAND,CHECK-INST %s
+# RUN: | FileCheck -check-prefixes=CHECK-EXPAND,CHECK-INST,CHECK-ASM-NOALIAS %s
# RUN: llvm-mc %s -triple=riscv32 \
-# RUN: | FileCheck -check-prefixes=CHECK-EXPAND,CHECK-ALIAS %s
+# RUN: | FileCheck -check-prefixes=CHECK-EXPAND,CHECK-ALIAS,CHECK-ASM %s
# RUN: llvm-mc -filetype=obj -triple riscv32 < %s \
# RUN: | llvm-objdump -M no-aliases -d -r - \
# RUN: | FileCheck -check-prefixes=CHECK-OBJ-NOALIAS,CHECK-EXPAND,CHECK-INST %s
@@ -17,6 +17,10 @@
# Needed for testing valid %pcrel_lo expressions
.Lpcrel_hi0: auipc a0, %pcrel_hi(foo)
+# Needed for testing li with a symbol
diff erence
+.Lbuf: .skip 8
+.Lbuf_end:
+
# CHECK-INST: addi a0, zero, 0
# CHECK-ALIAS: li a0, 0
li x10, 0
@@ -103,6 +107,12 @@ li a0, CONST+1
# CHECK-EXPAND: addi a0, a0, 801
li a0, CONST
+.equ CONST, .Lbuf_end - .Lbuf
+# CHECK-ASM: li a0, CONST
+# CHECK-ASM-NOALIAS: addi a0, zero, CONST
+# CHECK-OBJ-NOALIAS: addi a0, zero, 8
+li a0, CONST
+
# CHECK-INST: csrrs t4, instreth, zero
# CHECK-ALIAS: rdinstreth t4
rdinstreth x29
diff --git a/llvm/test/MC/RISCV/rv64i-aliases-valid.s b/llvm/test/MC/RISCV/rv64i-aliases-valid.s
index acdc083135554..b62ee3824e232 100644
--- a/llvm/test/MC/RISCV/rv64i-aliases-valid.s
+++ b/llvm/test/MC/RISCV/rv64i-aliases-valid.s
@@ -1,7 +1,7 @@
# RUN: llvm-mc %s -triple=riscv64 -riscv-no-aliases \
-# RUN: | FileCheck -check-prefixes=CHECK-EXPAND,CHECK-INST %s
+# RUN: | FileCheck -check-prefixes=CHECK-EXPAND,CHECK-INST,CHECK-ASM-NOALIAS %s
# RUN: llvm-mc %s -triple=riscv64 \
-# RUN: | FileCheck -check-prefixes=CHECK-EXPAND,CHECK-ALIAS %s
+# RUN: | FileCheck -check-prefixes=CHECK-EXPAND,CHECK-ALIAS,CHECK-ASM %s
# RUN: llvm-mc -filetype=obj -triple riscv64 < %s \
# RUN: | llvm-objdump -M no-aliases -d - \
# RUN: | FileCheck -check-prefixes=CHECK-OBJ-NOALIAS,CHECK-EXPAND,CHECK-INST %s
@@ -20,6 +20,10 @@
# Needed for testing valid %pcrel_lo expressions
.Lpcrel_hi0: auipc a0, %pcrel_hi(foo)
+# Needed for testing li with a symbol
diff erence
+.Lbuf: .skip 8
+.Lbuf_end:
+
# CHECK-INST: addi a0, zero, 0
# CHECK-ALIAS: li a0, 0
li x10, 0
@@ -215,6 +219,12 @@ li a0, CONST
# CHECK-EXPAND: addiw a0, a0, 801
li a0, CONST
+.equ CONST, .Lbuf_end - .Lbuf
+# CHECK-ASM: li a0, CONST
+# CHECK-ASM-NOALIAS: addi a0, zero, CONST
+# CHECK-OBJ-NOALIAS: addi a0, zero, 8
+li a0, CONST
+
# CHECK-INST: subw t6, zero, ra
# CHECK-ALIAS: negw t6, ra
negw x31, x1
More information about the llvm-commits
mailing list