[llvm-branch-commits] [llvm] [llvm][LoongArch] Add call30 and tail30 macro instruction support (PR #175356)

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Sat Jan 10 08:56:52 PST 2026


https://github.com/heiher created https://github.com/llvm/llvm-project/pull/175356

Link: https://sourceware.org/pipermail/binutils/2025-December/146091.html

>From da5357bdb120068c0e94c3765d8cc919c1038438 Mon Sep 17 00:00:00 2001
From: WANG Rui <wangrui at loongson.cn>
Date: Wed, 31 Dec 2025 10:21:14 +0800
Subject: [PATCH] [llvm][LoongArch] Add call30 and tail30 macro instruction
 support

Link: https://sourceware.org/pipermail/binutils/2025-December/146091.html
---
 .../AsmParser/LoongArchAsmParser.cpp          | 42 +++++++++++++------
 .../Target/LoongArch/LoongArchInstrInfo.cpp   |  1 +
 .../Target/LoongArch/LoongArchInstrInfo.td    | 10 +++++
 .../Target/LoongArch/LoongArchMCInstLower.cpp |  3 ++
 .../MCTargetDesc/LoongArchBaseInfo.h          |  1 +
 .../MCTargetDesc/LoongArchMCAsmInfo.cpp       |  3 ++
 .../MCTargetDesc/LoongArchMCCodeEmitter.cpp   |  1 +
 llvm/test/MC/LoongArch/Macros/macros-call.s   | 15 ++++++-
 8 files changed, 63 insertions(+), 13 deletions(-)

diff --git a/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp b/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp
index 9b11201d0312d..ef787a9352a9b 100644
--- a/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp
+++ b/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp
@@ -171,9 +171,9 @@ class LoongArchAsmParser : public MCTargetAsmParser {
   // Helper to emit pseudo instruction "li.w/d $rd, $imm".
   void emitLoadImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
 
-  // Helper to emit pseudo instruction "call36 sym" or "tail36 $rj, sym".
-  void emitFuncCall36(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
-                      bool IsTailCall);
+  // Helper to emit pseudo instruction "call{3x} sym" or "tail{3x} $rj, sym".
+  void emitFuncCall(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, bool IsTailCall,
+                    bool IsCall36);
 
 public:
   enum LoongArchMatchResultTy {
@@ -1465,8 +1465,19 @@ void LoongArchAsmParser::emitLoadImm(MCInst &Inst, SMLoc IDLoc,
   }
 }
 
-void LoongArchAsmParser::emitFuncCall36(MCInst &Inst, SMLoc IDLoc,
-                                        MCStreamer &Out, bool IsTailCall) {
+void LoongArchAsmParser::emitFuncCall(MCInst &Inst, SMLoc IDLoc,
+                                      MCStreamer &Out, bool IsTailCall,
+                                      bool IsCall36) {
+  // call30 sym
+  // expands to:
+  //   pcaddu12i $ra, %call30(sym)
+  //   jirl      $ra, $ra, 0
+  //
+  // tail30 $rj, sym
+  // expands to:
+  //   pcaddu12i $rj, %call30(sym)
+  //   jirl      $r0, $rj, 0
+  //
   // call36 sym
   // expands to:
   //   pcaddu18i $ra, %call36(sym)
@@ -1478,14 +1489,15 @@ void LoongArchAsmParser::emitFuncCall36(MCInst &Inst, SMLoc IDLoc,
   //   jirl      $r0, $rj, 0
   MCRegister ScratchReg =
       IsTailCall ? Inst.getOperand(0).getReg() : MCRegister(LoongArch::R1);
+  unsigned PCAI = IsCall36 ? LoongArch::PCADDU18I : LoongArch::PCADDU12I;
+  unsigned Rel = IsCall36 ? ELF::R_LARCH_CALL36 : ELF::R_LARCH_CALL30;
   const MCExpr *Sym =
       IsTailCall ? Inst.getOperand(1).getExpr() : Inst.getOperand(0).getExpr();
-  const LoongArchMCExpr *LE = LoongArchMCExpr::create(
-      Sym, ELF::R_LARCH_CALL36, getContext(), /*RelaxHint=*/true);
+  const LoongArchMCExpr *LE =
+      LoongArchMCExpr::create(Sym, Rel, getContext(), /*RelaxHint=*/true);
 
-  Out.emitInstruction(
-      MCInstBuilder(LoongArch::PCADDU18I).addReg(ScratchReg).addExpr(LE),
-      getSTI());
+  Out.emitInstruction(MCInstBuilder(PCAI).addReg(ScratchReg).addExpr(LE),
+                      getSTI());
   Out.emitInstruction(
       MCInstBuilder(LoongArch::JIRL)
           .addReg(IsTailCall ? MCRegister(LoongArch::R0) : ScratchReg)
@@ -1548,11 +1560,17 @@ bool LoongArchAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
   case LoongArch::PseudoLI_D:
     emitLoadImm(Inst, IDLoc, Out);
     return false;
+  case LoongArch::PseudoCALL30:
+    emitFuncCall(Inst, IDLoc, Out, /*IsTailCall=*/false, /*IsCall36=*/false);
+    return false;
   case LoongArch::PseudoCALL36:
-    emitFuncCall36(Inst, IDLoc, Out, /*IsTailCall=*/false);
+    emitFuncCall(Inst, IDLoc, Out, /*IsTailCall=*/false, /*IsCall36=*/true);
+    return false;
+  case LoongArch::PseudoTAIL30:
+    emitFuncCall(Inst, IDLoc, Out, /*IsTailCall=*/true, /*IsCall36=*/false);
     return false;
   case LoongArch::PseudoTAIL36:
-    emitFuncCall36(Inst, IDLoc, Out, /*IsTailCall=*/true);
+    emitFuncCall(Inst, IDLoc, Out, /*IsTailCall=*/true, /*IsCall36=*/true);
     return false;
   }
   Out.emitInstruction(Inst, getSTI());
diff --git a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp
index 9fc862af7ea24..39e105b5db4ce 100644
--- a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp
@@ -744,6 +744,7 @@ LoongArchInstrInfo::getSerializableDirectMachineOperandTargetFlags() const {
       {MO_IE_PC64_HI, "loongarch-ie-pc64-hi"},
       {MO_LD_PC_HI, "loongarch-ld-pc-hi"},
       {MO_GD_PC_HI, "loongarch-gd-pc-hi"},
+      {MO_CALL30, "loongarch-call30"},
       {MO_CALL36, "loongarch-call36"},
       {MO_DESC_PC_HI, "loongarch-desc-pc-hi"},
       {MO_DESC_PC_LO, "loongarch-desc-pc-lo"},
diff --git a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
index d971f8bc1986b..26315b13876c8 100644
--- a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
+++ b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
@@ -1718,6 +1718,16 @@ def PseudoJIRL_TAIL : Pseudo<(outs), (ins GPR:$rj, simm16_lsl2:$imm16)>,
                       PseudoInstExpansion<(JIRL R0, GPR:$rj,
                                            simm16_lsl2:$imm16)>;
 
+/// call30/tail30 macro instructions
+let isCall = 1, isBarrier = 1, isCodeGenOnly = 0, isAsmParserOnly = 1,
+    Defs = [R1], hasSideEffects = 0, mayStore = 0, mayLoad = 0 in
+def PseudoCALL30 : Pseudo<(outs), (ins bare_symbol:$dst), [], "call30", "$dst">;
+let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [R3],
+    isCodeGenOnly = 0, isAsmParserOnly = 1, hasSideEffects = 0,
+    mayStore = 0, mayLoad = 0 in
+def PseudoTAIL30 : Pseudo<(outs), (ins GPR:$tmp, bare_symbol:$dst), [],
+                          "tail30", "$tmp, $dst">;
+
 /// call36/taill36 macro instructions
 let isCall = 1, isBarrier = 1, isCodeGenOnly = 0, isAsmParserOnly = 1,
     Defs = [R1], hasSideEffects = 0, mayStore = 0, mayLoad = 0 in
diff --git a/llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp b/llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp
index 455e6ad7c3ac5..ae4090784a9f2 100644
--- a/llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp
@@ -92,6 +92,9 @@ static MCOperand lowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym,
   case LoongArchII::MO_GD_PC_HI:
     Kind = ELF::R_LARCH_TLS_GD_PC_HI20;
     break;
+  case LoongArchII::MO_CALL30:
+    Kind = ELF::R_LARCH_CALL30;
+    break;
   case LoongArchII::MO_CALL36:
     Kind = ELF::R_LARCH_CALL36;
     break;
diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.h b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.h
index 833cd06261624..99d7df63fce04 100644
--- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.h
+++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.h
@@ -48,6 +48,7 @@ enum {
   MO_IE_PC64_HI,
   MO_LD_PC_HI,
   MO_GD_PC_HI,
+  MO_CALL30,
   MO_CALL36,
   MO_DESC_PC_HI,
   MO_DESC_PC_LO,
diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCAsmInfo.cpp b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCAsmInfo.cpp
index 8ecb62d0ea7bb..3f9bea5d69bf9 100644
--- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCAsmInfo.cpp
+++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCAsmInfo.cpp
@@ -97,6 +97,8 @@ static StringRef getLoongArchSpecifierName(uint16_t S) {
     return "gd_pc_hi20";
   case ELF::R_LARCH_TLS_GD_HI20:
     return "gd_hi20";
+  case ELF::R_LARCH_CALL30:
+    return "call30";
   case ELF::R_LARCH_CALL36:
     return "call36";
   case ELF::R_LARCH_TLS_DESC_PC_HI20:
@@ -174,6 +176,7 @@ LoongArchMCExpr::Specifier LoongArch::parseSpecifier(StringRef name) {
       .Case("ld_hi20", ELF::R_LARCH_TLS_LD_HI20)
       .Case("gd_pc_hi20", ELF::R_LARCH_TLS_GD_PC_HI20)
       .Case("gd_hi20", ELF::R_LARCH_TLS_GD_HI20)
+      .Case("call30", ELF::R_LARCH_CALL30)
       .Case("call36", ELF::R_LARCH_CALL36)
       .Case("desc_pc_hi20", ELF::R_LARCH_TLS_DESC_PC_HI20)
       .Case("desc_pc_lo12", ELF::R_LARCH_TLS_DESC_PC_LO12)
diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCCodeEmitter.cpp b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCCodeEmitter.cpp
index 08fa51d333346..661cf8aae99e4 100644
--- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCCodeEmitter.cpp
+++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCCodeEmitter.cpp
@@ -180,6 +180,7 @@ LoongArchMCCodeEmitter::getExprOpValue(const MCInst &MI, const MCOperand &MO,
     case ELF::R_LARCH_ABS64_HI12:
       FixupKind = LoongArch::fixup_loongarch_abs64_hi12;
       break;
+    case ELF::R_LARCH_CALL30:
     case ELF::R_LARCH_CALL36:
     case ELF::R_LARCH_TLS_LE_HI20_R:
     case ELF::R_LARCH_TLS_LE_LO12_R:
diff --git a/llvm/test/MC/LoongArch/Macros/macros-call.s b/llvm/test/MC/LoongArch/Macros/macros-call.s
index df7715050a0f9..0fbc2160c14f5 100644
--- a/llvm/test/MC/LoongArch/Macros/macros-call.s
+++ b/llvm/test/MC/LoongArch/Macros/macros-call.s
@@ -7,6 +7,20 @@
 # RELOC:      Relocations [
 # RELOC-NEXT:   Section ({{.*}}) .rela.text {
 
+call30 sym_call
+# CHECK:      pcaddu12i $ra, %call30(sym_call)
+# CHECK-NEXT: jirl $ra, $ra, 0
+
+# RELOC-NEXT: R_LARCH_CALL30 sym_call 0x0
+# RELAX-NEXT: R_LARCH_RELAX - 0x0
+
+tail30 $t0, sym_tail
+# CHECK:      pcaddu12i $t0, %call30(sym_tail)
+# CHECK-NEXT: jr $t0
+
+# RELOC-NEXT: R_LARCH_CALL30 sym_tail 0x0
+# RELAX-NEXT: R_LARCH_RELAX - 0x0
+
 call36 sym_call
 # CHECK:      pcaddu18i $ra, %call36(sym_call)
 # CHECK-NEXT: jirl $ra, $ra, 0
@@ -21,6 +35,5 @@ tail36 $t0, sym_tail
 # RELOC-NEXT: R_LARCH_CALL36 sym_tail 0x0
 # RELAX-NEXT: R_LARCH_RELAX - 0x0
 
-
 # RELOC-NEXT:   }
 # RELOC-NEXT: ]



More information about the llvm-branch-commits mailing list