Skip to content

[LoongArch] Ensure pcaddu18i and jirl adjacency in tail calls for correct relocation #113932

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Oct 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 57 additions & 28 deletions llvm/lib/Target/LoongArch/LoongArchExpandPseudoInsts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -165,11 +165,9 @@ bool LoongArchPreRAExpandPseudo::expandMI(
case LoongArch::PseudoLA_TLS_DESC_LARGE:
return expandLoadAddressTLSDesc(MBB, MBBI, NextMBBI, /*Large=*/true);
case LoongArch::PseudoCALL:
case LoongArch::PseudoCALL_MEDIUM:
case LoongArch::PseudoCALL_LARGE:
return expandFunctionCALL(MBB, MBBI, NextMBBI, /*IsTailCall=*/false);
case LoongArch::PseudoTAIL:
case LoongArch::PseudoTAIL_MEDIUM:
case LoongArch::PseudoTAIL_LARGE:
return expandFunctionCALL(MBB, MBBI, NextMBBI, /*IsTailCall=*/true);
case LoongArch::PseudoBRIND:
Expand Down Expand Up @@ -545,7 +543,7 @@ bool LoongArchPreRAExpandPseudo::expandFunctionCALL(

switch (MF->getTarget().getCodeModel()) {
default:
report_fatal_error("Unsupported code model");
report_fatal_error("Unexpected code model");
break;
case CodeModel::Small: {
// CALL:
Expand All @@ -556,31 +554,6 @@ bool LoongArchPreRAExpandPseudo::expandFunctionCALL(
CALL = BuildMI(MBB, MBBI, DL, TII->get(Opcode)).add(Func);
break;
}
case CodeModel::Medium: {
// CALL:
// pcaddu18i $ra, %call36(func)
// jirl $ra, $ra, 0
// TAIL:
// pcaddu18i $scratch, %call36(func)
// jirl $r0, $scratch, 0
Opcode =
IsTailCall ? LoongArch::PseudoJIRL_TAIL : LoongArch::PseudoJIRL_CALL;
Register ScratchReg =
IsTailCall
? MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass)
: LoongArch::R1;
MachineInstrBuilder MIB =
BuildMI(MBB, MBBI, DL, TII->get(LoongArch::PCADDU18I), ScratchReg);

CALL =
BuildMI(MBB, MBBI, DL, TII->get(Opcode)).addReg(ScratchReg).addImm(0);

if (Func.isSymbol())
MIB.addExternalSymbol(Func.getSymbolName(), LoongArchII::MO_CALL36);
else
MIB.addDisp(Func, 0, LoongArchII::MO_CALL36);
break;
}
case CodeModel::Large: {
// Emit the 5-insn large address load sequence, either directly or
// indirectly in case of going through the GOT, then JIRL_TAIL or
Expand Down Expand Up @@ -671,6 +644,10 @@ class LoongArchExpandPseudo : public MachineFunctionPass {
MachineBasicBlock::iterator &NextMBBI);
bool expandCopyCFR(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
MachineBasicBlock::iterator &NextMBBI);
bool expandFunctionCALL(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MBBI,
MachineBasicBlock::iterator &NextMBBI,
bool IsTailCall);
};

char LoongArchExpandPseudo::ID = 0;
Expand Down Expand Up @@ -705,6 +682,10 @@ bool LoongArchExpandPseudo::expandMI(MachineBasicBlock &MBB,
switch (MBBI->getOpcode()) {
case LoongArch::PseudoCopyCFR:
return expandCopyCFR(MBB, MBBI, NextMBBI);
case LoongArch::PseudoCALL_MEDIUM:
return expandFunctionCALL(MBB, MBBI, NextMBBI, /*IsTailCall=*/false);
case LoongArch::PseudoTAIL_MEDIUM:
return expandFunctionCALL(MBB, MBBI, NextMBBI, /*IsTailCall=*/true);
}

return false;
Expand Down Expand Up @@ -763,6 +744,54 @@ bool LoongArchExpandPseudo::expandCopyCFR(
return true;
}

bool LoongArchExpandPseudo::expandFunctionCALL(
MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
MachineBasicBlock::iterator &NextMBBI, bool IsTailCall) {
MachineFunction *MF = MBB.getParent();
MachineInstr &MI = *MBBI;
DebugLoc DL = MI.getDebugLoc();
const MachineOperand &Func = MI.getOperand(0);
MachineInstrBuilder CALL;
unsigned Opcode;

switch (MF->getTarget().getCodeModel()) {
default:
report_fatal_error("Unexpected code model");
break;
case CodeModel::Medium: {
// 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);

CALL =
BuildMI(MBB, MBBI, DL, TII->get(Opcode)).addReg(ScratchReg).addImm(0);

if (Func.isSymbol())
MIB.addExternalSymbol(Func.getSymbolName(), LoongArchII::MO_CALL36);
else
MIB.addDisp(Func, 0, LoongArchII::MO_CALL36);
break;
}
}

// Transfer implicit operands.
CALL.copyImplicitOps(MI);

// Transfer MI flags.
CALL.setMIFlags(MI.getFlags());

MI.eraseFromParent();
return true;
}

} // end namespace

INITIALIZE_PASS(LoongArchPreRAExpandPseudo, "loongarch-prera-expand-pseudo",
Expand Down
7 changes: 0 additions & 7 deletions llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -391,9 +391,6 @@ bool LoongArchInstrInfo::isSchedulingBoundary(const MachineInstr &MI,
//
// The following instruction patterns are prohibited from being reordered:
//
// * pcaddu18 $ra, %call36(s)
// jirl $ra, $ra, 0
//
// * pcalau12i $a0, %pc_hi20(s)
// addi.d $a1, $zero, %pc_lo12(s)
// lu32i.d $a1, %pc64_lo20(s)
Expand All @@ -413,10 +410,6 @@ bool LoongArchInstrInfo::isSchedulingBoundary(const MachineInstr &MI,
// boundaries, and the instructions between them are guaranteed to be
// ordered according to data dependencies.
switch (MI.getOpcode()) {
case LoongArch::PCADDU18I:
if (MI.getOperand(1).getTargetFlags() == LoongArchII::MO_CALL36)
return true;
break;
case LoongArch::PCALAU12I: {
auto AddI = std::next(MII);
if (AddI == MIE || AddI->getOpcode() != LoongArch::ADDI_D)
Expand Down
5 changes: 3 additions & 2 deletions llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -1484,7 +1484,7 @@ def : Pat<(loongarch_call tglobaladdr:$func), (PseudoCALL tglobaladdr:$func)>;
def : Pat<(loongarch_call texternalsym:$func), (PseudoCALL texternalsym:$func)>;

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

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

// Tail call with 'Medium' code model.
let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [R3] in
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 {
Expand Down
4 changes: 2 additions & 2 deletions llvm/test/CodeGen/LoongArch/code-models.ll
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,8 @@ define i32 @caller_tail(i32 %i) nounwind {
;
; MEDIUM-LABEL: caller_tail:
; MEDIUM: # %bb.0: # %entry
; MEDIUM-NEXT: pcaddu18i $a1, %call36(callee_tail)
; MEDIUM-NEXT: jr $a1
; MEDIUM-NEXT: pcaddu18i $t8, %call36(callee_tail)
; MEDIUM-NEXT: jr $t8
;
; LARGE-LABEL: caller_tail:
; LARGE: # %bb.0: # %entry
Expand Down
7 changes: 2 additions & 5 deletions llvm/test/CodeGen/LoongArch/expand-adjacency.ll
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,8 @@ declare i32 @callee_tail(i32 %i)

define i32 @caller_call_tail(i32 %i) nounwind {
; MEDIUM-LABEL: caller_call_tail:
; MEDIUM: pcaddu18i $a1, %call36(callee_tail)
; MEDIUM-NEXT: ld.d {{.*}}
; MEDIUM-NEXT: ld.d {{.*}}
; MEDIUM-NEXT: addi.d {{.*}}
; MEDIUM-NEXT: jr $a1
; MEDIUM: pcaddu18i $t8, %call36(callee_tail)
; MEDIUM-NEXT: jr $t8
;
; LARGE-LABEL: caller_call_tail:
; LARGE: pcalau12i [[REG1:\$[a-z0-9]+]], %got_pc_hi20(callee_tail)
Expand Down
Loading