From 2bc76727e978a60a33062fa0904ce8bb5c7ef4f4 Mon Sep 17 00:00:00 2001 From: Sam Elliott Date: Tue, 5 May 2026 11:15:52 -0700 Subject: [PATCH 1/4] [RISCV] Add support for R_RISCV_QC_ACCESS_16 and R_RISCV_QC_ACCESS_32 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: - Extends the internal QUALCOMM relocation range to cover the new relocations - registers them with applyNone (marker semantics, no instruction changes), - and add tests covering loads, stores, and compressed instructions. Co-Authored-By: Claude Sonnet 4.6 Signed-off-by: Sam Elliott --- lib/Target/RISCV/RISCVRelocationInfo.cpp | 20 ++++++++ lib/Target/RISCV/RISCVRelocationInternal.h | 6 +-- lib/Target/RISCV/RISCVRelocator.cpp | 2 + .../Relocs/R_RISCV_QC_ACCESS_16/Inputs/1.s | 39 +++++++++++++++ .../R_RISCV_QC_ACCESS_16.test | 33 +++++++++++++ .../Relocs/R_RISCV_QC_ACCESS_32/Inputs/1.s | 49 +++++++++++++++++++ .../R_RISCV_QC_ACCESS_32.test | 38 ++++++++++++++ 7 files changed, 184 insertions(+), 3 deletions(-) create mode 100644 test/RISCV/standalone/Relocs/R_RISCV_QC_ACCESS_16/Inputs/1.s create mode 100644 test/RISCV/standalone/Relocs/R_RISCV_QC_ACCESS_16/R_RISCV_QC_ACCESS_16.test create mode 100644 test/RISCV/standalone/Relocs/R_RISCV_QC_ACCESS_32/Inputs/1.s create mode 100644 test/RISCV/standalone/Relocs/R_RISCV_QC_ACCESS_32/R_RISCV_QC_ACCESS_32.test diff --git a/lib/Target/RISCV/RISCVRelocationInfo.cpp b/lib/Target/RISCV/RISCVRelocationInfo.cpp index 5c952e9fc..32b764d77 100644 --- a/lib/Target/RISCV/RISCVRelocationInfo.cpp +++ b/lib/Target/RISCV/RISCVRelocationInfo.cpp @@ -738,6 +738,26 @@ RISCVRelocationMap RISCVRelocs = { /*.VerifyAlignment = */ true, /*.Signed = */ true, /*.Size = */ 48}}, + {eld::ELF::riscv::internal::R_RISCV_QC_ACCESS_16, + {/*.Name = */ "R_RISCV_QC_ACCESS_16", + /*.Type = */ eld::ELF::riscv::internal::R_RISCV_QC_ACCESS_16, + /*EncodingType = */ EncTy_None, + /*.Alignment = */ 0, + /*.shift = */ 0, + /*.VerifyRange = */ false, + /*.VerifyAlignment = */ false, + /*.Signed = */ false, + /*.Size = */ 16}}, + {eld::ELF::riscv::internal::R_RISCV_QC_ACCESS_32, + {/*.Name = */ "R_RISCV_QC_ACCESS_32", + /*.Type = */ eld::ELF::riscv::internal::R_RISCV_QC_ACCESS_32, + /*EncodingType = */ EncTy_None, + /*.Alignment = */ 0, + /*.shift = */ 0, + /*.VerifyRange = */ false, + /*.VerifyAlignment = */ false, + /*.Signed = */ false, + /*.Size = */ 32}}, }; } // namespace diff --git a/lib/Target/RISCV/RISCVRelocationInternal.h b/lib/Target/RISCV/RISCVRelocationInternal.h index 09d9f24b7..61addc8b8 100644 --- a/lib/Target/RISCV/RISCVRelocationInternal.h +++ b/lib/Target/RISCV/RISCVRelocationInternal.h @@ -66,11 +66,11 @@ enum : uint32_t { added to the nonstandard ID to get the internal ID. */ FirstInternalRelocation = 320, - LastInternalRelocation = 323, + LastInternalRelocation = 325, - /* 'QUALCOMM' vendor relocations: 192-195 are represented by 320-323 */ + /* 'QUALCOMM' vendor relocations: 192-197 are represented by 320-325 */ FirstQUALCOMMVendorRelocation = 320, - LastQUALCOMMVendorRelocation = 323, + LastQUALCOMMVendorRelocation = 325, QUALCOMMVendorRelocationOffset = FirstQUALCOMMVendorRelocation - FirstNonstandardRelocation, diff --git a/lib/Target/RISCV/RISCVRelocator.cpp b/lib/Target/RISCV/RISCVRelocator.cpp index a39f525d7..e9eb49703 100644 --- a/lib/Target/RISCV/RISCVRelocator.cpp +++ b/lib/Target/RISCV/RISCVRelocator.cpp @@ -213,6 +213,8 @@ RelocationDescMap RelocDescs = { INTERNAL_RELOC_DESC_ENTRY(R_RISCV_QC_E_BRANCH, applyJumpOrCall), INTERNAL_RELOC_DESC_ENTRY(R_RISCV_QC_E_32, applyAbs), INTERNAL_RELOC_DESC_ENTRY(R_RISCV_QC_E_CALL_PLT, applyJumpOrCall), + INTERNAL_RELOC_DESC_ENTRY(R_RISCV_QC_ACCESS_16, applyNone), + INTERNAL_RELOC_DESC_ENTRY(R_RISCV_QC_ACCESS_32, applyNone), }; #undef INTERNAL_RELOC_DESC_ENTRY diff --git a/test/RISCV/standalone/Relocs/R_RISCV_QC_ACCESS_16/Inputs/1.s b/test/RISCV/standalone/Relocs/R_RISCV_QC_ACCESS_16/Inputs/1.s new file mode 100644 index 000000000..8a0fc8c6b --- /dev/null +++ b/test/RISCV/standalone/Relocs/R_RISCV_QC_ACCESS_16/Inputs/1.s @@ -0,0 +1,39 @@ + + .text + .p2align 1 + + .option exact + + .set test_zero, 0 + +QUALCOMM: + +test_clw: + c.lw a0, 0(a2) + .reloc test_clw, R_RISCV_VENDOR, QUALCOMM + .reloc test_clw, R_RISCV_CUSTOM196, test_zero + +test_csw: + c.sw a0, 0(a2) + .reloc test_csw, R_RISCV_VENDOR, QUALCOMM + .reloc test_csw, R_RISCV_CUSTOM196, test_zero + +test_clbu: + c.lbu a0, 0(a2) + .reloc test_clbu, R_RISCV_VENDOR, QUALCOMM + .reloc test_clbu, R_RISCV_CUSTOM196, test_zero + +test_clh: + c.lh a0, 0(a2) + .reloc test_clh, R_RISCV_VENDOR, QUALCOMM + .reloc test_clh, R_RISCV_CUSTOM196, test_zero + +test_csb: + c.sb a0, 0(a2) + .reloc test_csb, R_RISCV_VENDOR, QUALCOMM + .reloc test_csb, R_RISCV_CUSTOM196, test_zero + +test_csh: + c.sh a0, 0(a2) + .reloc test_csh, R_RISCV_VENDOR, QUALCOMM + .reloc test_csh, R_RISCV_CUSTOM196, test_zero diff --git a/test/RISCV/standalone/Relocs/R_RISCV_QC_ACCESS_16/R_RISCV_QC_ACCESS_16.test b/test/RISCV/standalone/Relocs/R_RISCV_QC_ACCESS_16/R_RISCV_QC_ACCESS_16.test new file mode 100644 index 000000000..c4a48a3b6 --- /dev/null +++ b/test/RISCV/standalone/Relocs/R_RISCV_QC_ACCESS_16/R_RISCV_QC_ACCESS_16.test @@ -0,0 +1,33 @@ +#---R_RISCV_QC_ACCESS_16.test------------------ Executable------------# +#BEGIN_COMMENT +# Check that R_RISCV_QC_ACCESS_16 is correctly handled. +# It marks 16-bit compressed load and store instructions that are +# candidates for GP-relative linker relaxation from a QC_E_LI + +# compressed Load/Store sequence. Without relaxation, the instruction +# is left unchanged. +#-------------------------------------------------------------------- +#END_COMMENT +REQUIRES: riscv32 +#START_TEST +RUN: %clang %clangopts -march=rv32ic_zcb -c %p/Inputs/1.s -o %t1.1.o +RUN: %link %linkopts %t1.1.o -o %t1.out +RUN: %objdump --no-print-imm-hex -M no-aliases -d %t1.out | %filecheck %s +#END_TEST + +CHECK-LABEL: : +CHECK: c.lw a0, 0(a2) + +CHECK-LABEL: : +CHECK: c.sw a0, 0(a2) + +CHECK-LABEL: : +CHECK: c.lbu a0, 0(a2) + +CHECK-LABEL: : +CHECK: c.lh a0, 0(a2) + +CHECK-LABEL: : +CHECK: c.sb a0, 0(a2) + +CHECK-LABEL: : +CHECK: c.sh a0, 0(a2) diff --git a/test/RISCV/standalone/Relocs/R_RISCV_QC_ACCESS_32/Inputs/1.s b/test/RISCV/standalone/Relocs/R_RISCV_QC_ACCESS_32/Inputs/1.s new file mode 100644 index 000000000..278d2627a --- /dev/null +++ b/test/RISCV/standalone/Relocs/R_RISCV_QC_ACCESS_32/Inputs/1.s @@ -0,0 +1,49 @@ + + .text + .p2align 2 + + .option exact + + .set test_zero, 0 + +QUALCOMM: + +test_lb: + lb a0, 0(a1) + .reloc test_lb, R_RISCV_VENDOR, QUALCOMM + .reloc test_lb, R_RISCV_CUSTOM197, test_zero + +test_lbu: + lbu a0, 0(a1) + .reloc test_lbu, R_RISCV_VENDOR, QUALCOMM + .reloc test_lbu, R_RISCV_CUSTOM197, test_zero + +test_lh: + lh a0, 0(a1) + .reloc test_lh, R_RISCV_VENDOR, QUALCOMM + .reloc test_lh, R_RISCV_CUSTOM197, test_zero + +test_lhu: + lhu a0, 0(a1) + .reloc test_lhu, R_RISCV_VENDOR, QUALCOMM + .reloc test_lhu, R_RISCV_CUSTOM197, test_zero + +test_lw: + lw a0, 0(a1) + .reloc test_lw, R_RISCV_VENDOR, QUALCOMM + .reloc test_lw, R_RISCV_CUSTOM197, test_zero + +test_sb: + sb a0, 0(a1) + .reloc test_sb, R_RISCV_VENDOR, QUALCOMM + .reloc test_sb, R_RISCV_CUSTOM197, test_zero + +test_sh: + sh a0, 0(a1) + .reloc test_sh, R_RISCV_VENDOR, QUALCOMM + .reloc test_sh, R_RISCV_CUSTOM197, test_zero + +test_sw: + sw a0, 0(a1) + .reloc test_sw, R_RISCV_VENDOR, QUALCOMM + .reloc test_sw, R_RISCV_CUSTOM197, test_zero diff --git a/test/RISCV/standalone/Relocs/R_RISCV_QC_ACCESS_32/R_RISCV_QC_ACCESS_32.test b/test/RISCV/standalone/Relocs/R_RISCV_QC_ACCESS_32/R_RISCV_QC_ACCESS_32.test new file mode 100644 index 000000000..0ca3e1bb3 --- /dev/null +++ b/test/RISCV/standalone/Relocs/R_RISCV_QC_ACCESS_32/R_RISCV_QC_ACCESS_32.test @@ -0,0 +1,38 @@ +#---R_RISCV_QC_ACCESS_32.test------------------ Executable------------# +#BEGIN_COMMENT +# Check that R_RISCV_QC_ACCESS_32 is correctly handled. +# It marks 32-bit load and store instructions that are candidates for +# GP-relative linker relaxation from a QC_E_LI + Load/Store sequence. +# Without relaxation, the instruction is left unchanged. +#-------------------------------------------------------------------- +#END_COMMENT +REQUIRES: riscv32 +#START_TEST +RUN: %clang %clangopts -march=rv32i -c %p/Inputs/1.s -o %t1.1.o +RUN: %link %linkopts %t1.1.o -o %t1.out +RUN: %objdump --no-print-imm-hex -d %t1.out | %filecheck %s +#END_TEST + +CHECK-LABEL: : +CHECK: lb a0, 0(a1) + +CHECK-LABEL: : +CHECK: lbu a0, 0(a1) + +CHECK-LABEL: : +CHECK: lh a0, 0(a1) + +CHECK-LABEL: : +CHECK: lhu a0, 0(a1) + +CHECK-LABEL: : +CHECK: lw a0, 0(a1) + +CHECK-LABEL: : +CHECK: sb a0, 0(a1) + +CHECK-LABEL: : +CHECK: sh a0, 0(a1) + +CHECK-LABEL: : +CHECK: sw a0, 0(a1) From 76c91610dba40bbe56008849be4744473154b6c8 Mon Sep 17 00:00:00 2001 From: Sam Elliott Date: Wed, 6 May 2026 15:00:31 -0700 Subject: [PATCH 2/4] [RISCV] Implement linker relaxation for R_RISCV_QC_ACCESS_16 and R_RISCV_QC_ACCESS_32 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Relaxes qc.e.li + load/store pairs annotated with R_RISCV_QC_ACCESS_32 (32-bit instruction) or R_RISCV_QC_ACCESS_16 (16-bit compressed instruction). Four relaxation variants are applied in priority order: 1. GP-std: qc.e.li + ls → GP-relative 32-bit load/store (saves 6/4 bytes) 2. Abs-std: qc.e.li + ls → x0-based 32-bit load/store (saves 6/4 bytes) 3. GP-xqci: qc.e.li + ls → 6-byte qc.e.l*/qc.e.s* (saves 4/2 bytes) 4. Abs-xqci: qc.e.li + ls → 6-byte qc.e.l*/qc.e.s* (saves 4/2 bytes) All variants require --relax-xqci. The ACCESS relocation must carry R_RISCV_RELAX for pair relaxation to occur; without it the qc.e.li falls back to standalone relaxation. The ACCESS relocation must be exactly 6 bytes after the qc.e.li. New internal relocation types R_RISCV_QC_{ABS,GPREL}26_{I,S} are added for the xqcilo immediate field, along with encoding types EncTy_QC_EI/EncTy_QC_ES and their encode/clear helpers. ELFSection::hasFollowing(R, Type) is added to check whether a relocation is immediately followed by one of a given type in the section's relocation list. Co-Authored-By: Claude Opus 4.7 (1M context) Signed-off-by: Sam Elliott --- include/eld/Readers/ELFSection.h | 4 + lib/Readers/ELFSection.cpp | 10 + lib/Target/RISCV/RISCVHelper.h | 15 + lib/Target/RISCV/RISCVLDBackend.cpp | 324 +++++++++++++++++- lib/Target/RISCV/RISCVLDBackend.h | 22 ++ lib/Target/RISCV/RISCVLLVMExtern.h | 5 + lib/Target/RISCV/RISCVRelocationCompute.cpp | 13 + lib/Target/RISCV/RISCVRelocationHelper.h | 34 ++ lib/Target/RISCV/RISCVRelocationInfo.cpp | 40 +++ lib/Target/RISCV/RISCVRelocationInternal.h | 4 + lib/Target/RISCV/RISCVRelocator.cpp | 39 +++ .../Relaxation/QC_E_LI_ACCESS/Inputs/1.s | 49 +++ .../Relaxation/QC_E_LI_ACCESS/Inputs/1.t | 16 + .../Relaxation/QC_E_LI_ACCESS/Inputs/2.s | 87 +++++ .../Relaxation/QC_E_LI_ACCESS/Inputs/2.t | 10 + .../Relaxation/QC_E_LI_ACCESS/Inputs/3.s | 121 +++++++ .../Relaxation/QC_E_LI_ACCESS/Inputs/3.t | 35 ++ .../QC_E_LI_ACCESS/QC_E_LI_ACCESS.test | 250 ++++++++++++++ 18 files changed, 1076 insertions(+), 2 deletions(-) create mode 100644 test/RISCV/standalone/Relaxation/QC_E_LI_ACCESS/Inputs/1.s create mode 100644 test/RISCV/standalone/Relaxation/QC_E_LI_ACCESS/Inputs/1.t create mode 100644 test/RISCV/standalone/Relaxation/QC_E_LI_ACCESS/Inputs/2.s create mode 100644 test/RISCV/standalone/Relaxation/QC_E_LI_ACCESS/Inputs/2.t create mode 100644 test/RISCV/standalone/Relaxation/QC_E_LI_ACCESS/Inputs/3.s create mode 100644 test/RISCV/standalone/Relaxation/QC_E_LI_ACCESS/Inputs/3.t create mode 100644 test/RISCV/standalone/Relaxation/QC_E_LI_ACCESS/QC_E_LI_ACCESS.test diff --git a/include/eld/Readers/ELFSection.h b/include/eld/Readers/ELFSection.h index 2f8851713..7aa801247 100644 --- a/include/eld/Readers/ELFSection.h +++ b/include/eld/Readers/ELFSection.h @@ -320,6 +320,10 @@ class ELFSection : public ELFSectionBase { Relocation *findRelocation(uint64_t Offset, Relocation::Type Type, bool Reverse = true) const; + // Returns true if R is immediately followed by a relocation of the given + // type in the section's relocation list. + bool hasFollowing(const Relocation *R, Relocation::Type Type) const; + Relocation *createOneReloc(); // Linker Script support for sorting sections. diff --git a/lib/Readers/ELFSection.cpp b/lib/Readers/ELFSection.cpp index 7c9df3a48..278ad526d 100644 --- a/lib/Readers/ELFSection.cpp +++ b/lib/Readers/ELFSection.cpp @@ -14,6 +14,7 @@ #include "eld/Readers/ELFSection.h" #include "eld/Object/OutputSectionEntry.h" #include "llvm/ADT/StringRef.h" +#include "llvm/BinaryFormat/ELF.h" #include using namespace eld; @@ -178,6 +179,15 @@ Relocation *ELFSection::findRelocation(uint64_t Offset, Relocation::Type Type, return nullptr; } +bool ELFSection::hasFollowing(const Relocation *R, + Relocation::Type Type) const { + auto It = std::find(Relocations.begin(), Relocations.end(), R); + if (It == Relocations.end()) + return false; + ++It; + return It != Relocations.end() && (*It)->type() == Type; +} + Fragment *ELFSection::getFirstFragmentInRule() const { OutputSectionEntry *OE = getOutputSection(); if (!OE || !OE->size()) diff --git a/lib/Target/RISCV/RISCVHelper.h b/lib/Target/RISCV/RISCVHelper.h index bc3651959..b82aa833b 100644 --- a/lib/Target/RISCV/RISCVHelper.h +++ b/lib/Target/RISCV/RISCVHelper.h @@ -333,6 +333,21 @@ template T encodeQCEJ(T Result) { return Result; } +template T encodeQCEI(T Result) { + uint32_t Imm9_0 = extractBits(Result, 9, 0) << 20; + uint64_t Imm25_10 = static_cast(extractBits(Result, 25, 10)) << 32; + Result = Imm9_0 | Imm25_10; + return Result; +} + +template T encodeQCES(T Result) { + uint32_t Imm4_0 = extractBits(Result, 4, 0) << 7; + uint32_t Imm9_5 = extractBits(Result, 9, 5) << 25; + uint64_t Imm25_10 = static_cast(extractBits(Result, 25, 10)) << 32; + Result = Imm4_0 | Imm9_5 | Imm25_10; + return Result; +} + /// -------------------------------------------- /// Fetch Registers and Opcode from Instruction /// -------------------------------------------- diff --git a/lib/Target/RISCV/RISCVLDBackend.cpp b/lib/Target/RISCV/RISCVLDBackend.cpp index bbfd5bbe8..2d6a81165 100644 --- a/lib/Target/RISCV/RISCVLDBackend.cpp +++ b/lib/Target/RISCV/RISCVLDBackend.cpp @@ -645,6 +645,311 @@ bool RISCVLDBackend::doRelaxationQCELi(Relocation *reloc, Relocator::DWord G) { return false; } +uint64_t RISCVLDBackend::QCAccess::build48Bit(unsigned base_reg) const { + switch (op) { + case Operation::Lb: + return qceitype(0x5u, 0x0u, reg, base_reg, 0); + case Operation::Lbu: + return qceitype(0x5u, 0x1u, reg, base_reg, 0); + case Operation::Lh: + return qceitype(0x5u, 0x2u, reg, base_reg, 0); + case Operation::Lhu: + return qceitype(0x5u, 0x3u, reg, base_reg, 0); + case Operation::Lw: + return qceitype(0x6u, 0x0u, reg, base_reg, 0); + case Operation::Sb: + return qcestype(0x6u, 0x1u, reg, base_reg, 0); + case Operation::Sh: + return qcestype(0x6u, 0x2u, reg, base_reg, 0); + case Operation::Sw: + return qcestype(0x6u, 0x3u, reg, base_reg, 0); + } +} + +uint32_t RISCVLDBackend::QCAccess::build32Bit(unsigned base_reg) const { + switch (op) { + case Operation::Lb: + return itype(0x03u | (0x0u << 12), reg, base_reg, 0); + case Operation::Lh: + return itype(0x03u | (0x1u << 12), reg, base_reg, 0); + case Operation::Lw: + return itype(0x03u | (0x2u << 12), reg, base_reg, 0); + case Operation::Lbu: + return itype(0x03u | (0x4u << 12), reg, base_reg, 0); + case Operation::Lhu: + return itype(0x03u | (0x5u << 12), reg, base_reg, 0); + case Operation::Sb: + return stype(0x23u | (0x0u << 12), reg, base_reg, 0); + case Operation::Sh: + return stype(0x23u | (0x1u << 12), reg, base_reg, 0); + case Operation::Sw: + return stype(0x23u | (0x2u << 12), reg, base_reg, 0); + } +} + +bool RISCVLDBackend::doRelaxationQCAccess32(Relocation *QCELiReloc, + Relocation *AccessReloc, + Relocator::DWord G) { + Fragment *frag = QCELiReloc->targetRef()->frag(); + RegionFragmentEx *region = llvm::dyn_cast(frag); + if (!region) + return false; + + uint64_t qceli_offset = QCELiReloc->targetRef()->offset(); + uint64_t qceli_instr = QCELiReloc->target(); + if ((qceli_instr & 0xf07fu) != 0x1fu) + return false; + unsigned qceli_rd = extractBits(qceli_instr, 11, 7); + if (qceli_rd == X_ZERO) + return false; + + if (!config().options().getRISCVRelax() || !config().targets().is32Bits() || + !config().options().getRISCVRelaxXqci()) + return false; + + uint32_t access_instr = 0; + region->copyData(&access_instr, sizeof(access_instr), qceli_offset + 6); + QCAccess access; + + // Decode the RV32I access instruction so we have enough information to + // know what width the access is, what its operand register is (rd for loads, + // rs2 for stores), and (for loads) whether it does a sign or zero extension. + // Its size will always be 4 bytes in this function, but we need that for the + // doRelaxationQCCommon. + switch (extractBits(access_instr, 6, 0)) { + case 0x03u: + // Loads are I-type + access.reg = extractBits(access_instr, 11, 7); + switch (extractBits(access_instr, 14, 12)) { + case 0b000u: + access.op = QCAccess::Operation::Lb; + break; + case 0b100u: + access.op = QCAccess::Operation::Lbu; + break; + case 0b001u: + access.op = QCAccess::Operation::Lh; + break; + case 0b101u: + access.op = QCAccess::Operation::Lhu; + break; + case 0b010u: + access.op = QCAccess::Operation::Lw; + break; + default: + return false; + } + break; + case 0x23u: + // Stores are S-type + access.reg = extractBits(access_instr, 24, 20); + switch (extractBits(access_instr, 14, 12)) { + case 0b000u: + access.op = QCAccess::Operation::Sb; + break; + case 0b001u: + access.op = QCAccess::Operation::Sh; + break; + case 0b010u: + access.op = QCAccess::Operation::Sw; + break; + default: + return false; + } + break; + default: + return false; + } + + access.size = 4; + + // Check rd of qc.e.li against base register of access + if (qceli_rd != extractBits(access_instr, 19, 15)) + return false; + + return doRelaxationQCAccessCommon(QCELiReloc, AccessReloc, G, access); +} + +bool RISCVLDBackend::doRelaxationQCAccess16(Relocation *QCELiReloc, + Relocation *AccessReloc, + Relocator::DWord G) { + Fragment *frag = QCELiReloc->targetRef()->frag(); + RegionFragmentEx *region = llvm::dyn_cast(frag); + if (!region) + return false; + + uint64_t qceli_offset = QCELiReloc->targetRef()->offset(); + uint64_t qceli_instr = QCELiReloc->target(); + if ((qceli_instr & 0xf07fu) != 0x1fu) + return false; + unsigned qceli_rd = extractBits(qceli_instr, 11, 7); + if (qceli_rd == X_ZERO) + return false; + + if (!config().options().getRISCVRelax() || !config().targets().is32Bits() || + !config().options().getRISCVRelaxXqci()) + return false; + + uint16_t access_instr = 0; + region->copyData(&access_instr, sizeof(access_instr), qceli_offset + 6); + QCAccess access; + + // Decode the RV32 Zca/Zcb access instruction so we have enough information to + // know what width the access is, what its operand register is (rd for loads, + // rs2 for stores), and (for loads) whether it does a sign or zero extension. + // Its size will always be 2 bytes in this function, but we need that for the + // doRelaxationQCCommon. + // + // This decoding is more complex than for 32-bit instructions as the 16-bit + // instructions are much less regular. + if ((access_instr & 0x3u) != 0x0u) + return false; + switch (extractBits(access_instr, 15, 13)) { + case 0b010u: + // c.lw + access.op = QCAccess::Operation::Lw; + break; + case 0b110u: + // c.sw + access.op = QCAccess::Operation::Sw; + break; + case 0b100u: + switch (extractBits(access_instr, 11, 10)) { + case 0b00u: + access.op = QCAccess::Operation::Lbu; + break; + case 0b01u: + if (extractBits(access_instr, 6, 6) == 0b1u) + access.op = QCAccess::Operation::Lh; + else + access.op = QCAccess::Operation::Lhu; + break; + case 0b10u: + access.op = QCAccess::Operation::Sb; + break; + case 0b11u: + access.op = QCAccess::Operation::Sh; + break; + default: + llvm_unreachable("Impossible Encoding"); + } + break; + default: + return false; + } + + access.reg = 8 + extractBits(access_instr, 4, 2); + access.size = 2; + + // Check rd of qc.e.li against base register of access + if (qceli_rd != 8 + extractBits(access_instr, 9, 7)) + return false; + + return doRelaxationQCAccessCommon(QCELiReloc, AccessReloc, G, access); +} + +bool RISCVLDBackend::doRelaxationQCAccessCommon(Relocation *QCELiReloc, + Relocation *AccessReloc, + Relocator::DWord G, + QCAccess access) { + /* Four relaxation variants, applied in priority order: + * -- GP-relative standard: -> GP-relative 32-bit load/store (saves 6/4 bytes) + * -- Absolute standard: -> x0-based 32-bit load/store (saves 6/4 bytes) + * -- GP-relative xqcilo: -> 6-byte qc.e.l/qc.e.s (saves 4/2 bytes) + * -- Absolute xqcilo: -> 6-byte qc.e.l/qc.e.s (saves 4/2 bytes) + * All variants require --relax-xqci since qc.e.li is itself an xqci insn. + */ + + RegionFragmentEx *region = + llvm::cast(QCELiReloc->targetRef()->frag()); + uint64_t qceli_offset = QCELiReloc->targetRef()->offset(); + + Relocator::DWord S = getSymbolValuePLT(*QCELiReloc); + Relocator::DWord A = QCELiReloc->addend(); + Relocator::DWord Value = S + A; + size_t SymbolSize = QCELiReloc->symInfo()->outSymbol()->size(); + + bool canRelaxGPStd = + config().options().getRISCVGPRelax() && !config().isCodeIndep() && + G != 0 && S != 0 && + fitsInGP(G, Value, region, QCELiReloc->targetSection(), SymbolSize); + + bool canRelaxAbsStd = config().options().getRISCVZeroRelax() && S != 0 && + llvm::isInt<12>((int64_t)Value); + + bool canRelaxGPXqci = config().options().getRISCVGPRelax() && + !config().isCodeIndep() && G != 0 && S != 0 && + llvm::isInt<26>((int64_t)(Value - G)); + + bool canRelaxAbsXqci = S != 0 && llvm::isInt<26>((int64_t)Value); + + const char *msg = "RISCV_QC_E_LI_ACCESS"; + + // This replaces the `qc.e.li; access` sequence with a 4-byte RVI access + // instruction + auto applyStdRelax = [&](unsigned base_reg, uint32_t reloc_load, + uint32_t reloc_store, const char *variant_msg) { + uint32_t new_access = access.build32Bit(base_reg); + region->replaceInstruction(qceli_offset, QCELiReloc, + reinterpret_cast(&new_access), 4); + QCELiReloc->setTargetData(new_access); + QCELiReloc->setType(access.isLoad() ? reloc_load : reloc_store); + relaxDeleteBytes(variant_msg, *region, qceli_offset + 4, 2 + access.size, + QCELiReloc->symInfo()->name()); + AccessReloc->setType(llvm::ELF::R_RISCV_NONE); + }; + + // This replaces the `qc.e.li; access` sequence with a 6-byte Xqcilo access + // instruction. + auto applyXqciloRelax = [&](unsigned base_reg, uint32_t reloc_load, + uint32_t reloc_store, const char *variant_msg) { + uint64_t new_access = access.build48Bit(base_reg); + region->replaceInstruction(qceli_offset, QCELiReloc, + reinterpret_cast(&new_access), 6); + QCELiReloc->setTargetData(new_access); + QCELiReloc->setType(access.isLoad() ? reloc_load : reloc_store); + relaxDeleteBytes(variant_msg, *region, qceli_offset + 6, access.size, + QCELiReloc->symInfo()->name()); + AccessReloc->setType(llvm::ELF::R_RISCV_NONE); + }; + + // 1. GP-relative standard + if (canRelaxGPStd) { + applyStdRelax(X_GP, ELF::riscv::internal::R_RISCV_GPREL_I, + ELF::riscv::internal::R_RISCV_GPREL_S, + "RISCV_QC_E_LI_ACCESS_GP_STD"); + return true; + } + // 2. Absolute standard + if (canRelaxAbsStd) { + applyStdRelax(X_ZERO, llvm::ELF::R_RISCV_LO12_I, llvm::ELF::R_RISCV_LO12_S, + "RISCV_QC_E_LI_ACCESS_ABS_STD"); + return true; + } + // 3. GP-relative xqcilo + if (canRelaxGPXqci) { + applyXqciloRelax(X_GP, ELF::riscv::internal::R_RISCV_QC_GPREL26_I, + ELF::riscv::internal::R_RISCV_QC_GPREL26_S, + "RISCV_QC_E_LI_ACCESS_GP_XQCI"); + reportMissedRelaxation(msg, *region, qceli_offset, 2, + QCELiReloc->symInfo()->name()); + return true; + } + // 4. Absolute xqcilo + if (canRelaxAbsXqci) { + applyXqciloRelax(X_ZERO, ELF::riscv::internal::R_RISCV_QC_ABS26_I, + ELF::riscv::internal::R_RISCV_QC_ABS26_S, + "RISCV_QC_E_LI_ACCESS_ABS_XQCI"); + reportMissedRelaxation(msg, *region, qceli_offset, 2, + QCELiReloc->symInfo()->name()); + return true; + } + + reportMissedRelaxation(msg, *region, qceli_offset, access.size, + QCELiReloc->symInfo()->name()); + return false; +} + bool RISCVLDBackend::doRelaxationTLSDESC(Relocation &R, bool Relax) { Fragment *frag = R.targetRef()->frag(); @@ -1089,8 +1394,23 @@ void RISCVLDBackend::mayBeRelax(int relaxation_pass, bool &pFinished) { break; } case ELF::riscv::internal::R_RISCV_QC_E_32: { - if (nextRelax && relaxation_pass == RELAXATION_LUI) - doRelaxationQCELi(relocation, GP); + if (nextRelax && relaxation_pass == RELAXATION_LUI) { + uint64_t access_offset = relocation->targetRef()->offset() + 6; + bool relaxed = false; + if (Relocation *acc32 = rs->getLink()->findRelocation( + access_offset, ELF::riscv::internal::R_RISCV_QC_ACCESS_32)) + if (rs->getLink()->hasFollowing(acc32, llvm::ELF::R_RISCV_RELAX)) + relaxed = doRelaxationQCAccess32(relocation, acc32, GP); + if (!relaxed) + if (Relocation *acc16 = rs->getLink()->findRelocation( + access_offset, + ELF::riscv::internal::R_RISCV_QC_ACCESS_16)) + if (rs->getLink()->hasFollowing(acc16, + llvm::ELF::R_RISCV_RELAX)) + relaxed = doRelaxationQCAccess16(relocation, acc16, GP); + if (!relaxed) + doRelaxationQCELi(relocation, GP); + } break; } } diff --git a/lib/Target/RISCV/RISCVLDBackend.h b/lib/Target/RISCV/RISCVLDBackend.h index 7b01d0cda..453b2990a 100644 --- a/lib/Target/RISCV/RISCVLDBackend.h +++ b/lib/Target/RISCV/RISCVLDBackend.h @@ -232,6 +232,28 @@ class RISCVLDBackend : public GNULDBackend { bool doRelaxationLui(Relocation *R, Relocation::DWord G); bool doRelaxationQCELi(Relocation *R, Relocation::DWord G); + bool doRelaxationQCAccess32(Relocation *QCELiReloc, Relocation *AccessReloc, + Relocation::DWord G); + bool doRelaxationQCAccess16(Relocation *QCELiReloc, Relocation *AccessReloc, + Relocation::DWord G); + + // Decoded load/store instruction info for QC ACCESS relaxation. + struct QCAccess { + // Loads come first so isLoad() is a cheap comparison. + enum class Operation { Lb, Lbu, Lh, Lhu, Lw, Sb, Sh, Sw }; + Operation op; + unsigned reg; // destination (load) or source data (store) register + uint32_t size; // access instruction size (in bytes) + + bool isLoad() const { return op <= Operation::Lw; } + + uint32_t build32Bit(unsigned base_reg) const; + uint64_t build48Bit(unsigned base_reg) const; + }; + bool doRelaxationQCAccessCommon(Relocation *QCELiReloc, + Relocation *AccessReloc, Relocation::DWord G, + QCAccess access); + bool doRelaxationAlign(Relocation *R); bool doRelaxationPC(Relocation *R, Relocation::DWord G); diff --git a/lib/Target/RISCV/RISCVLLVMExtern.h b/lib/Target/RISCV/RISCVLLVMExtern.h index dd5f38cfc..49bf47acf 100644 --- a/lib/Target/RISCV/RISCVLLVMExtern.h +++ b/lib/Target/RISCV/RISCVLLVMExtern.h @@ -30,6 +30,8 @@ enum EncodingType { EncTy_QC_EB, EncTy_QC_EAI, EncTy_QC_EJ, + EncTy_QC_EI, + EncTy_QC_ES, EncTy_6, EncTy_8, EncTy_16, @@ -93,6 +95,9 @@ inline unsigned getEncodingBitWidth(EncodingType Type) { case EncTy_QC_EJ: case EncTy_32: return 32; + case EncTy_QC_EI: + case EncTy_QC_ES: + return 26; case EncTy_LEB128: case EncTy_None: return 0; diff --git a/lib/Target/RISCV/RISCVRelocationCompute.cpp b/lib/Target/RISCV/RISCVRelocationCompute.cpp index e5edfe2b3..23e4e0b1b 100644 --- a/lib/Target/RISCV/RISCVRelocationCompute.cpp +++ b/lib/Target/RISCV/RISCVRelocationCompute.cpp @@ -22,6 +22,9 @@ bool checkRange(uint64_t Value, bool IsSigned, EncodingType Type) { case EncTy_QC_EAI: case EncTy_QC_EJ: return llvm::isInt<32>(static_cast(Value)); + case EncTy_QC_EI: + case EncTy_QC_ES: + return llvm::isInt<26>(static_cast(Value)); case EncTy_U_HI20: case EncTy_U_ABS20: case EncTy_UJ: @@ -95,6 +98,10 @@ uint64_t clearImmediateBits(uint64_t Instr, EncodingType Type) { return Instr & 0x00000000FFFF; case EncTy_QC_EJ: return Instr & 0x000001F1F07F; + case EncTy_QC_EI: + return Instr & 0x00000000C00FFFFFull; + case EncTy_QC_ES: + return Instr & 0x00000000C1FFF07Full; /* C.LUI/C.LI clearing handled in doRelocHelper */ case EncTy_CI: /* No overwriting being performed */ @@ -154,6 +161,12 @@ uint64_t doRelocHelper(const RelocationInfo &RelocInfo, uint64_t Instruction, case EncTy_QC_EJ: Value = encodeQCEJ(Value); break; + case EncTy_QC_EI: + Value = encodeQCEI(Value); + break; + case EncTy_QC_ES: + Value = encodeQCES(Value); + break; case EncTy_32: Value = encode32(Value); break; diff --git a/lib/Target/RISCV/RISCVRelocationHelper.h b/lib/Target/RISCV/RISCVRelocationHelper.h index 135159fe2..5a3c380f1 100644 --- a/lib/Target/RISCV/RISCVRelocationHelper.h +++ b/lib/Target/RISCV/RISCVRelocationHelper.h @@ -48,6 +48,11 @@ enum Reg { uint32_t imm) { return op | (rd << 7) | (rs1 << 15) | (imm << 20); } +[[maybe_unused]] uint32_t stype(uint32_t op, uint32_t rs2, uint32_t rs1, + uint32_t imm) { + return op | ((imm & 0x1Fu) << 7) | (rs1 << 15) | (rs2 << 20) | + ((imm >> 5) << 25); +} [[maybe_unused]] uint32_t rtype(uint32_t op, uint32_t rd, uint32_t rs1, uint32_t rs2) { return op | (rd << 7) | (rs1 << 15) | (rs2 << 20); @@ -56,6 +61,35 @@ enum Reg { return op | (rd << 7) | (imm << 12); } +// QC.EI type instruction +[[maybe_unused]] uint64_t qceitype(uint32_t xf3, uint32_t xf2, uint32_t rd, + uint32_t rs1, int64_t imm) { + uint32_t uimm = (uint32_t)(imm & 0x3FFFFFFu); + uint64_t inst = 0x1fu; + inst |= (uint64_t)rd << 7; + inst |= (uint64_t)xf3 << 12; + inst |= (uint64_t)rs1 << 15; + inst |= (uint64_t)(uimm & 0x3FFu) << 20; + inst |= (uint64_t)xf2 << 30; + inst |= (uint64_t)((uimm >> 10) & 0xFFFFu) << 32; + return inst; +} + +// QC.ES type instruction +[[maybe_unused]] uint64_t qcestype(uint32_t xf3, uint32_t xf2, uint32_t rs2, + uint32_t rs1, int64_t imm) { + uint32_t uimm = (uint32_t)(imm & 0x3FFFFFFu); + uint64_t inst = 0x1fu; + inst |= (uint64_t)(uimm & 0x1Fu) << 7; + inst |= (uint64_t)xf3 << 12; + inst |= (uint64_t)rs1 << 15; + inst |= (uint64_t)rs2 << 20; + inst |= (uint64_t)((uimm >> 5) & 0x1Fu) << 25; + inst |= (uint64_t)xf2 << 30; + inst |= (uint64_t)((uimm >> 10) & 0xFFFFu) << 32; + return inst; +} + // Extract bits v[begin:end], where range is inclusive, and begin must be < 63. [[maybe_unused]] uint32_t extractBits(uint64_t v, uint32_t begin, uint32_t end) { diff --git a/lib/Target/RISCV/RISCVRelocationInfo.cpp b/lib/Target/RISCV/RISCVRelocationInfo.cpp index 32b764d77..69ae22278 100644 --- a/lib/Target/RISCV/RISCVRelocationInfo.cpp +++ b/lib/Target/RISCV/RISCVRelocationInfo.cpp @@ -697,6 +697,46 @@ RISCVRelocationMap RISCVRelocs = { /*.VerifyAlignment = */ false, /*.Signed = */ true, /*.Size = */ 32}}, + {eld::ELF::riscv::internal::R_RISCV_QC_ABS26_I, + {/*.Name = */ "R_RISCV_QC_ABS26_I", + /*.Type = */ eld::ELF::riscv::internal::R_RISCV_QC_ABS26_I, + /*EncodingType = */ EncTy_QC_EI, + /*.Alignment = */ 0, + /*.shift = */ 0, + /*.VerifyRange = */ false, + /*.VerifyAlignment = */ false, + /*.Signed = */ true, + /*.Size = */ 48}}, + {eld::ELF::riscv::internal::R_RISCV_QC_ABS26_S, + {/*.Name = */ "R_RISCV_QC_ABS26_S", + /*.Type = */ eld::ELF::riscv::internal::R_RISCV_QC_ABS26_S, + /*EncodingType = */ EncTy_QC_ES, + /*.Alignment = */ 0, + /*.shift = */ 0, + /*.VerifyRange = */ false, + /*.VerifyAlignment = */ false, + /*.Signed = */ true, + /*.Size = */ 48}}, + {eld::ELF::riscv::internal::R_RISCV_QC_GPREL26_I, + {/*.Name = */ "R_RISCV_QC_GPREL26_I", + /*.Type = */ eld::ELF::riscv::internal::R_RISCV_QC_GPREL26_I, + /*EncodingType = */ EncTy_QC_EI, + /*.Alignment = */ 0, + /*.shift = */ 0, + /*.VerifyRange = */ false, + /*.VerifyAlignment = */ false, + /*.Signed = */ true, + /*.Size = */ 48}}, + {eld::ELF::riscv::internal::R_RISCV_QC_GPREL26_S, + {/*.Name = */ "R_RISCV_QC_GPREL26_S", + /*.Type = */ eld::ELF::riscv::internal::R_RISCV_QC_GPREL26_S, + /*EncodingType = */ EncTy_QC_ES, + /*.Alignment = */ 0, + /*.shift = */ 0, + /*.VerifyRange = */ false, + /*.VerifyAlignment = */ false, + /*.Signed = */ true, + /*.Size = */ 48}}, /* Internal Relocations: Vendor */ {eld::ELF::riscv::internal::R_RISCV_QC_ABS20_U, {/*.Name = */ "R_RISCV_QC_ABS20_U", diff --git a/lib/Target/RISCV/RISCVRelocationInternal.h b/lib/Target/RISCV/RISCVRelocationInternal.h index 61addc8b8..a303c1e85 100644 --- a/lib/Target/RISCV/RISCVRelocationInternal.h +++ b/lib/Target/RISCV/RISCVRelocationInternal.h @@ -53,6 +53,10 @@ enum : uint32_t { R_RISCV_GPREL_S, R_RISCV_TPREL_I, R_RISCV_TPREL_S, + R_RISCV_QC_ABS26_I, // absolute xqcilo load (S+A) + R_RISCV_QC_ABS26_S, // absolute xqcilo store (S+A) + R_RISCV_QC_GPREL26_I, // GP-relative xqcilo load (S+A-G) + R_RISCV_QC_GPREL26_S, // GP-relative xqcilo store (S+A-G) /* Internal IDs for Nonstandard Relocations diff --git a/lib/Target/RISCV/RISCVRelocator.cpp b/lib/Target/RISCV/RISCVRelocator.cpp index e9eb49703..6911e30fb 100644 --- a/lib/Target/RISCV/RISCVRelocator.cpp +++ b/lib/Target/RISCV/RISCVRelocator.cpp @@ -56,6 +56,8 @@ DECL_RISCV_APPLY_RELOC_FUNC(applyGPRel) DECL_RISCV_APPLY_RELOC_FUNC(applyCompressedLUI) DECL_RISCV_APPLY_RELOC_FUNC(applyTprelAdd) DECL_RISCV_APPLY_RELOC_FUNC(applyGOT) +DECL_RISCV_APPLY_RELOC_FUNC(applyXqciloAbs) +DECL_RISCV_APPLY_RELOC_FUNC(applyXqciloGPRel) DECL_RISCV_APPLY_RELOC_FUNC(applyVendor) #undef DECL_RISCV_APPLY_RELOC_FUNC @@ -207,6 +209,10 @@ RelocationDescMap RelocDescs = { INTERNAL_RELOC_DESC_ENTRY(R_RISCV_GPREL_S, applyGPRel), INTERNAL_RELOC_DESC_ENTRY(R_RISCV_TPREL_I, unsupported), INTERNAL_RELOC_DESC_ENTRY(R_RISCV_TPREL_S, unsupported), + INTERNAL_RELOC_DESC_ENTRY(R_RISCV_QC_ABS26_I, applyXqciloAbs), + INTERNAL_RELOC_DESC_ENTRY(R_RISCV_QC_ABS26_S, applyXqciloAbs), + INTERNAL_RELOC_DESC_ENTRY(R_RISCV_QC_GPREL26_I, applyXqciloGPRel), + INTERNAL_RELOC_DESC_ENTRY(R_RISCV_QC_GPREL26_S, applyXqciloGPRel), /* Vendor Relocations: QUALCOMM */ INTERNAL_RELOC_DESC_ENTRY(R_RISCV_QC_ABS20_U, applyAbs), @@ -1099,6 +1105,39 @@ RISCVRelocator::Result applyGPRel(Relocation &pReloc, RISCVLDBackend &Backend, return ApplyReloc(pReloc, S + A - G, pRelocDesc, Backend.config(), Parent); } +RISCVRelocator::Result applyXqciloAbs(Relocation &pReloc, + RISCVLDBackend &Backend, + RISCVRelocator &Parent, + RelocationDescription &pRelocDesc) { + if (RelocDescs.count(pReloc.type()) == 0) + return RISCVRelocator::Unsupport; + int64_t S = Backend.getSymbolValuePLT(pReloc); + int64_t A = pReloc.addend(); + int64_t Result = S + A; + if (!llvm::isInt<26>(Result)) + return checkSignedRange(pReloc, Parent, Result, 26); + return ApplyReloc(pReloc, Result, pRelocDesc, Backend.config(), Parent); +} + +RISCVRelocator::Result applyXqciloGPRel(Relocation &pReloc, + RISCVLDBackend &Backend, + RISCVRelocator &Parent, + RelocationDescription &pRelocDesc) { + if (RelocDescs.count(pReloc.type()) == 0) + return RISCVRelocator::Unsupport; + int64_t S = Backend.getSymbolValuePLT(pReloc); + int64_t A = pReloc.addend(); + int64_t G = 0; + LDSymbol *gpSym = + Backend.getModule().getNamePool().findSymbol("__global_pointer$"); + if (gpSym) + G = gpSym->value(); + int64_t Result = S + A - G; + if (!llvm::isInt<26>(Result)) + return checkSignedRange(pReloc, Parent, Result, 26); + return ApplyReloc(pReloc, Result, pRelocDesc, Backend.config(), Parent); +} + RISCVRelocator::Result applyCompressedLUI(Relocation &pReloc, RISCVLDBackend &Backend, RISCVRelocator &Parent, diff --git a/test/RISCV/standalone/Relaxation/QC_E_LI_ACCESS/Inputs/1.s b/test/RISCV/standalone/Relaxation/QC_E_LI_ACCESS/Inputs/1.s new file mode 100644 index 000000000..90b4e28d7 --- /dev/null +++ b/test/RISCV/standalone/Relaxation/QC_E_LI_ACCESS/Inputs/1.s @@ -0,0 +1,49 @@ + # Required until https://github.com/llvm/llvm-project/pull/146184 lands + .option exact + + # Enable Relaxations + .option relax + + .text + .p2align 2 + .globl main + .type main, @function + +QUALCOMM: + +main: + + # ACCESS_32: 32-bit load (lw) test cases + + qc.e.li a1, sym_gprel_std +1: + lw a0, 0(a1) + .reloc 1b, R_RISCV_VENDOR, QUALCOMM + .reloc 1b, R_RISCV_CUSTOM197, sym_gprel_std + .reloc 1b, R_RISCV_RELAX + + qc.e.li a1, sym_gprel_xqci +2: + lw a0, 0(a1) + .reloc 2b, R_RISCV_VENDOR, QUALCOMM + .reloc 2b, R_RISCV_CUSTOM197, sym_gprel_xqci + .reloc 2b, R_RISCV_RELAX + + qc.e.li a1, sym_too_far +3: + lw a0, 0(a1) + .reloc 3b, R_RISCV_VENDOR, QUALCOMM + .reloc 3b, R_RISCV_CUSTOM197, sym_too_far + .reloc 3b, R_RISCV_RELAX + + # ACCESS_16: 16-bit compressed load (c.lw) test case + # a1 (x11) is in the CL-format register range (x8-x15) + + qc.e.li a1, sym_gprel_std +4: + c.lw a0, 0(a1) + .reloc 4b, R_RISCV_VENDOR, QUALCOMM + .reloc 4b, R_RISCV_CUSTOM196, sym_gprel_std + .reloc 4b, R_RISCV_RELAX + + .size main, .-main diff --git a/test/RISCV/standalone/Relaxation/QC_E_LI_ACCESS/Inputs/1.t b/test/RISCV/standalone/Relaxation/QC_E_LI_ACCESS/Inputs/1.t new file mode 100644 index 000000000..097565f94 --- /dev/null +++ b/test/RISCV/standalone/Relaxation/QC_E_LI_ACCESS/Inputs/1.t @@ -0,0 +1,16 @@ + +/* GP somewhere not reachable by a standard 12-bit GP-relative access */ +__global_pointer$ = 0x01000000; + +/* In 12-bit GP-relative range: GP + 0x20 */ +sym_gprel_std = __global_pointer$ + 0x20; + +/* In 26-bit GP-relative range but not 12-bit: GP + 0x100000 */ +sym_gprel_xqci = __global_pointer$ + 0x100000; + +/* Out of all ranges: GP + 0x4000000 > 2^25 */ +sym_too_far = __global_pointer$ + 0x4000000; + +SECTIONS { + .text : { *(.text) } +} diff --git a/test/RISCV/standalone/Relaxation/QC_E_LI_ACCESS/Inputs/2.s b/test/RISCV/standalone/Relaxation/QC_E_LI_ACCESS/Inputs/2.s new file mode 100644 index 000000000..11e0c9f74 --- /dev/null +++ b/test/RISCV/standalone/Relaxation/QC_E_LI_ACCESS/Inputs/2.s @@ -0,0 +1,87 @@ + # Required until https://github.com/llvm/llvm-project/pull/146184 lands + .option exact + + # Enable relaxations on qc.e.li instructions + .option relax + + .text + .p2align 2 + .globl main + .type main, @function + +QUALCOMM: + +main: + + ## Case 1: Abs-std relaxation + ## sym_abs_std = 0x100 is within isInt<12>, so Abs-std applies: + ## qc.e.li + lw -> lw a0, 256(zero), deletes 6 bytes + + qc.e.li a1, sym_abs_std +1: + lw a0, 0(a1) + .reloc 1b, R_RISCV_VENDOR, QUALCOMM + .reloc 1b, R_RISCV_CUSTOM197, sym_abs_std + .reloc 1b, R_RISCV_RELAX + + ## Case 2: ACCESS without R_RISCV_RELAX on the load/store + ## R_RISCV_RELAX is required on the ACCESS reloc for pair relaxation. + ## Without it, qc.e.li falls back to qc.li-only relaxation. + + qc.e.li a1, sym_abs_std +2: + lw a0, 0(a1) + .reloc 2b, R_RISCV_VENDOR, QUALCOMM + .reloc 2b, R_RISCV_CUSTOM197, sym_abs_std + # Intentionally no R_RISCV_RELAX on the ACCESS reloc + + ## Case 3: Base register mismatch — ACCESS decode fails, falls back to + ## qc.e.li-only relaxation. qc.e.li loads into a1 but the lw uses a2. + + qc.e.li a1, sym_gprel_std +3: + lw a0, 0(a2) + .reloc 3b, R_RISCV_VENDOR, QUALCOMM + .reloc 3b, R_RISCV_CUSTOM197, sym_gprel_std + .reloc 3b, R_RISCV_RELAX + + ## Case 4: Store (sw) with ACCESS_32, GP-std range + ## sym_gprel_std is within isInt<12>(sym - GP), so GP-std applies: + ## qc.e.li + sw -> sw a0, 32(gp) + + qc.e.li a1, sym_gprel_std +4: + sw a0, 0(a1) + .reloc 4b, R_RISCV_VENDOR, QUALCOMM + .reloc 4b, R_RISCV_CUSTOM197, sym_gprel_std + .reloc 4b, R_RISCV_RELAX + + ## Case 5: c.sw (ACCESS_16, CS format), GP-std range + ## 16-bit store; GP-std applies, result is a 4-byte sw. + + qc.e.li a1, sym_gprel_std +5: + c.sw a0, 0(a1) + .reloc 5b, R_RISCV_VENDOR, QUALCOMM + .reloc 5b, R_RISCV_CUSTOM196, sym_gprel_std + .reloc 5b, R_RISCV_RELAX + + ## Case 6: c.lbu (ACCESS_16, Zcb), GP-std range + + qc.e.li a1, sym_gprel_std +6: + c.lbu a0, 0(a1) + .reloc 6b, R_RISCV_VENDOR, QUALCOMM + .reloc 6b, R_RISCV_CUSTOM196, sym_gprel_std + .reloc 6b, R_RISCV_RELAX + + ## Case 7: c.sh (ACCESS_16, Zcb), GP-std range + + qc.e.li a1, sym_gprel_std +7: + c.sh a0, 0(a1) + .reloc 7b, R_RISCV_VENDOR, QUALCOMM + .reloc 7b, R_RISCV_CUSTOM196, sym_gprel_std + .reloc 7b, R_RISCV_RELAX + + .size main, .-main diff --git a/test/RISCV/standalone/Relaxation/QC_E_LI_ACCESS/Inputs/2.t b/test/RISCV/standalone/Relaxation/QC_E_LI_ACCESS/Inputs/2.t new file mode 100644 index 000000000..1fb048880 --- /dev/null +++ b/test/RISCV/standalone/Relaxation/QC_E_LI_ACCESS/Inputs/2.t @@ -0,0 +1,10 @@ +/* GP at a standard address */ +__global_pointer$ = 0x01000000; + +/* Abs-std: 0x100 is within isInt<12> (signed 12-bit range = -2048..2047) */ +sym_abs_std = 0x100; + +/* GP-std range: small positive offset from GP, within isInt<12>(sym - GP) */ +sym_gprel_std = __global_pointer$ + 0x20; + +SECTIONS { .text : { *(.text) } } diff --git a/test/RISCV/standalone/Relaxation/QC_E_LI_ACCESS/Inputs/3.s b/test/RISCV/standalone/Relaxation/QC_E_LI_ACCESS/Inputs/3.s new file mode 100644 index 000000000..739b83fcf --- /dev/null +++ b/test/RISCV/standalone/Relaxation/QC_E_LI_ACCESS/Inputs/3.s @@ -0,0 +1,121 @@ + .option exact + .option relax + + .text + .p2align 2 + .globl main + .type main, @function + +QUALCOMM: + +main: + + ## GP-std range boundary tests (--relax-xqci with GP relax). + ## isInt<12>(sym - GP): range is [-2048, +2047]. + + ## At the positive edge of GP-std range (+2047): → GP-std relaxation. + qc.e.li a1, sym_gp_std_pos_edge +1: + lw a0, 0(a1) + .reloc 1b, R_RISCV_VENDOR, QUALCOMM + .reloc 1b, R_RISCV_CUSTOM197, sym_gp_std_pos_edge + .reloc 1b, R_RISCV_RELAX + + ## At the negative edge of GP-std range (-2048): → GP-std relaxation. + qc.e.li a1, sym_gp_std_neg_edge +2: + lw a0, 0(a1) + .reloc 2b, R_RISCV_VENDOR, QUALCOMM + .reloc 2b, R_RISCV_CUSTOM197, sym_gp_std_neg_edge + .reloc 2b, R_RISCV_RELAX + + ## Just outside the positive GP-std range (+2048): → GP-xqci relaxation. + qc.e.li a1, sym_gp_std_pos_out +3: + lw a0, 0(a1) + .reloc 3b, R_RISCV_VENDOR, QUALCOMM + .reloc 3b, R_RISCV_CUSTOM197, sym_gp_std_pos_out + .reloc 3b, R_RISCV_RELAX + + ## Just outside the negative GP-std range (-2049): → GP-xqci relaxation. + qc.e.li a1, sym_gp_std_neg_out +4: + lw a0, 0(a1) + .reloc 4b, R_RISCV_VENDOR, QUALCOMM + .reloc 4b, R_RISCV_CUSTOM197, sym_gp_std_neg_out + .reloc 4b, R_RISCV_RELAX + + ## GP-xqci range boundary tests. + ## isInt<26>(sym - GP): range is [-33554432, +33554431]. + + ## At the positive edge of GP-xqci range (+33554431): → GP-xqci relaxation. + qc.e.li a1, sym_gp_xqci_pos_edge +5: + lw a0, 0(a1) + .reloc 5b, R_RISCV_VENDOR, QUALCOMM + .reloc 5b, R_RISCV_CUSTOM197, sym_gp_xqci_pos_edge + .reloc 5b, R_RISCV_RELAX + + ## At the negative edge of GP-xqci range (-33554432): → GP-xqci relaxation. + qc.e.li a1, sym_gp_xqci_neg_edge +6: + lw a0, 0(a1) + .reloc 6b, R_RISCV_VENDOR, QUALCOMM + .reloc 6b, R_RISCV_CUSTOM197, sym_gp_xqci_neg_edge + .reloc 6b, R_RISCV_RELAX + + ## Just outside the positive GP-xqci range (+33554432): → missed. + qc.e.li a1, sym_gp_xqci_pos_out +7: + lw a0, 0(a1) + .reloc 7b, R_RISCV_VENDOR, QUALCOMM + .reloc 7b, R_RISCV_CUSTOM197, sym_gp_xqci_pos_out + .reloc 7b, R_RISCV_RELAX + + ## Just outside the negative GP-xqci range (-33554433): → missed. + qc.e.li a1, sym_gp_xqci_neg_out +8: + lw a0, 0(a1) + .reloc 8b, R_RISCV_VENDOR, QUALCOMM + .reloc 8b, R_RISCV_CUSTOM197, sym_gp_xqci_neg_out + .reloc 8b, R_RISCV_RELAX + + ## Abs-std range boundary tests (ZeroRelax enabled, no GP relax). + ## isInt<12>(sym): range is [-2048, +2047]; sym must be non-zero. + + ## At the positive edge of Abs-std range (2047): → Abs-std relaxation. + qc.e.li a1, sym_abs_std_edge +9: + lw a0, 0(a1) + .reloc 9b, R_RISCV_VENDOR, QUALCOMM + .reloc 9b, R_RISCV_CUSTOM197, sym_abs_std_edge + .reloc 9b, R_RISCV_RELAX + + ## Just outside the positive Abs-std range (2048): → Abs-xqci relaxation. + qc.e.li a1, sym_abs_std_out +10: + lw a0, 0(a1) + .reloc 10b, R_RISCV_VENDOR, QUALCOMM + .reloc 10b, R_RISCV_CUSTOM197, sym_abs_std_out + .reloc 10b, R_RISCV_RELAX + + ## Abs-xqci range boundary tests (ZeroRelax disabled, no GP relax). + ## isInt<26>(sym): range is [1, 33554431]. + + ## At the positive edge of Abs-xqci range (33554431): → Abs-xqci relaxation. + qc.e.li a1, sym_abs_xqci_edge +11: + lw a0, 0(a1) + .reloc 11b, R_RISCV_VENDOR, QUALCOMM + .reloc 11b, R_RISCV_CUSTOM197, sym_abs_xqci_edge + .reloc 11b, R_RISCV_RELAX + + ## Just outside the positive Abs-xqci range (33554432): → missed. + qc.e.li a1, sym_abs_xqci_out +12: + lw a0, 0(a1) + .reloc 12b, R_RISCV_VENDOR, QUALCOMM + .reloc 12b, R_RISCV_CUSTOM197, sym_abs_xqci_out + .reloc 12b, R_RISCV_RELAX + + .size main, .-main diff --git a/test/RISCV/standalone/Relaxation/QC_E_LI_ACCESS/Inputs/3.t b/test/RISCV/standalone/Relaxation/QC_E_LI_ACCESS/Inputs/3.t new file mode 100644 index 000000000..8d8c7d768 --- /dev/null +++ b/test/RISCV/standalone/Relaxation/QC_E_LI_ACCESS/Inputs/3.t @@ -0,0 +1,35 @@ +/* GP placed so that GP-relative and absolute ranges don't overlap: + * GP = 0x10000000 (268435456) + * + * GP-std range: isInt<12>(sym - GP) → sym in [GP-2048 .. GP+2047] + * Abs-std range: isInt<12>(sym) → sym in [1 .. 2047] (non-zero) + * GP-xqci range: isInt<26>(sym - GP) → sym in [GP-33554432 .. GP+33554431] + * Abs-xqci range: isInt<26>(sym) → sym in [1 .. 33554431] (non-zero) + * + * With GP = 0x10000000: + * Abs range [1..33554431] = [0x1..0x1FFFFFF] lies entirely below GP, + * so GP-relative and absolute ranges do not overlap. + */ +__global_pointer$ = 0x10000000; + +/* GP-std: boundary symbols at GP ± 2047 (innermost) and GP ± 2048 (just out) */ +sym_gp_std_pos_edge = __global_pointer$ + 2047; /* isInt<12>(+2047) → GP-std */ +sym_gp_std_neg_edge = __global_pointer$ - 2048; /* isInt<12>(-2048) → GP-std */ +sym_gp_std_pos_out = __global_pointer$ + 2048; /* isInt<12>(+2048) → false → GP-xqci */ +sym_gp_std_neg_out = __global_pointer$ - 2049; /* isInt<12>(-2049) → false → GP-xqci */ + +/* GP-xqci: boundary symbols at GP ± 33554431 (innermost) and GP ± 33554432 (just out) */ +sym_gp_xqci_pos_edge = __global_pointer$ + 33554431; /* isInt<26>(+33554431) → GP-xqci */ +sym_gp_xqci_neg_edge = __global_pointer$ - 33554432; /* isInt<26>(-33554432) → GP-xqci */ +sym_gp_xqci_pos_out = __global_pointer$ + 33554432; /* isInt<26>(+33554432) → false → miss */ +sym_gp_xqci_neg_out = __global_pointer$ - 33554433; /* isInt<26>(-33554433) → false → miss */ + +/* Abs-std: boundary symbols at ± 2047 (innermost) and ± 2048 (just out) */ +sym_abs_std_edge = 2047; /* isInt<12>(2047) → Abs-std (if ZeroRelax) */ +sym_abs_std_out = 2048; /* isInt<12>(2048) → false → Abs-xqci */ + +/* Abs-xqci: boundary symbols at 33554431 (innermost) and 33554432 (just out) */ +sym_abs_xqci_edge = 33554431; /* isInt<26>(33554431) → Abs-xqci */ +sym_abs_xqci_out = 33554432; /* isInt<26>(33554432) → false → miss */ + +SECTIONS { .text : { *(.text) } } diff --git a/test/RISCV/standalone/Relaxation/QC_E_LI_ACCESS/QC_E_LI_ACCESS.test b/test/RISCV/standalone/Relaxation/QC_E_LI_ACCESS/QC_E_LI_ACCESS.test new file mode 100644 index 000000000..ed306ff44 --- /dev/null +++ b/test/RISCV/standalone/Relaxation/QC_E_LI_ACCESS/QC_E_LI_ACCESS.test @@ -0,0 +1,250 @@ +#----------QC_E_LI_ACCESS.test----------------- Executable------------------# +#BEGIN_COMMENT +# Linker relaxation for R_RISCV_QC_ACCESS_16 and R_RISCV_QC_ACCESS_32. +# A qc.e.li + load/store pair is replaced with a single GP-relative or +# absolute load/store (standard or xqcilo) when the symbol is in range. +# All variants require --relax-xqci. +#END_COMMENT +#-------------------------------------------------------------------- +REQUIRES: riscv32 +RUN: %clang %clangopts -c %p/Inputs/1.s -o %t.o -menable-experimental-extensions -march=rv32gc_xqcili0p2 + +## Link with Xqci and GP relaxations enabled (default). +RUN: %link %linkopts --relax-xqci -MapStyle txt -Map %t.1.map --verbose %t.o -o %t.1.out -T %p/Inputs/1.t 2>&1 | %filecheck %s --check-prefix=VERBOSE + +VERBOSE: RISCV_QC_E_LI_ACCESS_GP_STD : Deleting 6 bytes for symbol 'sym_gprel_std' in section .text+0x4 file {{.*}}.o +VERBOSE: RISCV_QC_E_LI_ACCESS_GP_XQCI : Deleting 4 bytes for symbol 'sym_gprel_xqci' in section .text+0xa file {{.*}}.o +VERBOSE: RISCV_QC_E_LI_ACCESS : Cannot relax 2 bytes for symbol 'sym_gprel_xqci' in section .text+0x4 file {{.*}}.o +VERBOSE: RISCV_QC_E_LI_ACCESS : Cannot relax 4 bytes for symbol 'sym_too_far' in section .text+0xa file {{.*}}.o +VERBOSE: RISCV_QC_E_LI_QC_LI : Cannot relax 2 bytes for symbol 'sym_too_far' in section .text+0xa file {{.*}}.o +VERBOSE: RISCV_QC_E_LI_ACCESS_GP_STD : Deleting 4 bytes for symbol 'sym_gprel_std' in section .text+0x18 file {{.*}}.o + +RUN: %filecheck %s --input-file=%t.1.map --check-prefix=MAP + +MAP: # LinkStats Begin +MAP: # RelaxationBytesDeleted : 14 +MAP: # RelaxationBytesMissed : 8 +MAP: # LinkStats End + +MAP: .text {{.+}}, Alignment: 0x4, Flags: SHF_ALLOC|SHF_EXECINSTR, Type: SHT_PROGBITS +MAP: # RelaxationBytesDeleted : 14 +MAP: # RelaxationBytesMissed : 8 +MAP: .text {{.+}}.o #SHT_PROGBITS,SHF_ALLOC|SHF_EXECINSTR,4 + +RUN: %objdump --no-print-imm-hex --mattr=+xqcilo -M no-aliases -d %t.1.out 2>&1 | %filecheck %s --check-prefix=EXE + +EXE:
: +EXE-NEXT: 0201a503 lw a0, 32(gp) +EXE-NEXT: e51f 0001 0400 qc.e.lw a0, 1048576(gp) +EXE-NEXT: 059f 0000 0500 qc.e.li a1, 83886080 +EXE-NEXT: 0005a503 lw a0, 0(a1) +EXE-NEXT: 0201a503 lw a0, 32(gp) + +## Link with Xqci enabled, GP relaxation disabled. +RUN: %link %linkopts --relax-xqci --no-relax-gp -MapStyle txt -Map %t.2.map --verbose %t.o -o %t.2.out -T %p/Inputs/1.t 2>&1 | %filecheck %s --check-prefix=VERBOSE-NO-GP + +VERBOSE-NO-GP: RISCV_QC_E_LI_ACCESS_ABS_XQCI : Deleting 4 bytes for symbol 'sym_gprel_std' in section .text+0x6 file {{.*}}.o +VERBOSE-NO-GP: RISCV_QC_E_LI_ACCESS : Cannot relax 2 bytes for symbol 'sym_gprel_std' in section .text+0x0 file {{.*}}.o +VERBOSE-NO-GP: RISCV_QC_E_LI_ACCESS_ABS_XQCI : Deleting 4 bytes for symbol 'sym_gprel_xqci' in section .text+0xc file {{.*}}.o +VERBOSE-NO-GP: RISCV_QC_E_LI_ACCESS : Cannot relax 2 bytes for symbol 'sym_gprel_xqci' in section .text+0x6 file {{.*}}.o +VERBOSE-NO-GP: RISCV_QC_E_LI_ACCESS : Cannot relax 4 bytes for symbol 'sym_too_far' in section .text+0xc file {{.*}}.o +VERBOSE-NO-GP: RISCV_QC_E_LI_QC_LI : Cannot relax 2 bytes for symbol 'sym_too_far' in section .text+0xc file {{.*}}.o +VERBOSE-NO-GP: RISCV_QC_E_LI_ACCESS_ABS_XQCI : Deleting 2 bytes for symbol 'sym_gprel_std' in section .text+0x1c file {{.*}}.o +VERBOSE-NO-GP: RISCV_QC_E_LI_ACCESS : Cannot relax 2 bytes for symbol 'sym_gprel_std' in section .text+0x16 file {{.*}}.o + +RUN: %filecheck %s --input-file=%t.2.map --check-prefix=MAP-NO-GP + +MAP-NO-GP: # LinkStats Begin +MAP-NO-GP: # RelaxationBytesDeleted : 10 +MAP-NO-GP: # RelaxationBytesMissed : 12 +MAP-NO-GP: # LinkStats End + +MAP-NO-GP: .text {{.+}}, Alignment: 0x4, Flags: SHF_ALLOC|SHF_EXECINSTR, Type: SHT_PROGBITS +MAP-NO-GP: # RelaxationBytesDeleted : 10 +MAP-NO-GP: # RelaxationBytesMissed : 12 +MAP-NO-GP: .text {{.+}}.o #SHT_PROGBITS,SHF_ALLOC|SHF_EXECINSTR,4 + +RUN: %objdump --no-print-imm-hex --mattr=+xqcilo -M no-aliases -d %t.2.out 2>&1 | %filecheck %s --check-prefix=EXE-NO-GP + +EXE-NO-GP:
: +EXE-NO-GP-NEXT: 651f 0200 4000 qc.e.lw a0, 16777248(zero) +EXE-NO-GP-NEXT: 651f 0000 4400 qc.e.lw a0, 17825792(zero) +EXE-NO-GP-NEXT: 059f 0000 0500 qc.e.li a1, 83886080 +EXE-NO-GP-NEXT: 0005a503 lw a0, 0(a1) +EXE-NO-GP-NEXT: 651f 0200 4000 qc.e.lw a0, 16777248(zero) + +## Link with Xqci relaxation disabled — no relaxation occurs. +RUN: %link %linkopts --no-relax-xqci -MapStyle txt -Map %t.3.map --verbose %t.o -o %t.3.out -T %p/Inputs/1.t 2>&1 | %filecheck %s --check-prefix=VERBOSE-NO-XQCI + +VERBOSE-NO-XQCI-NOT: Deleting {{.*}} bytes +VERBOSE-NO-XQCI-NOT: Cannot relax {{.*}} bytes + +RUN: %filecheck %s --input-file=%t.3.map --check-prefix=MAP-NO-XQCI + +MAP-NO-XQCI-NOT: RelaxationBytesDeleted +MAP-NO-XQCI-NOT: RelaxationBytesMissed + +RUN: %objdump --no-print-imm-hex --mattr=+xqcili,+xqcilo -M no-aliases -d %t.3.out 2>&1 | %filecheck %s --check-prefix=EXE-NO-XQCI + +EXE-NO-XQCI:
: +EXE-NO-XQCI-NEXT: 059f 0020 0100 qc.e.li a1, 16777248 +EXE-NO-XQCI-NEXT: 0005a503 lw a0, 0(a1) +EXE-NO-XQCI-NEXT: 059f 0000 0110 qc.e.li a1, 17825792 +EXE-NO-XQCI-NEXT: 0005a503 lw a0, 0(a1) +EXE-NO-XQCI-NEXT: 059f 0000 0500 qc.e.li a1, 83886080 +EXE-NO-XQCI-NEXT: 0005a503 lw a0, 0(a1) +EXE-NO-XQCI-NEXT: 059f 0020 0100 qc.e.li a1, 16777248 +EXE-NO-XQCI-NEXT: 4188 c.lw a0, 0(a1) + +## Additional cases from Inputs/2.s: +## Abs-std, no-RELAX-on-ACCESS, base-reg mismatch, store instructions, +## 16-bit CS store (c.sw) and Zcb instructions (c.lbu, c.sh). +RUN: %clang %clangopts -c %p/Inputs/2.s -o %t2.o -menable-experimental-extensions -march=rv32gc_zcb_xqcili0p2 + +## Abs-std wins by default (ZeroRelax enabled). +## Case 2 verifies that without R_RISCV_RELAX on the ACCESS reloc the pair is +## NOT relaxed — qc.e.li falls back to qc.li-only relaxation, leaving the lw. +## Base register mismatch falls back to qc.e.li-only relaxation. +## Store instructions (sw, c.sw) and Zcb (c.lbu, c.sh) are relaxed correctly. +RUN: %link %linkopts --relax-xqci -MapStyle txt -Map %t2.1.map --verbose %t2.o -o %t2.1.out -T %p/Inputs/2.t 2>&1 | %filecheck %s --check-prefix=VERBOSE2 + +VERBOSE2: RISCV_QC_E_LI_ACCESS_ABS_STD : Deleting 6 bytes for symbol 'sym_abs_std' in section .text+0x4 file {{.*}}.o +VERBOSE2: RISCV_QC_E_LI_QC_LI : Deleting 2 bytes for symbol 'sym_abs_std' in section .text+0x8 file {{.*}}.o +VERBOSE2: RISCV_QC_E_LI_GP : Deleting 2 bytes for symbol 'sym_gprel_std' in section .text+0x10 file {{.*}}.o +VERBOSE2: RISCV_QC_E_LI_ACCESS_GP_STD : Deleting 6 bytes for symbol 'sym_gprel_std' in section .text+0x18 file {{.*}}.o +VERBOSE2: RISCV_QC_E_LI_ACCESS_GP_STD : Deleting 4 bytes for symbol 'sym_gprel_std' in section .text+0x1c file {{.*}}.o +VERBOSE2: RISCV_QC_E_LI_ACCESS_GP_STD : Deleting 4 bytes for symbol 'sym_gprel_std' in section .text+0x20 file {{.*}}.o +VERBOSE2: RISCV_QC_E_LI_ACCESS_GP_STD : Deleting 4 bytes for symbol 'sym_gprel_std' in section .text+0x24 file {{.*}}.o + +RUN: %filecheck %s --input-file=%t2.1.map --check-prefix=MAP2 + +MAP2: # LinkStats Begin +MAP2: # RelaxationBytesDeleted : 28 +MAP2: # LinkStats End + +RUN: %objdump --no-print-imm-hex --mattr=+xqcilo,+zcb -M no-aliases -d %t2.1.out 2>&1 | %filecheck %s --check-prefix=EXE2 + +EXE2:
: +EXE2-NEXT: 10002503 lw a0, 256(zero) +EXE2-NEXT: 0100059b qc.li a1, 256 +EXE2-NEXT: 0005a503 lw a0, 0(a1) +EXE2-NEXT: 02018593 addi a1, gp, 32 +EXE2-NEXT: 00062503 lw a0, 0(a2) +EXE2-NEXT: 02a1a023 sw a0, 32(gp) +EXE2-NEXT: 02a1a023 sw a0, 32(gp) +EXE2-NEXT: 0201c503 lbu a0, 32(gp) +EXE2-NEXT: 02a19023 sh a0, 32(gp) + +## With --no-relax-zero, Abs-std is disabled. sym_abs_std (= 0x100) is +## within isInt<26>(sym - GP) so GP-xqci fires instead, producing qc.e.lw +## instructions. Cases using GP-std (sym_gprel_std) are unaffected. +RUN: %link %linkopts --relax-xqci --no-relax-zero -MapStyle txt -Map %t2.2.map --verbose %t2.o -o %t2.2.out -T %p/Inputs/2.t 2>&1 | %filecheck %s --check-prefix=VERBOSE2-NRZ + +VERBOSE2-NRZ: RISCV_QC_E_LI_ACCESS_GP_XQCI : Deleting 4 bytes for symbol 'sym_abs_std' in section .text+0x6 file {{.*}}.o +VERBOSE2-NRZ: RISCV_QC_E_LI_ACCESS : Cannot relax 2 bytes for symbol 'sym_abs_std' in section .text+0x0 file {{.*}}.o +VERBOSE2-NRZ: RISCV_QC_E_LI_QC_LI : Deleting 2 bytes for symbol 'sym_abs_std' in section .text+0xa file {{.*}}.o +VERBOSE2-NRZ: RISCV_QC_E_LI_GP : Deleting 2 bytes for symbol 'sym_gprel_std' in section .text+0x12 file {{.*}}.o +VERBOSE2-NRZ: RISCV_QC_E_LI_ACCESS_GP_STD : Deleting 6 bytes for symbol 'sym_gprel_std' in section .text+0x1a file {{.*}}.o +VERBOSE2-NRZ: RISCV_QC_E_LI_ACCESS_GP_STD : Deleting 4 bytes for symbol 'sym_gprel_std' in section .text+0x1e file {{.*}}.o +VERBOSE2-NRZ: RISCV_QC_E_LI_ACCESS_GP_STD : Deleting 4 bytes for symbol 'sym_gprel_std' in section .text+0x22 file {{.*}}.o +VERBOSE2-NRZ: RISCV_QC_E_LI_ACCESS_GP_STD : Deleting 4 bytes for symbol 'sym_gprel_std' in section .text+0x26 file {{.*}}.o + +RUN: %filecheck %s --input-file=%t2.2.map --check-prefix=MAP2-NRZ + +MAP2-NRZ: # LinkStats Begin +MAP2-NRZ: # RelaxationBytesDeleted : 26 +MAP2-NRZ: # RelaxationBytesMissed : 2 +MAP2-NRZ: # LinkStats End + +RUN: %objdump --no-print-imm-hex --mattr=+xqcilo,+zcb -M no-aliases -d %t2.2.out 2>&1 | %filecheck %s --check-prefix=EXE2-NRZ + +EXE2-NRZ:
: +EXE2-NRZ-NEXT: e51f 1001 c000 qc.e.lw a0, -16776960(gp) +EXE2-NRZ-NEXT: 0100059b qc.li a1, 256 +EXE2-NRZ-NEXT: 0005a503 lw a0, 0(a1) +EXE2-NRZ-NEXT: 02018593 addi a1, gp, 32 +EXE2-NRZ-NEXT: 00062503 lw a0, 0(a2) +EXE2-NRZ-NEXT: 02a1a023 sw a0, 32(gp) +EXE2-NRZ-NEXT: 02a1a023 sw a0, 32(gp) +EXE2-NRZ-NEXT: 0201c503 lbu a0, 32(gp) +EXE2-NRZ-NEXT: 02a19023 sh a0, 32(gp) + +## Boundary tests from Inputs/3.s + Inputs/3.t. +## GP = 0x10000000, so GP-relative and absolute symbol ranges do not overlap. +## Verifies relaxation at the exact edges of each range and that symbols one +## step outside the range are not relaxed by that variant. +RUN: %clang %clangopts -c %p/Inputs/3.s -o %t3.o -menable-experimental-extensions -march=rv32gc_xqcili0p2 + +## With GP and ZeroRelax enabled: all four variants are exercised. +## GP-std applies at ±2047 from GP, GP-xqci at ±33554431, Abs-std at 2047, +## Abs-xqci at 33554431. Symbols one step outside each threshold fall to the +## next cheaper variant (or miss entirely). +RUN: %link %linkopts --relax-xqci -MapStyle txt -Map %t3.1.map --verbose %t3.o -o %t3.1.out -T %p/Inputs/3.t 2>&1 | %filecheck %s --check-prefix=VERBOSE3 + +VERBOSE3: RISCV_QC_E_LI_ACCESS_GP_STD : Deleting 6 bytes for symbol 'sym_gp_std_pos_edge' in section .text+0x4 file {{.*}}.o +VERBOSE3: RISCV_QC_E_LI_ACCESS_GP_STD : Deleting 6 bytes for symbol 'sym_gp_std_neg_edge' in section .text+0x8 file {{.*}}.o +VERBOSE3: RISCV_QC_E_LI_ACCESS_GP_XQCI : Deleting 4 bytes for symbol 'sym_gp_std_pos_out' in section .text+0xe file {{.*}}.o +VERBOSE3: RISCV_QC_E_LI_ACCESS : Cannot relax 2 bytes for symbol 'sym_gp_std_pos_out' in section .text+0x8 file {{.*}}.o +VERBOSE3: RISCV_QC_E_LI_ACCESS_GP_XQCI : Deleting 4 bytes for symbol 'sym_gp_std_neg_out' in section .text+0x14 file {{.*}}.o +VERBOSE3: RISCV_QC_E_LI_ACCESS : Cannot relax 2 bytes for symbol 'sym_gp_std_neg_out' in section .text+0xe file {{.*}}.o +VERBOSE3: RISCV_QC_E_LI_ACCESS_GP_XQCI : Deleting 4 bytes for symbol 'sym_gp_xqci_pos_edge' in section .text+0x1a file {{.*}}.o +VERBOSE3: RISCV_QC_E_LI_ACCESS : Cannot relax 2 bytes for symbol 'sym_gp_xqci_pos_edge' in section .text+0x14 file {{.*}}.o +VERBOSE3: RISCV_QC_E_LI_ACCESS_GP_XQCI : Deleting 4 bytes for symbol 'sym_gp_xqci_neg_edge' in section .text+0x20 file {{.*}}.o +VERBOSE3: RISCV_QC_E_LI_ACCESS : Cannot relax 2 bytes for symbol 'sym_gp_xqci_neg_edge' in section .text+0x1a file {{.*}}.o +VERBOSE3: RISCV_QC_E_LI_ACCESS : Cannot relax 4 bytes for symbol 'sym_gp_xqci_pos_out' in section .text+0x20 file {{.*}}.o +VERBOSE3: RISCV_QC_E_LI_QC_LI : Cannot relax 2 bytes for symbol 'sym_gp_xqci_pos_out' in section .text+0x20 file {{.*}}.o +VERBOSE3: RISCV_QC_E_LI_ACCESS : Cannot relax 4 bytes for symbol 'sym_gp_xqci_neg_out' in section .text+0x2a file {{.*}}.o +VERBOSE3: RISCV_QC_E_LI_QC_LI : Cannot relax 2 bytes for symbol 'sym_gp_xqci_neg_out' in section .text+0x2a file {{.*}}.o +VERBOSE3: RISCV_QC_E_LI_ACCESS_ABS_STD : Deleting 6 bytes for symbol 'sym_abs_std_edge' in section .text+0x38 file {{.*}}.o +VERBOSE3: RISCV_QC_E_LI_ACCESS_ABS_XQCI : Deleting 4 bytes for symbol 'sym_abs_std_out' in section .text+0x3e file {{.*}}.o +VERBOSE3: RISCV_QC_E_LI_ACCESS : Cannot relax 2 bytes for symbol 'sym_abs_std_out' in section .text+0x38 file {{.*}}.o +VERBOSE3: RISCV_QC_E_LI_ACCESS_ABS_XQCI : Deleting 4 bytes for symbol 'sym_abs_xqci_edge' in section .text+0x44 file {{.*}}.o +VERBOSE3: RISCV_QC_E_LI_ACCESS : Cannot relax 2 bytes for symbol 'sym_abs_xqci_edge' in section .text+0x3e file {{.*}}.o +VERBOSE3: RISCV_QC_E_LI_ACCESS : Cannot relax 4 bytes for symbol 'sym_abs_xqci_out' in section .text+0x44 file {{.*}}.o +VERBOSE3: RISCV_QC_E_LI_QC_LI : Cannot relax 2 bytes for symbol 'sym_abs_xqci_out' in section .text+0x44 file {{.*}}.o + +RUN: %filecheck %s --input-file=%t3.1.map --check-prefix=MAP3 + +MAP3: # LinkStats Begin +MAP3: # RelaxationBytesDeleted : 42 +MAP3: # RelaxationBytesMissed : 30 +MAP3: # LinkStats End + +## Without GP relaxation: GP-relative symbols never relax (absolute values are +## all outside the isInt<12> and isInt<26> abs ranges). Abs-std and Abs-xqci +## still fire for the absolute symbols. +RUN: %link %linkopts --relax-xqci --no-relax-gp -MapStyle txt -Map %t3.2.map --verbose %t3.o -o %t3.2.out -T %p/Inputs/3.t 2>&1 | %filecheck %s --check-prefix=VERBOSE3-NO-GP + +VERBOSE3-NO-GP: RISCV_QC_E_LI_ACCESS : Cannot relax 4 bytes for symbol 'sym_gp_std_pos_edge' in section .text+0x0 file {{.*}}.o +VERBOSE3-NO-GP: RISCV_QC_E_LI_QC_LI : Cannot relax 2 bytes for symbol 'sym_gp_std_pos_edge' in section .text+0x0 file {{.*}}.o +VERBOSE3-NO-GP: RISCV_QC_E_LI_ACCESS : Cannot relax 4 bytes for symbol 'sym_gp_xqci_pos_edge' in section .text+0x28 file {{.*}}.o +VERBOSE3-NO-GP: RISCV_QC_E_LI_QC_LI : Cannot relax 2 bytes for symbol 'sym_gp_xqci_pos_edge' in section .text+0x28 file {{.*}}.o +VERBOSE3-NO-GP: RISCV_QC_E_LI_ACCESS_ABS_STD : Deleting 6 bytes for symbol 'sym_abs_std_edge' in section .text+0x54 file {{.*}}.o +VERBOSE3-NO-GP: RISCV_QC_E_LI_ACCESS_ABS_XQCI : Deleting 4 bytes for symbol 'sym_abs_xqci_edge' in section .text+0x60 file {{.*}}.o +VERBOSE3-NO-GP: RISCV_QC_E_LI_ACCESS : Cannot relax 4 bytes for symbol 'sym_abs_xqci_out' in section .text+0x60 file {{.*}}.o + +RUN: %filecheck %s --input-file=%t3.2.map --check-prefix=MAP3-NO-GP + +MAP3-NO-GP: # LinkStats Begin +MAP3-NO-GP: # RelaxationBytesDeleted : 14 +MAP3-NO-GP: # RelaxationBytesMissed : 58 +MAP3-NO-GP: # LinkStats End + +## Without GP relaxation or ZeroRelax: only Abs-xqci fires (isInt<26>). +## sym_abs_std_edge (2047) now uses Abs-xqci instead of Abs-std. +## sym_abs_xqci_out (33554432) still misses. +RUN: %link %linkopts --relax-xqci --no-relax-gp --no-relax-zero -MapStyle txt -Map %t3.3.map --verbose %t3.o -o %t3.3.out -T %p/Inputs/3.t 2>&1 | %filecheck %s --check-prefix=VERBOSE3-NO-ZERO + +VERBOSE3-NO-ZERO: RISCV_QC_E_LI_ACCESS_ABS_XQCI : Deleting 4 bytes for symbol 'sym_abs_std_edge' in section .text+0x56 file {{.*}}.o +VERBOSE3-NO-ZERO: RISCV_QC_E_LI_ACCESS : Cannot relax 2 bytes for symbol 'sym_abs_std_edge' in section .text+0x50 file {{.*}}.o +VERBOSE3-NO-ZERO: RISCV_QC_E_LI_ACCESS_ABS_XQCI : Deleting 4 bytes for symbol 'sym_abs_xqci_edge' in section .text+0x62 file {{.*}}.o +VERBOSE3-NO-ZERO: RISCV_QC_E_LI_ACCESS : Cannot relax 2 bytes for symbol 'sym_abs_xqci_edge' in section .text+0x5c file {{.*}}.o +VERBOSE3-NO-ZERO: RISCV_QC_E_LI_ACCESS : Cannot relax 4 bytes for symbol 'sym_abs_xqci_out' in section .text+0x62 file {{.*}}.o +VERBOSE3-NO-ZERO: RISCV_QC_E_LI_QC_LI : Cannot relax 2 bytes for symbol 'sym_abs_xqci_out' in section .text+0x62 file {{.*}}.o + +RUN: %filecheck %s --input-file=%t3.3.map --check-prefix=MAP3-NO-ZERO + +MAP3-NO-ZERO: # LinkStats Begin +MAP3-NO-ZERO: # RelaxationBytesDeleted : 12 +MAP3-NO-ZERO: # RelaxationBytesMissed : 60 +MAP3-NO-ZERO: # LinkStats End From 383595060e08471d4f436fb444eb20d74b1a0245 Mon Sep 17 00:00:00 2001 From: Sam Elliott Date: Thu, 7 May 2026 11:56:03 -0700 Subject: [PATCH 3/4] Read from correct targetRef Signed-off-by: Sam Elliott --- lib/Target/RISCV/RISCVLDBackend.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/lib/Target/RISCV/RISCVLDBackend.cpp b/lib/Target/RISCV/RISCVLDBackend.cpp index 2d6a81165..893de8979 100644 --- a/lib/Target/RISCV/RISCVLDBackend.cpp +++ b/lib/Target/RISCV/RISCVLDBackend.cpp @@ -695,7 +695,6 @@ bool RISCVLDBackend::doRelaxationQCAccess32(Relocation *QCELiReloc, if (!region) return false; - uint64_t qceli_offset = QCELiReloc->targetRef()->offset(); uint64_t qceli_instr = QCELiReloc->target(); if ((qceli_instr & 0xf07fu) != 0x1fu) return false; @@ -708,7 +707,7 @@ bool RISCVLDBackend::doRelaxationQCAccess32(Relocation *QCELiReloc, return false; uint32_t access_instr = 0; - region->copyData(&access_instr, sizeof(access_instr), qceli_offset + 6); + AccessReloc->targetRef()->memcpy(&access_instr, sizeof(access_instr), 0); QCAccess access; // Decode the RV32I access instruction so we have enough information to @@ -778,7 +777,6 @@ bool RISCVLDBackend::doRelaxationQCAccess16(Relocation *QCELiReloc, if (!region) return false; - uint64_t qceli_offset = QCELiReloc->targetRef()->offset(); uint64_t qceli_instr = QCELiReloc->target(); if ((qceli_instr & 0xf07fu) != 0x1fu) return false; @@ -791,7 +789,7 @@ bool RISCVLDBackend::doRelaxationQCAccess16(Relocation *QCELiReloc, return false; uint16_t access_instr = 0; - region->copyData(&access_instr, sizeof(access_instr), qceli_offset + 6); + AccessReloc->targetRef()->memcpy(&access_instr, sizeof(access_instr), 0); QCAccess access; // Decode the RV32 Zca/Zcb access instruction so we have enough information to From 33e64e5c2a5de045792376a888fedc92d925da06 Mon Sep 17 00:00:00 2001 From: Sam Elliott Date: Fri, 8 May 2026 16:39:55 -0700 Subject: [PATCH 4/4] Condense Tests, better validity checking, include access offset Signed-off-by: Sam Elliott --- lib/Target/RISCV/RISCVLDBackend.cpp | 99 ++- lib/Target/RISCV/RISCVLDBackend.h | 15 +- lib/Target/RISCV/RISCVRelocator.cpp | 3 +- .../Relaxation/QC_E_LI_ACCESS/Inputs/1.s | 241 ++++++- .../Relaxation/QC_E_LI_ACCESS/Inputs/1.t | 18 +- .../Relaxation/QC_E_LI_ACCESS/Inputs/2.s | 155 ++-- .../Relaxation/QC_E_LI_ACCESS/Inputs/2.t | 45 +- .../Relaxation/QC_E_LI_ACCESS/Inputs/3.s | 121 ---- .../Relaxation/QC_E_LI_ACCESS/Inputs/3.t | 35 - .../QC_E_LI_ACCESS/QC_E_LI_ACCESS.test | 661 +++++++++++++----- 10 files changed, 957 insertions(+), 436 deletions(-) delete mode 100644 test/RISCV/standalone/Relaxation/QC_E_LI_ACCESS/Inputs/3.s delete mode 100644 test/RISCV/standalone/Relaxation/QC_E_LI_ACCESS/Inputs/3.t diff --git a/lib/Target/RISCV/RISCVLDBackend.cpp b/lib/Target/RISCV/RISCVLDBackend.cpp index 893de8979..250458035 100644 --- a/lib/Target/RISCV/RISCVLDBackend.cpp +++ b/lib/Target/RISCV/RISCVLDBackend.cpp @@ -464,8 +464,8 @@ bool RISCVLDBackend::doRelaxationLui(Relocation *reloc, Relocator::DWord G) { bool canRelaxToGP = config().options().getRISCVRelax() && config().options().getRISCVGPRelax() && !config().isCodeIndep() && - G != 0 && fitsInGP(G, Value, frag, reloc->targetSection(), SymbolSize) && - S != 0; + G != 0 && S != 0 && + fitsInGP<12>(G, Value, frag, reloc->targetSection(), SymbolSize); if (type == llvm::ELF::R_RISCV_HI20) { @@ -615,7 +615,7 @@ bool RISCVLDBackend::doRelaxationQCELi(Relocation *reloc, Relocator::DWord G) { bool canRelaxGP = canRelaxXqci && config().options().getRISCVGPRelax() && !config().isCodeIndep() && G != 0 && S != 0 && - fitsInGP(G, Value, frag, reloc->targetSection(), SymbolSize); + fitsInGP<12>(G, Value, frag, reloc->targetSection(), SymbolSize); const char *msg = "RISCV_QC_E_LI_QC_LI"; if (canRelaxQcLi) { @@ -702,10 +702,6 @@ bool RISCVLDBackend::doRelaxationQCAccess32(Relocation *QCELiReloc, if (qceli_rd == X_ZERO) return false; - if (!config().options().getRISCVRelax() || !config().targets().is32Bits() || - !config().options().getRISCVRelaxXqci()) - return false; - uint32_t access_instr = 0; AccessReloc->targetRef()->memcpy(&access_instr, sizeof(access_instr), 0); QCAccess access; @@ -719,6 +715,7 @@ bool RISCVLDBackend::doRelaxationQCAccess32(Relocation *QCELiReloc, case 0x03u: // Loads are I-type access.reg = extractBits(access_instr, 11, 7); + access.offset = llvm::SignExtend64<12>(extractBits(access_instr, 31, 20)); switch (extractBits(access_instr, 14, 12)) { case 0b000u: access.op = QCAccess::Operation::Lb; @@ -742,6 +739,9 @@ bool RISCVLDBackend::doRelaxationQCAccess32(Relocation *QCELiReloc, case 0x23u: // Stores are S-type access.reg = extractBits(access_instr, 24, 20); + access.offset = + llvm::SignExtend64<12>((extractBits(access_instr, 31, 25) << 5) | + extractBits(access_instr, 11, 7)); switch (extractBits(access_instr, 14, 12)) { case 0b000u: access.op = QCAccess::Operation::Sb; @@ -784,10 +784,6 @@ bool RISCVLDBackend::doRelaxationQCAccess16(Relocation *QCELiReloc, if (qceli_rd == X_ZERO) return false; - if (!config().options().getRISCVRelax() || !config().targets().is32Bits() || - !config().options().getRISCVRelaxXqci()) - return false; - uint16_t access_instr = 0; AccessReloc->targetRef()->memcpy(&access_instr, sizeof(access_instr), 0); QCAccess access; @@ -804,29 +800,45 @@ bool RISCVLDBackend::doRelaxationQCAccess16(Relocation *QCELiReloc, return false; switch (extractBits(access_instr, 15, 13)) { case 0b010u: - // c.lw + // c.lw: CL-format access.op = QCAccess::Operation::Lw; + access.offset = (extractBits(access_instr, 5, 5) << 6) | + (extractBits(access_instr, 12, 10) << 3) | + (extractBits(access_instr, 6, 6) << 2); break; case 0b110u: - // c.sw + // c.sw: CS-format access.op = QCAccess::Operation::Sw; + access.offset = (extractBits(access_instr, 5, 5) << 6) | + (extractBits(access_instr, 12, 10) << 3) | + (extractBits(access_instr, 6, 6) << 2); break; case 0b100u: switch (extractBits(access_instr, 11, 10)) { case 0b00u: + // c.lbu: off[1:0] = {instr[5], instr[6]}, byte offset 0-3 access.op = QCAccess::Operation::Lbu; + access.offset = (extractBits(access_instr, 5, 5) << 1) | + extractBits(access_instr, 6, 6); break; case 0b01u: + // c.lhu/c.lh: off[1] = instr[5], halfword offset 0 or 2 if (extractBits(access_instr, 6, 6) == 0b1u) access.op = QCAccess::Operation::Lh; else access.op = QCAccess::Operation::Lhu; + access.offset = extractBits(access_instr, 5, 5) << 1; break; case 0b10u: + // c.sb: off[1:0] = {instr[5], instr[6]}, byte offset 0-3 access.op = QCAccess::Operation::Sb; + access.offset = (extractBits(access_instr, 5, 5) << 1) | + extractBits(access_instr, 6, 6); break; case 0b11u: + // c.sh: off[1] = instr[5], halfword offset 0 or 2 access.op = QCAccess::Operation::Sh; + access.offset = extractBits(access_instr, 5, 5) << 1; break; default: llvm_unreachable("Impossible Encoding"); @@ -862,35 +874,49 @@ bool RISCVLDBackend::doRelaxationQCAccessCommon(Relocation *QCELiReloc, llvm::cast(QCELiReloc->targetRef()->frag()); uint64_t qceli_offset = QCELiReloc->targetRef()->offset(); - Relocator::DWord S = getSymbolValuePLT(*QCELiReloc); + Relocator::Address S = getSymbolValuePLT(*QCELiReloc); Relocator::DWord A = QCELiReloc->addend(); - Relocator::DWord Value = S + A; + Relocator::Address Value = S + A; + // The effective address includes the offset from the access instruction; + // all range checks operate on this adjusted value. + Relocator::Address AdjValue = Value + (Relocator::DWord)access.offset; size_t SymbolSize = QCELiReloc->symInfo()->outSymbol()->size(); - bool canRelaxGPStd = - config().options().getRISCVGPRelax() && !config().isCodeIndep() && - G != 0 && S != 0 && - fitsInGP(G, Value, region, QCELiReloc->targetSection(), SymbolSize); + // These relaxations need to be enabled, and we need to be 32-bit. + bool canRelaxXqci = config().options().getRISCVRelax() && + config().targets().is32Bits() && + config().options().getRISCVRelaxXqci(); + + bool canRelaxGPStd = canRelaxXqci && config().options().getRISCVGPRelax() && + !config().isCodeIndep() && G != 0 && S != 0 && + fitsInGP<12>(G, AdjValue, region, + QCELiReloc->targetSection(), SymbolSize); - bool canRelaxAbsStd = config().options().getRISCVZeroRelax() && S != 0 && - llvm::isInt<12>((int64_t)Value); + bool canRelaxAbsStd = canRelaxXqci && + config().options().getRISCVZeroRelax() && S != 0 && + llvm::isInt<12>(signedAddress(AdjValue)); - bool canRelaxGPXqci = config().options().getRISCVGPRelax() && + bool canRelaxGPXqci = canRelaxXqci && config().options().getRISCVGPRelax() && !config().isCodeIndep() && G != 0 && S != 0 && - llvm::isInt<26>((int64_t)(Value - G)); + fitsInGP<26>(G, AdjValue, region, + QCELiReloc->targetSection(), SymbolSize); - bool canRelaxAbsXqci = S != 0 && llvm::isInt<26>((int64_t)Value); + bool canRelaxAbsXqci = canRelaxXqci && + config().options().getRISCVZeroRelax() && S != 0 && + llvm::isInt<26>(signedAddress(AdjValue)); const char *msg = "RISCV_QC_E_LI_ACCESS"; // This replaces the `qc.e.li; access` sequence with a 4-byte RVI access // instruction - auto applyStdRelax = [&](unsigned base_reg, uint32_t reloc_load, - uint32_t reloc_store, const char *variant_msg) { + auto applyStdRelax = [&](unsigned base_reg, Relocation::Type reloc_load, + Relocation::Type reloc_store, + const char *variant_msg) { uint32_t new_access = access.build32Bit(base_reg); region->replaceInstruction(qceli_offset, QCELiReloc, reinterpret_cast(&new_access), 4); QCELiReloc->setTargetData(new_access); + QCELiReloc->setAddend(A + (Relocator::DWord)access.offset); QCELiReloc->setType(access.isLoad() ? reloc_load : reloc_store); relaxDeleteBytes(variant_msg, *region, qceli_offset + 4, 2 + access.size, QCELiReloc->symInfo()->name()); @@ -899,12 +925,14 @@ bool RISCVLDBackend::doRelaxationQCAccessCommon(Relocation *QCELiReloc, // This replaces the `qc.e.li; access` sequence with a 6-byte Xqcilo access // instruction. - auto applyXqciloRelax = [&](unsigned base_reg, uint32_t reloc_load, - uint32_t reloc_store, const char *variant_msg) { + auto applyXqciloRelax = [&](unsigned base_reg, Relocation::Type reloc_load, + Relocation::Type reloc_store, + const char *variant_msg) { uint64_t new_access = access.build48Bit(base_reg); region->replaceInstruction(qceli_offset, QCELiReloc, reinterpret_cast(&new_access), 6); QCELiReloc->setTargetData(new_access); + QCELiReloc->setAddend(A + (Relocator::DWord)access.offset); QCELiReloc->setType(access.isLoad() ? reloc_load : reloc_store); relaxDeleteBytes(variant_msg, *region, qceli_offset + 6, access.size, QCELiReloc->symInfo()->name()); @@ -943,8 +971,9 @@ bool RISCVLDBackend::doRelaxationQCAccessCommon(Relocation *QCELiReloc, return true; } - reportMissedRelaxation(msg, *region, qceli_offset, access.size, - QCELiReloc->symInfo()->name()); + if (canRelaxXqci) + reportMissedRelaxation(msg, *region, qceli_offset, access.size, + QCELiReloc->symInfo()->name()); return false; } @@ -1101,6 +1130,7 @@ bool RISCVLDBackend::doRelaxationAlign(Relocation *pReloc) { return true; } +template bool RISCVLDBackend::fitsInGP(Relocator::DWord G, Relocation::DWord Value, Fragment *frag, ELFSection *TargetSection, size_t SymSize) const { @@ -1132,7 +1162,7 @@ bool RISCVLDBackend::fitsInGP(Relocator::DWord G, Relocation::DWord Value, X = Value - G + Alignment + SymSize; else X = Value - G - Alignment - SymSize; - return llvm::isInt<12>(X); + return llvm::isInt(X); } bool RISCVLDBackend::addSymbolToOutput(ResolveInfo *Info) { @@ -1213,9 +1243,10 @@ bool RISCVLDBackend::doRelaxationPC(Relocation *reloc, Relocator::DWord G) { } uint64_t offset = reloc->targetRef()->offset(); - bool canRelax = config().options().getRISCVRelax() && - config().options().getRISCVGPRelax() && G != 0 && - fitsInGP(G, S + A, frag, reloc->targetSection(), SymbolSize); + bool canRelax = + config().options().getRISCVRelax() && + config().options().getRISCVGPRelax() && G != 0 && + fitsInGP<12>(G, S + A, frag, reloc->targetSection(), SymbolSize); // HI will be deleted, Low will be converted to use gp as base. if (type == llvm::ELF::R_RISCV_PCREL_HI20) { diff --git a/lib/Target/RISCV/RISCVLDBackend.h b/lib/Target/RISCV/RISCVLDBackend.h index 453b2990a..b9cbe9a0b 100644 --- a/lib/Target/RISCV/RISCVLDBackend.h +++ b/lib/Target/RISCV/RISCVLDBackend.h @@ -207,6 +207,15 @@ class RISCVLDBackend : public GNULDBackend { // Get the value of the symbol, using the PLT slot if one exists. Relocation::Address getSymbolValuePLT(const Relocation &R); + // Interpret a raw address as a signed value at the target's pointer width. + // On a 32-bit target, truncate to 32 bits (applying the same wraparound the + // processor would) and then sign-extend for range checks; on a 64-bit target + // the address is already the right width. + int64_t signedAddress(uint64_t addr) const { + return config().targets().is32Bits() ? llvm::SignExtend64<32>(addr) + : (int64_t)addr; + } + private: Relocation *findHIRelocation(ELFSection *S, uint64_t Value); @@ -242,8 +251,9 @@ class RISCVLDBackend : public GNULDBackend { // Loads come first so isLoad() is a cheap comparison. enum class Operation { Lb, Lbu, Lh, Lhu, Lw, Sb, Sh, Sw }; Operation op; - unsigned reg; // destination (load) or source data (store) register - uint32_t size; // access instruction size (in bytes) + uint32_t size; // access instruction size (in bytes) + unsigned reg; // destination (load) or source data (store) register + int64_t offset; // immediate offset in the original access instruction bool isLoad() const { return op <= Operation::Lw; } @@ -276,6 +286,7 @@ class RISCVLDBackend : public GNULDBackend { bool finalizeScanRelocations() override; + template bool fitsInGP(Relocation::DWord, Relocation::DWord, Fragment *frag, ELFSection *TargetSection, size_t) const; diff --git a/lib/Target/RISCV/RISCVRelocator.cpp b/lib/Target/RISCV/RISCVRelocator.cpp index 6911e30fb..d34b78258 100644 --- a/lib/Target/RISCV/RISCVRelocator.cpp +++ b/lib/Target/RISCV/RISCVRelocator.cpp @@ -1111,7 +1111,8 @@ RISCVRelocator::Result applyXqciloAbs(Relocation &pReloc, RelocationDescription &pRelocDesc) { if (RelocDescs.count(pReloc.type()) == 0) return RISCVRelocator::Unsupport; - int64_t S = Backend.getSymbolValuePLT(pReloc); + uint64_t S_raw = Backend.getSymbolValuePLT(pReloc); + int64_t S = Backend.signedAddress(S_raw); int64_t A = pReloc.addend(); int64_t Result = S + A; if (!llvm::isInt<26>(Result)) diff --git a/test/RISCV/standalone/Relaxation/QC_E_LI_ACCESS/Inputs/1.s b/test/RISCV/standalone/Relaxation/QC_E_LI_ACCESS/Inputs/1.s index 90b4e28d7..83228dbfd 100644 --- a/test/RISCV/standalone/Relaxation/QC_E_LI_ACCESS/Inputs/1.s +++ b/test/RISCV/standalone/Relaxation/QC_E_LI_ACCESS/Inputs/1.s @@ -1,7 +1,4 @@ - # Required until https://github.com/llvm/llvm-project/pull/146184 lands .option exact - - # Enable Relaxations .option relax .text @@ -13,7 +10,8 @@ QUALCOMM: main: - # ACCESS_32: 32-bit load (lw) test cases + ## Five cases for lw (ACCESS_32): + ## GP-std, GP-xqci, Abs-std, Abs-xqci, missed. qc.e.li a1, sym_gprel_std 1: @@ -29,21 +27,240 @@ main: .reloc 2b, R_RISCV_CUSTOM197, sym_gprel_xqci .reloc 2b, R_RISCV_RELAX - qc.e.li a1, sym_too_far + qc.e.li a1, sym_abs_std 3: lw a0, 0(a1) .reloc 3b, R_RISCV_VENDOR, QUALCOMM - .reloc 3b, R_RISCV_CUSTOM197, sym_too_far + .reloc 3b, R_RISCV_CUSTOM197, sym_abs_std .reloc 3b, R_RISCV_RELAX - # ACCESS_16: 16-bit compressed load (c.lw) test case - # a1 (x11) is in the CL-format register range (x8-x15) - - qc.e.li a1, sym_gprel_std + qc.e.li a1, sym_abs_xqci 4: - c.lw a0, 0(a1) + lw a0, 0(a1) .reloc 4b, R_RISCV_VENDOR, QUALCOMM - .reloc 4b, R_RISCV_CUSTOM196, sym_gprel_std + .reloc 4b, R_RISCV_CUSTOM197, sym_abs_xqci .reloc 4b, R_RISCV_RELAX + qc.e.li a1, sym_too_far +5: + lw a0, 0(a1) + .reloc 5b, R_RISCV_VENDOR, QUALCOMM + .reloc 5b, R_RISCV_CUSTOM197, sym_too_far + .reloc 5b, R_RISCV_RELAX + + ## Five cases for c.lw (ACCESS_16): + ## GP-std, GP-xqci, Abs-std, Abs-xqci, missed. + + qc.e.li a1, sym_gprel_std +6: + c.lw a0, 0(a1) + .reloc 6b, R_RISCV_VENDOR, QUALCOMM + .reloc 6b, R_RISCV_CUSTOM196, sym_gprel_std + .reloc 6b, R_RISCV_RELAX + + qc.e.li a1, sym_gprel_xqci +7: + c.lw a0, 0(a1) + .reloc 7b, R_RISCV_VENDOR, QUALCOMM + .reloc 7b, R_RISCV_CUSTOM196, sym_gprel_xqci + .reloc 7b, R_RISCV_RELAX + + qc.e.li a1, sym_abs_std +8: + c.lw a0, 0(a1) + .reloc 8b, R_RISCV_VENDOR, QUALCOMM + .reloc 8b, R_RISCV_CUSTOM196, sym_abs_std + .reloc 8b, R_RISCV_RELAX + + qc.e.li a1, sym_abs_xqci +9: + c.lw a0, 0(a1) + .reloc 9b, R_RISCV_VENDOR, QUALCOMM + .reloc 9b, R_RISCV_CUSTOM196, sym_abs_xqci + .reloc 9b, R_RISCV_RELAX + + qc.e.li a1, sym_too_far +10: + c.lw a0, 0(a1) + .reloc 10b, R_RISCV_VENDOR, QUALCOMM + .reloc 10b, R_RISCV_CUSTOM196, sym_too_far + .reloc 10b, R_RISCV_RELAX + + ## One GP-std case for each remaining load type (ACCESS_32). + + qc.e.li a1, sym_gprel_std +11: + lb a0, 0(a1) + .reloc 11b, R_RISCV_VENDOR, QUALCOMM + .reloc 11b, R_RISCV_CUSTOM197, sym_gprel_std + .reloc 11b, R_RISCV_RELAX + + qc.e.li a1, sym_gprel_std +12: + lbu a0, 0(a1) + .reloc 12b, R_RISCV_VENDOR, QUALCOMM + .reloc 12b, R_RISCV_CUSTOM197, sym_gprel_std + .reloc 12b, R_RISCV_RELAX + + qc.e.li a1, sym_gprel_std +13: + lh a0, 0(a1) + .reloc 13b, R_RISCV_VENDOR, QUALCOMM + .reloc 13b, R_RISCV_CUSTOM197, sym_gprel_std + .reloc 13b, R_RISCV_RELAX + + qc.e.li a1, sym_gprel_std +14: + lhu a0, 0(a1) + .reloc 14b, R_RISCV_VENDOR, QUALCOMM + .reloc 14b, R_RISCV_CUSTOM197, sym_gprel_std + .reloc 14b, R_RISCV_RELAX + + ## One GP-std case for each store type (ACCESS_32). + + qc.e.li a1, sym_gprel_std +15: + sw a0, 0(a1) + .reloc 15b, R_RISCV_VENDOR, QUALCOMM + .reloc 15b, R_RISCV_CUSTOM197, sym_gprel_std + .reloc 15b, R_RISCV_RELAX + + qc.e.li a1, sym_gprel_std +16: + sb a0, 0(a1) + .reloc 16b, R_RISCV_VENDOR, QUALCOMM + .reloc 16b, R_RISCV_CUSTOM197, sym_gprel_std + .reloc 16b, R_RISCV_RELAX + + qc.e.li a1, sym_gprel_std +17: + sh a0, 0(a1) + .reloc 17b, R_RISCV_VENDOR, QUALCOMM + .reloc 17b, R_RISCV_CUSTOM197, sym_gprel_std + .reloc 17b, R_RISCV_RELAX + + ## One GP-std case for each remaining 16-bit compressed type (ACCESS_16). + + qc.e.li a1, sym_gprel_std +18: + c.sw a0, 0(a1) + .reloc 18b, R_RISCV_VENDOR, QUALCOMM + .reloc 18b, R_RISCV_CUSTOM196, sym_gprel_std + .reloc 18b, R_RISCV_RELAX + + qc.e.li a1, sym_gprel_std +19: + c.lbu a0, 0(a1) + .reloc 19b, R_RISCV_VENDOR, QUALCOMM + .reloc 19b, R_RISCV_CUSTOM196, sym_gprel_std + .reloc 19b, R_RISCV_RELAX + + qc.e.li a1, sym_gprel_std +20: + c.lhu a0, 0(a1) + .reloc 20b, R_RISCV_VENDOR, QUALCOMM + .reloc 20b, R_RISCV_CUSTOM196, sym_gprel_std + .reloc 20b, R_RISCV_RELAX + + qc.e.li a1, sym_gprel_std +21: + c.lh a0, 0(a1) + .reloc 21b, R_RISCV_VENDOR, QUALCOMM + .reloc 21b, R_RISCV_CUSTOM196, sym_gprel_std + .reloc 21b, R_RISCV_RELAX + + qc.e.li a1, sym_gprel_std +22: + c.sb a0, 0(a1) + .reloc 22b, R_RISCV_VENDOR, QUALCOMM + .reloc 22b, R_RISCV_CUSTOM196, sym_gprel_std + .reloc 22b, R_RISCV_RELAX + + qc.e.li a1, sym_gprel_std +23: + c.sh a0, 0(a1) + .reloc 23b, R_RISCV_VENDOR, QUALCOMM + .reloc 23b, R_RISCV_CUSTOM196, sym_gprel_std + .reloc 23b, R_RISCV_RELAX + + ## Non-zero offsets: the offset in the access instruction is folded into the + ## addend; with sym_gprel_std = GP+32, all effective addresses remain within + ## isInt<12> of GP and GP-std fires. + + qc.e.li a1, sym_gprel_std +24: + lw a0, 4(a1) + .reloc 24b, R_RISCV_VENDOR, QUALCOMM + .reloc 24b, R_RISCV_CUSTOM197, sym_gprel_std + .reloc 24b, R_RISCV_RELAX + + qc.e.li a1, sym_gprel_std +25: + sw a0, 4(a1) + .reloc 25b, R_RISCV_VENDOR, QUALCOMM + .reloc 25b, R_RISCV_CUSTOM197, sym_gprel_std + .reloc 25b, R_RISCV_RELAX + + qc.e.li a1, sym_gprel_std +26: + c.lw a0, 4(a1) + .reloc 26b, R_RISCV_VENDOR, QUALCOMM + .reloc 26b, R_RISCV_CUSTOM196, sym_gprel_std + .reloc 26b, R_RISCV_RELAX + + qc.e.li a1, sym_gprel_std +27: + c.lbu a0, 1(a1) + .reloc 27b, R_RISCV_VENDOR, QUALCOMM + .reloc 27b, R_RISCV_CUSTOM196, sym_gprel_std + .reloc 27b, R_RISCV_RELAX + + qc.e.li a1, sym_gprel_std +28: + c.lhu a0, 2(a1) + .reloc 28b, R_RISCV_VENDOR, QUALCOMM + .reloc 28b, R_RISCV_CUSTOM196, sym_gprel_std + .reloc 28b, R_RISCV_RELAX + + qc.e.li a1, sym_gprel_std +29: + c.lh a0, 2(a1) + .reloc 29b, R_RISCV_VENDOR, QUALCOMM + .reloc 29b, R_RISCV_CUSTOM196, sym_gprel_std + .reloc 29b, R_RISCV_RELAX + + qc.e.li a1, sym_gprel_std +30: + c.sb a0, 1(a1) + .reloc 30b, R_RISCV_VENDOR, QUALCOMM + .reloc 30b, R_RISCV_CUSTOM196, sym_gprel_std + .reloc 30b, R_RISCV_RELAX + + qc.e.li a1, sym_gprel_std +31: + c.sh a0, 2(a1) + .reloc 31b, R_RISCV_VENDOR, QUALCOMM + .reloc 31b, R_RISCV_CUSTOM196, sym_gprel_std + .reloc 31b, R_RISCV_RELAX + + ## Edge cases: ACCESS without R_RISCV_RELAX, and base-register mismatch. + + # ACCESS without R_RISCV_RELAX: R_RISCV_RELAX is required on the ACCESS reloc + # for pair relaxation; without it qc.e.li falls back to qc.li-only relaxation. + qc.e.li a1, sym_abs_std +32: + lw a0, 0(a1) + .reloc 32b, R_RISCV_VENDOR, QUALCOMM + .reloc 32b, R_RISCV_CUSTOM197, sym_abs_std + # Intentionally no R_RISCV_RELAX on the ACCESS reloc + + # Base-register mismatch: qc.e.li loads into a1 but the lw uses a2, + # so ACCESS decode fails and qc.e.li falls back to standalone relaxation. + qc.e.li a1, sym_gprel_std +33: + lw a0, 0(a2) + .reloc 33b, R_RISCV_VENDOR, QUALCOMM + .reloc 33b, R_RISCV_CUSTOM197, sym_gprel_std + .reloc 33b, R_RISCV_RELAX + .size main, .-main diff --git a/test/RISCV/standalone/Relaxation/QC_E_LI_ACCESS/Inputs/1.t b/test/RISCV/standalone/Relaxation/QC_E_LI_ACCESS/Inputs/1.t index 097565f94..2cda796b1 100644 --- a/test/RISCV/standalone/Relaxation/QC_E_LI_ACCESS/Inputs/1.t +++ b/test/RISCV/standalone/Relaxation/QC_E_LI_ACCESS/Inputs/1.t @@ -1,14 +1,20 @@ +/* GP placed far enough from zero that the GP-relative and absolute symbol + * ranges do not overlap. */ +__global_pointer$ = 0x10000000; -/* GP somewhere not reachable by a standard 12-bit GP-relative access */ -__global_pointer$ = 0x01000000; - -/* In 12-bit GP-relative range: GP + 0x20 */ +/* Within isInt<12> of GP */ sym_gprel_std = __global_pointer$ + 0x20; -/* In 26-bit GP-relative range but not 12-bit: GP + 0x100000 */ +/* Within isInt<26> of GP, but not isInt<12> */ sym_gprel_xqci = __global_pointer$ + 0x100000; -/* Out of all ranges: GP + 0x4000000 > 2^25 */ +/* Within isInt<12> of 0 */ +sym_abs_std = 0x100; + +/* Within isInt<26> of 0, but not isInt<12> */ +sym_abs_xqci = 0x200000; + +/* Outwith isInt<26> of both 0 and GP. */ sym_too_far = __global_pointer$ + 0x4000000; SECTIONS { diff --git a/test/RISCV/standalone/Relaxation/QC_E_LI_ACCESS/Inputs/2.s b/test/RISCV/standalone/Relaxation/QC_E_LI_ACCESS/Inputs/2.s index 11e0c9f74..850002df3 100644 --- a/test/RISCV/standalone/Relaxation/QC_E_LI_ACCESS/Inputs/2.s +++ b/test/RISCV/standalone/Relaxation/QC_E_LI_ACCESS/Inputs/2.s @@ -1,7 +1,4 @@ - # Required until https://github.com/llvm/llvm-project/pull/146184 lands .option exact - - # Enable relaxations on qc.e.li instructions .option relax .text @@ -13,75 +10,147 @@ QUALCOMM: main: - ## Case 1: Abs-std relaxation - ## sym_abs_std = 0x100 is within isInt<12>, so Abs-std applies: - ## qc.e.li + lw -> lw a0, 256(zero), deletes 6 bytes + ## GP-std range boundary tests (--relax-xqci with GP relax). + ## isInt<12>(sym - GP): range is [-2048, +2047]. - qc.e.li a1, sym_abs_std + ## At the positive edge of GP-std range (+2047): → GP-std relaxation. + qc.e.li a1, sym_gp_std_pos_edge 1: lw a0, 0(a1) .reloc 1b, R_RISCV_VENDOR, QUALCOMM - .reloc 1b, R_RISCV_CUSTOM197, sym_abs_std + .reloc 1b, R_RISCV_CUSTOM197, sym_gp_std_pos_edge .reloc 1b, R_RISCV_RELAX - ## Case 2: ACCESS without R_RISCV_RELAX on the load/store - ## R_RISCV_RELAX is required on the ACCESS reloc for pair relaxation. - ## Without it, qc.e.li falls back to qc.li-only relaxation. - - qc.e.li a1, sym_abs_std + ## At the negative edge of GP-std range (-2048): → GP-std relaxation. + qc.e.li a1, sym_gp_std_neg_edge 2: lw a0, 0(a1) .reloc 2b, R_RISCV_VENDOR, QUALCOMM - .reloc 2b, R_RISCV_CUSTOM197, sym_abs_std - # Intentionally no R_RISCV_RELAX on the ACCESS reloc + .reloc 2b, R_RISCV_CUSTOM197, sym_gp_std_neg_edge + .reloc 2b, R_RISCV_RELAX - ## Case 3: Base register mismatch — ACCESS decode fails, falls back to - ## qc.e.li-only relaxation. qc.e.li loads into a1 but the lw uses a2. - - qc.e.li a1, sym_gprel_std + ## Just outside the positive GP-std range (+2048): → GP-xqci relaxation. + qc.e.li a1, sym_gp_std_pos_out 3: - lw a0, 0(a2) + lw a0, 0(a1) .reloc 3b, R_RISCV_VENDOR, QUALCOMM - .reloc 3b, R_RISCV_CUSTOM197, sym_gprel_std + .reloc 3b, R_RISCV_CUSTOM197, sym_gp_std_pos_out .reloc 3b, R_RISCV_RELAX - ## Case 4: Store (sw) with ACCESS_32, GP-std range - ## sym_gprel_std is within isInt<12>(sym - GP), so GP-std applies: - ## qc.e.li + sw -> sw a0, 32(gp) - - qc.e.li a1, sym_gprel_std + ## Just outside the negative GP-std range (-2049): → GP-xqci relaxation. + qc.e.li a1, sym_gp_std_neg_out 4: - sw a0, 0(a1) + lw a0, 0(a1) .reloc 4b, R_RISCV_VENDOR, QUALCOMM - .reloc 4b, R_RISCV_CUSTOM197, sym_gprel_std + .reloc 4b, R_RISCV_CUSTOM197, sym_gp_std_neg_out .reloc 4b, R_RISCV_RELAX - ## Case 5: c.sw (ACCESS_16, CS format), GP-std range - ## 16-bit store; GP-std applies, result is a 4-byte sw. + ## GP-xqci range boundary tests. + ## isInt<26>(sym - GP): range is [-33554432, +33554431]. - qc.e.li a1, sym_gprel_std + ## At the positive edge of GP-xqci range (+33554431): → GP-xqci relaxation. + qc.e.li a1, sym_gp_xqci_pos_edge 5: - c.sw a0, 0(a1) + lw a0, 0(a1) .reloc 5b, R_RISCV_VENDOR, QUALCOMM - .reloc 5b, R_RISCV_CUSTOM196, sym_gprel_std + .reloc 5b, R_RISCV_CUSTOM197, sym_gp_xqci_pos_edge .reloc 5b, R_RISCV_RELAX - ## Case 6: c.lbu (ACCESS_16, Zcb), GP-std range - - qc.e.li a1, sym_gprel_std + ## At the negative edge of GP-xqci range (-33554432): → GP-xqci relaxation. + qc.e.li a1, sym_gp_xqci_neg_edge 6: - c.lbu a0, 0(a1) + lw a0, 0(a1) .reloc 6b, R_RISCV_VENDOR, QUALCOMM - .reloc 6b, R_RISCV_CUSTOM196, sym_gprel_std + .reloc 6b, R_RISCV_CUSTOM197, sym_gp_xqci_neg_edge .reloc 6b, R_RISCV_RELAX - ## Case 7: c.sh (ACCESS_16, Zcb), GP-std range - - qc.e.li a1, sym_gprel_std + ## Just outside the positive GP-xqci range (+33554432): → missed. + qc.e.li a1, sym_gp_xqci_pos_out 7: - c.sh a0, 0(a1) + lw a0, 0(a1) .reloc 7b, R_RISCV_VENDOR, QUALCOMM - .reloc 7b, R_RISCV_CUSTOM196, sym_gprel_std + .reloc 7b, R_RISCV_CUSTOM197, sym_gp_xqci_pos_out .reloc 7b, R_RISCV_RELAX + ## Just outside the negative GP-xqci range (-33554433): → missed. + qc.e.li a1, sym_gp_xqci_neg_out +8: + lw a0, 0(a1) + .reloc 8b, R_RISCV_VENDOR, QUALCOMM + .reloc 8b, R_RISCV_CUSTOM197, sym_gp_xqci_neg_out + .reloc 8b, R_RISCV_RELAX + + ## Abs-std range boundary tests (ZeroRelax enabled, no GP relax). + ## isInt<12>(sym): range is [-2048, +2047]; sym must be non-zero. + + ## At the positive edge of Abs-std range (2047): → Abs-std relaxation. + qc.e.li a1, sym_abs_std_edge +9: + lw a0, 0(a1) + .reloc 9b, R_RISCV_VENDOR, QUALCOMM + .reloc 9b, R_RISCV_CUSTOM197, sym_abs_std_edge + .reloc 9b, R_RISCV_RELAX + + ## Just outside the positive Abs-std range (2048): → Abs-xqci relaxation. + qc.e.li a1, sym_abs_std_out +10: + lw a0, 0(a1) + .reloc 10b, R_RISCV_VENDOR, QUALCOMM + .reloc 10b, R_RISCV_CUSTOM197, sym_abs_std_out + .reloc 10b, R_RISCV_RELAX + + ## Abs-xqci range boundary tests (ZeroRelax disabled, no GP relax). + ## isInt<26>(sym): range is [1, 33554431]. + + ## At the positive edge of Abs-xqci range (33554431): → Abs-xqci relaxation. + qc.e.li a1, sym_abs_xqci_edge +11: + lw a0, 0(a1) + .reloc 11b, R_RISCV_VENDOR, QUALCOMM + .reloc 11b, R_RISCV_CUSTOM197, sym_abs_xqci_edge + .reloc 11b, R_RISCV_RELAX + + ## Just outside the positive Abs-xqci range (33554432): → missed. + qc.e.li a1, sym_abs_xqci_out +12: + lw a0, 0(a1) + .reloc 12b, R_RISCV_VENDOR, QUALCOMM + .reloc 12b, R_RISCV_CUSTOM197, sym_abs_xqci_out + .reloc 12b, R_RISCV_RELAX + + ## Negative absolute boundary tests: addresses in the upper 32-bit half that + ## the 32-bit core treats as negative (sign-extended before range check). + + ## Negative edge of Abs-std range (sign-ext → -2048): → Abs-std relaxation. + qc.e.li a1, sym_abs_std_neg_edge +13: + lw a0, 0(a1) + .reloc 13b, R_RISCV_VENDOR, QUALCOMM + .reloc 13b, R_RISCV_CUSTOM197, sym_abs_std_neg_edge + .reloc 13b, R_RISCV_RELAX + + ## Just outside the negative Abs-std range (sign-ext → -2049): → Abs-xqci. + qc.e.li a1, sym_abs_std_neg_out +14: + lw a0, 0(a1) + .reloc 14b, R_RISCV_VENDOR, QUALCOMM + .reloc 14b, R_RISCV_CUSTOM197, sym_abs_std_neg_out + .reloc 14b, R_RISCV_RELAX + + ## Negative edge of Abs-xqci range (sign-ext → -33554432): → Abs-xqci. + qc.e.li a1, sym_abs_xqci_neg_edge +15: + lw a0, 0(a1) + .reloc 15b, R_RISCV_VENDOR, QUALCOMM + .reloc 15b, R_RISCV_CUSTOM197, sym_abs_xqci_neg_edge + .reloc 15b, R_RISCV_RELAX + + ## Just outside the negative Abs-xqci range (sign-ext → -33554433): → miss. + qc.e.li a1, sym_abs_xqci_neg_out +16: + lw a0, 0(a1) + .reloc 16b, R_RISCV_VENDOR, QUALCOMM + .reloc 16b, R_RISCV_CUSTOM197, sym_abs_xqci_neg_out + .reloc 16b, R_RISCV_RELAX + .size main, .-main diff --git a/test/RISCV/standalone/Relaxation/QC_E_LI_ACCESS/Inputs/2.t b/test/RISCV/standalone/Relaxation/QC_E_LI_ACCESS/Inputs/2.t index 1fb048880..58f3b1f2f 100644 --- a/test/RISCV/standalone/Relaxation/QC_E_LI_ACCESS/Inputs/2.t +++ b/test/RISCV/standalone/Relaxation/QC_E_LI_ACCESS/Inputs/2.t @@ -1,10 +1,43 @@ -/* GP at a standard address */ -__global_pointer$ = 0x01000000; +/* GP placed so that GP-relative and absolute ranges don't overlap: + * GP = 0x10000000 (268435456) + * + * GP-std range: isInt<12>(sym - GP) → sym in [GP-2048 .. GP+2047] + * Abs-std range: isInt<12>(sym) → sym in [1 .. 2047] (non-zero) + * GP-xqci range: isInt<26>(sym - GP) → sym in [GP-33554432 .. GP+33554431] + * Abs-xqci range: isInt<26>(sym) → sym in [1 .. 33554431] (non-zero) + * + * With GP = 0x10000000: + * Abs range [1..33554431] = [0x1..0x1FFFFFF] lies entirely below GP, + * so GP-relative and absolute ranges do not overlap. + */ +__global_pointer$ = 0x10000000; -/* Abs-std: 0x100 is within isInt<12> (signed 12-bit range = -2048..2047) */ -sym_abs_std = 0x100; +/* GP-std: boundary symbols at GP ± 2047 (innermost) and GP ± 2048 (just out) */ +sym_gp_std_pos_edge = __global_pointer$ + 2047; /* isInt<12>(+2047) → GP-std */ +sym_gp_std_neg_edge = __global_pointer$ - 2048; /* isInt<12>(-2048) → GP-std */ +sym_gp_std_pos_out = __global_pointer$ + 2048; /* isInt<12>(+2048) → false → GP-xqci */ +sym_gp_std_neg_out = __global_pointer$ - 2049; /* isInt<12>(-2049) → false → GP-xqci */ -/* GP-std range: small positive offset from GP, within isInt<12>(sym - GP) */ -sym_gprel_std = __global_pointer$ + 0x20; +/* GP-xqci: boundary symbols at GP ± 33554431 (innermost) and GP ± 33554432 (just out) */ +sym_gp_xqci_pos_edge = __global_pointer$ + 33554431; /* isInt<26>(+33554431) → GP-xqci */ +sym_gp_xqci_neg_edge = __global_pointer$ - 33554432; /* isInt<26>(-33554432) → GP-xqci */ +sym_gp_xqci_pos_out = __global_pointer$ + 33554432; /* isInt<26>(+33554432) → false → miss */ +sym_gp_xqci_neg_out = __global_pointer$ - 33554433; /* isInt<26>(-33554433) → false → miss */ + +/* Abs-std: boundary symbols at ± 2047 (innermost) and ± 2048 (just out) */ +sym_abs_std_edge = 2047; /* isInt<12>(2047) → Abs-std (if ZeroRelax) */ +sym_abs_std_out = 2048; /* isInt<12>(2048) → false → Abs-xqci */ + +/* Abs-xqci: boundary symbols at 33554431 (innermost) and 33554432 (just out) */ +sym_abs_xqci_edge = 33554431; /* isInt<26>(33554431) → Abs-xqci */ +sym_abs_xqci_out = 33554432; /* isInt<26>(33554432) → false → miss */ + +/* Negative absolute symbols: addresses in the upper 32-bit half that the + * 32-bit core treats as negative. The linker sign-extends from 32 bits + * before checking absolute immediate ranges. */ +sym_abs_std_neg_edge = 0xFFFFF800; /* sign-ext → -2048, isInt<12>(-2048) → Abs-std */ +sym_abs_std_neg_out = 0xFFFFF7FF; /* sign-ext → -2049, isInt<12>(-2049) → Abs-xqci */ +sym_abs_xqci_neg_edge = 0xFE000000; /* sign-ext → -33554432, isInt<26>(-33554432) → Abs-xqci */ +sym_abs_xqci_neg_out = 0xFDFFFFFF; /* sign-ext → -33554433, isInt<26>(-33554433) → miss */ SECTIONS { .text : { *(.text) } } diff --git a/test/RISCV/standalone/Relaxation/QC_E_LI_ACCESS/Inputs/3.s b/test/RISCV/standalone/Relaxation/QC_E_LI_ACCESS/Inputs/3.s deleted file mode 100644 index 739b83fcf..000000000 --- a/test/RISCV/standalone/Relaxation/QC_E_LI_ACCESS/Inputs/3.s +++ /dev/null @@ -1,121 +0,0 @@ - .option exact - .option relax - - .text - .p2align 2 - .globl main - .type main, @function - -QUALCOMM: - -main: - - ## GP-std range boundary tests (--relax-xqci with GP relax). - ## isInt<12>(sym - GP): range is [-2048, +2047]. - - ## At the positive edge of GP-std range (+2047): → GP-std relaxation. - qc.e.li a1, sym_gp_std_pos_edge -1: - lw a0, 0(a1) - .reloc 1b, R_RISCV_VENDOR, QUALCOMM - .reloc 1b, R_RISCV_CUSTOM197, sym_gp_std_pos_edge - .reloc 1b, R_RISCV_RELAX - - ## At the negative edge of GP-std range (-2048): → GP-std relaxation. - qc.e.li a1, sym_gp_std_neg_edge -2: - lw a0, 0(a1) - .reloc 2b, R_RISCV_VENDOR, QUALCOMM - .reloc 2b, R_RISCV_CUSTOM197, sym_gp_std_neg_edge - .reloc 2b, R_RISCV_RELAX - - ## Just outside the positive GP-std range (+2048): → GP-xqci relaxation. - qc.e.li a1, sym_gp_std_pos_out -3: - lw a0, 0(a1) - .reloc 3b, R_RISCV_VENDOR, QUALCOMM - .reloc 3b, R_RISCV_CUSTOM197, sym_gp_std_pos_out - .reloc 3b, R_RISCV_RELAX - - ## Just outside the negative GP-std range (-2049): → GP-xqci relaxation. - qc.e.li a1, sym_gp_std_neg_out -4: - lw a0, 0(a1) - .reloc 4b, R_RISCV_VENDOR, QUALCOMM - .reloc 4b, R_RISCV_CUSTOM197, sym_gp_std_neg_out - .reloc 4b, R_RISCV_RELAX - - ## GP-xqci range boundary tests. - ## isInt<26>(sym - GP): range is [-33554432, +33554431]. - - ## At the positive edge of GP-xqci range (+33554431): → GP-xqci relaxation. - qc.e.li a1, sym_gp_xqci_pos_edge -5: - lw a0, 0(a1) - .reloc 5b, R_RISCV_VENDOR, QUALCOMM - .reloc 5b, R_RISCV_CUSTOM197, sym_gp_xqci_pos_edge - .reloc 5b, R_RISCV_RELAX - - ## At the negative edge of GP-xqci range (-33554432): → GP-xqci relaxation. - qc.e.li a1, sym_gp_xqci_neg_edge -6: - lw a0, 0(a1) - .reloc 6b, R_RISCV_VENDOR, QUALCOMM - .reloc 6b, R_RISCV_CUSTOM197, sym_gp_xqci_neg_edge - .reloc 6b, R_RISCV_RELAX - - ## Just outside the positive GP-xqci range (+33554432): → missed. - qc.e.li a1, sym_gp_xqci_pos_out -7: - lw a0, 0(a1) - .reloc 7b, R_RISCV_VENDOR, QUALCOMM - .reloc 7b, R_RISCV_CUSTOM197, sym_gp_xqci_pos_out - .reloc 7b, R_RISCV_RELAX - - ## Just outside the negative GP-xqci range (-33554433): → missed. - qc.e.li a1, sym_gp_xqci_neg_out -8: - lw a0, 0(a1) - .reloc 8b, R_RISCV_VENDOR, QUALCOMM - .reloc 8b, R_RISCV_CUSTOM197, sym_gp_xqci_neg_out - .reloc 8b, R_RISCV_RELAX - - ## Abs-std range boundary tests (ZeroRelax enabled, no GP relax). - ## isInt<12>(sym): range is [-2048, +2047]; sym must be non-zero. - - ## At the positive edge of Abs-std range (2047): → Abs-std relaxation. - qc.e.li a1, sym_abs_std_edge -9: - lw a0, 0(a1) - .reloc 9b, R_RISCV_VENDOR, QUALCOMM - .reloc 9b, R_RISCV_CUSTOM197, sym_abs_std_edge - .reloc 9b, R_RISCV_RELAX - - ## Just outside the positive Abs-std range (2048): → Abs-xqci relaxation. - qc.e.li a1, sym_abs_std_out -10: - lw a0, 0(a1) - .reloc 10b, R_RISCV_VENDOR, QUALCOMM - .reloc 10b, R_RISCV_CUSTOM197, sym_abs_std_out - .reloc 10b, R_RISCV_RELAX - - ## Abs-xqci range boundary tests (ZeroRelax disabled, no GP relax). - ## isInt<26>(sym): range is [1, 33554431]. - - ## At the positive edge of Abs-xqci range (33554431): → Abs-xqci relaxation. - qc.e.li a1, sym_abs_xqci_edge -11: - lw a0, 0(a1) - .reloc 11b, R_RISCV_VENDOR, QUALCOMM - .reloc 11b, R_RISCV_CUSTOM197, sym_abs_xqci_edge - .reloc 11b, R_RISCV_RELAX - - ## Just outside the positive Abs-xqci range (33554432): → missed. - qc.e.li a1, sym_abs_xqci_out -12: - lw a0, 0(a1) - .reloc 12b, R_RISCV_VENDOR, QUALCOMM - .reloc 12b, R_RISCV_CUSTOM197, sym_abs_xqci_out - .reloc 12b, R_RISCV_RELAX - - .size main, .-main diff --git a/test/RISCV/standalone/Relaxation/QC_E_LI_ACCESS/Inputs/3.t b/test/RISCV/standalone/Relaxation/QC_E_LI_ACCESS/Inputs/3.t deleted file mode 100644 index 8d8c7d768..000000000 --- a/test/RISCV/standalone/Relaxation/QC_E_LI_ACCESS/Inputs/3.t +++ /dev/null @@ -1,35 +0,0 @@ -/* GP placed so that GP-relative and absolute ranges don't overlap: - * GP = 0x10000000 (268435456) - * - * GP-std range: isInt<12>(sym - GP) → sym in [GP-2048 .. GP+2047] - * Abs-std range: isInt<12>(sym) → sym in [1 .. 2047] (non-zero) - * GP-xqci range: isInt<26>(sym - GP) → sym in [GP-33554432 .. GP+33554431] - * Abs-xqci range: isInt<26>(sym) → sym in [1 .. 33554431] (non-zero) - * - * With GP = 0x10000000: - * Abs range [1..33554431] = [0x1..0x1FFFFFF] lies entirely below GP, - * so GP-relative and absolute ranges do not overlap. - */ -__global_pointer$ = 0x10000000; - -/* GP-std: boundary symbols at GP ± 2047 (innermost) and GP ± 2048 (just out) */ -sym_gp_std_pos_edge = __global_pointer$ + 2047; /* isInt<12>(+2047) → GP-std */ -sym_gp_std_neg_edge = __global_pointer$ - 2048; /* isInt<12>(-2048) → GP-std */ -sym_gp_std_pos_out = __global_pointer$ + 2048; /* isInt<12>(+2048) → false → GP-xqci */ -sym_gp_std_neg_out = __global_pointer$ - 2049; /* isInt<12>(-2049) → false → GP-xqci */ - -/* GP-xqci: boundary symbols at GP ± 33554431 (innermost) and GP ± 33554432 (just out) */ -sym_gp_xqci_pos_edge = __global_pointer$ + 33554431; /* isInt<26>(+33554431) → GP-xqci */ -sym_gp_xqci_neg_edge = __global_pointer$ - 33554432; /* isInt<26>(-33554432) → GP-xqci */ -sym_gp_xqci_pos_out = __global_pointer$ + 33554432; /* isInt<26>(+33554432) → false → miss */ -sym_gp_xqci_neg_out = __global_pointer$ - 33554433; /* isInt<26>(-33554433) → false → miss */ - -/* Abs-std: boundary symbols at ± 2047 (innermost) and ± 2048 (just out) */ -sym_abs_std_edge = 2047; /* isInt<12>(2047) → Abs-std (if ZeroRelax) */ -sym_abs_std_out = 2048; /* isInt<12>(2048) → false → Abs-xqci */ - -/* Abs-xqci: boundary symbols at 33554431 (innermost) and 33554432 (just out) */ -sym_abs_xqci_edge = 33554431; /* isInt<26>(33554431) → Abs-xqci */ -sym_abs_xqci_out = 33554432; /* isInt<26>(33554432) → false → miss */ - -SECTIONS { .text : { *(.text) } } diff --git a/test/RISCV/standalone/Relaxation/QC_E_LI_ACCESS/QC_E_LI_ACCESS.test b/test/RISCV/standalone/Relaxation/QC_E_LI_ACCESS/QC_E_LI_ACCESS.test index ed306ff44..e65c10784 100644 --- a/test/RISCV/standalone/Relaxation/QC_E_LI_ACCESS/QC_E_LI_ACCESS.test +++ b/test/RISCV/standalone/Relaxation/QC_E_LI_ACCESS/QC_E_LI_ACCESS.test @@ -7,7 +7,13 @@ #END_COMMENT #-------------------------------------------------------------------- REQUIRES: riscv32 -RUN: %clang %clangopts -c %p/Inputs/1.s -o %t.o -menable-experimental-extensions -march=rv32gc_xqcili0p2 + +## Inputs/1.s: five range cases for lw (GP-std, GP-xqci, Abs-std, Abs-xqci, +## missed), then the same five for c.lw, then one GP-std case for each +## remaining load/store instruction type, then non-zero offset cases in order +## lw, sw, compressed loads, compressed stores, then the edge cases (ACCESS +## without R_RISCV_RELAX, base-register mismatch). +RUN: %clang %clangopts -c %p/Inputs/1.s -o %t.o -menable-experimental-extensions -march=rv32gc_zcb_xqcili0p2 ## Link with Xqci and GP relaxations enabled (default). RUN: %link %linkopts --relax-xqci -MapStyle txt -Map %t.1.map --verbose %t.o -o %t.1.out -T %p/Inputs/1.t 2>&1 | %filecheck %s --check-prefix=VERBOSE @@ -15,63 +21,179 @@ RUN: %link %linkopts --relax-xqci -MapStyle txt -Map %t.1.map --verbose %t.o -o VERBOSE: RISCV_QC_E_LI_ACCESS_GP_STD : Deleting 6 bytes for symbol 'sym_gprel_std' in section .text+0x4 file {{.*}}.o VERBOSE: RISCV_QC_E_LI_ACCESS_GP_XQCI : Deleting 4 bytes for symbol 'sym_gprel_xqci' in section .text+0xa file {{.*}}.o VERBOSE: RISCV_QC_E_LI_ACCESS : Cannot relax 2 bytes for symbol 'sym_gprel_xqci' in section .text+0x4 file {{.*}}.o -VERBOSE: RISCV_QC_E_LI_ACCESS : Cannot relax 4 bytes for symbol 'sym_too_far' in section .text+0xa file {{.*}}.o -VERBOSE: RISCV_QC_E_LI_QC_LI : Cannot relax 2 bytes for symbol 'sym_too_far' in section .text+0xa file {{.*}}.o -VERBOSE: RISCV_QC_E_LI_ACCESS_GP_STD : Deleting 4 bytes for symbol 'sym_gprel_std' in section .text+0x18 file {{.*}}.o +VERBOSE: RISCV_QC_E_LI_ACCESS_ABS_STD : Deleting 6 bytes for symbol 'sym_abs_std' in section .text+0xe file {{.*}}.o +VERBOSE: RISCV_QC_E_LI_ACCESS_ABS_XQCI : Deleting 4 bytes for symbol 'sym_abs_xqci' in section .text+0x14 file {{.*}}.o +VERBOSE: RISCV_QC_E_LI_ACCESS : Cannot relax 2 bytes for symbol 'sym_abs_xqci' in section .text+0xe file {{.*}}.o +VERBOSE: RISCV_QC_E_LI_ACCESS : Cannot relax 4 bytes for symbol 'sym_too_far' in section .text+0x14 file {{.*}}.o +VERBOSE: RISCV_QC_E_LI_QC_LI : Cannot relax 2 bytes for symbol 'sym_too_far' in section .text+0x14 file {{.*}}.o +VERBOSE: RISCV_QC_E_LI_ACCESS_GP_STD : Deleting 4 bytes for symbol 'sym_gprel_std' in section .text+0x22 file {{.*}}.o +VERBOSE: RISCV_QC_E_LI_ACCESS_GP_XQCI : Deleting 2 bytes for symbol 'sym_gprel_xqci' in section .text+0x28 file {{.*}}.o +VERBOSE: RISCV_QC_E_LI_ACCESS : Cannot relax 2 bytes for symbol 'sym_gprel_xqci' in section .text+0x22 file {{.*}}.o +VERBOSE: RISCV_QC_E_LI_ACCESS_ABS_STD : Deleting 4 bytes for symbol 'sym_abs_std' in section .text+0x2c file {{.*}}.o +VERBOSE: RISCV_QC_E_LI_ACCESS_ABS_XQCI : Deleting 2 bytes for symbol 'sym_abs_xqci' in section .text+0x32 file {{.*}}.o +VERBOSE: RISCV_QC_E_LI_ACCESS : Cannot relax 2 bytes for symbol 'sym_abs_xqci' in section .text+0x2c file {{.*}}.o +VERBOSE: RISCV_QC_E_LI_ACCESS : Cannot relax 2 bytes for symbol 'sym_too_far' in section .text+0x32 file {{.*}}.o +VERBOSE: RISCV_QC_E_LI_QC_LI : Cannot relax 2 bytes for symbol 'sym_too_far' in section .text+0x32 file {{.*}}.o +VERBOSE: RISCV_QC_E_LI_ACCESS_GP_STD : Deleting 6 bytes for symbol 'sym_gprel_std' in section .text+0x3e file {{.*}}.o +VERBOSE: RISCV_QC_E_LI_ACCESS_GP_STD : Deleting 6 bytes for symbol 'sym_gprel_std' in section .text+0x42 file {{.*}}.o +VERBOSE: RISCV_QC_E_LI_ACCESS_GP_STD : Deleting 6 bytes for symbol 'sym_gprel_std' in section .text+0x46 file {{.*}}.o +VERBOSE: RISCV_QC_E_LI_ACCESS_GP_STD : Deleting 6 bytes for symbol 'sym_gprel_std' in section .text+0x4a file {{.*}}.o +VERBOSE: RISCV_QC_E_LI_ACCESS_GP_STD : Deleting 6 bytes for symbol 'sym_gprel_std' in section .text+0x4e file {{.*}}.o +VERBOSE: RISCV_QC_E_LI_ACCESS_GP_STD : Deleting 6 bytes for symbol 'sym_gprel_std' in section .text+0x52 file {{.*}}.o +VERBOSE: RISCV_QC_E_LI_ACCESS_GP_STD : Deleting 6 bytes for symbol 'sym_gprel_std' in section .text+0x56 file {{.*}}.o +VERBOSE: RISCV_QC_E_LI_ACCESS_GP_STD : Deleting 4 bytes for symbol 'sym_gprel_std' in section .text+0x5a file {{.*}}.o +VERBOSE: RISCV_QC_E_LI_ACCESS_GP_STD : Deleting 4 bytes for symbol 'sym_gprel_std' in section .text+0x5e file {{.*}}.o +VERBOSE: RISCV_QC_E_LI_ACCESS_GP_STD : Deleting 4 bytes for symbol 'sym_gprel_std' in section .text+0x62 file {{.*}}.o +VERBOSE: RISCV_QC_E_LI_ACCESS_GP_STD : Deleting 4 bytes for symbol 'sym_gprel_std' in section .text+0x66 file {{.*}}.o +VERBOSE: RISCV_QC_E_LI_ACCESS_GP_STD : Deleting 4 bytes for symbol 'sym_gprel_std' in section .text+0x6a file {{.*}}.o +VERBOSE: RISCV_QC_E_LI_ACCESS_GP_STD : Deleting 4 bytes for symbol 'sym_gprel_std' in section .text+0x6e file {{.*}}.o +VERBOSE: RISCV_QC_E_LI_ACCESS_GP_STD : Deleting 6 bytes for symbol 'sym_gprel_std' in section .text+0x72 file {{.*}}.o +VERBOSE: RISCV_QC_E_LI_ACCESS_GP_STD : Deleting 6 bytes for symbol 'sym_gprel_std' in section .text+0x76 file {{.*}}.o +VERBOSE: RISCV_QC_E_LI_ACCESS_GP_STD : Deleting 4 bytes for symbol 'sym_gprel_std' in section .text+0x7a file {{.*}}.o +VERBOSE: RISCV_QC_E_LI_ACCESS_GP_STD : Deleting 4 bytes for symbol 'sym_gprel_std' in section .text+0x7e file {{.*}}.o +VERBOSE: RISCV_QC_E_LI_ACCESS_GP_STD : Deleting 4 bytes for symbol 'sym_gprel_std' in section .text+0x82 file {{.*}}.o +VERBOSE: RISCV_QC_E_LI_ACCESS_GP_STD : Deleting 4 bytes for symbol 'sym_gprel_std' in section .text+0x86 file {{.*}}.o +VERBOSE: RISCV_QC_E_LI_ACCESS_GP_STD : Deleting 4 bytes for symbol 'sym_gprel_std' in section .text+0x8a file {{.*}}.o +VERBOSE: RISCV_QC_E_LI_ACCESS_GP_STD : Deleting 4 bytes for symbol 'sym_gprel_std' in section .text+0x8e file {{.*}}.o +VERBOSE: RISCV_QC_E_LI_QC_LI : Deleting 2 bytes for symbol 'sym_abs_std' in section .text+0x92 file {{.*}}.o +VERBOSE: RISCV_QC_E_LI_GP : Deleting 2 bytes for symbol 'sym_gprel_std' in section .text+0x9a file {{.*}}.o RUN: %filecheck %s --input-file=%t.1.map --check-prefix=MAP MAP: # LinkStats Begin -MAP: # RelaxationBytesDeleted : 14 -MAP: # RelaxationBytesMissed : 8 +MAP: # RelaxationBytesDeleted : 138 +MAP: # RelaxationBytesMissed : 18 MAP: # LinkStats End -MAP: .text {{.+}}, Alignment: 0x4, Flags: SHF_ALLOC|SHF_EXECINSTR, Type: SHT_PROGBITS -MAP: # RelaxationBytesDeleted : 14 -MAP: # RelaxationBytesMissed : 8 -MAP: .text {{.+}}.o #SHT_PROGBITS,SHF_ALLOC|SHF_EXECINSTR,4 - -RUN: %objdump --no-print-imm-hex --mattr=+xqcilo -M no-aliases -d %t.1.out 2>&1 | %filecheck %s --check-prefix=EXE +RUN: %objdump --no-print-imm-hex --mattr=+xqcilo,+zcb -M no-aliases -d %t.1.out 2>&1 | %filecheck %s --check-prefix=EXE EXE:
: EXE-NEXT: 0201a503 lw a0, 32(gp) EXE-NEXT: e51f 0001 0400 qc.e.lw a0, 1048576(gp) -EXE-NEXT: 059f 0000 0500 qc.e.li a1, 83886080 +EXE-NEXT: 10002503 lw a0, 256(zero) +EXE-NEXT: 651f 0000 0800 qc.e.lw a0, 2097152(zero) +EXE-NEXT: 059f 0000 1400 qc.e.li a1, 335544320 EXE-NEXT: 0005a503 lw a0, 0(a1) EXE-NEXT: 0201a503 lw a0, 32(gp) +EXE-NEXT: e51f 0001 0400 qc.e.lw a0, 1048576(gp) +EXE-NEXT: 10002503 lw a0, 256(zero) +EXE-NEXT: 651f 0000 0800 qc.e.lw a0, 2097152(zero) +EXE-NEXT: 059f 0000 1400 qc.e.li a1, 335544320 +EXE-NEXT: 4188 c.lw a0, 0(a1) +EXE-NEXT: 02018503 lb a0, 32(gp) +EXE-NEXT: 0201c503 lbu a0, 32(gp) +EXE-NEXT: 02019503 lh a0, 32(gp) +EXE-NEXT: 0201d503 lhu a0, 32(gp) +EXE-NEXT: 02a1a023 sw a0, 32(gp) +EXE-NEXT: 02a18023 sb a0, 32(gp) +EXE-NEXT: 02a19023 sh a0, 32(gp) +EXE-NEXT: 02a1a023 sw a0, 32(gp) +EXE-NEXT: 0201c503 lbu a0, 32(gp) +EXE-NEXT: 0201d503 lhu a0, 32(gp) +EXE-NEXT: 02019503 lh a0, 32(gp) +EXE-NEXT: 02a18023 sb a0, 32(gp) +EXE-NEXT: 02a19023 sh a0, 32(gp) +EXE-NEXT: 0241a503 lw a0, 36(gp) +EXE-NEXT: 02a1a223 sw a0, 36(gp) +EXE-NEXT: 0241a503 lw a0, 36(gp) +EXE-NEXT: 0211c503 lbu a0, 33(gp) +EXE-NEXT: 0221d503 lhu a0, 34(gp) +EXE-NEXT: 02219503 lh a0, 34(gp) +EXE-NEXT: 02a180a3 sb a0, 33(gp) +EXE-NEXT: 02a19123 sh a0, 34(gp) +EXE-NEXT: 0100059b qc.li a1, 256 +EXE-NEXT: 0005a503 lw a0, 0(a1) +EXE-NEXT: 02018593 addi a1, gp, 32 +EXE-NEXT: 00062503 lw a0, 0(a2) -## Link with Xqci enabled, GP relaxation disabled. +## Link with Xqci enabled, GP relaxation disabled. With GP = 0x10000000, +## all GP-relative symbols exceed the Abs-xqci range too, so they cannot +## relax via any path. Only the explicitly small absolute symbols relax. RUN: %link %linkopts --relax-xqci --no-relax-gp -MapStyle txt -Map %t.2.map --verbose %t.o -o %t.2.out -T %p/Inputs/1.t 2>&1 | %filecheck %s --check-prefix=VERBOSE-NO-GP -VERBOSE-NO-GP: RISCV_QC_E_LI_ACCESS_ABS_XQCI : Deleting 4 bytes for symbol 'sym_gprel_std' in section .text+0x6 file {{.*}}.o -VERBOSE-NO-GP: RISCV_QC_E_LI_ACCESS : Cannot relax 2 bytes for symbol 'sym_gprel_std' in section .text+0x0 file {{.*}}.o -VERBOSE-NO-GP: RISCV_QC_E_LI_ACCESS_ABS_XQCI : Deleting 4 bytes for symbol 'sym_gprel_xqci' in section .text+0xc file {{.*}}.o -VERBOSE-NO-GP: RISCV_QC_E_LI_ACCESS : Cannot relax 2 bytes for symbol 'sym_gprel_xqci' in section .text+0x6 file {{.*}}.o -VERBOSE-NO-GP: RISCV_QC_E_LI_ACCESS : Cannot relax 4 bytes for symbol 'sym_too_far' in section .text+0xc file {{.*}}.o -VERBOSE-NO-GP: RISCV_QC_E_LI_QC_LI : Cannot relax 2 bytes for symbol 'sym_too_far' in section .text+0xc file {{.*}}.o -VERBOSE-NO-GP: RISCV_QC_E_LI_ACCESS_ABS_XQCI : Deleting 2 bytes for symbol 'sym_gprel_std' in section .text+0x1c file {{.*}}.o -VERBOSE-NO-GP: RISCV_QC_E_LI_ACCESS : Cannot relax 2 bytes for symbol 'sym_gprel_std' in section .text+0x16 file {{.*}}.o +VERBOSE-NO-GP: RISCV_QC_E_LI_ACCESS : Cannot relax 4 bytes for symbol 'sym_gprel_std' in section .text+0x0 file {{.*}}.o +VERBOSE-NO-GP: RISCV_QC_E_LI_QC_LI : Cannot relax 2 bytes for symbol 'sym_gprel_std' in section .text+0x0 file {{.*}}.o +VERBOSE-NO-GP: RISCV_QC_E_LI_ACCESS : Cannot relax 4 bytes for symbol 'sym_gprel_xqci' in section .text+0xa file {{.*}}.o +VERBOSE-NO-GP: RISCV_QC_E_LI_ACCESS_ABS_STD : Deleting 6 bytes for symbol 'sym_abs_std' in section .text+0x18 file {{.*}}.o +VERBOSE-NO-GP: RISCV_QC_E_LI_ACCESS_ABS_XQCI : Deleting 4 bytes for symbol 'sym_abs_xqci' in section .text+0x1e file {{.*}}.o +VERBOSE-NO-GP: RISCV_QC_E_LI_ACCESS : Cannot relax 2 bytes for symbol 'sym_abs_xqci' in section .text+0x18 file {{.*}}.o +VERBOSE-NO-GP: RISCV_QC_E_LI_ACCESS : Cannot relax 4 bytes for symbol 'sym_too_far' in section .text+0x1e file {{.*}}.o +VERBOSE-NO-GP: RISCV_QC_E_LI_ACCESS_ABS_STD : Deleting 4 bytes for symbol 'sym_abs_std' in section .text+0x3c file {{.*}}.o +VERBOSE-NO-GP: RISCV_QC_E_LI_ACCESS_ABS_XQCI : Deleting 2 bytes for symbol 'sym_abs_xqci' in section .text+0x42 file {{.*}}.o +VERBOSE-NO-GP: RISCV_QC_E_LI_ACCESS : Cannot relax 2 bytes for symbol 'sym_abs_xqci' in section .text+0x3c file {{.*}}.o RUN: %filecheck %s --input-file=%t.2.map --check-prefix=MAP-NO-GP MAP-NO-GP: # LinkStats Begin -MAP-NO-GP: # RelaxationBytesDeleted : 10 -MAP-NO-GP: # RelaxationBytesMissed : 12 +MAP-NO-GP: # RelaxationBytesDeleted : 18 +MAP-NO-GP: # RelaxationBytesMissed : 138 MAP-NO-GP: # LinkStats End -MAP-NO-GP: .text {{.+}}, Alignment: 0x4, Flags: SHF_ALLOC|SHF_EXECINSTR, Type: SHT_PROGBITS -MAP-NO-GP: # RelaxationBytesDeleted : 10 -MAP-NO-GP: # RelaxationBytesMissed : 12 -MAP-NO-GP: .text {{.+}}.o #SHT_PROGBITS,SHF_ALLOC|SHF_EXECINSTR,4 - -RUN: %objdump --no-print-imm-hex --mattr=+xqcilo -M no-aliases -d %t.2.out 2>&1 | %filecheck %s --check-prefix=EXE-NO-GP +RUN: %objdump --no-print-imm-hex --mattr=+xqcilo,+zcb -M no-aliases -d %t.2.out 2>&1 | %filecheck %s --check-prefix=EXE-NO-GP EXE-NO-GP:
: -EXE-NO-GP-NEXT: 651f 0200 4000 qc.e.lw a0, 16777248(zero) -EXE-NO-GP-NEXT: 651f 0000 4400 qc.e.lw a0, 17825792(zero) -EXE-NO-GP-NEXT: 059f 0000 0500 qc.e.li a1, 83886080 +EXE-NO-GP-NEXT: 059f 0020 1000 qc.e.li a1, 268435488 +EXE-NO-GP-NEXT: 0005a503 lw a0, 0(a1) +EXE-NO-GP-NEXT: 059f 0000 1010 qc.e.li a1, 269484032 +EXE-NO-GP-NEXT: 0005a503 lw a0, 0(a1) +EXE-NO-GP-NEXT: 10002503 lw a0, 256(zero) +EXE-NO-GP-NEXT: 651f 0000 0800 qc.e.lw a0, 2097152(zero) +EXE-NO-GP-NEXT: 059f 0000 1400 qc.e.li a1, 335544320 +EXE-NO-GP-NEXT: 0005a503 lw a0, 0(a1) +EXE-NO-GP-NEXT: 059f 0020 1000 qc.e.li a1, 268435488 +EXE-NO-GP-NEXT: 4188 c.lw a0, 0(a1) +EXE-NO-GP-NEXT: 059f 0000 1010 qc.e.li a1, 269484032 +EXE-NO-GP-NEXT: 4188 c.lw a0, 0(a1) +EXE-NO-GP-NEXT: 10002503 lw a0, 256(zero) +EXE-NO-GP-NEXT: 651f 0000 0800 qc.e.lw a0, 2097152(zero) +EXE-NO-GP-NEXT: 059f 0000 1400 qc.e.li a1, 335544320 +EXE-NO-GP-NEXT: 4188 c.lw a0, 0(a1) +EXE-NO-GP-NEXT: 059f 0020 1000 qc.e.li a1, 268435488 +EXE-NO-GP-NEXT: 00058503 lb a0, 0(a1) +EXE-NO-GP-NEXT: 059f 0020 1000 qc.e.li a1, 268435488 +EXE-NO-GP-NEXT: 0005c503 lbu a0, 0(a1) +EXE-NO-GP-NEXT: 059f 0020 1000 qc.e.li a1, 268435488 +EXE-NO-GP-NEXT: 00059503 lh a0, 0(a1) +EXE-NO-GP-NEXT: 059f 0020 1000 qc.e.li a1, 268435488 +EXE-NO-GP-NEXT: 0005d503 lhu a0, 0(a1) +EXE-NO-GP-NEXT: 059f 0020 1000 qc.e.li a1, 268435488 +EXE-NO-GP-NEXT: 00a5a023 sw a0, 0(a1) +EXE-NO-GP-NEXT: 059f 0020 1000 qc.e.li a1, 268435488 +EXE-NO-GP-NEXT: 00a58023 sb a0, 0(a1) +EXE-NO-GP-NEXT: 059f 0020 1000 qc.e.li a1, 268435488 +EXE-NO-GP-NEXT: 00a59023 sh a0, 0(a1) +EXE-NO-GP-NEXT: 059f 0020 1000 qc.e.li a1, 268435488 +EXE-NO-GP-NEXT: c188 c.sw a0, 0(a1) +EXE-NO-GP-NEXT: 059f 0020 1000 qc.e.li a1, 268435488 +EXE-NO-GP-NEXT: 8188 c.lbu a0, 0(a1) +EXE-NO-GP-NEXT: 059f 0020 1000 qc.e.li a1, 268435488 +EXE-NO-GP-NEXT: 8588 c.lhu a0, 0(a1) +EXE-NO-GP-NEXT: 059f 0020 1000 qc.e.li a1, 268435488 +EXE-NO-GP-NEXT: 85c8 c.lh a0, 0(a1) +EXE-NO-GP-NEXT: 059f 0020 1000 qc.e.li a1, 268435488 +EXE-NO-GP-NEXT: 8988 c.sb a0, 0(a1) +EXE-NO-GP-NEXT: 059f 0020 1000 qc.e.li a1, 268435488 +EXE-NO-GP-NEXT: 8d88 c.sh a0, 0(a1) +EXE-NO-GP-NEXT: 059f 0020 1000 qc.e.li a1, 268435488 +EXE-NO-GP-NEXT: 0045a503 lw a0, 4(a1) +EXE-NO-GP-NEXT: 059f 0020 1000 qc.e.li a1, 268435488 +EXE-NO-GP-NEXT: 00a5a223 sw a0, 4(a1) +EXE-NO-GP-NEXT: 059f 0020 1000 qc.e.li a1, 268435488 +EXE-NO-GP-NEXT: 41c8 c.lw a0, 4(a1) +EXE-NO-GP-NEXT: 059f 0020 1000 qc.e.li a1, 268435488 +EXE-NO-GP-NEXT: 81c8 c.lbu a0, 1(a1) +EXE-NO-GP-NEXT: 059f 0020 1000 qc.e.li a1, 268435488 +EXE-NO-GP-NEXT: 85a8 c.lhu a0, 2(a1) +EXE-NO-GP-NEXT: 059f 0020 1000 qc.e.li a1, 268435488 +EXE-NO-GP-NEXT: 85e8 c.lh a0, 2(a1) +EXE-NO-GP-NEXT: 059f 0020 1000 qc.e.li a1, 268435488 +EXE-NO-GP-NEXT: 89c8 c.sb a0, 1(a1) +EXE-NO-GP-NEXT: 059f 0020 1000 qc.e.li a1, 268435488 +EXE-NO-GP-NEXT: 8da8 c.sh a0, 2(a1) +EXE-NO-GP-NEXT: 0100059b qc.li a1, 256 EXE-NO-GP-NEXT: 0005a503 lw a0, 0(a1) -EXE-NO-GP-NEXT: 651f 0200 4000 qc.e.lw a0, 16777248(zero) +EXE-NO-GP-NEXT: 059f 0020 1000 qc.e.li a1, 268435488 +EXE-NO-GP-NEXT: 00062503 lw a0, 0(a2) ## Link with Xqci relaxation disabled — no relaxation occurs. RUN: %link %linkopts --no-relax-xqci -MapStyle txt -Map %t.3.map --verbose %t.o -o %t.3.out -T %p/Inputs/1.t 2>&1 | %filecheck %s --check-prefix=VERBOSE-NO-XQCI @@ -84,167 +206,354 @@ RUN: %filecheck %s --input-file=%t.3.map --check-prefix=MAP-NO-XQCI MAP-NO-XQCI-NOT: RelaxationBytesDeleted MAP-NO-XQCI-NOT: RelaxationBytesMissed -RUN: %objdump --no-print-imm-hex --mattr=+xqcili,+xqcilo -M no-aliases -d %t.3.out 2>&1 | %filecheck %s --check-prefix=EXE-NO-XQCI +RUN: %objdump --no-print-imm-hex --mattr=+xqcili,+xqcilo,+zcb -M no-aliases -d %t.3.out 2>&1 | %filecheck %s --check-prefix=EXE-NO-XQCI EXE-NO-XQCI:
: -EXE-NO-XQCI-NEXT: 059f 0020 0100 qc.e.li a1, 16777248 +EXE-NO-XQCI-NEXT: 059f 0020 1000 qc.e.li a1, 268435488 EXE-NO-XQCI-NEXT: 0005a503 lw a0, 0(a1) -EXE-NO-XQCI-NEXT: 059f 0000 0110 qc.e.li a1, 17825792 +EXE-NO-XQCI-NEXT: 059f 0000 1010 qc.e.li a1, 269484032 EXE-NO-XQCI-NEXT: 0005a503 lw a0, 0(a1) -EXE-NO-XQCI-NEXT: 059f 0000 0500 qc.e.li a1, 83886080 +EXE-NO-XQCI-NEXT: 059f 0100 0000 qc.e.li a1, 256 EXE-NO-XQCI-NEXT: 0005a503 lw a0, 0(a1) -EXE-NO-XQCI-NEXT: 059f 0020 0100 qc.e.li a1, 16777248 +EXE-NO-XQCI-NEXT: 059f 0000 0020 qc.e.li a1, 2097152 +EXE-NO-XQCI-NEXT: 0005a503 lw a0, 0(a1) +EXE-NO-XQCI-NEXT: 059f 0000 1400 qc.e.li a1, 335544320 +EXE-NO-XQCI-NEXT: 0005a503 lw a0, 0(a1) +EXE-NO-XQCI-NEXT: 059f 0020 1000 qc.e.li a1, 268435488 EXE-NO-XQCI-NEXT: 4188 c.lw a0, 0(a1) +EXE-NO-XQCI-NEXT: 059f 0000 1010 qc.e.li a1, 269484032 +EXE-NO-XQCI-NEXT: 4188 c.lw a0, 0(a1) +EXE-NO-XQCI-NEXT: 059f 0100 0000 qc.e.li a1, 256 +EXE-NO-XQCI-NEXT: 4188 c.lw a0, 0(a1) +EXE-NO-XQCI-NEXT: 059f 0000 0020 qc.e.li a1, 2097152 +EXE-NO-XQCI-NEXT: 4188 c.lw a0, 0(a1) +EXE-NO-XQCI-NEXT: 059f 0000 1400 qc.e.li a1, 335544320 +EXE-NO-XQCI-NEXT: 4188 c.lw a0, 0(a1) +EXE-NO-XQCI-NEXT: 059f 0020 1000 qc.e.li a1, 268435488 +EXE-NO-XQCI-NEXT: 00058503 lb a0, 0(a1) +EXE-NO-XQCI-NEXT: 059f 0020 1000 qc.e.li a1, 268435488 +EXE-NO-XQCI-NEXT: 0005c503 lbu a0, 0(a1) +EXE-NO-XQCI-NEXT: 059f 0020 1000 qc.e.li a1, 268435488 +EXE-NO-XQCI-NEXT: 00059503 lh a0, 0(a1) +EXE-NO-XQCI-NEXT: 059f 0020 1000 qc.e.li a1, 268435488 +EXE-NO-XQCI-NEXT: 0005d503 lhu a0, 0(a1) +EXE-NO-XQCI-NEXT: 059f 0020 1000 qc.e.li a1, 268435488 +EXE-NO-XQCI-NEXT: 00a5a023 sw a0, 0(a1) +EXE-NO-XQCI-NEXT: 059f 0020 1000 qc.e.li a1, 268435488 +EXE-NO-XQCI-NEXT: 00a58023 sb a0, 0(a1) +EXE-NO-XQCI-NEXT: 059f 0020 1000 qc.e.li a1, 268435488 +EXE-NO-XQCI-NEXT: 00a59023 sh a0, 0(a1) +EXE-NO-XQCI-NEXT: 059f 0020 1000 qc.e.li a1, 268435488 +EXE-NO-XQCI-NEXT: c188 c.sw a0, 0(a1) +EXE-NO-XQCI-NEXT: 059f 0020 1000 qc.e.li a1, 268435488 +EXE-NO-XQCI-NEXT: 8188 c.lbu a0, 0(a1) +EXE-NO-XQCI-NEXT: 059f 0020 1000 qc.e.li a1, 268435488 +EXE-NO-XQCI-NEXT: 8588 c.lhu a0, 0(a1) +EXE-NO-XQCI-NEXT: 059f 0020 1000 qc.e.li a1, 268435488 +EXE-NO-XQCI-NEXT: 85c8 c.lh a0, 0(a1) +EXE-NO-XQCI-NEXT: 059f 0020 1000 qc.e.li a1, 268435488 +EXE-NO-XQCI-NEXT: 8988 c.sb a0, 0(a1) +EXE-NO-XQCI-NEXT: 059f 0020 1000 qc.e.li a1, 268435488 +EXE-NO-XQCI-NEXT: 8d88 c.sh a0, 0(a1) +EXE-NO-XQCI-NEXT: 059f 0020 1000 qc.e.li a1, 268435488 +EXE-NO-XQCI-NEXT: 0045a503 lw a0, 4(a1) +EXE-NO-XQCI-NEXT: 059f 0020 1000 qc.e.li a1, 268435488 +EXE-NO-XQCI-NEXT: 00a5a223 sw a0, 4(a1) +EXE-NO-XQCI-NEXT: 059f 0020 1000 qc.e.li a1, 268435488 +EXE-NO-XQCI-NEXT: 41c8 c.lw a0, 4(a1) +EXE-NO-XQCI-NEXT: 059f 0020 1000 qc.e.li a1, 268435488 +EXE-NO-XQCI-NEXT: 81c8 c.lbu a0, 1(a1) +EXE-NO-XQCI-NEXT: 059f 0020 1000 qc.e.li a1, 268435488 +EXE-NO-XQCI-NEXT: 85a8 c.lhu a0, 2(a1) +EXE-NO-XQCI-NEXT: 059f 0020 1000 qc.e.li a1, 268435488 +EXE-NO-XQCI-NEXT: 85e8 c.lh a0, 2(a1) +EXE-NO-XQCI-NEXT: 059f 0020 1000 qc.e.li a1, 268435488 +EXE-NO-XQCI-NEXT: 89c8 c.sb a0, 1(a1) +EXE-NO-XQCI-NEXT: 059f 0020 1000 qc.e.li a1, 268435488 +EXE-NO-XQCI-NEXT: 8da8 c.sh a0, 2(a1) +EXE-NO-XQCI-NEXT: 059f 0100 0000 qc.e.li a1, 256 +EXE-NO-XQCI-NEXT: 0005a503 lw a0, 0(a1) +EXE-NO-XQCI-NEXT: 059f 0020 1000 qc.e.li a1, 268435488 +EXE-NO-XQCI-NEXT: 00062503 lw a0, 0(a2) + +## With --no-relax-zero, both Abs-std and Abs-xqci are disabled. sym_abs_std +## falls back to qc.li (256 fits in isInt<20>); sym_abs_xqci misses entirely. +RUN: %link %linkopts --relax-xqci --no-relax-zero -MapStyle txt -Map %t.4.map --verbose %t.o -o %t.4.out -T %p/Inputs/1.t 2>&1 | %filecheck %s --check-prefix=VERBOSE-NO-ZERO + +VERBOSE-NO-ZERO: RISCV_QC_E_LI_ACCESS_GP_STD : Deleting 6 bytes for symbol 'sym_gprel_std' in section .text+0x4 file {{.*}}.o +VERBOSE-NO-ZERO: RISCV_QC_E_LI_ACCESS_GP_XQCI : Deleting 4 bytes for symbol 'sym_gprel_xqci' in section .text+0xa file {{.*}}.o +VERBOSE-NO-ZERO: RISCV_QC_E_LI_ACCESS : Cannot relax 4 bytes for symbol 'sym_abs_std' in section .text+0xa file {{.*}}.o +VERBOSE-NO-ZERO: RISCV_QC_E_LI_QC_LI : Deleting 2 bytes for symbol 'sym_abs_std' in section .text+0xe file {{.*}}.o +VERBOSE-NO-ZERO: RISCV_QC_E_LI_ACCESS : Cannot relax 4 bytes for symbol 'sym_abs_xqci' in section .text+0x12 file {{.*}}.o +VERBOSE-NO-ZERO: RISCV_QC_E_LI_QC_LI : Cannot relax 2 bytes for symbol 'sym_abs_xqci' in section .text+0x12 file {{.*}}.o +VERBOSE-NO-ZERO: RISCV_QC_E_LI_ACCESS : Cannot relax 4 bytes for symbol 'sym_too_far' in section .text+0x1c file {{.*}}.o +VERBOSE-NO-ZERO: RISCV_QC_E_LI_ACCESS_GP_STD : Deleting 4 bytes for symbol 'sym_gprel_std' in section .text+0x2a file {{.*}}.o +VERBOSE-NO-ZERO: RISCV_QC_E_LI_ACCESS_GP_XQCI : Deleting 2 bytes for symbol 'sym_gprel_xqci' in section .text+0x30 file {{.*}}.o +VERBOSE-NO-ZERO: RISCV_QC_E_LI_ACCESS : Cannot relax 2 bytes for symbol 'sym_abs_std' in section .text+0x30 file {{.*}}.o +VERBOSE-NO-ZERO: RISCV_QC_E_LI_QC_LI : Deleting 2 bytes for symbol 'sym_abs_std' in section .text+0x34 file {{.*}}.o +VERBOSE-NO-ZERO: RISCV_QC_E_LI_ACCESS : Cannot relax 2 bytes for symbol 'sym_abs_xqci' in section .text+0x36 file {{.*}}.o +VERBOSE-NO-ZERO: RISCV_QC_E_LI_QC_LI : Cannot relax 2 bytes for symbol 'sym_abs_xqci' in section .text+0x36 file {{.*}}.o +VERBOSE-NO-ZERO: RISCV_QC_E_LI_ACCESS : Cannot relax 2 bytes for symbol 'sym_too_far' in section .text+0x3e file {{.*}}.o +VERBOSE-NO-ZERO: RISCV_QC_E_LI_ACCESS_GP_STD : Deleting 6 bytes for symbol 'sym_gprel_std' in section .text+0x4a file {{.*}}.o +VERBOSE-NO-ZERO: RISCV_QC_E_LI_ACCESS_GP_STD : Deleting 6 bytes for symbol 'sym_gprel_std' in section .text+0x4e file {{.*}}.o +VERBOSE-NO-ZERO: RISCV_QC_E_LI_ACCESS_GP_STD : Deleting 6 bytes for symbol 'sym_gprel_std' in section .text+0x52 file {{.*}}.o +VERBOSE-NO-ZERO: RISCV_QC_E_LI_ACCESS_GP_STD : Deleting 6 bytes for symbol 'sym_gprel_std' in section .text+0x56 file {{.*}}.o +VERBOSE-NO-ZERO: RISCV_QC_E_LI_ACCESS_GP_STD : Deleting 6 bytes for symbol 'sym_gprel_std' in section .text+0x5a file {{.*}}.o +VERBOSE-NO-ZERO: RISCV_QC_E_LI_ACCESS_GP_STD : Deleting 6 bytes for symbol 'sym_gprel_std' in section .text+0x5e file {{.*}}.o +VERBOSE-NO-ZERO: RISCV_QC_E_LI_ACCESS_GP_STD : Deleting 6 bytes for symbol 'sym_gprel_std' in section .text+0x62 file {{.*}}.o +VERBOSE-NO-ZERO: RISCV_QC_E_LI_ACCESS_GP_STD : Deleting 4 bytes for symbol 'sym_gprel_std' in section .text+0x66 file {{.*}}.o +VERBOSE-NO-ZERO: RISCV_QC_E_LI_ACCESS_GP_STD : Deleting 4 bytes for symbol 'sym_gprel_std' in section .text+0x6a file {{.*}}.o +VERBOSE-NO-ZERO: RISCV_QC_E_LI_ACCESS_GP_STD : Deleting 4 bytes for symbol 'sym_gprel_std' in section .text+0x6e file {{.*}}.o +VERBOSE-NO-ZERO: RISCV_QC_E_LI_ACCESS_GP_STD : Deleting 4 bytes for symbol 'sym_gprel_std' in section .text+0x72 file {{.*}}.o +VERBOSE-NO-ZERO: RISCV_QC_E_LI_ACCESS_GP_STD : Deleting 4 bytes for symbol 'sym_gprel_std' in section .text+0x76 file {{.*}}.o +VERBOSE-NO-ZERO: RISCV_QC_E_LI_ACCESS_GP_STD : Deleting 4 bytes for symbol 'sym_gprel_std' in section .text+0x7a file {{.*}}.o +VERBOSE-NO-ZERO: RISCV_QC_E_LI_ACCESS_GP_STD : Deleting 6 bytes for symbol 'sym_gprel_std' in section .text+0x7e file {{.*}}.o +VERBOSE-NO-ZERO: RISCV_QC_E_LI_ACCESS_GP_STD : Deleting 6 bytes for symbol 'sym_gprel_std' in section .text+0x82 file {{.*}}.o +VERBOSE-NO-ZERO: RISCV_QC_E_LI_ACCESS_GP_STD : Deleting 4 bytes for symbol 'sym_gprel_std' in section .text+0x86 file {{.*}}.o +VERBOSE-NO-ZERO: RISCV_QC_E_LI_ACCESS_GP_STD : Deleting 4 bytes for symbol 'sym_gprel_std' in section .text+0x8a file {{.*}}.o +VERBOSE-NO-ZERO: RISCV_QC_E_LI_ACCESS_GP_STD : Deleting 4 bytes for symbol 'sym_gprel_std' in section .text+0x8e file {{.*}}.o +VERBOSE-NO-ZERO: RISCV_QC_E_LI_ACCESS_GP_STD : Deleting 4 bytes for symbol 'sym_gprel_std' in section .text+0x92 file {{.*}}.o +VERBOSE-NO-ZERO: RISCV_QC_E_LI_ACCESS_GP_STD : Deleting 4 bytes for symbol 'sym_gprel_std' in section .text+0x96 file {{.*}}.o +VERBOSE-NO-ZERO: RISCV_QC_E_LI_ACCESS_GP_STD : Deleting 4 bytes for symbol 'sym_gprel_std' in section .text+0x9a file {{.*}}.o +VERBOSE-NO-ZERO: RISCV_QC_E_LI_QC_LI : Deleting 2 bytes for symbol 'sym_abs_std' in section .text+0x9e file {{.*}}.o +VERBOSE-NO-ZERO: RISCV_QC_E_LI_GP : Deleting 2 bytes for symbol 'sym_gprel_std' in section .text+0xa6 file {{.*}}.o + +RUN: %filecheck %s --input-file=%t.4.map --check-prefix=MAP-NO-ZERO + +MAP-NO-ZERO: # LinkStats Begin +MAP-NO-ZERO: # RelaxationBytesDeleted : 126 +MAP-NO-ZERO: # RelaxationBytesMissed : 30 +MAP-NO-ZERO: # LinkStats End + +RUN: %objdump --no-print-imm-hex --mattr=+xqcilo,+zcb -M no-aliases -d %t.4.out 2>&1 | %filecheck %s --check-prefix=EXE-NO-ZERO + +EXE-NO-ZERO:
: +EXE-NO-ZERO-NEXT: 0201a503 lw a0, 32(gp) +EXE-NO-ZERO-NEXT: e51f 0001 0400 qc.e.lw a0, 1048576(gp) +EXE-NO-ZERO-NEXT: 0100059b qc.li a1, 256 +EXE-NO-ZERO-NEXT: 0005a503 lw a0, 0(a1) +EXE-NO-ZERO-NEXT: 059f 0000 0020 qc.e.li a1, 2097152 +EXE-NO-ZERO-NEXT: 0005a503 lw a0, 0(a1) +EXE-NO-ZERO-NEXT: 059f 0000 1400 qc.e.li a1, 335544320 +EXE-NO-ZERO-NEXT: 0005a503 lw a0, 0(a1) +EXE-NO-ZERO-NEXT: 0201a503 lw a0, 32(gp) +EXE-NO-ZERO-NEXT: e51f 0001 0400 qc.e.lw a0, 1048576(gp) +EXE-NO-ZERO-NEXT: 0100059b qc.li a1, 256 +EXE-NO-ZERO-NEXT: 4188 c.lw a0, 0(a1) +EXE-NO-ZERO-NEXT: 059f 0000 0020 qc.e.li a1, 2097152 +EXE-NO-ZERO-NEXT: 4188 c.lw a0, 0(a1) +EXE-NO-ZERO-NEXT: 059f 0000 1400 qc.e.li a1, 335544320 +EXE-NO-ZERO-NEXT: 4188 c.lw a0, 0(a1) +EXE-NO-ZERO-NEXT: 02018503 lb a0, 32(gp) +EXE-NO-ZERO-NEXT: 0201c503 lbu a0, 32(gp) +EXE-NO-ZERO-NEXT: 02019503 lh a0, 32(gp) +EXE-NO-ZERO-NEXT: 0201d503 lhu a0, 32(gp) +EXE-NO-ZERO-NEXT: 02a1a023 sw a0, 32(gp) +EXE-NO-ZERO-NEXT: 02a18023 sb a0, 32(gp) +EXE-NO-ZERO-NEXT: 02a19023 sh a0, 32(gp) +EXE-NO-ZERO-NEXT: 02a1a023 sw a0, 32(gp) +EXE-NO-ZERO-NEXT: 0201c503 lbu a0, 32(gp) +EXE-NO-ZERO-NEXT: 0201d503 lhu a0, 32(gp) +EXE-NO-ZERO-NEXT: 02019503 lh a0, 32(gp) +EXE-NO-ZERO-NEXT: 02a18023 sb a0, 32(gp) +EXE-NO-ZERO-NEXT: 02a19023 sh a0, 32(gp) +EXE-NO-ZERO-NEXT: 0241a503 lw a0, 36(gp) +EXE-NO-ZERO-NEXT: 02a1a223 sw a0, 36(gp) +EXE-NO-ZERO-NEXT: 0241a503 lw a0, 36(gp) +EXE-NO-ZERO-NEXT: 0211c503 lbu a0, 33(gp) +EXE-NO-ZERO-NEXT: 0221d503 lhu a0, 34(gp) +EXE-NO-ZERO-NEXT: 02219503 lh a0, 34(gp) +EXE-NO-ZERO-NEXT: 02a180a3 sb a0, 33(gp) +EXE-NO-ZERO-NEXT: 02a19123 sh a0, 34(gp) +EXE-NO-ZERO-NEXT: 0100059b qc.li a1, 256 +EXE-NO-ZERO-NEXT: 0005a503 lw a0, 0(a1) +EXE-NO-ZERO-NEXT: 02018593 addi a1, gp, 32 +EXE-NO-ZERO-NEXT: 00062503 lw a0, 0(a2) + +## Boundary tests from Inputs/2.s + Inputs/2.t. +## GP = 0x10000000, so GP-relative and absolute symbol ranges do not overlap. +## Verifies relaxation at the exact edges of each range and that symbols one +## step outside the range are not relaxed by that variant. +RUN: %clang %clangopts -c %p/Inputs/2.s -o %t2.o -menable-experimental-extensions -march=rv32gc_xqcili0p2 -## Additional cases from Inputs/2.s: -## Abs-std, no-RELAX-on-ACCESS, base-reg mismatch, store instructions, -## 16-bit CS store (c.sw) and Zcb instructions (c.lbu, c.sh). -RUN: %clang %clangopts -c %p/Inputs/2.s -o %t2.o -menable-experimental-extensions -march=rv32gc_zcb_xqcili0p2 - -## Abs-std wins by default (ZeroRelax enabled). -## Case 2 verifies that without R_RISCV_RELAX on the ACCESS reloc the pair is -## NOT relaxed — qc.e.li falls back to qc.li-only relaxation, leaving the lw. -## Base register mismatch falls back to qc.e.li-only relaxation. -## Store instructions (sw, c.sw) and Zcb (c.lbu, c.sh) are relaxed correctly. +## With GP and ZeroRelax enabled: all four variants are exercised. RUN: %link %linkopts --relax-xqci -MapStyle txt -Map %t2.1.map --verbose %t2.o -o %t2.1.out -T %p/Inputs/2.t 2>&1 | %filecheck %s --check-prefix=VERBOSE2 -VERBOSE2: RISCV_QC_E_LI_ACCESS_ABS_STD : Deleting 6 bytes for symbol 'sym_abs_std' in section .text+0x4 file {{.*}}.o -VERBOSE2: RISCV_QC_E_LI_QC_LI : Deleting 2 bytes for symbol 'sym_abs_std' in section .text+0x8 file {{.*}}.o -VERBOSE2: RISCV_QC_E_LI_GP : Deleting 2 bytes for symbol 'sym_gprel_std' in section .text+0x10 file {{.*}}.o -VERBOSE2: RISCV_QC_E_LI_ACCESS_GP_STD : Deleting 6 bytes for symbol 'sym_gprel_std' in section .text+0x18 file {{.*}}.o -VERBOSE2: RISCV_QC_E_LI_ACCESS_GP_STD : Deleting 4 bytes for symbol 'sym_gprel_std' in section .text+0x1c file {{.*}}.o -VERBOSE2: RISCV_QC_E_LI_ACCESS_GP_STD : Deleting 4 bytes for symbol 'sym_gprel_std' in section .text+0x20 file {{.*}}.o -VERBOSE2: RISCV_QC_E_LI_ACCESS_GP_STD : Deleting 4 bytes for symbol 'sym_gprel_std' in section .text+0x24 file {{.*}}.o +VERBOSE2: RISCV_QC_E_LI_ACCESS_GP_STD : Deleting 6 bytes for symbol 'sym_gp_std_pos_edge' in section .text+0x4 file {{.*}}.o +VERBOSE2: RISCV_QC_E_LI_ACCESS_GP_STD : Deleting 6 bytes for symbol 'sym_gp_std_neg_edge' in section .text+0x8 file {{.*}}.o +VERBOSE2: RISCV_QC_E_LI_ACCESS_GP_XQCI : Deleting 4 bytes for symbol 'sym_gp_std_pos_out' in section .text+0xe file {{.*}}.o +VERBOSE2: RISCV_QC_E_LI_ACCESS : Cannot relax 2 bytes for symbol 'sym_gp_std_pos_out' in section .text+0x8 file {{.*}}.o +VERBOSE2: RISCV_QC_E_LI_ACCESS_GP_XQCI : Deleting 4 bytes for symbol 'sym_gp_std_neg_out' in section .text+0x14 file {{.*}}.o +VERBOSE2: RISCV_QC_E_LI_ACCESS : Cannot relax 2 bytes for symbol 'sym_gp_std_neg_out' in section .text+0xe file {{.*}}.o +VERBOSE2: RISCV_QC_E_LI_ACCESS_GP_XQCI : Deleting 4 bytes for symbol 'sym_gp_xqci_pos_edge' in section .text+0x1a file {{.*}}.o +VERBOSE2: RISCV_QC_E_LI_ACCESS : Cannot relax 2 bytes for symbol 'sym_gp_xqci_pos_edge' in section .text+0x14 file {{.*}}.o +VERBOSE2: RISCV_QC_E_LI_ACCESS_GP_XQCI : Deleting 4 bytes for symbol 'sym_gp_xqci_neg_edge' in section .text+0x20 file {{.*}}.o +VERBOSE2: RISCV_QC_E_LI_ACCESS : Cannot relax 2 bytes for symbol 'sym_gp_xqci_neg_edge' in section .text+0x1a file {{.*}}.o +VERBOSE2: RISCV_QC_E_LI_ACCESS : Cannot relax 4 bytes for symbol 'sym_gp_xqci_pos_out' in section .text+0x20 file {{.*}}.o +VERBOSE2: RISCV_QC_E_LI_QC_LI : Cannot relax 2 bytes for symbol 'sym_gp_xqci_pos_out' in section .text+0x20 file {{.*}}.o +VERBOSE2: RISCV_QC_E_LI_ACCESS : Cannot relax 4 bytes for symbol 'sym_gp_xqci_neg_out' in section .text+0x2a file {{.*}}.o +VERBOSE2: RISCV_QC_E_LI_QC_LI : Cannot relax 2 bytes for symbol 'sym_gp_xqci_neg_out' in section .text+0x2a file {{.*}}.o +VERBOSE2: RISCV_QC_E_LI_ACCESS_ABS_STD : Deleting 6 bytes for symbol 'sym_abs_std_edge' in section .text+0x38 file {{.*}}.o +VERBOSE2: RISCV_QC_E_LI_ACCESS_ABS_XQCI : Deleting 4 bytes for symbol 'sym_abs_std_out' in section .text+0x3e file {{.*}}.o +VERBOSE2: RISCV_QC_E_LI_ACCESS : Cannot relax 2 bytes for symbol 'sym_abs_std_out' in section .text+0x38 file {{.*}}.o +VERBOSE2: RISCV_QC_E_LI_ACCESS_ABS_XQCI : Deleting 4 bytes for symbol 'sym_abs_xqci_edge' in section .text+0x44 file {{.*}}.o +VERBOSE2: RISCV_QC_E_LI_ACCESS : Cannot relax 2 bytes for symbol 'sym_abs_xqci_edge' in section .text+0x3e file {{.*}}.o +VERBOSE2: RISCV_QC_E_LI_ACCESS : Cannot relax 4 bytes for symbol 'sym_abs_xqci_out' in section .text+0x44 file {{.*}}.o +VERBOSE2: RISCV_QC_E_LI_QC_LI : Cannot relax 2 bytes for symbol 'sym_abs_xqci_out' in section .text+0x44 file {{.*}}.o +VERBOSE2: RISCV_QC_E_LI_ACCESS_ABS_STD : Deleting 6 bytes for symbol 'sym_abs_std_neg_edge' in section .text+0x52 file {{.*}}.o +VERBOSE2: RISCV_QC_E_LI_ACCESS_ABS_XQCI : Deleting 4 bytes for symbol 'sym_abs_std_neg_out' in section .text+0x58 file {{.*}}.o +VERBOSE2: RISCV_QC_E_LI_ACCESS : Cannot relax 2 bytes for symbol 'sym_abs_std_neg_out' in section .text+0x52 file {{.*}}.o +VERBOSE2: RISCV_QC_E_LI_ACCESS_ABS_XQCI : Deleting 4 bytes for symbol 'sym_abs_xqci_neg_edge' in section .text+0x5e file {{.*}}.o +VERBOSE2: RISCV_QC_E_LI_ACCESS : Cannot relax 2 bytes for symbol 'sym_abs_xqci_neg_edge' in section .text+0x58 file {{.*}}.o +VERBOSE2: RISCV_QC_E_LI_ACCESS : Cannot relax 4 bytes for symbol 'sym_abs_xqci_neg_out' in section .text+0x5e file {{.*}}.o +VERBOSE2: RISCV_QC_E_LI_QC_LI : Cannot relax 2 bytes for symbol 'sym_abs_xqci_neg_out' in section .text+0x5e file {{.*}}.o RUN: %filecheck %s --input-file=%t2.1.map --check-prefix=MAP2 MAP2: # LinkStats Begin -MAP2: # RelaxationBytesDeleted : 28 +MAP2: # RelaxationBytesDeleted : 56 +MAP2: # RelaxationBytesMissed : 40 MAP2: # LinkStats End -RUN: %objdump --no-print-imm-hex --mattr=+xqcilo,+zcb -M no-aliases -d %t2.1.out 2>&1 | %filecheck %s --check-prefix=EXE2 +RUN: %objdump --no-print-imm-hex --mattr=+xqcilo -M no-aliases -d %t2.1.out 2>&1 | %filecheck %s --check-prefix=EXE2 EXE2:
: -EXE2-NEXT: 10002503 lw a0, 256(zero) -EXE2-NEXT: 0100059b qc.li a1, 256 +EXE2-NEXT: 7ff1a503 lw a0, 2047(gp) +EXE2-NEXT: 8001a503 lw a0, -2048(gp) +EXE2-NEXT: e51f 0001 0002 qc.e.lw a0, 2048(gp) +EXE2-NEXT: e51f 3ff1 fffd qc.e.lw a0, -2049(gp) +EXE2-NEXT: e51f 3ff1 7fff qc.e.lw a0, 33554431(gp) +EXE2-NEXT: e51f 0001 8000 qc.e.lw a0, -33554432(gp) +EXE2-NEXT: 059f 0000 1200 qc.e.li a1, 301989888 +EXE2-NEXT: 0005a503 lw a0, 0(a1) +EXE2-NEXT: 059f ffff 0dff qc.e.li a1, 234881023 +EXE2-NEXT: 0005a503 lw a0, 0(a1) +EXE2-NEXT: 7ff02503 lw a0, 2047(zero) +EXE2-NEXT: 651f 0000 0002 qc.e.lw a0, 2048(zero) +EXE2-NEXT: 651f 3ff0 7fff qc.e.lw a0, 33554431(zero) +EXE2-NEXT: 059f 0000 0200 qc.e.li a1, 33554432 +EXE2-NEXT: 0005a503 lw a0, 0(a1) +EXE2-NEXT: 80002503 lw a0, -2048(zero) +EXE2-NEXT: 651f 3ff0 fffd qc.e.lw a0, -2049(zero) +EXE2-NEXT: 651f 0000 8000 qc.e.lw a0, -33554432(zero) +EXE2-NEXT: 059f ffff fdff qc.e.li a1, -33554433 EXE2-NEXT: 0005a503 lw a0, 0(a1) -EXE2-NEXT: 02018593 addi a1, gp, 32 -EXE2-NEXT: 00062503 lw a0, 0(a2) -EXE2-NEXT: 02a1a023 sw a0, 32(gp) -EXE2-NEXT: 02a1a023 sw a0, 32(gp) -EXE2-NEXT: 0201c503 lbu a0, 32(gp) -EXE2-NEXT: 02a19023 sh a0, 32(gp) - -## With --no-relax-zero, Abs-std is disabled. sym_abs_std (= 0x100) is -## within isInt<26>(sym - GP) so GP-xqci fires instead, producing qc.e.lw -## instructions. Cases using GP-std (sym_gprel_std) are unaffected. -RUN: %link %linkopts --relax-xqci --no-relax-zero -MapStyle txt -Map %t2.2.map --verbose %t2.o -o %t2.2.out -T %p/Inputs/2.t 2>&1 | %filecheck %s --check-prefix=VERBOSE2-NRZ - -VERBOSE2-NRZ: RISCV_QC_E_LI_ACCESS_GP_XQCI : Deleting 4 bytes for symbol 'sym_abs_std' in section .text+0x6 file {{.*}}.o -VERBOSE2-NRZ: RISCV_QC_E_LI_ACCESS : Cannot relax 2 bytes for symbol 'sym_abs_std' in section .text+0x0 file {{.*}}.o -VERBOSE2-NRZ: RISCV_QC_E_LI_QC_LI : Deleting 2 bytes for symbol 'sym_abs_std' in section .text+0xa file {{.*}}.o -VERBOSE2-NRZ: RISCV_QC_E_LI_GP : Deleting 2 bytes for symbol 'sym_gprel_std' in section .text+0x12 file {{.*}}.o -VERBOSE2-NRZ: RISCV_QC_E_LI_ACCESS_GP_STD : Deleting 6 bytes for symbol 'sym_gprel_std' in section .text+0x1a file {{.*}}.o -VERBOSE2-NRZ: RISCV_QC_E_LI_ACCESS_GP_STD : Deleting 4 bytes for symbol 'sym_gprel_std' in section .text+0x1e file {{.*}}.o -VERBOSE2-NRZ: RISCV_QC_E_LI_ACCESS_GP_STD : Deleting 4 bytes for symbol 'sym_gprel_std' in section .text+0x22 file {{.*}}.o -VERBOSE2-NRZ: RISCV_QC_E_LI_ACCESS_GP_STD : Deleting 4 bytes for symbol 'sym_gprel_std' in section .text+0x26 file {{.*}}.o - -RUN: %filecheck %s --input-file=%t2.2.map --check-prefix=MAP2-NRZ - -MAP2-NRZ: # LinkStats Begin -MAP2-NRZ: # RelaxationBytesDeleted : 26 -MAP2-NRZ: # RelaxationBytesMissed : 2 -MAP2-NRZ: # LinkStats End - -RUN: %objdump --no-print-imm-hex --mattr=+xqcilo,+zcb -M no-aliases -d %t2.2.out 2>&1 | %filecheck %s --check-prefix=EXE2-NRZ - -EXE2-NRZ:
: -EXE2-NRZ-NEXT: e51f 1001 c000 qc.e.lw a0, -16776960(gp) -EXE2-NRZ-NEXT: 0100059b qc.li a1, 256 -EXE2-NRZ-NEXT: 0005a503 lw a0, 0(a1) -EXE2-NRZ-NEXT: 02018593 addi a1, gp, 32 -EXE2-NRZ-NEXT: 00062503 lw a0, 0(a2) -EXE2-NRZ-NEXT: 02a1a023 sw a0, 32(gp) -EXE2-NRZ-NEXT: 02a1a023 sw a0, 32(gp) -EXE2-NRZ-NEXT: 0201c503 lbu a0, 32(gp) -EXE2-NRZ-NEXT: 02a19023 sh a0, 32(gp) - -## Boundary tests from Inputs/3.s + Inputs/3.t. -## GP = 0x10000000, so GP-relative and absolute symbol ranges do not overlap. -## Verifies relaxation at the exact edges of each range and that symbols one -## step outside the range are not relaxed by that variant. -RUN: %clang %clangopts -c %p/Inputs/3.s -o %t3.o -menable-experimental-extensions -march=rv32gc_xqcili0p2 -## With GP and ZeroRelax enabled: all four variants are exercised. -## GP-std applies at ±2047 from GP, GP-xqci at ±33554431, Abs-std at 2047, -## Abs-xqci at 33554431. Symbols one step outside each threshold fall to the -## next cheaper variant (or miss entirely). -RUN: %link %linkopts --relax-xqci -MapStyle txt -Map %t3.1.map --verbose %t3.o -o %t3.1.out -T %p/Inputs/3.t 2>&1 | %filecheck %s --check-prefix=VERBOSE3 - -VERBOSE3: RISCV_QC_E_LI_ACCESS_GP_STD : Deleting 6 bytes for symbol 'sym_gp_std_pos_edge' in section .text+0x4 file {{.*}}.o -VERBOSE3: RISCV_QC_E_LI_ACCESS_GP_STD : Deleting 6 bytes for symbol 'sym_gp_std_neg_edge' in section .text+0x8 file {{.*}}.o -VERBOSE3: RISCV_QC_E_LI_ACCESS_GP_XQCI : Deleting 4 bytes for symbol 'sym_gp_std_pos_out' in section .text+0xe file {{.*}}.o -VERBOSE3: RISCV_QC_E_LI_ACCESS : Cannot relax 2 bytes for symbol 'sym_gp_std_pos_out' in section .text+0x8 file {{.*}}.o -VERBOSE3: RISCV_QC_E_LI_ACCESS_GP_XQCI : Deleting 4 bytes for symbol 'sym_gp_std_neg_out' in section .text+0x14 file {{.*}}.o -VERBOSE3: RISCV_QC_E_LI_ACCESS : Cannot relax 2 bytes for symbol 'sym_gp_std_neg_out' in section .text+0xe file {{.*}}.o -VERBOSE3: RISCV_QC_E_LI_ACCESS_GP_XQCI : Deleting 4 bytes for symbol 'sym_gp_xqci_pos_edge' in section .text+0x1a file {{.*}}.o -VERBOSE3: RISCV_QC_E_LI_ACCESS : Cannot relax 2 bytes for symbol 'sym_gp_xqci_pos_edge' in section .text+0x14 file {{.*}}.o -VERBOSE3: RISCV_QC_E_LI_ACCESS_GP_XQCI : Deleting 4 bytes for symbol 'sym_gp_xqci_neg_edge' in section .text+0x20 file {{.*}}.o -VERBOSE3: RISCV_QC_E_LI_ACCESS : Cannot relax 2 bytes for symbol 'sym_gp_xqci_neg_edge' in section .text+0x1a file {{.*}}.o -VERBOSE3: RISCV_QC_E_LI_ACCESS : Cannot relax 4 bytes for symbol 'sym_gp_xqci_pos_out' in section .text+0x20 file {{.*}}.o -VERBOSE3: RISCV_QC_E_LI_QC_LI : Cannot relax 2 bytes for symbol 'sym_gp_xqci_pos_out' in section .text+0x20 file {{.*}}.o -VERBOSE3: RISCV_QC_E_LI_ACCESS : Cannot relax 4 bytes for symbol 'sym_gp_xqci_neg_out' in section .text+0x2a file {{.*}}.o -VERBOSE3: RISCV_QC_E_LI_QC_LI : Cannot relax 2 bytes for symbol 'sym_gp_xqci_neg_out' in section .text+0x2a file {{.*}}.o -VERBOSE3: RISCV_QC_E_LI_ACCESS_ABS_STD : Deleting 6 bytes for symbol 'sym_abs_std_edge' in section .text+0x38 file {{.*}}.o -VERBOSE3: RISCV_QC_E_LI_ACCESS_ABS_XQCI : Deleting 4 bytes for symbol 'sym_abs_std_out' in section .text+0x3e file {{.*}}.o -VERBOSE3: RISCV_QC_E_LI_ACCESS : Cannot relax 2 bytes for symbol 'sym_abs_std_out' in section .text+0x38 file {{.*}}.o -VERBOSE3: RISCV_QC_E_LI_ACCESS_ABS_XQCI : Deleting 4 bytes for symbol 'sym_abs_xqci_edge' in section .text+0x44 file {{.*}}.o -VERBOSE3: RISCV_QC_E_LI_ACCESS : Cannot relax 2 bytes for symbol 'sym_abs_xqci_edge' in section .text+0x3e file {{.*}}.o -VERBOSE3: RISCV_QC_E_LI_ACCESS : Cannot relax 4 bytes for symbol 'sym_abs_xqci_out' in section .text+0x44 file {{.*}}.o -VERBOSE3: RISCV_QC_E_LI_QC_LI : Cannot relax 2 bytes for symbol 'sym_abs_xqci_out' in section .text+0x44 file {{.*}}.o - -RUN: %filecheck %s --input-file=%t3.1.map --check-prefix=MAP3 - -MAP3: # LinkStats Begin -MAP3: # RelaxationBytesDeleted : 42 -MAP3: # RelaxationBytesMissed : 30 -MAP3: # LinkStats End - -## Without GP relaxation: GP-relative symbols never relax (absolute values are -## all outside the isInt<12> and isInt<26> abs ranges). Abs-std and Abs-xqci +## Without GP relaxation: GP-relative symbols never relax. Abs-std and Abs-xqci ## still fire for the absolute symbols. -RUN: %link %linkopts --relax-xqci --no-relax-gp -MapStyle txt -Map %t3.2.map --verbose %t3.o -o %t3.2.out -T %p/Inputs/3.t 2>&1 | %filecheck %s --check-prefix=VERBOSE3-NO-GP - -VERBOSE3-NO-GP: RISCV_QC_E_LI_ACCESS : Cannot relax 4 bytes for symbol 'sym_gp_std_pos_edge' in section .text+0x0 file {{.*}}.o -VERBOSE3-NO-GP: RISCV_QC_E_LI_QC_LI : Cannot relax 2 bytes for symbol 'sym_gp_std_pos_edge' in section .text+0x0 file {{.*}}.o -VERBOSE3-NO-GP: RISCV_QC_E_LI_ACCESS : Cannot relax 4 bytes for symbol 'sym_gp_xqci_pos_edge' in section .text+0x28 file {{.*}}.o -VERBOSE3-NO-GP: RISCV_QC_E_LI_QC_LI : Cannot relax 2 bytes for symbol 'sym_gp_xqci_pos_edge' in section .text+0x28 file {{.*}}.o -VERBOSE3-NO-GP: RISCV_QC_E_LI_ACCESS_ABS_STD : Deleting 6 bytes for symbol 'sym_abs_std_edge' in section .text+0x54 file {{.*}}.o -VERBOSE3-NO-GP: RISCV_QC_E_LI_ACCESS_ABS_XQCI : Deleting 4 bytes for symbol 'sym_abs_xqci_edge' in section .text+0x60 file {{.*}}.o -VERBOSE3-NO-GP: RISCV_QC_E_LI_ACCESS : Cannot relax 4 bytes for symbol 'sym_abs_xqci_out' in section .text+0x60 file {{.*}}.o - -RUN: %filecheck %s --input-file=%t3.2.map --check-prefix=MAP3-NO-GP - -MAP3-NO-GP: # LinkStats Begin -MAP3-NO-GP: # RelaxationBytesDeleted : 14 -MAP3-NO-GP: # RelaxationBytesMissed : 58 -MAP3-NO-GP: # LinkStats End +RUN: %link %linkopts --relax-xqci --no-relax-gp -MapStyle txt -Map %t2.2.map --verbose %t2.o -o %t2.2.out -T %p/Inputs/2.t 2>&1 | %filecheck %s --check-prefix=VERBOSE2-NO-GP + +VERBOSE2-NO-GP: RISCV_QC_E_LI_ACCESS : Cannot relax 4 bytes for symbol 'sym_gp_std_pos_edge' in section .text+0x0 file {{.*}}.o +VERBOSE2-NO-GP: RISCV_QC_E_LI_QC_LI : Cannot relax 2 bytes for symbol 'sym_gp_std_pos_edge' in section .text+0x0 file {{.*}}.o +VERBOSE2-NO-GP: RISCV_QC_E_LI_ACCESS : Cannot relax 4 bytes for symbol 'sym_gp_xqci_pos_edge' in section .text+0x28 file {{.*}}.o +VERBOSE2-NO-GP: RISCV_QC_E_LI_QC_LI : Cannot relax 2 bytes for symbol 'sym_gp_xqci_pos_edge' in section .text+0x28 file {{.*}}.o +VERBOSE2-NO-GP: RISCV_QC_E_LI_ACCESS_ABS_STD : Deleting 6 bytes for symbol 'sym_abs_std_edge' in section .text+0x54 file {{.*}}.o +VERBOSE2-NO-GP: RISCV_QC_E_LI_ACCESS_ABS_XQCI : Deleting 4 bytes for symbol 'sym_abs_xqci_edge' in section .text+0x60 file {{.*}}.o +VERBOSE2-NO-GP: RISCV_QC_E_LI_ACCESS : Cannot relax 4 bytes for symbol 'sym_abs_xqci_out' in section .text+0x60 file {{.*}}.o +VERBOSE2-NO-GP: RISCV_QC_E_LI_ACCESS_ABS_STD : Deleting 6 bytes for symbol 'sym_abs_std_neg_edge' in section .text+0x6e file {{.*}}.o +VERBOSE2-NO-GP: RISCV_QC_E_LI_ACCESS_ABS_XQCI : Deleting 4 bytes for symbol 'sym_abs_std_neg_out' in section .text+0x74 file {{.*}}.o +VERBOSE2-NO-GP: RISCV_QC_E_LI_ACCESS : Cannot relax 2 bytes for symbol 'sym_abs_std_neg_out' in section .text+0x6e file {{.*}}.o +VERBOSE2-NO-GP: RISCV_QC_E_LI_ACCESS_ABS_XQCI : Deleting 4 bytes for symbol 'sym_abs_xqci_neg_edge' in section .text+0x7a file {{.*}}.o +VERBOSE2-NO-GP: RISCV_QC_E_LI_ACCESS : Cannot relax 2 bytes for symbol 'sym_abs_xqci_neg_edge' in section .text+0x74 file {{.*}}.o +VERBOSE2-NO-GP: RISCV_QC_E_LI_ACCESS : Cannot relax 4 bytes for symbol 'sym_abs_xqci_neg_out' in section .text+0x7a file {{.*}}.o +VERBOSE2-NO-GP: RISCV_QC_E_LI_QC_LI : Cannot relax 2 bytes for symbol 'sym_abs_xqci_neg_out' in section .text+0x7a file {{.*}}.o + +RUN: %filecheck %s --input-file=%t2.2.map --check-prefix=MAP2-NO-GP + +MAP2-NO-GP: # LinkStats Begin +MAP2-NO-GP: # RelaxationBytesDeleted : 28 +MAP2-NO-GP: # RelaxationBytesMissed : 68 +MAP2-NO-GP: # LinkStats End + +RUN: %objdump --no-print-imm-hex --mattr=+xqcilo -M no-aliases -d %t2.2.out 2>&1 | %filecheck %s --check-prefix=EXE2-NO-GP + +EXE2-NO-GP:
: +EXE2-NO-GP-NEXT: 059f 07ff 1000 qc.e.li a1, 268437503 +EXE2-NO-GP-NEXT: 0005a503 lw a0, 0(a1) +EXE2-NO-GP-NEXT: 059f f800 0fff qc.e.li a1, 268433408 +EXE2-NO-GP-NEXT: 0005a503 lw a0, 0(a1) +EXE2-NO-GP-NEXT: 059f 0800 1000 qc.e.li a1, 268437504 +EXE2-NO-GP-NEXT: 0005a503 lw a0, 0(a1) +EXE2-NO-GP-NEXT: 059f f7ff 0fff qc.e.li a1, 268433407 +EXE2-NO-GP-NEXT: 0005a503 lw a0, 0(a1) +EXE2-NO-GP-NEXT: 059f ffff 11ff qc.e.li a1, 301989887 +EXE2-NO-GP-NEXT: 0005a503 lw a0, 0(a1) +EXE2-NO-GP-NEXT: 059f 0000 0e00 qc.e.li a1, 234881024 +EXE2-NO-GP-NEXT: 0005a503 lw a0, 0(a1) +EXE2-NO-GP-NEXT: 059f 0000 1200 qc.e.li a1, 301989888 +EXE2-NO-GP-NEXT: 0005a503 lw a0, 0(a1) +EXE2-NO-GP-NEXT: 059f ffff 0dff qc.e.li a1, 234881023 +EXE2-NO-GP-NEXT: 0005a503 lw a0, 0(a1) +EXE2-NO-GP-NEXT: 7ff02503 lw a0, 2047(zero) +EXE2-NO-GP-NEXT: 651f 0000 0002 qc.e.lw a0, 2048(zero) +EXE2-NO-GP-NEXT: 651f 3ff0 7fff qc.e.lw a0, 33554431(zero) +EXE2-NO-GP-NEXT: 059f 0000 0200 qc.e.li a1, 33554432 +EXE2-NO-GP-NEXT: 0005a503 lw a0, 0(a1) +EXE2-NO-GP-NEXT: 80002503 lw a0, -2048(zero) +EXE2-NO-GP-NEXT: 651f 3ff0 fffd qc.e.lw a0, -2049(zero) +EXE2-NO-GP-NEXT: 651f 0000 8000 qc.e.lw a0, -33554432(zero) +EXE2-NO-GP-NEXT: 059f ffff fdff qc.e.li a1, -33554433 +EXE2-NO-GP-NEXT: 0005a503 lw a0, 0(a1) ## Without GP relaxation or ZeroRelax: only Abs-xqci fires (isInt<26>). -## sym_abs_std_edge (2047) now uses Abs-xqci instead of Abs-std. -## sym_abs_xqci_out (33554432) still misses. -RUN: %link %linkopts --relax-xqci --no-relax-gp --no-relax-zero -MapStyle txt -Map %t3.3.map --verbose %t3.o -o %t3.3.out -T %p/Inputs/3.t 2>&1 | %filecheck %s --check-prefix=VERBOSE3-NO-ZERO - -VERBOSE3-NO-ZERO: RISCV_QC_E_LI_ACCESS_ABS_XQCI : Deleting 4 bytes for symbol 'sym_abs_std_edge' in section .text+0x56 file {{.*}}.o -VERBOSE3-NO-ZERO: RISCV_QC_E_LI_ACCESS : Cannot relax 2 bytes for symbol 'sym_abs_std_edge' in section .text+0x50 file {{.*}}.o -VERBOSE3-NO-ZERO: RISCV_QC_E_LI_ACCESS_ABS_XQCI : Deleting 4 bytes for symbol 'sym_abs_xqci_edge' in section .text+0x62 file {{.*}}.o -VERBOSE3-NO-ZERO: RISCV_QC_E_LI_ACCESS : Cannot relax 2 bytes for symbol 'sym_abs_xqci_edge' in section .text+0x5c file {{.*}}.o -VERBOSE3-NO-ZERO: RISCV_QC_E_LI_ACCESS : Cannot relax 4 bytes for symbol 'sym_abs_xqci_out' in section .text+0x62 file {{.*}}.o -VERBOSE3-NO-ZERO: RISCV_QC_E_LI_QC_LI : Cannot relax 2 bytes for symbol 'sym_abs_xqci_out' in section .text+0x62 file {{.*}}.o - -RUN: %filecheck %s --input-file=%t3.3.map --check-prefix=MAP3-NO-ZERO - -MAP3-NO-ZERO: # LinkStats Begin -MAP3-NO-ZERO: # RelaxationBytesDeleted : 12 -MAP3-NO-ZERO: # RelaxationBytesMissed : 60 -MAP3-NO-ZERO: # LinkStats End +RUN: %link %linkopts --relax-xqci --no-relax-gp --no-relax-zero -MapStyle txt -Map %t2.3.map --verbose %t2.o -o %t2.3.out -T %p/Inputs/2.t 2>&1 | %filecheck %s --check-prefix=VERBOSE2-NO-ZERO + +VERBOSE2-NO-ZERO: RISCV_QC_E_LI_ACCESS : Cannot relax 4 bytes for symbol 'sym_abs_std_edge' in section .text+0x50 file {{.*}}.o +VERBOSE2-NO-ZERO: RISCV_QC_E_LI_QC_LI : Deleting 2 bytes for symbol 'sym_abs_std_edge' in section .text+0x54 file {{.*}}.o +VERBOSE2-NO-ZERO: RISCV_QC_E_LI_ACCESS : Cannot relax 4 bytes for symbol 'sym_abs_std_out' in section .text+0x58 file {{.*}}.o +VERBOSE2-NO-ZERO: RISCV_QC_E_LI_QC_LI : Deleting 2 bytes for symbol 'sym_abs_std_out' in section .text+0x5c file {{.*}}.o +VERBOSE2-NO-ZERO: RISCV_QC_E_LI_ACCESS : Cannot relax 4 bytes for symbol 'sym_abs_xqci_edge' in section .text+0x60 file {{.*}}.o +VERBOSE2-NO-ZERO: RISCV_QC_E_LI_QC_LI : Cannot relax 2 bytes for symbol 'sym_abs_xqci_edge' in section .text+0x60 file {{.*}}.o +VERBOSE2-NO-ZERO: RISCV_QC_E_LI_ACCESS : Cannot relax 4 bytes for symbol 'sym_abs_xqci_out' in section .text+0x6a file {{.*}}.o +VERBOSE2-NO-ZERO: RISCV_QC_E_LI_QC_LI : Cannot relax 2 bytes for symbol 'sym_abs_xqci_out' in section .text+0x6a file {{.*}}.o +VERBOSE2-NO-ZERO: RISCV_QC_E_LI_ACCESS : Cannot relax 4 bytes for symbol 'sym_abs_std_neg_edge' in section .text+0x74 file {{.*}}.o +VERBOSE2-NO-ZERO: RISCV_QC_E_LI_QC_LI : Cannot relax 2 bytes for symbol 'sym_abs_std_neg_edge' in section .text+0x74 file {{.*}}.o +VERBOSE2-NO-ZERO: RISCV_QC_E_LI_ACCESS : Cannot relax 4 bytes for symbol 'sym_abs_std_neg_out' in section .text+0x7e file {{.*}}.o +VERBOSE2-NO-ZERO: RISCV_QC_E_LI_QC_LI : Cannot relax 2 bytes for symbol 'sym_abs_std_neg_out' in section .text+0x7e file {{.*}}.o +VERBOSE2-NO-ZERO: RISCV_QC_E_LI_ACCESS : Cannot relax 4 bytes for symbol 'sym_abs_xqci_neg_edge' in section .text+0x88 file {{.*}}.o +VERBOSE2-NO-ZERO: RISCV_QC_E_LI_QC_LI : Cannot relax 2 bytes for symbol 'sym_abs_xqci_neg_edge' in section .text+0x88 file {{.*}}.o +VERBOSE2-NO-ZERO: RISCV_QC_E_LI_ACCESS : Cannot relax 4 bytes for symbol 'sym_abs_xqci_neg_out' in section .text+0x92 file {{.*}}.o +VERBOSE2-NO-ZERO: RISCV_QC_E_LI_QC_LI : Cannot relax 2 bytes for symbol 'sym_abs_xqci_neg_out' in section .text+0x92 file {{.*}}.o + +RUN: %filecheck %s --input-file=%t2.3.map --check-prefix=MAP2-NO-ZERO + +MAP2-NO-ZERO: # LinkStats Begin +MAP2-NO-ZERO: # RelaxationBytesDeleted : 4 +MAP2-NO-ZERO: # RelaxationBytesMissed : 92 +MAP2-NO-ZERO: # LinkStats End + +RUN: %objdump --no-print-imm-hex --mattr=+xqcilo -M no-aliases -d %t2.3.out 2>&1 | %filecheck %s --check-prefix=EXE2-NO-ZERO + +EXE2-NO-ZERO:
: +EXE2-NO-ZERO-NEXT: 059f 07ff 1000 qc.e.li a1, 268437503 +EXE2-NO-ZERO-NEXT: 0005a503 lw a0, 0(a1) +EXE2-NO-ZERO-NEXT: 059f f800 0fff qc.e.li a1, 268433408 +EXE2-NO-ZERO-NEXT: 0005a503 lw a0, 0(a1) +EXE2-NO-ZERO-NEXT: 059f 0800 1000 qc.e.li a1, 268437504 +EXE2-NO-ZERO-NEXT: 0005a503 lw a0, 0(a1) +EXE2-NO-ZERO-NEXT: 059f f7ff 0fff qc.e.li a1, 268433407 +EXE2-NO-ZERO-NEXT: 0005a503 lw a0, 0(a1) +EXE2-NO-ZERO-NEXT: 059f ffff 11ff qc.e.li a1, 301989887 +EXE2-NO-ZERO-NEXT: 0005a503 lw a0, 0(a1) +EXE2-NO-ZERO-NEXT: 059f 0000 0e00 qc.e.li a1, 234881024 +EXE2-NO-ZERO-NEXT: 0005a503 lw a0, 0(a1) +EXE2-NO-ZERO-NEXT: 059f 0000 1200 qc.e.li a1, 301989888 +EXE2-NO-ZERO-NEXT: 0005a503 lw a0, 0(a1) +EXE2-NO-ZERO-NEXT: 059f ffff 0dff qc.e.li a1, 234881023 +EXE2-NO-ZERO-NEXT: 0005a503 lw a0, 0(a1) +EXE2-NO-ZERO-NEXT: 07ff059b qc.li a1, 2047 +EXE2-NO-ZERO-NEXT: 0005a503 lw a0, 0(a1) +EXE2-NO-ZERO-NEXT: 0800059b qc.li a1, 2048 +EXE2-NO-ZERO-NEXT: 0005a503 lw a0, 0(a1) +EXE2-NO-ZERO-NEXT: 059f ffff 01ff qc.e.li a1, 33554431 +EXE2-NO-ZERO-NEXT: 0005a503 lw a0, 0(a1) +EXE2-NO-ZERO-NEXT: 059f 0000 0200 qc.e.li a1, 33554432 +EXE2-NO-ZERO-NEXT: 0005a503 lw a0, 0(a1) +EXE2-NO-ZERO-NEXT: 059f f800 ffff qc.e.li a1, -2048 +EXE2-NO-ZERO-NEXT: 0005a503 lw a0, 0(a1) +EXE2-NO-ZERO-NEXT: 059f f7ff ffff qc.e.li a1, -2049 +EXE2-NO-ZERO-NEXT: 0005a503 lw a0, 0(a1) +EXE2-NO-ZERO-NEXT: 059f 0000 fe00 qc.e.li a1, -33554432 +EXE2-NO-ZERO-NEXT: 0005a503 lw a0, 0(a1) +EXE2-NO-ZERO-NEXT: 059f ffff fdff qc.e.li a1, -33554433 +EXE2-NO-ZERO-NEXT: 0005a503 lw a0, 0(a1)