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..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) { @@ -645,6 +645,338 @@ 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_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; + + uint32_t access_instr = 0; + AccessReloc->targetRef()->memcpy(&access_instr, sizeof(access_instr), 0); + 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); + access.offset = llvm::SignExtend64<12>(extractBits(access_instr, 31, 20)); + 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); + 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; + 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_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; + + uint16_t access_instr = 0; + AccessReloc->targetRef()->memcpy(&access_instr, sizeof(access_instr), 0); + 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: 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: 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"); + } + 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::Address S = getSymbolValuePLT(*QCELiReloc); + Relocator::DWord A = QCELiReloc->addend(); + 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(); + + // 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 = canRelaxXqci && + config().options().getRISCVZeroRelax() && S != 0 && + llvm::isInt<12>(signedAddress(AdjValue)); + + bool canRelaxGPXqci = canRelaxXqci && config().options().getRISCVGPRelax() && + !config().isCodeIndep() && G != 0 && S != 0 && + fitsInGP<26>(G, AdjValue, region, + QCELiReloc->targetSection(), SymbolSize); + + 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, 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()); + 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, 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()); + 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; + } + + if (canRelaxXqci) + reportMissedRelaxation(msg, *region, qceli_offset, access.size, + QCELiReloc->symInfo()->name()); + return false; +} + bool RISCVLDBackend::doRelaxationTLSDESC(Relocation &R, bool Relax) { Fragment *frag = R.targetRef()->frag(); @@ -798,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 { @@ -829,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) { @@ -910,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) { @@ -1089,8 +1423,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..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); @@ -232,6 +241,29 @@ 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; + 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; } + + 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); @@ -254,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/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 5c952e9fc..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", @@ -738,6 +778,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..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 @@ -66,11 +70,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..d34b78258 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,12 +209,18 @@ 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), 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 @@ -1097,6 +1105,40 @@ 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; + 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)) + 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..83228dbfd --- /dev/null +++ b/test/RISCV/standalone/Relaxation/QC_E_LI_ACCESS/Inputs/1.s @@ -0,0 +1,266 @@ + .option exact + .option relax + + .text + .p2align 2 + .globl main + .type main, @function + +QUALCOMM: + +main: + + ## Five cases for lw (ACCESS_32): + ## GP-std, GP-xqci, Abs-std, Abs-xqci, missed. + + 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_abs_std +3: + lw a0, 0(a1) + .reloc 3b, R_RISCV_VENDOR, QUALCOMM + .reloc 3b, R_RISCV_CUSTOM197, sym_abs_std + .reloc 3b, R_RISCV_RELAX + + qc.e.li a1, sym_abs_xqci +4: + lw a0, 0(a1) + .reloc 4b, R_RISCV_VENDOR, QUALCOMM + .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 new file mode 100644 index 000000000..2cda796b1 --- /dev/null +++ b/test/RISCV/standalone/Relaxation/QC_E_LI_ACCESS/Inputs/1.t @@ -0,0 +1,22 @@ +/* GP placed far enough from zero that the GP-relative and absolute symbol + * ranges do not overlap. */ +__global_pointer$ = 0x10000000; + +/* Within isInt<12> of GP */ +sym_gprel_std = __global_pointer$ + 0x20; + +/* Within isInt<26> of GP, but not isInt<12> */ +sym_gprel_xqci = __global_pointer$ + 0x100000; + +/* 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 { + .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..850002df3 --- /dev/null +++ b/test/RISCV/standalone/Relaxation/QC_E_LI_ACCESS/Inputs/2.s @@ -0,0 +1,156 @@ + .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 + + ## 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 new file mode 100644 index 000000000..58f3b1f2f --- /dev/null +++ b/test/RISCV/standalone/Relaxation/QC_E_LI_ACCESS/Inputs/2.t @@ -0,0 +1,43 @@ +/* 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 */ + +/* 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/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..e65c10784 --- /dev/null +++ b/test/RISCV/standalone/Relaxation/QC_E_LI_ACCESS/QC_E_LI_ACCESS.test @@ -0,0 +1,559 @@ +#----------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 + +## 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 + +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_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 : 138 +MAP: # RelaxationBytesMissed : 18 +MAP: # LinkStats End + +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: 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. 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 : 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 : 18 +MAP-NO-GP: # RelaxationBytesMissed : 138 +MAP-NO-GP: # LinkStats End + +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: 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: 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 + +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,+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 1000 qc.e.li a1, 268435488 +EXE-NO-XQCI-NEXT: 0005a503 lw a0, 0(a1) +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 0100 0000 qc.e.li a1, 256 +EXE-NO-XQCI-NEXT: 0005a503 lw a0, 0(a1) +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 + +## 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_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 : 56 +MAP2: # RelaxationBytesMissed : 40 +MAP2: # LinkStats End + +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: 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) + +## 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 %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>). +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) 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)