[llvm] [RISCV] Add symbol parsing support for XAndesPerf branch and gp-related instructions (PR #137748)
Jim Lin via llvm-commits
llvm-commits at lists.llvm.org
Mon Apr 28 20:53:06 PDT 2025
https://github.com/tclin914 created https://github.com/llvm/llvm-project/pull/137748
This patch adds support for parsing symbols in the XAndesPerf branch immediate and gp-related instructions. The branch immediate instructions use `R_RISCV_NDS_BRANCH_10` relocation. The gp-related instructions use `R_RISCV_NDS_GPREL_*` relocations to allow linker to calculate the offset from gp to the symbol.
>From 0a88c79b7eb5495f6ff8d424196dd37c0baa41d7 Mon Sep 17 00:00:00 2001
From: Jim Lin <jim at andestech.com>
Date: Mon, 31 Mar 2025 13:30:47 +0800
Subject: [PATCH] [RISCV] Add relocation support for XAndesperf branch and
gp-related instructions
---
.../ELFRelocs/RISCV_nonstandard.def | 11 ++
.../Target/RISCV/AsmParser/RISCVAsmParser.cpp | 36 ++----
.../RISCV/MCTargetDesc/RISCVAsmBackend.cpp | 18 +++
.../Target/RISCV/MCTargetDesc/RISCVBaseInfo.h | 17 ++-
.../MCTargetDesc/RISCVELFObjectWriter.cpp | 2 +
.../RISCV/MCTargetDesc/RISCVFixupKinds.h | 4 +
.../RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp | 18 +++
llvm/lib/Target/RISCV/RISCVInstrFormats.td | 103 ++++++++++--------
llvm/lib/Target/RISCV/RISCVInstrInfo.td | 17 ++-
llvm/lib/Target/RISCV/RISCVInstrInfoXAndes.td | 66 +++++------
llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td | 5 -
llvm/test/MC/RISCV/custom_reloc.s | 13 +++
.../MC/RISCV/xandesperf-fixups-diagnostics.s | 13 +++
llvm/test/MC/RISCV/xandesperf-fixups.s | 33 ++++++
llvm/test/MC/RISCV/xandesperf-relocation.s | 66 +++++++++++
.../MC/RISCV/xandesperf-rv64-relocation.s | 26 +++++
16 files changed, 330 insertions(+), 118 deletions(-)
create mode 100644 llvm/test/MC/RISCV/xandesperf-fixups-diagnostics.s
create mode 100644 llvm/test/MC/RISCV/xandesperf-fixups.s
create mode 100644 llvm/test/MC/RISCV/xandesperf-relocation.s
create mode 100644 llvm/test/MC/RISCV/xandesperf-rv64-relocation.s
diff --git a/llvm/include/llvm/BinaryFormat/ELFRelocs/RISCV_nonstandard.def b/llvm/include/llvm/BinaryFormat/ELFRelocs/RISCV_nonstandard.def
index 7ae3d3f205772..7437533d5041b 100644
--- a/llvm/include/llvm/BinaryFormat/ELFRelocs/RISCV_nonstandard.def
+++ b/llvm/include/llvm/BinaryFormat/ELFRelocs/RISCV_nonstandard.def
@@ -26,3 +26,14 @@ ELF_RISCV_NONSTANDARD_RELOC(QUALCOMM, R_RISCV_QC_ABS20_U, 192)
ELF_RISCV_NONSTANDARD_RELOC(QUALCOMM, R_RISCV_QC_E_BRANCH, 193)
ELF_RISCV_NONSTANDARD_RELOC(QUALCOMM, R_RISCV_QC_E_32, 194)
ELF_RISCV_NONSTANDARD_RELOC(QUALCOMM, R_RISCV_QC_E_JUMP_PLT, 195)
+
+// Andes Nonstandard Relocations
+ELF_RISCV_NONSTANDARD_RELOC(ANDES, R_RISCV_NDS_BRANCH_10, 241)
+ELF_RISCV_NONSTANDARD_RELOC(ANDES, R_RISCV_NDS_GPREL_18S0_I, 246)
+ELF_RISCV_NONSTANDARD_RELOC(ANDES, R_RISCV_NDS_GPREL_17S1_I, 247)
+ELF_RISCV_NONSTANDARD_RELOC(ANDES, R_RISCV_NDS_GPREL_17S2_I, 248)
+ELF_RISCV_NONSTANDARD_RELOC(ANDES, R_RISCV_NDS_GPREL_17S3_I, 249)
+ELF_RISCV_NONSTANDARD_RELOC(ANDES, R_RISCV_NDS_GPREL_18S0_S, 250)
+ELF_RISCV_NONSTANDARD_RELOC(ANDES, R_RISCV_NDS_GPREL_17S1_S, 251)
+ELF_RISCV_NONSTANDARD_RELOC(ANDES, R_RISCV_NDS_GPREL_17S2_S, 252)
+ELF_RISCV_NONSTANDARD_RELOC(ANDES, R_RISCV_NDS_GPREL_17S3_S, 253)
diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
index 9bc4734815364..fa11268bec835 100644
--- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
+++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
@@ -533,14 +533,14 @@ struct RISCVOperand final : public MCParsedAsmOperand {
}
// True if operand is a symbol with no modifiers, or a constant with no
- // modifiers and isShiftedInt<N-1, 1>(Op).
- template <int N> bool isBareSimmNLsb0() const {
+ // modifiers and isShiftedInt<N-K, K>(Op).
+ template <int N, int K> bool isBareSimmNLsbK() const {
if (!isImm())
return false;
int64_t Imm;
if (evaluateConstantImm(getImm(), Imm))
- return isShiftedInt<N - 1, 1>(fixImmediateForRV32(Imm, isRV64Imm()));
+ return isShiftedInt<N - K, K>(fixImmediateForRV32(Imm, isRV64Imm()));
RISCVMCExpr::Specifier VK = RISCVMCExpr::VK_None;
return RISCVAsmParser::classifySymbolRef(getImm(), VK) &&
@@ -852,10 +852,6 @@ struct RISCVOperand final : public MCParsedAsmOperand {
return SignExtend64<32>(Imm);
}
- bool isSImm11Lsb0() const {
- return isSImmPred([](int64_t Imm) { return isShiftedInt<10, 1>(Imm); });
- }
-
bool isSImm12() const {
if (!isImm())
return false;
@@ -948,22 +944,6 @@ struct RISCVOperand final : public MCParsedAsmOperand {
[](int64_t Imm) { return Imm != INT64_MIN && isInt<5>(Imm - 1); });
}
- bool isSImm18() const {
- return isSImmPred([](int64_t Imm) { return isInt<18>(Imm); });
- }
-
- bool isSImm18Lsb0() const {
- return isSImmPred([](int64_t Imm) { return isShiftedInt<17, 1>(Imm); });
- }
-
- bool isSImm19Lsb00() const {
- return isSImmPred([](int64_t Imm) { return isShiftedInt<17, 2>(Imm); });
- }
-
- bool isSImm20Lsb000() const {
- return isSImmPred([](int64_t Imm) { return isShiftedInt<17, 3>(Imm); });
- }
-
bool isSImm32Lsb0() const {
return isSImmPred([](int64_t Imm) { return isShiftedInt<31, 1>(Imm); });
}
@@ -1535,7 +1515,7 @@ bool RISCVAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
case Match_InvalidSImm11:
return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 10),
(1 << 10) - 1);
- case Match_InvalidSImm11Lsb0:
+ case Match_InvalidBareSImm11Lsb0:
return generateImmOutOfRangeError(
Operands, ErrorInfo, -(1 << 10), (1 << 10) - 2,
"immediate must be a multiple of 2 bytes in the range");
@@ -1611,18 +1591,18 @@ bool RISCVAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
(1 << 4),
"immediate must be in the range");
}
- case Match_InvalidSImm18:
+ case Match_InvalidBareSImm18:
return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 17),
(1 << 17) - 1);
- case Match_InvalidSImm18Lsb0:
+ case Match_InvalidBareSImm18Lsb0:
return generateImmOutOfRangeError(
Operands, ErrorInfo, -(1 << 17), (1 << 17) - 2,
"immediate must be a multiple of 2 bytes in the range");
- case Match_InvalidSImm19Lsb00:
+ case Match_InvalidBareSImm19Lsb00:
return generateImmOutOfRangeError(
Operands, ErrorInfo, -(1 << 18), (1 << 18) - 4,
"immediate must be a multiple of 4 bytes in the range");
- case Match_InvalidSImm20Lsb000:
+ case Match_InvalidBareSImm20Lsb000:
return generateImmOutOfRangeError(
Operands, ErrorInfo, -(1 << 19), (1 << 19) - 8,
"immediate must be a multiple of 8 bytes in the range");
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp
index d8cfeb07e52b6..43a93e64aee6e 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp
@@ -88,6 +88,9 @@ MCFixupKindInfo RISCVAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
{"fixup_riscv_qc_e_32", 16, 32, 0},
{"fixup_riscv_qc_abs20_u", 12, 20, 0},
{"fixup_riscv_qc_e_jump_plt", 0, 48, MCFixupKindInfo::FKF_IsPCRel},
+
+ // Andes fixups
+ {"fixup_riscv_nds_branch_10", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
};
static_assert((std::size(Infos)) == RISCV::NumTargetFixupKinds,
"Not all fixup kinds added to Infos array");
@@ -568,6 +571,21 @@ static uint64_t adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
(Bit15_13 << 17) | (Bit4_1 << 8) | (Bit11 << 7);
return Value;
}
+ case RISCV::fixup_riscv_nds_branch_10: {
+ if (!isInt<11>(Value))
+ Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
+ if (Value & 0x1)
+ Ctx.reportError(Fixup.getLoc(), "fixup value must be 2-byte aligned");
+ // Need to extract imm[10], imm[9:5], imm[4:1] from the 11-bit Value.
+ unsigned Sbit = (Value >> 10) & 0x1;
+ unsigned Hi5 = (Value >> 5) & 0x1f;
+ unsigned Lo4 = (Value >> 1) & 0xf;
+ // Inst{31} = Sbit;
+ // Inst{29-25} = Hi5;
+ // Inst{11-8} = Lo4;
+ Value = (Sbit << 31) | (Hi5 << 25) | (Lo4 << 8);
+ return Value;
+ }
}
}
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
index 6ef94fb5e93da..545bfea66ea8f 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
@@ -56,12 +56,21 @@ enum {
InstFormatQC_EB = 24,
InstFormatQC_EJ = 25,
InstFormatQC_ES = 26,
- InstFormatOther = 31,
-
- InstFormatMask = 31,
+ InstFormatNDS_BRANCH_10 = 27,
+ InstFormatNDS_GPREL_18S0_I = 28,
+ InstFormatNDS_GPREL_17S1_I = 29,
+ InstFormatNDS_GPREL_17S2_I = 30,
+ InstFormatNDS_GPREL_17S3_I = 31,
+ InstFormatNDS_GPREL_18S0_S = 32,
+ InstFormatNDS_GPREL_17S1_S = 33,
+ InstFormatNDS_GPREL_17S2_S = 34,
+ InstFormatNDS_GPREL_17S3_S = 35,
+ InstFormatOther = 63,
+
+ InstFormatMask = 63,
InstFormatShift = 0,
- ConstraintShift = InstFormatShift + 5,
+ ConstraintShift = InstFormatShift + 6,
VS2Constraint = 0b001 << ConstraintShift,
VS1Constraint = 0b010 << ConstraintShift,
VMConstraint = 0b100 << ConstraintShift,
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFObjectWriter.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFObjectWriter.cpp
index 35e75489794f7..ed6bbc9fa9a6a 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFObjectWriter.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFObjectWriter.cpp
@@ -108,6 +108,8 @@ unsigned RISCVELFObjectWriter::getRelocType(MCContext &Ctx,
return ELF::R_RISCV_QC_E_BRANCH;
case RISCV::fixup_riscv_qc_e_jump_plt:
return ELF::R_RISCV_QC_E_JUMP_PLT;
+ case RISCV::fixup_riscv_nds_branch_10:
+ return ELF::R_RISCV_NDS_BRANCH_10;
}
}
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVFixupKinds.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVFixupKinds.h
index 80fbed8d10f99..0bdb35e2c573b 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVFixupKinds.h
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVFixupKinds.h
@@ -56,6 +56,10 @@ enum Fixups {
// 32-bit fixup for symbol references in the 48-bit qc.j/qc.jal instructions
fixup_riscv_qc_e_jump_plt,
+ // Andes specific fixups
+ // 10-bit fixup for symbol references in the xandesperf branch instruction
+ fixup_riscv_nds_branch_10,
+
// Used as a sentinel, must be the last
fixup_riscv_invalid,
NumTargetFixupKinds = fixup_riscv_invalid - FirstTargetFixupKind
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
index 7486618782e6c..dec98e1028124 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
@@ -677,6 +677,24 @@ uint64_t RISCVMCCodeEmitter::getImmOpValue(const MCInst &MI, unsigned OpNo,
FixupKind = RISCV::fixup_riscv_qc_e_32;
} else if (MIFrm == RISCVII::InstFormatQC_EJ) {
FixupKind = RISCV::fixup_riscv_qc_e_jump_plt;
+ } else if (MIFrm == RISCVII::InstFormatNDS_BRANCH_10) {
+ FixupKind = RISCV::fixup_riscv_nds_branch_10;
+ } else if (MIFrm == RISCVII::InstFormatNDS_GPREL_18S0_I) {
+ FixupKind = ELF::R_RISCV_NDS_GPREL_18S0_I;
+ } else if (MIFrm == RISCVII::InstFormatNDS_GPREL_17S1_I) {
+ FixupKind = ELF::R_RISCV_NDS_GPREL_17S1_I;
+ } else if (MIFrm == RISCVII::InstFormatNDS_GPREL_17S2_I) {
+ FixupKind = ELF::R_RISCV_NDS_GPREL_17S2_I;
+ } else if (MIFrm == RISCVII::InstFormatNDS_GPREL_17S3_I) {
+ FixupKind = ELF::R_RISCV_NDS_GPREL_17S3_I;
+ } else if (MIFrm == RISCVII::InstFormatNDS_GPREL_18S0_S) {
+ FixupKind = ELF::R_RISCV_NDS_GPREL_18S0_S;
+ } else if (MIFrm == RISCVII::InstFormatNDS_GPREL_17S1_S) {
+ FixupKind = ELF::R_RISCV_NDS_GPREL_17S1_S;
+ } else if (MIFrm == RISCVII::InstFormatNDS_GPREL_17S2_S) {
+ FixupKind = ELF::R_RISCV_NDS_GPREL_17S2_S;
+ } else if (MIFrm == RISCVII::InstFormatNDS_GPREL_17S3_S) {
+ FixupKind = ELF::R_RISCV_NDS_GPREL_17S3_S;
}
}
diff --git a/llvm/lib/Target/RISCV/RISCVInstrFormats.td b/llvm/lib/Target/RISCV/RISCVInstrFormats.td
index 8d56637d8b281..fd125e6f4bdbe 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrFormats.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrFormats.td
@@ -27,37 +27,46 @@
// Format specifies the encoding used by the instruction. This is used by
// RISCVMCCodeEmitter to determine which form of fixup to use. These
// definitions must be kept in-sync with RISCVBaseInfo.h.
-class InstFormat<bits<5> val> {
- bits<5> Value = val;
-}
-def InstFormatPseudo : InstFormat<0>;
-def InstFormatR : InstFormat<1>;
-def InstFormatR4 : InstFormat<2>;
-def InstFormatI : InstFormat<3>;
-def InstFormatS : InstFormat<4>;
-def InstFormatB : InstFormat<5>;
-def InstFormatU : InstFormat<6>;
-def InstFormatJ : InstFormat<7>;
-def InstFormatCR : InstFormat<8>;
-def InstFormatCI : InstFormat<9>;
-def InstFormatCSS : InstFormat<10>;
-def InstFormatCIW : InstFormat<11>;
-def InstFormatCL : InstFormat<12>;
-def InstFormatCS : InstFormat<13>;
-def InstFormatCA : InstFormat<14>;
-def InstFormatCB : InstFormat<15>;
-def InstFormatCJ : InstFormat<16>;
-def InstFormatCU : InstFormat<17>;
-def InstFormatCLB : InstFormat<18>;
-def InstFormatCLH : InstFormat<19>;
-def InstFormatCSB : InstFormat<20>;
-def InstFormatCSH : InstFormat<21>;
-def InstFormatQC_EAI : InstFormat<22>;
-def InstFormatQC_EI : InstFormat<23>;
-def InstFormatQC_EB : InstFormat<24>;
-def InstFormatQC_EJ : InstFormat<25>;
-def InstFormatQC_ES : InstFormat<26>;
-def InstFormatOther : InstFormat<31>;
+class InstFormat<bits<6> val> {
+ bits<6> Value = val;
+}
+def InstFormatPseudo : InstFormat<0>;
+def InstFormatR : InstFormat<1>;
+def InstFormatR4 : InstFormat<2>;
+def InstFormatI : InstFormat<3>;
+def InstFormatS : InstFormat<4>;
+def InstFormatB : InstFormat<5>;
+def InstFormatU : InstFormat<6>;
+def InstFormatJ : InstFormat<7>;
+def InstFormatCR : InstFormat<8>;
+def InstFormatCI : InstFormat<9>;
+def InstFormatCSS : InstFormat<10>;
+def InstFormatCIW : InstFormat<11>;
+def InstFormatCL : InstFormat<12>;
+def InstFormatCS : InstFormat<13>;
+def InstFormatCA : InstFormat<14>;
+def InstFormatCB : InstFormat<15>;
+def InstFormatCJ : InstFormat<16>;
+def InstFormatCU : InstFormat<17>;
+def InstFormatCLB : InstFormat<18>;
+def InstFormatCLH : InstFormat<19>;
+def InstFormatCSB : InstFormat<20>;
+def InstFormatCSH : InstFormat<21>;
+def InstFormatQC_EAI : InstFormat<22>;
+def InstFormatQC_EI : InstFormat<23>;
+def InstFormatQC_EB : InstFormat<24>;
+def InstFormatQC_EJ : InstFormat<25>;
+def InstFormatQC_ES : InstFormat<26>;
+def InstFormatNDS_BRANCH_10 : InstFormat<27>;
+def InstFormatNDS_GPREL_18S0_I : InstFormat<28>;
+def InstFormatNDS_GPREL_17S1_I : InstFormat<29>;
+def InstFormatNDS_GPREL_17S2_I : InstFormat<30>;
+def InstFormatNDS_GPREL_17S3_I : InstFormat<31>;
+def InstFormatNDS_GPREL_18S0_S : InstFormat<32>;
+def InstFormatNDS_GPREL_17S1_S : InstFormat<33>;
+def InstFormatNDS_GPREL_17S2_S : InstFormat<34>;
+def InstFormatNDS_GPREL_17S3_S : InstFormat<35>;
+def InstFormatOther : InstFormat<63>;
class RISCVVConstraint<bits<3> val> {
@@ -190,42 +199,42 @@ class RVInstCommon<dag outs, dag ins, string opcodestr, string argstr,
let AsmString = opcodestr # !if(!empty(argstr), "", "\t" # argstr);
let Pattern = pattern;
- let TSFlags{4-0} = format.Value;
+ let TSFlags{5-0} = format.Value;
// Defaults
RISCVVConstraint RVVConstraint = NoConstraint;
- let TSFlags{7-5} = RVVConstraint.Value;
+ let TSFlags{8-6} = RVVConstraint.Value;
bits<3> VLMul = 0;
- let TSFlags{10-8} = VLMul;
+ let TSFlags{11-9} = VLMul;
bit IsTiedPseudo = 0;
- let TSFlags{11} = IsTiedPseudo;
+ let TSFlags{12} = IsTiedPseudo;
bit HasSEWOp = 0;
- let TSFlags{12} = HasSEWOp;
+ let TSFlags{13} = HasSEWOp;
bit HasVLOp = 0;
- let TSFlags{13} = HasVLOp;
+ let TSFlags{14} = HasVLOp;
bit HasVecPolicyOp = 0;
- let TSFlags{14} = HasVecPolicyOp;
+ let TSFlags{15} = HasVecPolicyOp;
bit IsRVVWideningReduction = 0;
- let TSFlags{15} = IsRVVWideningReduction;
+ let TSFlags{16} = IsRVVWideningReduction;
bit UsesMaskPolicy = 0;
- let TSFlags{16} = UsesMaskPolicy;
+ let TSFlags{17} = UsesMaskPolicy;
// Indicates that the result can be considered sign extended from bit 31. Some
// instructions with this flag aren't W instructions, but are either sign
// extended from a smaller size, always outputs a small integer, or put zeros
// in bits 63:31. Used by the SExtWRemoval pass.
bit IsSignExtendingOpW = 0;
- let TSFlags{17} = IsSignExtendingOpW;
+ let TSFlags{18} = IsSignExtendingOpW;
bit HasRoundModeOp = 0;
- let TSFlags{18} = HasRoundModeOp;
+ let TSFlags{19} = HasRoundModeOp;
// This is only valid when HasRoundModeOp is set to 1. HasRoundModeOp is set
// to 1 for vector fixed-point or floating-point intrinsics. This bit is
@@ -233,7 +242,7 @@ class RVInstCommon<dag outs, dag ins, string opcodestr, string argstr,
// fixed-point / floating-point instructions and emit appropriate read/write
// to the correct CSR.
bit UsesVXRM = 0;
- let TSFlags{19} = UsesVXRM;
+ let TSFlags{20} = UsesVXRM;
// Indicates whether these instructions can partially overlap between source
// registers and destination registers according to the vector spec.
@@ -242,19 +251,19 @@ class RVInstCommon<dag outs, dag ins, string opcodestr, string argstr,
// 2 -> narrowing case
// 3 -> widening case
bits<2> TargetOverlapConstraintType = 0;
- let TSFlags{21-20} = TargetOverlapConstraintType;
+ let TSFlags{22-21} = TargetOverlapConstraintType;
// Most vector instructions are elementwise, but some may depend on the value
// of VL (e.g. vslide1down.vx), and others may depend on the VL and mask
// (e.g. vredsum.vs, viota.m). Mark these instructions so that peepholes avoid
// changing their VL and/or mask.
EltDeps ElementsDependOn = EltDepsNone;
- let TSFlags{22} = ElementsDependOn.VL;
- let TSFlags{23} = ElementsDependOn.Mask;
+ let TSFlags{23} = ElementsDependOn.VL;
+ let TSFlags{24} = ElementsDependOn.Mask;
// Indicates the EEW of a vector instruction's destination operand.
EEW DestEEW = EEWSEWx1;
- let TSFlags{25-24} = DestEEW.Value;
+ let TSFlags{26-25} = DestEEW.Value;
}
class RVInst<dag outs, dag ins, string opcodestr, string argstr,
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
index 7cd36aa46efbe..1dccc6d07c78f 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
@@ -161,9 +161,24 @@ class UImmAsmOperand<int width, string suffix = "">
: ImmAsmOperand<"U", width, suffix> {
}
+class BareSImmNAsmOperand<int width>
+ : ImmAsmOperand<"BareS", width, ""> {
+ let PredicateMethod = "isBareSimmN<" # width # ">";
+}
+
class BareSImmNLsb0AsmOperand<int width>
: ImmAsmOperand<"BareS", width, "Lsb0"> {
- let PredicateMethod = "isBareSimmNLsb0<" # width # ">";
+ let PredicateMethod = "isBareSimmNLsbK<" # width # ", 1>";
+}
+
+class BareSImmNLsb00AsmOperand<int width>
+ : ImmAsmOperand<"BareS", width, "Lsb00"> {
+ let PredicateMethod = "isBareSimmNLsbK<" # width # ", 2>";
+}
+
+class BareSImmNLsb000AsmOperand<int width>
+ : ImmAsmOperand<"BareS", width, "Lsb000"> {
+ let PredicateMethod = "isBareSimmNLsbK<" # width # ", 3>";
}
class RISCVOp<ValueType vt = XLenVT> : Operand<vt> {
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoXAndes.td b/llvm/lib/Target/RISCV/RISCVInstrInfoXAndes.td
index 2ec768435259c..60fbeff5ab116 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoXAndes.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoXAndes.td
@@ -15,40 +15,40 @@
//===----------------------------------------------------------------------===//
// A 11-bit signed immediate where the least significant bit is zero.
-def simm11_lsb0 : Operand<OtherVT> {
- let ParserMatchClass = SImmAsmOperand<11, "Lsb0">;
+def bare_simm11_lsb0 : Operand<OtherVT> {
+ let ParserMatchClass = BareSImmNLsb0AsmOperand<11>;
let PrintMethod = "printBranchOperand";
let EncoderMethod = "getImmOpValueAsrN<1>";
let DecoderMethod = "decodeSImmOperandAndLslN<11, 1>";
let MCOperandPredicate = [{
int64_t Imm;
- if (!MCOp.evaluateAsConstantImm(Imm))
- return false;
- return isShiftedInt<10, 1>(Imm);
+ if (MCOp.evaluateAsConstantImm(Imm))
+ return isShiftedInt<10, 1>(Imm);
+ return MCOp.isBareSymbolRef();
}];
let OperandType = "OPERAND_PCREL";
}
-def simm18 : Operand<XLenVT> {
- let ParserMatchClass = SImmAsmOperand<18>;
+def bare_simm18 : Operand<XLenVT> {
+ let ParserMatchClass = BareSImmNAsmOperand<18>;
let EncoderMethod = "getImmOpValue";
let DecoderMethod = "decodeSImmOperand<18>";
}
-def simm18_lsb0 : Operand<XLenVT> {
- let ParserMatchClass = SImmAsmOperand<18, "Lsb0">;
+def bare_simm18_lsb0 : Operand<XLenVT> {
+ let ParserMatchClass = BareSImmNLsb0AsmOperand<18>;
let EncoderMethod = "getImmOpValueAsrN<1>";
let DecoderMethod = "decodeSImmOperandAndLslN<18, 1>";
}
-def simm19_lsb00 : Operand<XLenVT> {
- let ParserMatchClass = SImmAsmOperand<19, "Lsb00">;
+def bare_simm19_lsb00 : Operand<XLenVT> {
+ let ParserMatchClass = BareSImmNLsb00AsmOperand<19>;
let EncoderMethod = "getImmOpValueAsrN<2>";
let DecoderMethod = "decodeSImmOperandAndLslN<19, 2>";
}
-def simm20_lsb000 : Operand<XLenVT> {
- let ParserMatchClass = SImmAsmOperand<20, "Lsb000">;
+def bare_simm20_lsb000 : Operand<XLenVT> {
+ let ParserMatchClass = BareSImmNLsb000AsmOperand<20>;
let EncoderMethod = "getImmOpValueAsrN<3>";
let DecoderMethod = "decodeSImmOperandAndLslN<20, 3>";
}
@@ -58,8 +58,8 @@ def simm20_lsb000 : Operand<XLenVT> {
//===----------------------------------------------------------------------===//
class NDSRVInstBB<bit cs, string opcodestr>
- : RVInst<(outs), (ins GPR:$rs1, uimmlog2xlen:$cimm, simm11_lsb0:$imm10),
- opcodestr, "$rs1, $cimm, $imm10", [], InstFormatOther>,
+ : RVInst<(outs), (ins GPR:$rs1, uimmlog2xlen:$cimm, bare_simm11_lsb0:$imm10),
+ opcodestr, "$rs1, $cimm, $imm10", [], InstFormatNDS_BRANCH_10>,
Sched<[WriteJmp, ReadIALU]> {
bits<10> imm10;
bits<5> rs1;
@@ -82,8 +82,8 @@ class NDSRVInstBB<bit cs, string opcodestr>
}
class NDSRVInstBC<bits<3> funct3, string opcodestr>
- : RVInst<(outs), (ins GPR:$rs1, uimm7:$cimm, simm11_lsb0:$imm10),
- opcodestr, "$rs1, $cimm, $imm10", [], InstFormatOther>,
+ : RVInst<(outs), (ins GPR:$rs1, uimm7:$cimm, bare_simm11_lsb0:$imm10),
+ opcodestr, "$rs1, $cimm, $imm10", [], InstFormatNDS_BRANCH_10>,
Sched<[WriteJmp, ReadIALU]> {
bits<10> imm10;
bits<5> rs1;
@@ -137,8 +137,8 @@ class NDSRVInstRR<bits<7> funct7, string opcodestr>
// GP: ADDI, LB, LBU
class NDSRVInstLBGP<bits<2> funct2, string opcodestr>
- : RVInst<(outs GPR:$rd), (ins simm18:$imm18),
- opcodestr, "$rd, ${imm18}", [], InstFormatOther> {
+ : RVInst<(outs GPR:$rd), (ins bare_simm18:$imm18),
+ opcodestr, "$rd, ${imm18}", [], InstFormatNDS_GPREL_18S0_I> {
bits<18> imm18;
bits<5> rd;
@@ -158,8 +158,8 @@ class NDSRVInstLBGP<bits<2> funct2, string opcodestr>
// GP: LH, LHU
class NDSRVInstLHGP<bits<3> funct3, string opcodestr>
- : RVInst<(outs GPR:$rd), (ins simm18_lsb0:$imm17),
- opcodestr, "$rd, ${imm17}", [], InstFormatOther> {
+ : RVInst<(outs GPR:$rd), (ins bare_simm18_lsb0:$imm17),
+ opcodestr, "$rd, ${imm17}", [], InstFormatNDS_GPREL_17S1_I> {
bits<17> imm17;
bits<5> rd;
@@ -178,8 +178,8 @@ class NDSRVInstLHGP<bits<3> funct3, string opcodestr>
// GP: LW, LWU
class NDSRVInstLWGP<bits<3> funct3, string opcodestr>
- : RVInst<(outs GPR:$rd), (ins simm19_lsb00:$imm17),
- opcodestr, "$rd, ${imm17}", [], InstFormatOther> {
+ : RVInst<(outs GPR:$rd), (ins bare_simm19_lsb00:$imm17),
+ opcodestr, "$rd, ${imm17}", [], InstFormatNDS_GPREL_17S2_I> {
bits<17> imm17;
bits<5> rd;
@@ -199,8 +199,8 @@ class NDSRVInstLWGP<bits<3> funct3, string opcodestr>
// GP: LD
class NDSRVInstLDGP<bits<3> funct3, string opcodestr>
- : RVInst<(outs GPR:$rd), (ins simm20_lsb000:$imm17),
- opcodestr, "$rd, ${imm17}", [], InstFormatOther> {
+ : RVInst<(outs GPR:$rd), (ins bare_simm20_lsb000:$imm17),
+ opcodestr, "$rd, ${imm17}", [], InstFormatNDS_GPREL_17S3_I> {
bits<17> imm17;
bits<5> rd;
@@ -220,8 +220,8 @@ class NDSRVInstLDGP<bits<3> funct3, string opcodestr>
// GP: SB
class NDSRVInstSBGP<bits<2> funct2, string opcodestr>
- : RVInst<(outs), (ins GPR:$rs2, simm18:$imm18),
- opcodestr, "$rs2, ${imm18}", [], InstFormatOther> {
+ : RVInst<(outs), (ins GPR:$rs2, bare_simm18:$imm18),
+ opcodestr, "$rs2, ${imm18}", [], InstFormatNDS_GPREL_18S0_S> {
bits<18> imm18;
bits<5> rs2;
@@ -242,8 +242,8 @@ class NDSRVInstSBGP<bits<2> funct2, string opcodestr>
// GP: SH
class NDSRVInstSHGP<bits<3> funct3, string opcodestr>
- : RVInst<(outs), (ins GPR:$rs2, simm18_lsb0:$imm17),
- opcodestr, "$rs2, ${imm17}", [], InstFormatOther> {
+ : RVInst<(outs), (ins GPR:$rs2, bare_simm18_lsb0:$imm17),
+ opcodestr, "$rs2, ${imm17}", [], InstFormatNDS_GPREL_17S1_S> {
bits<17> imm17;
bits<5> rs2;
@@ -263,8 +263,8 @@ class NDSRVInstSHGP<bits<3> funct3, string opcodestr>
// GP: SW
class NDSRVInstSWGP<bits<3> funct3, string opcodestr>
- : RVInst<(outs), (ins GPR:$rs2, simm19_lsb00:$imm17),
- opcodestr, "$rs2, ${imm17}", [], InstFormatOther> {
+ : RVInst<(outs), (ins GPR:$rs2, bare_simm19_lsb00:$imm17),
+ opcodestr, "$rs2, ${imm17}", [], InstFormatNDS_GPREL_17S2_S> {
bits<17> imm17;
bits<5> rs2;
@@ -285,8 +285,8 @@ class NDSRVInstSWGP<bits<3> funct3, string opcodestr>
// GP: SD
class NDSRVInstSDGP<bits<3> funct3, string opcodestr>
- : RVInst<(outs), (ins GPR:$rs2, simm20_lsb000:$imm17),
- opcodestr, "$rs2, ${imm17}", [], InstFormatOther> {
+ : RVInst<(outs), (ins GPR:$rs2, bare_simm20_lsb000:$imm17),
+ opcodestr, "$rs2, ${imm17}", [], InstFormatNDS_GPREL_17S3_S> {
bits<17> imm17;
bits<5> rs2;
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td b/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
index 52bd893c881e8..31b88b1ffe8af 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
@@ -124,11 +124,6 @@ def simm26_nosimm12 : ImmLeaf<XLenVT, [{
def simm32_nosimm26 : ImmLeaf<XLenVT, [{
return isInt<32>(Imm) && !isInt<26>(Imm);}]>;
-class BareSImmNAsmOperand<int width>
- : ImmAsmOperand<"BareS", width, ""> {
- let PredicateMethod = "isBareSimmN<" # width # ">";
-}
-
// 32-bit Immediate, used by RV32 Instructions in 32-bit operations, so no
// sign-/zero-extension. This is represented internally as a signed 32-bit value.
def bare_simm32 : RISCVOp<XLenVT> {
diff --git a/llvm/test/MC/RISCV/custom_reloc.s b/llvm/test/MC/RISCV/custom_reloc.s
index cdb819467875f..a68f71063ea92 100644
--- a/llvm/test/MC/RISCV/custom_reloc.s
+++ b/llvm/test/MC/RISCV/custom_reloc.s
@@ -48,6 +48,19 @@
# CHECK-OBJ-NEXT: R_RISCV_VENDOR QUALCOMM
# CHECK-OBJ-NEXT: R_RISCV_CUSTOM192 my_bar+0x2
+ .reloc ., R_RISCV_VENDOR, ANDES
+ .reloc ., R_RISCV_NDS_BRANCH_10, my_bar + 2
+ addi a1, a1, 0
+ # CHECK-ASM: [[L3:.L[^:]+]]:
+ # CHECK-ASM-NEXT: .reloc [[L3]], R_RISCV_VENDOR, ANDES
+ # CHECK-ASM-NEXT: [[L4:.L[^:]+]]:
+ # CHECK-ASM-NEXT: .reloc [[L4]], R_RISCV_NDS_BRANCH_10, my_bar+2
+ # CHECK-ASM-NEXT: mv a1, a1
+
+ # CHECK-OBJ: addi a1, a1, 0
+ # CHECK-OBJ-NEXT: R_RISCV_VENDOR ANDES
+ # CHECK-OBJ-NEXT: R_RISCV_CUSTOM241 my_bar+0x2
+
nop
# CHECK-ASM: nop
# CHECK-OBJ: addi zero, zero, 0x0
diff --git a/llvm/test/MC/RISCV/xandesperf-fixups-diagnostics.s b/llvm/test/MC/RISCV/xandesperf-fixups-diagnostics.s
new file mode 100644
index 0000000000000..e52f8129129d7
--- /dev/null
+++ b/llvm/test/MC/RISCV/xandesperf-fixups-diagnostics.s
@@ -0,0 +1,13 @@
+# RUN: not llvm-mc -triple riscv32 -filetype obj -mattr=+xandesperf < %s -o /dev/null 2>&1 | FileCheck %s
+
+ nds.bbc t0, 7, far_distant # CHECK: :[[@LINE]]:3: error: fixup value out of range
+ nds.bbc t0, 7, unaligned # CHECK: :[[@LINE]]:3: error: fixup value must be 2-byte aligned
+
+ .byte 0
+unaligned:
+ .byte 0
+ .byte 0
+ .byte 0
+
+ .space 1<<10
+far_distant:
diff --git a/llvm/test/MC/RISCV/xandesperf-fixups.s b/llvm/test/MC/RISCV/xandesperf-fixups.s
new file mode 100644
index 0000000000000..f2e41aca3a067
--- /dev/null
+++ b/llvm/test/MC/RISCV/xandesperf-fixups.s
@@ -0,0 +1,33 @@
+# RUN: llvm-mc -triple riscv32 -mattr=+xandesperf -M no-aliases < %s -show-encoding \
+# RUN: | FileCheck -check-prefix=CHECK-FIXUP %s
+# RUN: llvm-mc -filetype=obj -triple riscv32 -mattr=+xandesperf < %s \
+# RUN: | llvm-objdump --mattr=+xandesperf --no-print-imm-hex -M no-aliases -d - \
+# RUN: | FileCheck -check-prefix=CHECK-INSTR %s
+# RUN: llvm-mc -filetype=obj -triple=riscv32 -mattr=+xandesperf %s \
+# RUN: | llvm-readobj -r - | FileCheck %s -check-prefix=CHECK-REL
+
+.LBB0:
+
+.fill 1000
+
+nds.bbc t0, 7, .LBB0
+# CHECK-FIXUP: fixup A - offset: 0, value: .LBB0, kind: fixup_riscv_nds_branch_10
+# CHECK-INSTR: nds.bbc t0, 7, 0
+
+nds.bbs t0, 7, .LBB1
+# CHECK-FIXUP: fixup A - offset: 0, value: .LBB1, kind: fixup_riscv_nds_branch_10
+# CHECK-INSTR: nds.bbs t0, 7, 0x7e0
+
+nds.beqc t0, 7, .LBB0
+# CHECK-FIXUP: fixup A - offset: 0, value: .LBB0, kind: fixup_riscv_nds_branch_10
+# CHECK-INSTR: nds.beqc t0, 7, 0
+
+nds.bnec t0, 7, .LBB1
+# CHECK-FIXUP: fixup A - offset: 0, value: .LBB1, kind: fixup_riscv_nds_branch_10
+# CHECK-INSTR: nds.bnec t0, 7, 0x7e0
+
+.fill 1000
+
+.LBB1:
+
+# CHECK-REL-NOT: R_RISCV
diff --git a/llvm/test/MC/RISCV/xandesperf-relocation.s b/llvm/test/MC/RISCV/xandesperf-relocation.s
new file mode 100644
index 0000000000000..1b5b41fcc0c3c
--- /dev/null
+++ b/llvm/test/MC/RISCV/xandesperf-relocation.s
@@ -0,0 +1,66 @@
+# RUN: llvm-mc -triple riscv32 -mattr=+xandesperf -M no-aliases < %s -show-encoding \
+# RUN: | FileCheck -check-prefix=INSTR %s
+# RUN: llvm-mc -filetype=obj -triple riscv32 -mattr=+xandesperf < %s \
+# RUN: | llvm-readobj -r - | FileCheck -check-prefix=RELOC %s
+
+# Check prefixes:
+# RELOC - Check the relocation in the object.
+# INSTR - Check the instruction is handled properly by the ASMPrinter
+
+.long foo
+# RELOC: R_RISCV_32 foo
+
+.quad foo
+# RELOC: R_RISCV_64 foo
+
+nds.bbc t0, 7, foo
+# RELOC: R_RISCV_CUSTOM241
+# INSTR: nds.bbc t0, 7, foo
+
+nds.bbs t0, 7, foo
+# RELOC: R_RISCV_CUSTOM241
+# INSTR: nds.bbs t0, 7, foo
+
+nds.beqc t0, 7, foo
+# RELOC: R_RISCV_CUSTOM241
+# INSTR: nds.beqc t0, 7, foo
+
+nds.bnec t0, 7, foo
+# RELOC: R_RISCV_CUSTOM241
+# INSTR: nds.bnec t0, 7, foo
+
+nds.addigp t0, foo
+# RELOC: R_RISCV_CUSTOM246
+# INSTR: nds.addigp t0, foo
+
+nds.lbgp t0, foo
+# RELOC: R_RISCV_CUSTOM246
+# INSTR: nds.lbgp t0, foo
+
+nds.lbugp t0, foo
+# RELOC: R_RISCV_CUSTOM246
+# INSTR: nds.lbugp t0, foo
+
+nds.lhgp t0, foo
+# RELOC: R_RISCV_CUSTOM247
+# INSTR: nds.lhgp t0, foo
+
+nds.lhugp t0, foo
+# RELOC: R_RISCV_CUSTOM247
+# INSTR: nds.lhugp t0, foo
+
+nds.lwgp t0, foo
+# RELOC: R_RISCV_CUSTOM248
+# INSTR: nds.lwgp t0, foo
+
+nds.sbgp t0, foo
+# RELOC: R_RISCV_CUSTOM250
+# INSTR: nds.sbgp t0, foo
+
+nds.shgp t0, foo
+# RELOC: R_RISCV_CUSTOM251
+# INSTR: nds.shgp t0, foo
+
+nds.swgp t0, foo
+# RELOC: R_RISCV_CUSTOM252
+# INSTR: nds.swgp t0, foo
diff --git a/llvm/test/MC/RISCV/xandesperf-rv64-relocation.s b/llvm/test/MC/RISCV/xandesperf-rv64-relocation.s
new file mode 100644
index 0000000000000..5bb4b553f6c3d
--- /dev/null
+++ b/llvm/test/MC/RISCV/xandesperf-rv64-relocation.s
@@ -0,0 +1,26 @@
+# RUN: llvm-mc -triple riscv64 -mattr=+xandesperf -M no-aliases < %s -show-encoding \
+# RUN: | FileCheck -check-prefix=INSTR %s
+# RUN: llvm-mc -filetype=obj -triple riscv64 -mattr=+xandesperf < %s \
+# RUN: | llvm-readobj -r - | FileCheck -check-prefix=RELOC %s
+
+# Check prefixes:
+# RELOC - Check the relocation in the object.
+# INSTR - Check the instruction is handled properly by the ASMPrinter
+
+.long foo
+# RELOC: R_RISCV_32 foo
+
+.quad foo
+# RELOC: R_RISCV_64 foo
+
+nds.lwugp t0, foo
+# RELOC: R_RISCV_CUSTOM248
+# INSTR: nds.lwugp t0, foo
+
+nds.ldgp t0, foo
+# RELOC: R_RISCV_CUSTOM249
+# INSTR: nds.ldgp t0, foo
+
+nds.sdgp t0, foo
+# RELOC: R_RISCV_CUSTOM253
+# INSTR: nds.sdgp t0, foo
More information about the llvm-commits
mailing list