diff --git a/llvm/lib/Target/LoongArch/LoongArch.td b/llvm/lib/Target/LoongArch/LoongArch.td index 0675caa3b6014..75b65fe69f262 100644 --- a/llvm/lib/Target/LoongArch/LoongArch.td +++ b/llvm/lib/Target/LoongArch/LoongArch.td @@ -102,6 +102,10 @@ def FeatureUAL : SubtargetFeature<"ual", "HasUAL", "true", "Allow memory accesses to be unaligned">; +def FeatureRelax + : SubtargetFeature<"relax", "HasLinkerRelax", "true", + "Enable Linker relaxation">; + //===----------------------------------------------------------------------===// // Registers, instruction descriptions ... //===----------------------------------------------------------------------===// diff --git a/llvm/lib/Target/LoongArch/LoongArchSubtarget.h b/llvm/lib/Target/LoongArch/LoongArchSubtarget.h index 0fbe23f2f62d9..5c173675cca4c 100644 --- a/llvm/lib/Target/LoongArch/LoongArchSubtarget.h +++ b/llvm/lib/Target/LoongArch/LoongArchSubtarget.h @@ -43,6 +43,7 @@ class LoongArchSubtarget : public LoongArchGenSubtargetInfo { bool HasLaGlobalWithAbs = false; bool HasLaLocalWithAbs = false; bool HasUAL = false; + bool HasLinkerRelax = false; unsigned GRLen = 32; MVT GRLenVT = MVT::i32; LoongArchABI::ABI TargetABI = LoongArchABI::ABI_Unknown; @@ -100,6 +101,7 @@ class LoongArchSubtarget : public LoongArchGenSubtargetInfo { bool hasLaGlobalWithAbs() const { return HasLaGlobalWithAbs; } bool hasLaLocalWithAbs() const { return HasLaLocalWithAbs; } bool hasUAL() const { return HasUAL; } + bool hasLinkerRelax() const { return HasLinkerRelax; } MVT getGRLenVT() const { return GRLenVT; } unsigned getGRLen() const { return GRLen; } LoongArchABI::ABI getTargetABI() const { return TargetABI; } diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp index 8744bcb45f75f..a35916d2ad219 100644 --- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp +++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp @@ -167,7 +167,7 @@ bool LoongArchAsmBackend::shouldForceRelocation(const MCAssembler &Asm, return true; switch (Fixup.getTargetKind()) { default: - return false; + return STI.hasFeature(LoongArch::FeatureRelax); case FK_Data_1: case FK_Data_2: case FK_Data_4: @@ -192,7 +192,8 @@ bool LoongArchAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count, std::unique_ptr LoongArchAsmBackend::createObjectTargetWriter() const { - return createLoongArchELFObjectWriter(OSABI, Is64Bit); + return createLoongArchELFObjectWriter( + OSABI, Is64Bit, STI.hasFeature(LoongArch::FeatureRelax)); } MCAsmBackend *llvm::createLoongArchAsmBackend(const Target &T, diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchELFObjectWriter.cpp b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchELFObjectWriter.cpp index a6b9c0652639f..fe19a4f2d3c86 100644 --- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchELFObjectWriter.cpp +++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchELFObjectWriter.cpp @@ -20,19 +20,27 @@ using namespace llvm; namespace { class LoongArchELFObjectWriter : public MCELFObjectTargetWriter { public: - LoongArchELFObjectWriter(uint8_t OSABI, bool Is64Bit); + LoongArchELFObjectWriter(uint8_t OSABI, bool Is64Bit, bool EnableRelax); ~LoongArchELFObjectWriter() override; + bool needsRelocateWithSymbol(const MCValue &Val, const MCSymbol &Sym, + unsigned Type) const override { + return EnableRelax; + } + protected: unsigned getRelocType(MCContext &Ctx, const MCValue &Target, const MCFixup &Fixup, bool IsPCRel) const override; + bool EnableRelax; }; } // end namespace -LoongArchELFObjectWriter::LoongArchELFObjectWriter(uint8_t OSABI, bool Is64Bit) +LoongArchELFObjectWriter::LoongArchELFObjectWriter(uint8_t OSABI, bool Is64Bit, + bool EnableRelax) : MCELFObjectTargetWriter(Is64Bit, OSABI, ELF::EM_LOONGARCH, - /*HasRelocationAddend*/ true) {} + /*HasRelocationAddend=*/true), + EnableRelax(EnableRelax) {} LoongArchELFObjectWriter::~LoongArchELFObjectWriter() {} @@ -87,6 +95,6 @@ unsigned LoongArchELFObjectWriter::getRelocType(MCContext &Ctx, } std::unique_ptr -llvm::createLoongArchELFObjectWriter(uint8_t OSABI, bool Is64Bit) { - return std::make_unique(OSABI, Is64Bit); +llvm::createLoongArchELFObjectWriter(uint8_t OSABI, bool Is64Bit, bool Relax) { + return std::make_unique(OSABI, Is64Bit, Relax); } diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCTargetDesc.h b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCTargetDesc.h index ab35a0096c8a2..bb05baa9b717c 100644 --- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCTargetDesc.h +++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCTargetDesc.h @@ -36,7 +36,7 @@ MCAsmBackend *createLoongArchAsmBackend(const Target &T, const MCTargetOptions &Options); std::unique_ptr -createLoongArchELFObjectWriter(uint8_t OSABI, bool Is64Bit); +createLoongArchELFObjectWriter(uint8_t OSABI, bool Is64Bit, bool Relax); } // end namespace llvm diff --git a/llvm/test/MC/LoongArch/Relocations/relax-attr.s b/llvm/test/MC/LoongArch/Relocations/relax-attr.s new file mode 100644 index 0000000000000..b1e648d850bb9 --- /dev/null +++ b/llvm/test/MC/LoongArch/Relocations/relax-attr.s @@ -0,0 +1,32 @@ +# RUN: llvm-mc --filetype=obj --triple=loongarch64 %s -o %t +# RUN: llvm-readobj -r %t | FileCheck %s +# RUN: llvm-mc --filetype=obj --triple=loongarch64 -mattr=+relax %s -o %t +# RUN: llvm-readobj -r %t | FileCheck %s --check-prefix=CHECKR + +# CHECK: Relocations [ +# CHECK-NEXT: Section ({{.*}}) .rela.data { +# CHECK-NEXT: 0x0 R_LARCH_64 .text 0x4 +# CHECK-NEXT: } +# CHECK-NEXT: ] + +# CHECKR: Relocations [ +# CHECKR-NEXT: Section ({{.*}}) .rela.text { +# CHECKR-NEXT: 0x8 R_LARCH_B21 .L1 0x0 +# CHECKR-NEXT: 0xC R_LARCH_B16 .L1 0x0 +# CHECKR-NEXT: 0x10 R_LARCH_B26 .L1 0x0 +# CHECKR-NEXT: } +# CHECKR-NEXT: Section ({{.*}}) .rela.data { +# CHECKR-NEXT: 0x0 R_LARCH_64 .L1 0x0 +# CHECKR-NEXT: } +# CHECKR-NEXT: ] + +.text + nop +.L1: + nop + beqz $a0, .L1 + blt $a0, $a1, .L1 + b .L1 + +.data +.dword .L1