[RISCV] Support Qualcomm Access Relocations#188671
Conversation
🐧 Linux x64 Test Results
✅ The build succeeded and all tests passed. |
🪟 Windows x64 Test Results
✅ The build succeeded and all tests passed. |
fe60291 to
1c3e13c
Compare
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
This adds a pass and the infrastructure to mark specific Loads/Stores as eligible for a new relaxation we are specifying in the Qualcomm psABI extensions.
1c3e13c to
190da79
Compare
|
@llvm/pr-subscribers-llvm-binary-utilities @llvm/pr-subscribers-backend-risc-v Author: Sam Elliott (lenary) ChangesThese QUALCOMM vendor relocations mark 16-bit compressed and 32-bit load/store instructions as candidates for relaxation from a QC_E_LI + Load/Store sequence. This change adds support for assembling instructions with these relocations. These relocations are documented in https://github.com/quic/riscv-elf-psabi-quic-extensions Patch is 27.39 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/188671.diff 15 Files Affected:
diff --git a/llvm/include/llvm/BinaryFormat/ELFRelocs/RISCV_nonstandard.def b/llvm/include/llvm/BinaryFormat/ELFRelocs/RISCV_nonstandard.def
index fb0e29b2aaae5..ba81072fc5cb4 100644
--- a/llvm/include/llvm/BinaryFormat/ELFRelocs/RISCV_nonstandard.def
+++ b/llvm/include/llvm/BinaryFormat/ELFRelocs/RISCV_nonstandard.def
@@ -26,6 +26,8 @@ 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_CALL_PLT, 195)
+ELF_RISCV_NONSTANDARD_RELOC(QUALCOMM, R_RISCV_QC_ACCESS_16, 196)
+ELF_RISCV_NONSTANDARD_RELOC(QUALCOMM, R_RISCV_QC_ACCESS_32, 197)
// Andes Nonstandard Relocations
// Calculation: S + A - P (10-bit PC-relative branch offset)
diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
index 93fb1fa5a889f..ca5841e8e6c57 100644
--- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
+++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
@@ -625,6 +625,17 @@ struct RISCVOperand final : public MCParsedAsmOperand {
VK == ELF::R_RISCV_TLSDESC_CALL;
}
+ bool isQCAccessSymbol() const {
+ int64_t Imm;
+ // Must be of 'immediate' type but not a constant.
+ if (!isExpr() || evaluateConstantExpr(getExpr(), Imm))
+ return false;
+
+ RISCV::Specifier VK = RISCV::S_None;
+ return RISCVAsmParser::classifySymbolRef(getExpr(), VK) &&
+ VK == RISCV::S_QC_ACCESS;
+ }
+
bool isCSRSystemRegister() const { return isSystemRegister(); }
// If the last operand of the vsetvli/vsetvli instruction is a constant
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp
index 4e3ed3f5ae31f..8e4dab0a59c98 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp
@@ -88,10 +88,13 @@ MCFixupKindInfo RISCVAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
{"fixup_riscv_call", 0, 64, 0},
{"fixup_riscv_call_plt", 0, 64, 0},
+ // Qualcomm fixups
{"fixup_riscv_qc_e_branch", 0, 48, 0},
{"fixup_riscv_qc_e_32", 16, 32, 0},
{"fixup_riscv_qc_abs20_u", 0, 32, 0},
{"fixup_riscv_qc_e_call_plt", 0, 48, 0},
+ {"fixup_qc_access_16", 0, 0, 0},
+ {"fixup_qc_access_32", 0, 0, 0},
// Andes fixups
{"fixup_riscv_nds_branch_10", 0, 32, 0},
@@ -638,6 +641,9 @@ static uint64_t adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
(Bit15_13 << 17) | (Bit4_1 << 8) | (Bit11 << 7);
return Value;
}
+ case RISCV::fixup_qc_access_16:
+ case RISCV::fixup_qc_access_32:
+ return 0;
case RISCV::fixup_riscv_nds_branch_10: {
if (!isInt<11>(Value))
Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
@@ -737,6 +743,10 @@ std::optional<bool> RISCVAsmBackend::evaluateFixup(const MCFragment &,
default:
// Use default handling for `Value` and `IsResolved`.
return {};
+ case RISCV::fixup_qc_access_16:
+ case RISCV::fixup_qc_access_32:
+ // Never resolved in the assembler
+ return false;
case RISCV::fixup_riscv_pcrel_lo12_i:
case RISCV::fixup_riscv_pcrel_lo12_s: {
AUIPCFixup =
@@ -787,6 +797,8 @@ void RISCVAsmBackend::maybeAddVendorReloc(const MCFragment &F,
case RISCV::fixup_riscv_qc_abs20_u:
case RISCV::fixup_riscv_qc_e_32:
case RISCV::fixup_riscv_qc_e_call_plt:
+ case RISCV::fixup_qc_access_16:
+ case RISCV::fixup_qc_access_32:
VendorIdentifier = "QUALCOMM";
break;
case RISCV::fixup_riscv_nds_branch_10:
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.cpp
index d5645dc61e6b8..72889be9ca5a2 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.cpp
@@ -13,6 +13,7 @@
#include "RISCVBaseInfo.h"
#include "RISCVInstrInfo.h"
+#include "RISCVMCAsmInfo.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCSubtargetInfo.h"
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
index 7f1aa83075f1f..0eba38f2c8962 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
@@ -80,6 +80,7 @@ enum OperandType : unsigned {
OPERAND_SIMM10_LSB0000_NONZERO,
OPERAND_SIMM10_UNSIGNED,
OPERAND_SIMM11,
+ OPERAND_SIMM12,
OPERAND_SIMM12_LSB00000,
OPERAND_SIMM16,
OPERAND_SIMM16_NONZERO,
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFObjectWriter.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFObjectWriter.cpp
index 2885e3cca8722..e47102b508cda 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFObjectWriter.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFObjectWriter.cpp
@@ -142,6 +142,10 @@ unsigned RISCVELFObjectWriter::getRelocType(const MCFixup &Fixup,
return ELF::R_RISCV_QC_E_32;
case RISCV::fixup_riscv_qc_abs20_u:
return ELF::R_RISCV_QC_ABS20_U;
+ case RISCV::fixup_qc_access_16:
+ return ELF::R_RISCV_QC_ACCESS_16;
+ case RISCV::fixup_qc_access_32:
+ return ELF::R_RISCV_QC_ACCESS_32;
}
}
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVFixupKinds.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVFixupKinds.h
index a2b75e4a42e76..8104ee0291b34 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVFixupKinds.h
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVFixupKinds.h
@@ -59,6 +59,9 @@ enum Fixups {
// 32-bit fixup for symbol references in the 48-bit qc.j/qc.jal instructions
fixup_riscv_qc_e_call_plt,
+ fixup_qc_access_16,
+ fixup_qc_access_32,
+
// Andes specific fixups
// 10-bit fixup for symbol references in the xandesperf branch instruction
fixup_riscv_nds_branch_10,
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp
index aa7ce5bf5e2a2..28e7839493c6d 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp
@@ -12,6 +12,7 @@
#include "RISCVInstPrinter.h"
#include "RISCVBaseInfo.h"
+#include "RISCVMCAsmInfo.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInst.h"
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCAsmInfo.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCAsmInfo.h
index f9477b00a6744..ee1fffc4886c8 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCAsmInfo.h
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCAsmInfo.h
@@ -49,6 +49,7 @@ enum {
// Vendor-specific relocation types might conflict across vendors.
// Refer to them using Specifier constants.
S_QC_ABS20,
+ S_QC_ACCESS,
};
Specifier parseSpecifierName(StringRef name);
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
index 7a8926b197cb7..1b947ecc5f2bd 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
@@ -76,6 +76,10 @@ class RISCVMCCodeEmitter : public MCCodeEmitter {
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI, unsigned Size) const;
+ void expandPseudoQCAccess(const MCInst &MI, SmallVectorImpl<char> &CB,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const;
+
/// TableGen'erated function for getting the binary encoding for an
/// instruction.
uint64_t getBinaryCodeForInstr(const MCInst &MI,
@@ -477,6 +481,77 @@ void RISCVMCCodeEmitter::expandQCLongCondBrImm(const MCInst &MI,
}
}
+void RISCVMCCodeEmitter::expandPseudoQCAccess(
+ const MCInst &MI, SmallVectorImpl<char> &CB,
+ SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const {
+ unsigned AccessOpc;
+
+ switch (MI.getOpcode()) {
+#define QC_ACCESS_CASE(_Suffix) \
+ case RISCV::PseudoQCAccess##_Suffix: \
+ AccessOpc = RISCV::_Suffix; \
+ break;
+ // clang-format off
+ QC_ACCESS_CASE(LB)
+ QC_ACCESS_CASE(LBU)
+ QC_ACCESS_CASE(LH)
+ QC_ACCESS_CASE(LHU)
+ QC_ACCESS_CASE(LW)
+ QC_ACCESS_CASE(SB)
+ QC_ACCESS_CASE(SH)
+ QC_ACCESS_CASE(SW)
+ QC_ACCESS_CASE(C_LBU)
+ QC_ACCESS_CASE(C_LH)
+ QC_ACCESS_CASE(C_LHU)
+ QC_ACCESS_CASE(C_LW)
+ QC_ACCESS_CASE(C_SB)
+ QC_ACCESS_CASE(C_SH)
+ QC_ACCESS_CASE(C_SW)
+ // clang-format on
+ default:
+ llvm_unreachable("Unhandled QC Access Opcode");
+ };
+
+ MCInst TmpAccess = MCInstBuilder(AccessOpc)
+ .addOperand(MI.getOperand(0))
+ .addOperand(MI.getOperand(1))
+ .addOperand(MI.getOperand(2));
+ unsigned Size = MCII.get(AccessOpc).getSize();
+ uint16_t FixupKind;
+ switch (Size) {
+ default:
+ llvm_unreachable("Unhandled QC Access Instruction Size");
+ case 2: {
+ uint16_t AccessBinary = getBinaryCodeForInstr(TmpAccess, Fixups, STI);
+ support::endian::write(CB, AccessBinary, llvm::endianness::little);
+ FixupKind = RISCV::fixup_qc_access_16;
+ break;
+ }
+ case 4: {
+ uint32_t AccessBinary = getBinaryCodeForInstr(TmpAccess, Fixups, STI);
+ support::endian::write(CB, AccessBinary, llvm::endianness::little);
+ FixupKind = RISCV::fixup_qc_access_32;
+ break;
+ }
+ }
+ // Only emit the qc.access fixup if linker relaxation is enabled. The pass has
+ // already checked for this before using the Pseudos, but the user may have
+ // written the instructions directly in assembly.
+ if (!STI.hasFeature(RISCV::FeatureRelax))
+ return;
+
+ const MCOperand &AccessSymbol = MI.getOperand(3);
+ assert(AccessSymbol.isExpr() && "Expected expression in PseudoQCAccess");
+
+ const auto *AccessExpr = dyn_cast<MCSpecifierExpr>(AccessSymbol.getExpr());
+ assert(AccessExpr && AccessExpr->getSpecifier() == RISCV::S_QC_ACCESS &&
+ "Expected qc.access specifier on symbol");
+
+ addFixup(Fixups, /*Offset=*/0, AccessExpr, FixupKind);
+ // The added fixup is always linker relaxable.
+ Fixups.back().setLinkerRelaxable();
+}
+
void RISCVMCCodeEmitter::encodeInstruction(const MCInst &MI,
SmallVectorImpl<char> &CB,
SmallVectorImpl<MCFixup> &Fixups,
@@ -543,6 +618,24 @@ void RISCVMCCodeEmitter::encodeInstruction(const MCInst &MI,
expandTLSDESCCall(MI, CB, Fixups, STI);
MCNumEmitted += 1;
return;
+ case RISCV::PseudoQCAccessLB:
+ case RISCV::PseudoQCAccessLBU:
+ case RISCV::PseudoQCAccessLH:
+ case RISCV::PseudoQCAccessLHU:
+ case RISCV::PseudoQCAccessLW:
+ case RISCV::PseudoQCAccessSB:
+ case RISCV::PseudoQCAccessSH:
+ case RISCV::PseudoQCAccessSW:
+ case RISCV::PseudoQCAccessC_LBU:
+ case RISCV::PseudoQCAccessC_LH:
+ case RISCV::PseudoQCAccessC_LHU:
+ case RISCV::PseudoQCAccessC_LW:
+ case RISCV::PseudoQCAccessC_SB:
+ case RISCV::PseudoQCAccessC_SH:
+ case RISCV::PseudoQCAccessC_SW:
+ expandPseudoQCAccess(MI, CB, Fixups, STI);
+ MCNumEmitted += 1;
+ return;
}
switch (Size) {
@@ -714,6 +807,12 @@ uint64_t RISCVMCCodeEmitter::getImmOpValue(const MCInst &MI, unsigned OpNo,
// encounter it here is an error.
llvm_unreachable(
"ELF::R_RISCV_TPREL_ADD should not represent an instruction operand");
+ case RISCV::S_QC_ACCESS:
+ // The same logic for tprel_add applies to S_QC_ACCESS, for similar
+ // reasons, but we use a specifier becuase %qc.access() gets expanded
+ // differently depending on the underlying instruction.
+ llvm_unreachable(
+ "S_QC_ACCESS should not represent an instruction operand");
case RISCV::S_LO:
if (MIFrm == RISCVII::InstFormatI)
FixupKind = RISCV::fixup_riscv_lo12_i;
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.cpp
index e6366af9163e6..cf9db21a47dcb 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.cpp
@@ -37,6 +37,7 @@ RISCV::Specifier RISCV::parseSpecifierName(StringRef name) {
.Case("tlsdesc_add_lo", ELF::R_RISCV_TLSDESC_ADD_LO12)
.Case("tlsdesc_call", ELF::R_RISCV_TLSDESC_CALL)
.Case("qc.abs20", RISCV::S_QC_ABS20)
+ .Case("qc.access", RISCV::S_QC_ACCESS)
// Used in data directives
.Case("pltpcrel", ELF::R_RISCV_PLT32)
.Case("gotpcrel", ELF::R_RISCV_GOT32_PCREL)
@@ -85,6 +86,8 @@ StringRef RISCV::getSpecifierName(Specifier S) {
return "pltpcrel";
case RISCV::S_QC_ABS20:
return "qc.abs20";
+ case RISCV::S_QC_ACCESS:
+ return "qc.access";
}
llvm_unreachable("Invalid ELF symbol kind");
}
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
index c622d188c67a1..7ccffdbdb36d9 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
@@ -3075,6 +3075,7 @@ bool RISCVInstrInfo::verifyInstruction(const MachineInstr &MI,
CASE_OPERAND_SIMM(8)
CASE_OPERAND_SIMM(10)
CASE_OPERAND_SIMM(11)
+ CASE_OPERAND_SIMM(12)
CASE_OPERAND_SIMM(26)
// clang-format on
case RISCVOp::OPERAND_SIMM5_PLUS1:
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td b/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
index 96203641513e9..1c66893800e76 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
@@ -1365,6 +1365,119 @@ def PseudoCCQC_E_LHU : SFBQCLoad;
def PseudoCCQC_E_LBU : SFBQCLoad;
}
+def simm12 : RISCVSImmOp<12>;
+
+def QCAccessSymbol : AsmOperandClass {
+ let Name = "QCAccessSymbol";
+ let RenderMethod = "addImmOperands";
+ let DiagnosticType = "InvalidQCAccessSymbol";
+ let DiagnosticString = "operand must be a symbol with a %qc.access specifier";
+ let ParserMethod = "parseOperandWithSpecifier";
+}
+
+def qc_access_symbol : Operand<XLenVT> {
+ let ParserMatchClass = QCAccessSymbol;
+
+ let MCOperandPredicate = [{
+ return MCOp.isExpr() && MCOp.getExpr()->getKind() == MCExpr::Specifier &&
+ cast<MCSpecifierExpr>(MCOp.getExpr())->getSpecifier() == RISCV::S_QC_ACCESS;
+ }];
+}
+
+// This is modelled after `PseudoAddTPRel` but with `mayLoad = true`
+let hasSideEffects = false, mayLoad = true, mayStore = false, Size = 4,
+ isCodeGenOnly = false in
+class PseudoQCAccessLoad_ri<string opcodestr>
+ : Pseudo<(outs GPR:$rd),
+ (ins GPRMem:$rs1, simm12:$imm12, qc_access_symbol:$expr), [],
+ opcodestr, "$rd, ${imm12}(${rs1}), $expr">;
+
+let hasSideEffects = false, mayLoad = false, mayStore = true, Size = 4,
+ isCodeGenOnly = false in
+class PseudoQCAccessStore_rri<string opcodestr>
+ : Pseudo<(outs), (ins GPR:$rs2, GPRMem:$rs1, simm12:$imm12, qc_access_symbol:$expr),
+ [], opcodestr, "$rs2, ${imm12}(${rs1}), $expr">;
+
+
+let Predicates = [IsRV32] in {
+def PseudoQCAccessLB : PseudoQCAccessLoad_ri<"lb">;
+def PseudoQCAccessLBU : PseudoQCAccessLoad_ri<"lbu">;
+def PseudoQCAccessLH : PseudoQCAccessLoad_ri<"lh">;
+def PseudoQCAccessLHU : PseudoQCAccessLoad_ri<"lhu">;
+def PseudoQCAccessLW : PseudoQCAccessLoad_ri<"lw">;
+
+let EmitPriority = 0 in {
+def : InstAlias<"lb $rd, (${rs1}), $expr", (PseudoQCAccessLB GPR:$rd, GPRMem:$rs1, 0, qc_access_symbol:$expr)>;
+def : InstAlias<"lbu $rd, (${rs1}), $expr", (PseudoQCAccessLB GPR:$rd, GPRMem:$rs1, 0, qc_access_symbol:$expr)>;
+def : InstAlias<"lh $rd, (${rs1}), $expr", (PseudoQCAccessLH GPR:$rd, GPRMem:$rs1, 0, qc_access_symbol:$expr)>;
+def : InstAlias<"lhu $rd, (${rs1}), $expr", (PseudoQCAccessLHU GPR:$rd, GPRMem:$rs1, 0, qc_access_symbol:$expr)>;
+def : InstAlias<"lw $rd, (${rs1}), $expr", (PseudoQCAccessLW GPR:$rd, GPRMem:$rs1, 0, qc_access_symbol:$expr)>;
+}
+
+def PseudoQCAccessSW : PseudoQCAccessStore_rri<"sw">;
+def PseudoQCAccessSH : PseudoQCAccessStore_rri<"sh">;
+def PseudoQCAccessSB : PseudoQCAccessStore_rri<"sb">;
+
+let EmitPriority = 0 in {
+def : InstAlias<"sb $rs2, (${rs1}), $expr", (PseudoQCAccessSB GPR:$rs2, GPRMem:$rs1, 0, qc_access_symbol:$expr)>;
+def : InstAlias<"sh $rs2, (${rs1}), $expr", (PseudoQCAccessSH GPR:$rs2, GPRMem:$rs1, 0, qc_access_symbol:$expr)>;
+def : InstAlias<"sw $rs2, (${rs1}), $expr", (PseudoQCAccessSW GPR:$rs2, GPRMem:$rs1, 0, qc_access_symbol:$expr)>;
+}
+}
+
+let hasSideEffects = false, mayLoad = true, mayStore = false, Size = 2,
+ isCodeGenOnly = false in
+class PseudoQCAccessCLoad_ri<string opcodestr, DAGOperand immop>
+ : Pseudo<(outs GPRC:$rd),
+ (ins GPRCMem:$rs1, immop:$imm, qc_access_symbol:$expr),
+ [], opcodestr, "$rd, ${imm}(${rs1}), $expr">;
+
+let hasSideEffects = false, mayLoad = false, mayStore = true, Size = 2,
+ isCodeGenOnly = false in
+class PseudoQCAccessCStore_rri<string opcodestr, DAGOperand immop>
+ : Pseudo<(outs),
+ (ins GPRC:$rs2, GPRCMem:$rs1, immop:$imm, qc_access_symbol:$expr),
+ [], opcodestr, "$rs2, ${imm}(${rs1}), $expr">;
+
+let Predicates = [IsRV32, HasStdExtZca] in {
+def PseudoQCAccessC_LW : PseudoQCAccessCLoad_ri<"c.lw", uimm7_lsb00>;
+let EmitPriority = 0 in
+def : InstAlias<"c.lw $rd, (${rs1}), $expr", (PseudoQCAccessC_LW GPRC:$rd, GPRCMem:$rs1, 0, qc_access_symbol:$expr)>;
+
+def PseudoQCAccessC_SW : PseudoQCAccessCStore_rri<"c.sw", uimm7_lsb00>;
+let EmitPriority = 0 in
+def : InstAlias<"c.sw $rs2, (${rs1}), $expr", (PseudoQCAccessC_SW GPRC:$rs2, GPRCMem:$rs1, 0, qc_access_symbol:$expr)>;
+}
+
+let Predicates = [IsRV32, HasStdExtZcb] in {
+// no C_LB so no PseudoQCAccessC_LB
+def PseudoQCAccessC_LBU : PseudoQCAccessCLoad_ri<"c.lbu", uimm2>;
+def PseudoQCAccessC_LH : PseudoQCAccessCLoad_ri<"c.lh", uimm2_lsb0>;
+def PseudoQCAccessC_LHU : PseudoQCAccessCLoad_ri<"c.lhu", uimm2_lsb0>;
+
+let EmitPriority = 0 in {
+// No c.lb so no alias
+def : InstAlias<"c.lbu $rd, (${rs1}), $expr", (PseudoQCAccessC_LBU GPRC:$rd, GPRCMem:$rs1, 0, qc_access_symbol:$expr)>;
+def : InstAlias<"c.lh $rd, (${rs1}), $expr", (PseudoQCAccessC_LH GPRC:$rd, GPRCMem:$rs1, 0, qc_access_symbol:$expr)>;
+def : InstAlias<"c.lhu $rd, (${rs1}), $expr", (PseudoQCAccessC_LHU GPRC:$rd, GPRCMem:$rs1, 0, qc_access_symbol:$expr)>;
+}
+
+def PseudoQCAccessC_SB : PseudoQCAccessCStore_rri<"c.sb", uimm2>;
+def PseudoQCAccessC_SH : PseudoQCAccessCStore_rri<"c.sh", uimm2_lsb0>;
+
+let EmitPriority = 0 in {
+def : InstAlias<"c.sb $rs2, (${rs1}), $expr", (PseudoQCAccessC_SB GPRC:$rs2, GPRCMem:$rs1, 0, qc_access_symbol:$expr)>;
+def : InstAlias<"c.sh $rs2, (${rs1}), $expr", (PseudoQCAccessC_SH GPRC:$rs2, GPRCMem:$rs1, 0, qc_access_symbol:$expr)>;
+}
+}
+
+// FIXME: We would like to add these but they are not supported by CompressPat.
+// let Predicates = [HasVendorXqcili, HasStdExtZca] in {
+// def : CompressPat<(PseudoQCAccessLW GPRC:$rd, GPRCMem:$rs1, uimm7_lsb00:$imm, qc_access_symbol:$expr),
+// (PseudoQCAccessC_LW GPRC:$rd, GPRCMem:$rs1, uimm7_lsb00:$imm, qc_access_symbol:$expr)>;
+// }
+
+
//===----------------------------------------------------------------------===//
// Code Gen Patterns
//===----------------------------------------------------------------------===//
diff --git a/llvm/test/MC/RISCV/rvi-pseudos-invalid.s b/llvm/test/MC/RISCV/rvi-pseudos-invalid.s
index 2dcab572fb7b6..d5b6db3b80b21 100644
--- a/llvm/test/MC/RISCV/rvi-pseudos-invalid.s
+++ b/llvm/test/MC/RISCV/rvi-pseudos-invalid.s
@@ -1,5 +1,5 @@
-# RUN: not llvm-mc %s -triple=riscv32 2>&1 | FileCheck %s
-# RUN: not llvm-mc %s -triple=riscv64 2>&1 | FileCheck %s
+# RUN: not llvm-mc %s -triple=riscv32 2>&1 | FileCheck --check-prefixes=CHECK,CHECK-RV32 %s
+# RUN: not llvm-mc %s -triple=riscv64 2>&1 | FileCheck --check-prefixes=CHECK,CHECK-RV64 %s
lga x1, 1234 # CHECK: :[[@LINE]]:9: error: operand must be a bare symbol name
lga x1, %pcrel_hi(1234) # CHECK: :[[@LINE]]:9: error: operand must be a bare symbol name
@@ -11,9 +11,12 @@ lga x1, %lo(1234) # CHECK: :[[@LINE]]:9: error: operand must be a bare symbol na
lga x1, %hi(foo) # CHECK: :[[@LINE]]:9: error: operan...
[truncated]
|
| def PseudoQCAccessLW : PseudoQCAccessLoad_ri<"lw">; | ||
|
|
||
| let EmitPriority = 0 in { | ||
| def : InstAlias<"lb $rd, (${rs1}), $expr", (PseudoQCAccessLB GPR:$rd, GPRMem:$rs1, 0, qc_access_symbol:$expr)>; |
There was a problem hiding this comment.
Can we wrap these closer to 80 columns?
There was a problem hiding this comment.
They're closer now, but not yet at 80 cols.
There was a problem hiding this comment.
That's fine. I'm not going be strict about it. They just looked quite a bit over.
|
I will leave this another 24 hours before merging. |
These QUALCOMM vendor relocations mark 16-bit compressed and 32-bit load/store instructions as candidates for relaxation from a QC_E_LI + Load/Store sequence.
This change adds support for assembling instructions with these relocations. These relocations are documented in https://github.com/quic/riscv-elf-psabi-quic-extensions