Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
83 changes: 56 additions & 27 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 @@ -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("Unsupported 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
61 changes: 59 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 All @@ -120,3 +120,60 @@ entry:
%r = tail call i32 @callee_tail(i32 %i)
ret i32 %r
}

define i32 @caller_call_tail(i32 %i) nounwind {
; SMALL-LABEL: caller_call_tail:
; SMALL: # %bb.0: # %entry
; SMALL-NEXT: addi.d $sp, $sp, -16
; SMALL-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill
; SMALL-NEXT: st.d $fp, $sp, 0 # 8-byte Folded Spill
; SMALL-NEXT: move $fp, $a0
; SMALL-NEXT: bl %plt(callee_tail)
; SMALL-NEXT: move $a0, $fp
; SMALL-NEXT: ld.d $fp, $sp, 0 # 8-byte Folded Reload
; SMALL-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload
; SMALL-NEXT: addi.d $sp, $sp, 16
; SMALL-NEXT: b %plt(callee_tail)
;
; MEDIUM-LABEL: caller_call_tail:
; MEDIUM: # %bb.0: # %entry
; MEDIUM-NEXT: addi.d $sp, $sp, -16
; MEDIUM-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill
; MEDIUM-NEXT: st.d $fp, $sp, 0 # 8-byte Folded Spill
; MEDIUM-NEXT: move $fp, $a0
; MEDIUM-NEXT: pcaddu18i $ra, %call36(callee_tail)
; MEDIUM-NEXT: jirl $ra, $ra, 0
; MEDIUM-NEXT: move $a0, $fp
; MEDIUM-NEXT: ld.d $fp, $sp, 0 # 8-byte Folded Reload
; MEDIUM-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload
; MEDIUM-NEXT: addi.d $sp, $sp, 16
; MEDIUM-NEXT: pcaddu18i $t8, %call36(callee_tail)
; MEDIUM-NEXT: jr $t8
;
; LARGE-LABEL: caller_call_tail:
; LARGE: # %bb.0: # %entry
; LARGE-NEXT: addi.d $sp, $sp, -16
; LARGE-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill
; LARGE-NEXT: st.d $fp, $sp, 0 # 8-byte Folded Spill
; LARGE-NEXT: move $fp, $a0
; LARGE-NEXT: pcalau12i $a1, %got_pc_hi20(callee_tail)
; LARGE-NEXT: addi.d $ra, $zero, %got_pc_lo12(callee_tail)
; LARGE-NEXT: lu32i.d $ra, %got64_pc_lo20(callee_tail)
; LARGE-NEXT: lu52i.d $ra, $ra, %got64_pc_hi12(callee_tail)
; LARGE-NEXT: ldx.d $ra, $ra, $a1
; LARGE-NEXT: jirl $ra, $ra, 0
; LARGE-NEXT: move $a0, $fp
; LARGE-NEXT: pcalau12i $a1, %got_pc_hi20(callee_tail)
; LARGE-NEXT: addi.d $a2, $zero, %got_pc_lo12(callee_tail)
; LARGE-NEXT: lu32i.d $a2, %got64_pc_lo20(callee_tail)
; LARGE-NEXT: lu52i.d $a2, $a2, %got64_pc_hi12(callee_tail)
; LARGE-NEXT: ldx.d $a1, $a2, $a1
; LARGE-NEXT: ld.d $fp, $sp, 0 # 8-byte Folded Reload
; LARGE-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload
; LARGE-NEXT: addi.d $sp, $sp, 16
; LARGE-NEXT: jr $a1
entry:
call i32 @callee_tail(i32 %i)
%r = tail call i32 @callee_tail(i32 %i)
ret i32 %r
}
Loading