https://github.com/heiher created https://github.com/llvm/llvm-project/pull/175357
Link: https://sourceware.org/pipermail/binutils/2025-December/146091.html >From 2ac5fbb3a699f98ef75d82b539a4e730a2ae066e Mon Sep 17 00:00:00 2001 From: WANG Rui <[email protected]> Date: Wed, 31 Dec 2025 10:26:31 +0800 Subject: [PATCH] [llvm][LoongArch] Add call and tail macro instruction support Link: https://sourceware.org/pipermail/binutils/2025-December/146091.html --- .../AsmParser/LoongArchAsmParser.cpp | 7 ++++ .../LoongArch/LoongArchExpandPseudoInsts.cpp | 31 ++++++++++------ .../LoongArch/LoongArchISelLowering.cpp | 3 +- .../Target/LoongArch/LoongArchInstrInfo.td | 36 +++++++++++-------- .../Target/LoongArch/LoongArchOptWInstrs.cpp | 2 +- .../LoongArch/LoongArchTargetMachine.cpp | 4 +-- llvm/test/CodeGen/LoongArch/expand-call.ll | 2 +- llvm/test/MC/LoongArch/Macros/macros-call.s | 14 ++++++++ 8 files changed, 68 insertions(+), 31 deletions(-) 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 _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
