Skip to content

[LoongArch] Emit R_LARCH_RELAX when expanding some LoadAddress #72961

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Dec 27, 2023

Conversation

MQ-mengqing
Copy link
Contributor

Emit relax relocs when expand non-large la.pcrel and non-large la.got on llvm-mc stage, which like what does on GAS.
1, la.pcrel -> PCALA_HI20 + RELAX + PCALA_LO12 + RELAX
2, la.got -> GOT_PC_HI20 + RELAX + GOT_PC_LO12 + RELAX

@llvmbot llvmbot added mc Machine (object) code backend:loongarch labels Nov 21, 2023
@llvmbot
Copy link
Member

llvmbot commented Nov 21, 2023

@llvm/pr-subscribers-backend-loongarch

@llvm/pr-subscribers-mc

Author: Jinyang He (MQ-mengqing)

Changes

Emit relax relocs when expand non-large la.pcrel and non-large la.got on llvm-mc stage, which like what does on GAS.
1, la.pcrel -> PCALA_HI20 + RELAX + PCALA_LO12 + RELAX
2, la.got -> GOT_PC_HI20 + RELAX + GOT_PC_LO12 + RELAX


Full diff: https://github.com/llvm/llvm-project/pull/72961.diff

6 Files Affected:

  • (modified) llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp (+7-5)
  • (modified) llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchFixupKinds.h (+3-1)
  • (modified) llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCCodeEmitter.cpp (+13)
  • (modified) llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.cpp (+4-3)
  • (modified) llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.h (+5-3)
  • (added) llvm/test/MC/LoongArch/Relocations/relax-la.s (+19)
diff --git a/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp b/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp
index 276374afee38087..66a37fce5dda11b 100644
--- a/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp
+++ b/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp
@@ -85,7 +85,7 @@ class LoongArchAsmParser : public MCTargetAsmParser {
   // "emitLoadAddress*" functions.
   void emitLAInstSeq(MCRegister DestReg, MCRegister TmpReg,
                      const MCExpr *Symbol, SmallVectorImpl<Inst> &Insts,
-                     SMLoc IDLoc, MCStreamer &Out);
+                     SMLoc IDLoc, MCStreamer &Out, bool RelaxHint = false);
 
   // Helper to emit pseudo instruction "la.abs $rd, sym".
   void emitLoadAddressAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
@@ -748,12 +748,14 @@ bool LoongArchAsmParser::ParseInstruction(ParseInstructionInfo &Info,
 void LoongArchAsmParser::emitLAInstSeq(MCRegister DestReg, MCRegister TmpReg,
                                        const MCExpr *Symbol,
                                        SmallVectorImpl<Inst> &Insts,
-                                       SMLoc IDLoc, MCStreamer &Out) {
+                                       SMLoc IDLoc, MCStreamer &Out,
+                                       bool RelaxHint) {
   MCContext &Ctx = getContext();
   for (LoongArchAsmParser::Inst &Inst : Insts) {
     unsigned Opc = Inst.Opc;
     LoongArchMCExpr::VariantKind VK = Inst.VK;
-    const LoongArchMCExpr *LE = LoongArchMCExpr::create(Symbol, VK, Ctx);
+    const LoongArchMCExpr *LE =
+        LoongArchMCExpr::create(Symbol, VK, Ctx, RelaxHint);
     switch (Opc) {
     default:
       llvm_unreachable("unexpected opcode");
@@ -854,7 +856,7 @@ void LoongArchAsmParser::emitLoadAddressPcrel(MCInst &Inst, SMLoc IDLoc,
   Insts.push_back(
       LoongArchAsmParser::Inst(ADDI, LoongArchMCExpr::VK_LoongArch_PCALA_LO12));
 
-  emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out);
+  emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out, true);
 }
 
 void LoongArchAsmParser::emitLoadAddressPcrelLarge(MCInst &Inst, SMLoc IDLoc,
@@ -900,7 +902,7 @@ void LoongArchAsmParser::emitLoadAddressGot(MCInst &Inst, SMLoc IDLoc,
   Insts.push_back(
       LoongArchAsmParser::Inst(LD, LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12));
 
-  emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out);
+  emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out, true);
 }
 
 void LoongArchAsmParser::emitLoadAddressGotLarge(MCInst &Inst, SMLoc IDLoc,
diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchFixupKinds.h b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchFixupKinds.h
index ba2d6718cdf9a27..178fa6e5262be33 100644
--- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchFixupKinds.h
+++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchFixupKinds.h
@@ -106,7 +106,9 @@ enum Fixups {
   // 20-bit fixup corresponding to %gd_pc_hi20(foo) for instruction pcalau12i.
   fixup_loongarch_tls_gd_pc_hi20,
   // 20-bit fixup corresponding to %gd_hi20(foo) for instruction lu12i.w.
-  fixup_loongarch_tls_gd_hi20
+  fixup_loongarch_tls_gd_hi20,
+  // Generate an R_LARCH_RELAX which indicates the linker may relax here.
+  fixup_loongarch_relax = FirstLiteralRelocationKind + ELF::R_LARCH_RELAX
 };
 } // end namespace LoongArch
 } // end namespace llvm
diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCCodeEmitter.cpp b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCCodeEmitter.cpp
index fbe817a2b5475a2..937d18f7effedba 100644
--- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCCodeEmitter.cpp
+++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCCodeEmitter.cpp
@@ -19,6 +19,7 @@
 #include "llvm/MC/MCInstBuilder.h"
 #include "llvm/MC/MCInstrInfo.h"
 #include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/MC/MCSubtargetInfo.h"
 #include "llvm/Support/Casting.h"
 #include "llvm/Support/EndianStream.h"
 
@@ -120,12 +121,15 @@ LoongArchMCCodeEmitter::getExprOpValue(const MCInst &MI, const MCOperand &MO,
                                        SmallVectorImpl<MCFixup> &Fixups,
                                        const MCSubtargetInfo &STI) const {
   assert(MO.isExpr() && "getExprOpValue expects only expressions");
+  bool RelaxCandidate = false;
+  bool EnableRelax = STI.hasFeature(LoongArch::FeatureRelax);
   const MCExpr *Expr = MO.getExpr();
   MCExpr::ExprKind Kind = Expr->getKind();
   LoongArch::Fixups FixupKind = LoongArch::fixup_loongarch_invalid;
   if (Kind == MCExpr::Target) {
     const LoongArchMCExpr *LAExpr = cast<LoongArchMCExpr>(Expr);
 
+    RelaxCandidate = LAExpr->getRelaxHint();
     switch (LAExpr->getKind()) {
     case LoongArchMCExpr::VK_LoongArch_None:
     case LoongArchMCExpr::VK_LoongArch_Invalid:
@@ -269,6 +273,15 @@ LoongArchMCCodeEmitter::getExprOpValue(const MCInst &MI, const MCOperand &MO,
 
   Fixups.push_back(
       MCFixup::create(0, Expr, MCFixupKind(FixupKind), MI.getLoc()));
+
+  // Emit an R_LARCH_RELAX if linker relaxation is enabled and LAExpr has relax
+  // hint.
+  if (EnableRelax && RelaxCandidate) {
+    const MCConstantExpr *Dummy = MCConstantExpr::create(0, Ctx);
+    Fixups.push_back(MCFixup::create(
+        0, Dummy, MCFixupKind(LoongArch::fixup_loongarch_relax), MI.getLoc()));
+  }
+
   return 0;
 }
 
diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.cpp b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.cpp
index 993111552a31430..82c992b1cc8c4e8 100644
--- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.cpp
+++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.cpp
@@ -25,9 +25,10 @@ using namespace llvm;
 
 #define DEBUG_TYPE "loongarch-mcexpr"
 
-const LoongArchMCExpr *
-LoongArchMCExpr::create(const MCExpr *Expr, VariantKind Kind, MCContext &Ctx) {
-  return new (Ctx) LoongArchMCExpr(Expr, Kind);
+const LoongArchMCExpr *LoongArchMCExpr::create(const MCExpr *Expr,
+                                               VariantKind Kind, MCContext &Ctx,
+                                               bool Hint) {
+  return new (Ctx) LoongArchMCExpr(Expr, Kind, Hint);
 }
 
 void LoongArchMCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const {
diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.h b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.h
index 0945cf82db865cd..93251f8241033b6 100644
--- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.h
+++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.h
@@ -67,16 +67,18 @@ class LoongArchMCExpr : public MCTargetExpr {
 private:
   const MCExpr *Expr;
   const VariantKind Kind;
+  const bool RelaxHint;
 
-  explicit LoongArchMCExpr(const MCExpr *Expr, VariantKind Kind)
-      : Expr(Expr), Kind(Kind) {}
+  explicit LoongArchMCExpr(const MCExpr *Expr, VariantKind Kind, bool Hint)
+      : Expr(Expr), Kind(Kind), RelaxHint(Hint) {}
 
 public:
   static const LoongArchMCExpr *create(const MCExpr *Expr, VariantKind Kind,
-                                       MCContext &Ctx);
+                                       MCContext &Ctx, bool Hint = false);
 
   VariantKind getKind() const { return Kind; }
   const MCExpr *getSubExpr() const { return Expr; }
+  bool getRelaxHint() const { return RelaxHint; }
 
   void printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const override;
   bool evaluateAsRelocatableImpl(MCValue &Res, const MCAsmLayout *Layout,
diff --git a/llvm/test/MC/LoongArch/Relocations/relax-la.s b/llvm/test/MC/LoongArch/Relocations/relax-la.s
new file mode 100644
index 000000000000000..a17605b42f851dd
--- /dev/null
+++ b/llvm/test/MC/LoongArch/Relocations/relax-la.s
@@ -0,0 +1,19 @@
+# RUN: llvm-mc --filetype=obj --triple=loongarch64 -mattr=+relax %s -o %t
+# RUN: llvm-readobj -r %t | FileCheck %s
+
+# CHECK:       Relocations [
+# CHECK-NEXT:    Section ({{.*}}) .rela.text {
+# CHECK-NEXT:      0x0 R_LARCH_PCALA_HI20 .L1 0x0
+# CHECK-NEXT:      0x0 R_LARCH_RELAX - 0x0
+# CHECK-NEXT:      0x4 R_LARCH_PCALA_LO12 .L1 0x0
+# CHECK-NEXT:      0x4 R_LARCH_RELAX - 0x0
+# CHECK-NEXT:      0x8 R_LARCH_GOT_PC_HI20 .L1 0x0
+# CHECK-NEXT:      0x8 R_LARCH_RELAX - 0x0
+# CHECK-NEXT:      0xC R_LARCH_GOT_PC_LO12 .L1 0x0
+# CHECK-NEXT:      0xC R_LARCH_RELAX - 0x0
+# CHECK-NEXT:    }
+
+.text
+.L1:
+  la.pcrel $a0, .L1
+  la.got   $a0, .L1

@MQ-mengqing
Copy link
Contributor Author

@MaskRay
Copy link
Member

MaskRay commented Dec 4, 2023

Emit relax relocs when expand some LoadAddress

I suggest [LoongArch] Emit R_LARCH_RELAX when expanding some LoadAddress

@SixWeining SixWeining changed the title Emit relax relocs when expand some LoadAddress [LoongArch] Emit R_LARCH_RELAX when expanding some LoadAddress Dec 19, 2023
Emit relax relocs when expand non-large la.pcrel and non-large la.got
on llvm-mc stage, which like what does on GAS.
1, la.pcrel -> PCALA_HI20 + RELAX + PCALA_LO12 + RELAX
2, la.got -> GOT_PC_HI20 + RELAX + GOT_PC_LO12 + RELAX
…nts.

1, update relax-addsub test to check `la.pcrel` RELAX.
2, update subsection test to check RELAX.
3, add check reloc start/end flags.
4, change non-first CHECK to CHECK-NEXT and add CHECK-EMPTY.
Copy link
Contributor

@SixWeining SixWeining left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@SixWeining SixWeining merged commit b3ef8dc into llvm:main Dec 27, 2023
zhaoqi5 added a commit to zhaoqi5/llvm-project that referenced this pull request Dec 16, 2024
Emit R_LARCH_RELAX relocations when expanding some macros,
including:

- `la.tls.ie`, `la.tls.ld`, `la.tls.gd`, `la.tls.desc`,
- `call36`, `tail36`.

Other macros that need to emit R_LARCH_RELAX relocations
was implemented in llvm#72961, including:

- `la.local`, `la.pcrel`, `la.pcrel` expanded as `la.abs`,
  `la`, `la.global`, `la/la.global` expanded as `la.pcrel`,
  `la.got`.

FIXME: `la.tls.le` macro can be relaxed when expanded with
`R_LARCH_TLS_LE_{HI20/ADD/LO12}_R` relocations. But if we
do so, previously handwritten assembly code will occur error
due to the redundant `add.{w/d}` followed by `la.tls.le`.
So `la.tls.le` keeps to expands with R_LARCH_TLS_LE_{HI20/LO12}.
ylzsx pushed a commit to ylzsx/llvm-project that referenced this pull request Dec 29, 2024
Emit R_LARCH_RELAX relocations when expanding some macros,
including:

- `la.tls.ie`, `la.tls.ld`, `la.tls.gd`, `la.tls.desc`,
- `call36`, `tail36`.

Other macros that need to emit R_LARCH_RELAX relocations
was implemented in llvm#72961, including:

- `la.local`, `la.pcrel`, `la.pcrel` expanded as `la.abs`,
  `la`, `la.global`, `la/la.global` expanded as `la.pcrel`,
  `la.got`.

FIXME: `la.tls.le` macro can be relaxed when expanded with
`R_LARCH_TLS_LE_{HI20/ADD/LO12}_R` relocations. But if we
do so, previously handwritten assembly code will occur error
due to the redundant `add.{w/d}` followed by `la.tls.le`.
So `la.tls.le` keeps to expands with R_LARCH_TLS_LE_{HI20/LO12}.
ylzsx pushed a commit to ylzsx/llvm-project that referenced this pull request Dec 31, 2024
Emit R_LARCH_RELAX relocations when expanding some macros,
including:

- `la.tls.ie`, `la.tls.ld`, `la.tls.gd`, `la.tls.desc`,
- `call36`, `tail36`.

Other macros that need to emit R_LARCH_RELAX relocations
was implemented in llvm#72961, including:

- `la.local`, `la.pcrel`, `la.pcrel` expanded as `la.abs`,
  `la`, `la.global`, `la/la.global` expanded as `la.pcrel`,
  `la.got`.

FIXME: `la.tls.le` macro can be relaxed when expanded with
`R_LARCH_TLS_LE_{HI20/ADD/LO12}_R` relocations. But if we
do so, previously handwritten assembly code will occur error
due to the redundant `add.{w/d}` followed by `la.tls.le`.
So `la.tls.le` keeps to expands with R_LARCH_TLS_LE_{HI20/LO12}.
ylzsx pushed a commit to ylzsx/llvm-project that referenced this pull request Jan 15, 2025
Emit R_LARCH_RELAX relocations when expanding some macros,
including:

- `la.tls.ie`, `la.tls.ld`, `la.tls.gd`, `la.tls.desc`,
- `call36`, `tail36`.

Other macros that need to emit R_LARCH_RELAX relocations
was implemented in llvm#72961, including:

- `la.local`, `la.pcrel`, `la.pcrel` expanded as `la.abs`,
  `la`, `la.global`, `la/la.global` expanded as `la.pcrel`,
  `la.got`.

FIXME: `la.tls.le` macro can be relaxed when expanded with
`R_LARCH_TLS_LE_{HI20/ADD/LO12}_R` relocations. But if we
do so, previously handwritten assembly code will occur error
due to the redundant `add.{w/d}` followed by `la.tls.le`.
So `la.tls.le` keeps to expands with R_LARCH_TLS_LE_{HI20/LO12}.
zhaoqi5 added a commit that referenced this pull request Jan 17, 2025
Emit `R_LARCH_RELAX` relocations when expanding some macros, including:

- `la.tls.ie`, `la.tls.ld`, `la.tls.gd`, `la.tls.desc`,
- `call36`, `tail36`.

Other macros that need to emit `R_LARCH_RELAX` relocations was
implemented in #72961, including:

- `la.local`, `la.pcrel`, `la.pcrel` expanded as `la.abs`, `la`,
`la.global`, `la/la.global` expanded as `la.pcrel`, `la.got`.

Note: `la.tls.le` macro can be relaxed when expanded with
`R_LARCH_TLS_LE_{HI20/ADD/LO12}_R` relocations. But if we do so,
previously handwritten assembly code will occur error due to the
redundant `add.{w/d}` followed by `la.tls.le`. So `la.tls.le` keeps to
expands with `R_LARCH_TLS_LE_{HI20/LO12}`.
github-actions bot pushed a commit to arm/arm-toolchain that referenced this pull request Jan 17, 2025
…(#120067)

Emit `R_LARCH_RELAX` relocations when expanding some macros, including:

- `la.tls.ie`, `la.tls.ld`, `la.tls.gd`, `la.tls.desc`,
- `call36`, `tail36`.

Other macros that need to emit `R_LARCH_RELAX` relocations was
implemented in llvm/llvm-project#72961, including:

- `la.local`, `la.pcrel`, `la.pcrel` expanded as `la.abs`, `la`,
`la.global`, `la/la.global` expanded as `la.pcrel`, `la.got`.

Note: `la.tls.le` macro can be relaxed when expanded with
`R_LARCH_TLS_LE_{HI20/ADD/LO12}_R` relocations. But if we do so,
previously handwritten assembly code will occur error due to the
redundant `add.{w/d}` followed by `la.tls.le`. So `la.tls.le` keeps to
expands with `R_LARCH_TLS_LE_{HI20/LO12}`.
leecheechen pushed a commit to leecheechen/llvm-project that referenced this pull request Jun 9, 2025
…72961)

Emit relax relocs when expand non-large la.pcrel and non-large la.got on
llvm-mc stage, which like what does on GAS.
1, la.pcrel -> PCALA_HI20 + RELAX + PCALA_LO12 + RELAX
2, la.got -> GOT_PC_HI20 + RELAX + GOT_PC_LO12 + RELAX

(cherry picked from commit b3ef8dc)
Change-Id: I222daf60b36ee70e23c76b753e1d2a3b8148f44b
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backend:loongarch mc Machine (object) code
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants