Skip to content

Commit f7a96dc

Browse files
authored
[LoongArch] Ensure pcaddu18i and jirl adjacency in tail calls for correct relocation (#113932)
Prior to this patch, both `pcaddu18i` and `jirl` were marked as scheduling boundaries to prevent instruction reordering that would disrupt their adjacency. However, in certain cases, epilogues were still being inserted between these two instructions, breaking the required proximity. This patch ensures that `pcaddu18i` and `jirl` remain adjacent even in the presence of epilogues, maintaining correct relocation behavior for tail calls on LoongArch.
1 parent be60afe commit f7a96dc

File tree

5 files changed

+64
-44
lines changed

5 files changed

+64
-44
lines changed

llvm/lib/Target/LoongArch/LoongArchExpandPseudoInsts.cpp

Lines changed: 57 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -165,11 +165,9 @@ bool LoongArchPreRAExpandPseudo::expandMI(
165165
case LoongArch::PseudoLA_TLS_DESC_LARGE:
166166
return expandLoadAddressTLSDesc(MBB, MBBI, NextMBBI, /*Large=*/true);
167167
case LoongArch::PseudoCALL:
168-
case LoongArch::PseudoCALL_MEDIUM:
169168
case LoongArch::PseudoCALL_LARGE:
170169
return expandFunctionCALL(MBB, MBBI, NextMBBI, /*IsTailCall=*/false);
171170
case LoongArch::PseudoTAIL:
172-
case LoongArch::PseudoTAIL_MEDIUM:
173171
case LoongArch::PseudoTAIL_LARGE:
174172
return expandFunctionCALL(MBB, MBBI, NextMBBI, /*IsTailCall=*/true);
175173
case LoongArch::PseudoBRIND:
@@ -545,7 +543,7 @@ bool LoongArchPreRAExpandPseudo::expandFunctionCALL(
545543

546544
switch (MF->getTarget().getCodeModel()) {
547545
default:
548-
report_fatal_error("Unsupported code model");
546+
report_fatal_error("Unexpected code model");
549547
break;
550548
case CodeModel::Small: {
551549
// CALL:
@@ -556,31 +554,6 @@ bool LoongArchPreRAExpandPseudo::expandFunctionCALL(
556554
CALL = BuildMI(MBB, MBBI, DL, TII->get(Opcode)).add(Func);
557555
break;
558556
}
559-
case CodeModel::Medium: {
560-
// CALL:
561-
// pcaddu18i $ra, %call36(func)
562-
// jirl $ra, $ra, 0
563-
// TAIL:
564-
// pcaddu18i $scratch, %call36(func)
565-
// jirl $r0, $scratch, 0
566-
Opcode =
567-
IsTailCall ? LoongArch::PseudoJIRL_TAIL : LoongArch::PseudoJIRL_CALL;
568-
Register ScratchReg =
569-
IsTailCall
570-
? MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass)
571-
: LoongArch::R1;
572-
MachineInstrBuilder MIB =
573-
BuildMI(MBB, MBBI, DL, TII->get(LoongArch::PCADDU18I), ScratchReg);
574-
575-
CALL =
576-
BuildMI(MBB, MBBI, DL, TII->get(Opcode)).addReg(ScratchReg).addImm(0);
577-
578-
if (Func.isSymbol())
579-
MIB.addExternalSymbol(Func.getSymbolName(), LoongArchII::MO_CALL36);
580-
else
581-
MIB.addDisp(Func, 0, LoongArchII::MO_CALL36);
582-
break;
583-
}
584557
case CodeModel::Large: {
585558
// Emit the 5-insn large address load sequence, either directly or
586559
// indirectly in case of going through the GOT, then JIRL_TAIL or
@@ -671,6 +644,10 @@ class LoongArchExpandPseudo : public MachineFunctionPass {
671644
MachineBasicBlock::iterator &NextMBBI);
672645
bool expandCopyCFR(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
673646
MachineBasicBlock::iterator &NextMBBI);
647+
bool expandFunctionCALL(MachineBasicBlock &MBB,
648+
MachineBasicBlock::iterator MBBI,
649+
MachineBasicBlock::iterator &NextMBBI,
650+
bool IsTailCall);
674651
};
675652

676653
char LoongArchExpandPseudo::ID = 0;
@@ -705,6 +682,10 @@ bool LoongArchExpandPseudo::expandMI(MachineBasicBlock &MBB,
705682
switch (MBBI->getOpcode()) {
706683
case LoongArch::PseudoCopyCFR:
707684
return expandCopyCFR(MBB, MBBI, NextMBBI);
685+
case LoongArch::PseudoCALL_MEDIUM:
686+
return expandFunctionCALL(MBB, MBBI, NextMBBI, /*IsTailCall=*/false);
687+
case LoongArch::PseudoTAIL_MEDIUM:
688+
return expandFunctionCALL(MBB, MBBI, NextMBBI, /*IsTailCall=*/true);
708689
}
709690

710691
return false;
@@ -763,6 +744,54 @@ bool LoongArchExpandPseudo::expandCopyCFR(
763744
return true;
764745
}
765746

747+
bool LoongArchExpandPseudo::expandFunctionCALL(
748+
MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
749+
MachineBasicBlock::iterator &NextMBBI, bool IsTailCall) {
750+
MachineFunction *MF = MBB.getParent();
751+
MachineInstr &MI = *MBBI;
752+
DebugLoc DL = MI.getDebugLoc();
753+
const MachineOperand &Func = MI.getOperand(0);
754+
MachineInstrBuilder CALL;
755+
unsigned Opcode;
756+
757+
switch (MF->getTarget().getCodeModel()) {
758+
default:
759+
report_fatal_error("Unexpected code model");
760+
break;
761+
case CodeModel::Medium: {
762+
// CALL:
763+
// pcaddu18i $ra, %call36(func)
764+
// jirl $ra, $ra, 0
765+
// TAIL:
766+
// pcaddu18i $t8, %call36(func)
767+
// jirl $r0, $t8, 0
768+
Opcode =
769+
IsTailCall ? LoongArch::PseudoJIRL_TAIL : LoongArch::PseudoJIRL_CALL;
770+
Register ScratchReg = IsTailCall ? LoongArch::R20 : LoongArch::R1;
771+
MachineInstrBuilder MIB =
772+
BuildMI(MBB, MBBI, DL, TII->get(LoongArch::PCADDU18I), ScratchReg);
773+
774+
CALL =
775+
BuildMI(MBB, MBBI, DL, TII->get(Opcode)).addReg(ScratchReg).addImm(0);
776+
777+
if (Func.isSymbol())
778+
MIB.addExternalSymbol(Func.getSymbolName(), LoongArchII::MO_CALL36);
779+
else
780+
MIB.addDisp(Func, 0, LoongArchII::MO_CALL36);
781+
break;
782+
}
783+
}
784+
785+
// Transfer implicit operands.
786+
CALL.copyImplicitOps(MI);
787+
788+
// Transfer MI flags.
789+
CALL.setMIFlags(MI.getFlags());
790+
791+
MI.eraseFromParent();
792+
return true;
793+
}
794+
766795
} // end namespace
767796

768797
INITIALIZE_PASS(LoongArchPreRAExpandPseudo, "loongarch-prera-expand-pseudo",

llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -391,9 +391,6 @@ bool LoongArchInstrInfo::isSchedulingBoundary(const MachineInstr &MI,
391391
//
392392
// The following instruction patterns are prohibited from being reordered:
393393
//
394-
// * pcaddu18 $ra, %call36(s)
395-
// jirl $ra, $ra, 0
396-
//
397394
// * pcalau12i $a0, %pc_hi20(s)
398395
// addi.d $a1, $zero, %pc_lo12(s)
399396
// lu32i.d $a1, %pc64_lo20(s)
@@ -413,10 +410,6 @@ bool LoongArchInstrInfo::isSchedulingBoundary(const MachineInstr &MI,
413410
// boundaries, and the instructions between them are guaranteed to be
414411
// ordered according to data dependencies.
415412
switch (MI.getOpcode()) {
416-
case LoongArch::PCADDU18I:
417-
if (MI.getOperand(1).getTargetFlags() == LoongArchII::MO_CALL36)
418-
return true;
419-
break;
420413
case LoongArch::PCALAU12I: {
421414
auto AddI = std::next(MII);
422415
if (AddI == MIE || AddI->getOpcode() != LoongArch::ADDI_D)

llvm/lib/Target/LoongArch/LoongArchInstrInfo.td

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1484,7 +1484,7 @@ def : Pat<(loongarch_call tglobaladdr:$func), (PseudoCALL tglobaladdr:$func)>;
14841484
def : Pat<(loongarch_call texternalsym:$func), (PseudoCALL texternalsym:$func)>;
14851485

14861486
// Function call with 'Medium' code model.
1487-
let isCall = 1, Defs = [R1] in
1487+
let isCall = 1, Defs = [R1, R20], Size = 8 in
14881488
def PseudoCALL_MEDIUM : Pseudo<(outs), (ins bare_symbol:$func)>;
14891489

14901490
let Predicates = [IsLA64] in {
@@ -1533,7 +1533,8 @@ def : Pat<(loongarch_tail (iPTR texternalsym:$dst)),
15331533
(PseudoTAIL texternalsym:$dst)>;
15341534

15351535
// Tail call with 'Medium' code model.
1536-
let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [R3] in
1536+
let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1,
1537+
Uses = [R3], Defs = [R20], Size = 8 in
15371538
def PseudoTAIL_MEDIUM : Pseudo<(outs), (ins bare_symbol:$dst)>;
15381539

15391540
let Predicates = [IsLA64] in {

llvm/test/CodeGen/LoongArch/code-models.ll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,8 +105,8 @@ define i32 @caller_tail(i32 %i) nounwind {
105105
;
106106
; MEDIUM-LABEL: caller_tail:
107107
; MEDIUM: # %bb.0: # %entry
108-
; MEDIUM-NEXT: pcaddu18i $a1, %call36(callee_tail)
109-
; MEDIUM-NEXT: jr $a1
108+
; MEDIUM-NEXT: pcaddu18i $t8, %call36(callee_tail)
109+
; MEDIUM-NEXT: jr $t8
110110
;
111111
; LARGE-LABEL: caller_tail:
112112
; LARGE: # %bb.0: # %entry

llvm/test/CodeGen/LoongArch/expand-adjacency.ll

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,8 @@ declare i32 @callee_tail(i32 %i)
2727

2828
define i32 @caller_call_tail(i32 %i) nounwind {
2929
; MEDIUM-LABEL: caller_call_tail:
30-
; MEDIUM: pcaddu18i $a1, %call36(callee_tail)
31-
; MEDIUM-NEXT: ld.d {{.*}}
32-
; MEDIUM-NEXT: ld.d {{.*}}
33-
; MEDIUM-NEXT: addi.d {{.*}}
34-
; MEDIUM-NEXT: jr $a1
30+
; MEDIUM: pcaddu18i $t8, %call36(callee_tail)
31+
; MEDIUM-NEXT: jr $t8
3532
;
3633
; LARGE-LABEL: caller_call_tail:
3734
; LARGE: pcalau12i [[REG1:\$[a-z0-9]+]], %got_pc_hi20(callee_tail)

0 commit comments

Comments
 (0)