Author: hev
Date: 2026-01-22T08:27:35Z
New Revision: cb16312a22177cd05809843b3c8d43875c75750a

URL: 
https://github.com/llvm/llvm-project/commit/cb16312a22177cd05809843b3c8d43875c75750a
DIFF: 
https://github.com/llvm/llvm-project/commit/cb16312a22177cd05809843b3c8d43875c75750a.diff

LOG: [llvm][LoongArch] Add call30 and tail30 macro instruction support (#175356)

Link:
https://sourceware.org/pipermail/binutils/2025-December/146091.html
(cherry picked from commit c88cbaf2b204795c04596ee3071ce3484f0e610a)

Added: 
    

Modified: 
    llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp
    llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp
    llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
    llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp
    llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.h
    llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCAsmInfo.cpp
    llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCCodeEmitter.cpp
    llvm/test/MC/LoongArch/Basic/Integer/invalid.s
    llvm/test/MC/LoongArch/Macros/macros-call.s

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp 
b/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp
index 9b11201d0312d..483be6b9a1a57 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 {
@@ -463,6 +463,22 @@ class LoongArchOperand : public MCParsedAsmOperand {
                      IsValidKind;
   }
 
+  bool isSImm20pcaddu12i() const {
+    if (!isImm())
+      return false;
+
+    int64_t Imm;
+    LoongArchMCExpr::Specifier VK = LoongArchMCExpr::VK_None;
+    bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
+    bool IsValidKind =
+        VK == LoongArchMCExpr::VK_None || VK == ELF::R_LARCH_CALL30;
+
+    return IsConstantImm
+               ? isInt<20>(Imm) && IsValidKind
+               : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
+                     IsValidKind;
+  }
+
   bool isSImm20pcaddu18i() const {
     if (!isImm())
       return false;
@@ -1465,8 +1481,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 +1505,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 +1576,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());
@@ -1849,6 +1883,12 @@ bool LoongArchAsmParser::matchAndEmitInstruction(SMLoc 
IDLoc, unsigned &Opcode,
         /*Upper=*/(1 << 19) - 1,
         "operand must be a symbol with modifier (e.g. %pc_hi20) or an integer "
         "in the range");
+  case Match_InvalidSImm20pcaddu12i:
+    return generateImmOutOfRangeError(
+        Operands, ErrorInfo, /*Lower=*/-(1 << 19),
+        /*Upper=*/(1 << 19) - 1,
+        "operand must be a symbol with modifier (e.g. %call30) or an integer "
+        "in the range");
   case Match_InvalidSImm20pcaddu18i:
     return generateImmOutOfRangeError(
         Operands, ErrorInfo, /*Lower=*/-(1 << 19),

diff  --git a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp 
b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp
index 69ef349042d8a..44bb1f011dc6d 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..6f840dae3f0ae 100644
--- a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
+++ b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
@@ -474,6 +474,10 @@ def simm20_lu32id : SImm20Operand {
   let ParserMatchClass = SImmAsmOperand<20, "lu32id">;
 }
 
+def simm20_pcaddu12i : SImm20Operand {
+  let ParserMatchClass = SImmAsmOperand<20, "pcaddu12i">;
+}
+
 def simm20_pcaddu18i : SImm20Operand {
   let ParserMatchClass = SImmAsmOperand<20, "pcaddu18i">;
 }
@@ -855,7 +859,7 @@ def SLT  : ALU_3R<0x00120000>;
 def SLTU : ALU_3R<0x00128000>;
 def SLTI  : ALU_2RI12<0x02000000, simm12>;
 def SLTUI : ALU_2RI12<0x02400000, simm12>;
-def PCADDU12I : ALU_1RI20<0x1c000000, simm20>;
+def PCADDU12I : ALU_1RI20<0x1c000000, simm20_pcaddu12i>;
 def AND  : ALU_3R<0x00148000>;
 def OR   : ALU_3R<0x00150000>;
 def NOR  : ALU_3R<0x00140000>;
@@ -1718,6 +1722,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/Basic/Integer/invalid.s 
b/llvm/test/MC/LoongArch/Basic/Integer/invalid.s
index 08a131d4d43f9..8488129bc253a 100644
--- a/llvm/test/MC/LoongArch/Basic/Integer/invalid.s
+++ b/llvm/test/MC/LoongArch/Basic/Integer/invalid.s
@@ -98,9 +98,9 @@ bgeu $a0, $a0, 0x1FFFF
 jirl $a0, $a0, 0x20000
 # CHECK: :[[#@LINE-1]]:16: error: operand must be a symbol with modifier (e.g. 
%b16) or an integer in the range [-131072, 131068]
 
-## simm20
+## simm20_pcaddu12i
 pcaddu12i $a0, 0x80000
-# CHECK: :[[#@LINE-1]]:16: error: immediate must be an integer in the range 
[-524288, 524287]
+# CHECK: :[[#@LINE-1]]:16: error: operand must be a symbol with modifier (e.g. 
%call30) or an integer in the range [-524288, 524287]
 
 ## simm20_pcaddi
 pcaddi $a0, -0x80001

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: ]


        
_______________________________________________
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits

Reply via email to