[llvm-branch-commits] [llvm] [llvm][LoongArch] Add call and tail macro instruction support (PR #175357)
via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Sat Jan 10 08:57:49 PST 2026
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-loongarch
Author: hev (heiher)
<details>
<summary>Changes</summary>
Link: https://sourceware.org/pipermail/binutils/2025-December/146091.html
---
Full diff: https://github.com/llvm/llvm-project/pull/175357.diff
8 Files Affected:
- (modified) llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp (+7)
- (modified) llvm/lib/Target/LoongArch/LoongArchExpandPseudoInsts.cpp (+21-10)
- (modified) llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp (+1-2)
- (modified) llvm/lib/Target/LoongArch/LoongArchInstrInfo.td (+21-15)
- (modified) llvm/lib/Target/LoongArch/LoongArchOptWInstrs.cpp (+1-1)
- (modified) llvm/lib/Target/LoongArch/LoongArchTargetMachine.cpp (+2-2)
- (modified) llvm/test/CodeGen/LoongArch/expand-call.ll (+1-1)
- (modified) llvm/test/MC/LoongArch/Macros/macros-call.s (+14)
``````````diff
diff --git a/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp b/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp
index ef787a9352a9b..fa545f740b529 100644
--- a/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp
+++ b/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp
@@ -1560,12 +1560,19 @@ bool LoongArchAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
case LoongArch::PseudoLI_D:
emitLoadImm(Inst, IDLoc, Out);
return false;
+ case LoongArch::PseudoCALL:
+ emitFuncCall(Inst, IDLoc, Out, /*IsTailCall=*/false,
+ /*IsCall36=*/is64Bit());
+ return false;
case LoongArch::PseudoCALL30:
emitFuncCall(Inst, IDLoc, Out, /*IsTailCall=*/false, /*IsCall36=*/false);
return false;
case LoongArch::PseudoCALL36:
emitFuncCall(Inst, IDLoc, Out, /*IsTailCall=*/false, /*IsCall36=*/true);
return false;
+ case LoongArch::PseudoTAIL:
+ emitFuncCall(Inst, IDLoc, Out, /*IsTailCall=*/true, /*IsCall36=*/is64Bit());
+ return false;
case LoongArch::PseudoTAIL30:
emitFuncCall(Inst, IDLoc, Out, /*IsTailCall=*/true, /*IsCall36=*/false);
return false;
diff --git a/llvm/lib/Target/LoongArch/LoongArchExpandPseudoInsts.cpp b/llvm/lib/Target/LoongArch/LoongArchExpandPseudoInsts.cpp
index 7aef4ab53e4ea..6cef279c6131c 100644
--- a/llvm/lib/Target/LoongArch/LoongArchExpandPseudoInsts.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchExpandPseudoInsts.cpp
@@ -161,10 +161,10 @@ bool LoongArchPreRAExpandPseudo::expandMI(
return expandLoadAddressTLSDesc(MBB, MBBI, NextMBBI);
case LoongArch::PseudoLA_TLS_DESC_LARGE:
return expandLoadAddressTLSDesc(MBB, MBBI, NextMBBI, /*Large=*/true);
- case LoongArch::PseudoCALL:
+ case LoongArch::PseudoCALL_SMALL:
case LoongArch::PseudoCALL_LARGE:
return expandFunctionCALL(MBB, MBBI, NextMBBI, /*IsTailCall=*/false);
- case LoongArch::PseudoTAIL:
+ case LoongArch::PseudoTAIL_SMALL:
case LoongArch::PseudoTAIL_LARGE:
return expandFunctionCALL(MBB, MBBI, NextMBBI, /*IsTailCall=*/true);
case LoongArch::PseudoBRIND:
@@ -784,25 +784,36 @@ bool LoongArchExpandPseudo::expandFunctionCALL(
report_fatal_error("Unexpected code model");
break;
case CodeModel::Medium: {
+ // for la32 expands to:
// CALL:
- // pcaddu18i $ra, %call36(func)
- // jirl $ra, $ra, 0
+ // pcaddu12i $ra, %call30(func)
+ // jirl $ra, $ra, 0
// TAIL:
- // pcaddu18i $t8, %call36(func)
- // jirl $r0, $t8, 0
+ // pcaddu12i $t8, %call30(func)
+ // jirl $r0, $t8, 0
+ //
+ // for la64 expands to:
+ // CALL:
+ // pcaddu18i $ra, %call36(func)
+ // jirl $ra, $ra, 0
+ // TAIL:
+ // pcaddu18i $t8, %call36(func)
+ // jirl $r0, $t8, 0
Opcode =
IsTailCall ? LoongArch::PseudoJIRL_TAIL : LoongArch::PseudoJIRL_CALL;
Register ScratchReg = IsTailCall ? LoongArch::R20 : LoongArch::R1;
- MachineInstrBuilder MIB =
- BuildMI(MBB, MBBI, DL, TII->get(LoongArch::PCADDU18I), ScratchReg);
+ bool Is64Bit = MF->getSubtarget<LoongArchSubtarget>().is64Bit();
+ unsigned PC = Is64Bit ? LoongArch::PCADDU18I : LoongArch::PCADDU12I;
+ unsigned MO = Is64Bit ? LoongArchII::MO_CALL36 : LoongArchII::MO_CALL30;
+ MachineInstrBuilder MIB = BuildMI(MBB, MBBI, DL, TII->get(PC), ScratchReg);
CALL =
BuildMI(MBB, MBBI, DL, TII->get(Opcode)).addReg(ScratchReg).addImm(0);
if (Func.isSymbol())
- MIB.addExternalSymbol(Func.getSymbolName(), LoongArchII::MO_CALL36);
+ MIB.addExternalSymbol(Func.getSymbolName(), MO);
else
- MIB.addDisp(Func, 0, LoongArchII::MO_CALL36);
+ MIB.addDisp(Func, 0, MO);
break;
}
}
diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
index fc999b9727521..6cc2f9175c6b7 100644
--- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
@@ -8577,7 +8577,7 @@ LoongArchTargetLowering::LowerCall(CallLoweringInfo &CLI,
// If the callee is a GlobalAddress/ExternalSymbol node, turn it into a
// TargetGlobalAddress/TargetExternalSymbol node so that legalize won't
- // split it and then direct call can be matched by PseudoCALL.
+ // split it and then direct call can be matched by PseudoCALL_SMALL.
if (GlobalAddressSDNode *S = dyn_cast<GlobalAddressSDNode>(Callee)) {
const GlobalValue *GV = S->getGlobal();
unsigned OpFlags = getTargetMachine().shouldAssumeDSOLocal(GV)
@@ -8623,7 +8623,6 @@ LoongArchTargetLowering::LowerCall(CallLoweringInfo &CLI,
Op = IsTailCall ? LoongArchISD::TAIL : LoongArchISD::CALL;
break;
case CodeModel::Medium:
- assert(Subtarget.is64Bit() && "Medium code model requires LA64");
Op = IsTailCall ? LoongArchISD::TAIL_MEDIUM : LoongArchISD::CALL_MEDIUM;
break;
case CodeModel::Large:
diff --git a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
index 26315b13876c8..0923cfd87050f 100644
--- a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
+++ b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
@@ -511,7 +511,7 @@ def SImm26OperandBL: AsmOperandClass {
let ParserMethod = "parseSImm26Operand";
}
-// A symbol or an imm used in BL/PseudoCALL/PseudoTAIL.
+// A symbol or an imm used in BL/PseudoCALL_SMALL/PseudoTAIL_SMALL.
def simm26_symbol : Operand<GRLenVT> {
let ParserMatchClass = SImm26OperandBL;
let EncoderMethod = "getImmOpValueAsr<2>";
@@ -1621,21 +1621,21 @@ def : Pat<(brind (add GPRJR:$rj, simm16_lsl2:$imm16)),
// Function call with 'Small' code model.
let isCall = 1, Defs = [R1] in
-def PseudoCALL : Pseudo<(outs), (ins bare_symbol:$func)>;
+def PseudoCALL_SMALL : Pseudo<(outs), (ins bare_symbol:$func)>;
-def : Pat<(loongarch_call tglobaladdr:$func), (PseudoCALL tglobaladdr:$func)>;
-def : Pat<(loongarch_call texternalsym:$func), (PseudoCALL texternalsym:$func)>;
+def : Pat<(loongarch_call tglobaladdr:$func),
+ (PseudoCALL_SMALL tglobaladdr:$func)>;
+def : Pat<(loongarch_call texternalsym:$func),
+ (PseudoCALL_SMALL texternalsym:$func)>;
// Function call with 'Medium' code model.
let isCall = 1, Defs = [R1, R20], Size = 8 in
def PseudoCALL_MEDIUM : Pseudo<(outs), (ins bare_symbol:$func)>;
-let Predicates = [IsLA64] in {
def : Pat<(loongarch_call_medium tglobaladdr:$func),
(PseudoCALL_MEDIUM tglobaladdr:$func)>;
def : Pat<(loongarch_call_medium texternalsym:$func),
(PseudoCALL_MEDIUM texternalsym:$func)>;
-} // Predicates = [IsLA64]
// Function call with 'Large' code model.
let isCall = 1, Defs = [R1] in
@@ -1652,10 +1652,9 @@ let isCall = 1, Defs = [R1] in
def PseudoCALLIndirect : Pseudo<(outs), (ins GPR:$rj),
[(loongarch_call GPR:$rj)]>,
PseudoInstExpansion<(JIRL R1, GPR:$rj, 0)>;
-let Predicates = [IsLA64] in {
def : Pat<(loongarch_call_medium GPR:$rj), (PseudoCALLIndirect GPR:$rj)>;
+let Predicates = [IsLA64] in
def : Pat<(loongarch_call_large GPR:$rj), (PseudoCALLIndirect GPR:$rj)>;
-}
let isCall = 1, hasSideEffects = 0, mayStore = 0, mayLoad = 0, Defs = [R1] in
def PseudoJIRL_CALL : Pseudo<(outs), (ins GPR:$rj, simm16_lsl2:$imm16)>,
@@ -1668,24 +1667,22 @@ def PseudoRET : Pseudo<(outs), (ins), [(loongarch_ret)]>,
// Tail call with 'Small' code model.
let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [R3] in
-def PseudoTAIL : Pseudo<(outs), (ins bare_symbol:$dst)>;
+def PseudoTAIL_SMALL : Pseudo<(outs), (ins bare_symbol:$dst)>;
def : Pat<(loongarch_tail (iPTR tglobaladdr:$dst)),
- (PseudoTAIL tglobaladdr:$dst)>;
+ (PseudoTAIL_SMALL tglobaladdr:$dst)>;
def : Pat<(loongarch_tail (iPTR texternalsym:$dst)),
- (PseudoTAIL texternalsym:$dst)>;
+ (PseudoTAIL_SMALL texternalsym:$dst)>;
// Tail call with 'Medium' code model.
let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1,
Uses = [R3], Defs = [R20], Size = 8 in
def PseudoTAIL_MEDIUM : Pseudo<(outs), (ins bare_symbol:$dst)>;
-let Predicates = [IsLA64] in {
def : Pat<(loongarch_tail_medium (iPTR tglobaladdr:$dst)),
(PseudoTAIL_MEDIUM tglobaladdr:$dst)>;
def : Pat<(loongarch_tail_medium (iPTR texternalsym:$dst)),
(PseudoTAIL_MEDIUM texternalsym:$dst)>;
-} // Predicates = [IsLA64]
// Tail call with 'Large' code model.
let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [R3] in
@@ -1702,10 +1699,9 @@ let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [R3] in
def PseudoTAILIndirect : Pseudo<(outs), (ins GPRT:$rj),
[(loongarch_tail GPRT:$rj)]>,
PseudoInstExpansion<(JIRL R0, GPR:$rj, 0)>;
-let Predicates = [IsLA64] in {
def : Pat<(loongarch_tail_medium GPR:$rj), (PseudoTAILIndirect GPR:$rj)>;
+let Predicates = [IsLA64] in
def : Pat<(loongarch_tail_large GPR:$rj), (PseudoTAILIndirect GPR:$rj)>;
-}
let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1,
hasSideEffects = 0, mayStore = 0, mayLoad = 0, Uses = [R3] in
@@ -1718,6 +1714,16 @@ def PseudoJIRL_TAIL : Pseudo<(outs), (ins GPR:$rj, simm16_lsl2:$imm16)>,
PseudoInstExpansion<(JIRL R0, GPR:$rj,
simm16_lsl2:$imm16)>;
+/// call/tail macro instructions
+let isCall = 1, isBarrier = 1, isCodeGenOnly = 0, isAsmParserOnly = 1,
+ Defs = [R1], hasSideEffects = 0, mayStore = 0, mayLoad = 0 in
+def PseudoCALL : Pseudo<(outs), (ins bare_symbol:$dst), [], "call", "$dst">;
+let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [R3],
+ isCodeGenOnly = 0, isAsmParserOnly = 1, hasSideEffects = 0,
+ mayStore = 0, mayLoad = 0 in
+def PseudoTAIL : Pseudo<(outs), (ins GPR:$tmp, bare_symbol:$dst), [],
+ "tail", "$tmp, $dst">;
+
/// call30/tail30 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/LoongArchOptWInstrs.cpp b/llvm/lib/Target/LoongArch/LoongArchOptWInstrs.cpp
index 0e5acff5d1cbc..b91724e0112a9 100644
--- a/llvm/lib/Target/LoongArch/LoongArchOptWInstrs.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchOptWInstrs.cpp
@@ -561,7 +561,7 @@ static bool isSignExtendedW(Register SrcReg, const LoongArchSubtarget &ST,
if (CopySrcReg == LoongArch::R4) {
// For a method return value, we check the ZExt/SExt flags in attribute.
// We assume the following code sequence for method call.
- // PseudoCALL @bar, ...
+ // PseudoCALL_SMALL @bar, ...
// ADJCALLSTACKUP 0, 0, implicit-def dead $r3, implicit $r3
// %0:gpr = COPY $r4
//
diff --git a/llvm/lib/Target/LoongArch/LoongArchTargetMachine.cpp b/llvm/lib/Target/LoongArch/LoongArchTargetMachine.cpp
index 92a9388e5cb7b..8054cb2d5e896 100644
--- a/llvm/lib/Target/LoongArch/LoongArchTargetMachine.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchTargetMachine.cpp
@@ -79,11 +79,11 @@ getEffectiveLoongArchCodeModel(const Triple &TT,
switch (*CM) {
case CodeModel::Small:
- return *CM;
case CodeModel::Medium:
+ return *CM;
case CodeModel::Large:
if (!TT.isArch64Bit())
- report_fatal_error("Medium/Large code model requires LA64");
+ report_fatal_error("Large code model requires LA64");
return *CM;
default:
report_fatal_error(
diff --git a/llvm/test/CodeGen/LoongArch/expand-call.ll b/llvm/test/CodeGen/LoongArch/expand-call.ll
index 495cf04c95b32..7a9a5067c54ce 100644
--- a/llvm/test/CodeGen/LoongArch/expand-call.ll
+++ b/llvm/test/CodeGen/LoongArch/expand-call.ll
@@ -7,7 +7,7 @@ declare void @callee()
define void @caller() nounwind {
; NOEXPAND-LABEL: name: caller
-; NOEXPAND: PseudoCALL target-flags{{.*}}callee
+; NOEXPAND: PseudoCALL_SMALL target-flags{{.*}}callee
;
; EXPAND-LABEL: name: caller
; EXPAND: BL target-flags{{.*}}callee
diff --git a/llvm/test/MC/LoongArch/Macros/macros-call.s b/llvm/test/MC/LoongArch/Macros/macros-call.s
index 0fbc2160c14f5..92499efddfadb 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 {
+call sym_call
+# CHECK: pcaddu18i $ra, %call36(sym_call)
+# CHECK-NEXT: jirl $ra, $ra, 0
+
+# RELOC-NEXT: R_LARCH_CALL36 sym_call 0x0
+# RELAX-NEXT: R_LARCH_RELAX - 0x0
+
+tail $t0, sym_tail
+# CHECK: pcaddu18i $t0, %call36(sym_tail)
+# CHECK-NEXT: jr $t0
+
+# RELOC-NEXT: R_LARCH_CALL36 sym_tail 0x0
+# RELAX-NEXT: R_LARCH_RELAX - 0x0
+
call30 sym_call
# CHECK: pcaddu12i $ra, %call30(sym_call)
# CHECK-NEXT: jirl $ra, $ra, 0
``````````
</details>
https://github.com/llvm/llvm-project/pull/175357
More information about the llvm-branch-commits
mailing list