mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-09-09 10:30:47 +00:00
Clean up ARM tail calls a bit. They're pseudo-instructions for normal branches.
Also more cleanly separate the ARM vs. Thumb functionality. Previously, the encoding would be incorrect for some Thumb instructions (the indirect calls). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@127637 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -1707,6 +1707,49 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) {
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// Tail jump branches are really just branch instructions with additional
|
||||||
|
// code-gen attributes. Convert them to the cannonical form here.
|
||||||
|
case ARM::TAILJMPd:
|
||||||
|
case ARM::TAILJMPdND: {
|
||||||
|
MCInst TmpInst, TmpInst2;
|
||||||
|
// Lower the instruction as-is to get the operands properly converted.
|
||||||
|
LowerARMMachineInstrToMCInst(MI, TmpInst2, *this);
|
||||||
|
TmpInst.setOpcode(ARM::Bcc);
|
||||||
|
TmpInst.addOperand(TmpInst2.getOperand(0));
|
||||||
|
// Add predicate operands.
|
||||||
|
TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
|
||||||
|
TmpInst.addOperand(MCOperand::CreateReg(0));
|
||||||
|
OutStreamer.AddComment("TAILCALL");
|
||||||
|
OutStreamer.EmitInstruction(TmpInst);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case ARM::tTAILJMPd:
|
||||||
|
case ARM::tTAILJMPdND: {
|
||||||
|
MCInst TmpInst, TmpInst2;
|
||||||
|
LowerARMMachineInstrToMCInst(MI, TmpInst2, *this);
|
||||||
|
TmpInst.setOpcode(ARM::tB);
|
||||||
|
TmpInst.addOperand(TmpInst2.getOperand(0));
|
||||||
|
OutStreamer.AddComment("TAILCALL");
|
||||||
|
OutStreamer.EmitInstruction(TmpInst);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case ARM::TAILJMPrND:
|
||||||
|
case ARM::tTAILJMPrND:
|
||||||
|
case ARM::TAILJMPr:
|
||||||
|
case ARM::tTAILJMPr: {
|
||||||
|
unsigned newOpc = (Opc == ARM::TAILJMPr || Opc == ARM::TAILJMPrND)
|
||||||
|
? ARM::BX : ARM::tBX;
|
||||||
|
MCInst TmpInst;
|
||||||
|
TmpInst.setOpcode(newOpc);
|
||||||
|
TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg()));
|
||||||
|
// Predicate.
|
||||||
|
TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
|
||||||
|
TmpInst.addOperand(MCOperand::CreateReg(0));
|
||||||
|
OutStreamer.AddComment("TAILCALL");
|
||||||
|
OutStreamer.EmitInstruction(TmpInst);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// These are the pseudos created to comply with stricter operand restrictions
|
// These are the pseudos created to comply with stricter operand restrictions
|
||||||
// on ARMv5. Lower them now to "normal" instructions, since all the
|
// on ARMv5. Lower them now to "normal" instructions, since all the
|
||||||
// restrictions are already satisfied.
|
// restrictions are already satisfied.
|
||||||
|
@@ -400,8 +400,8 @@ void ARMFrameLowering::emitEpilogue(MachineFunction &MF,
|
|||||||
// Jump to label or value in register.
|
// Jump to label or value in register.
|
||||||
if (RetOpcode == ARM::TCRETURNdi || RetOpcode == ARM::TCRETURNdiND) {
|
if (RetOpcode == ARM::TCRETURNdi || RetOpcode == ARM::TCRETURNdiND) {
|
||||||
unsigned TCOpcode = (RetOpcode == ARM::TCRETURNdi)
|
unsigned TCOpcode = (RetOpcode == ARM::TCRETURNdi)
|
||||||
? (STI.isThumb() ? ARM::TAILJMPdt : ARM::TAILJMPd)
|
? (STI.isThumb() ? ARM::tTAILJMPd : ARM::TAILJMPd)
|
||||||
: (STI.isThumb() ? ARM::TAILJMPdNDt : ARM::TAILJMPdND);
|
: (STI.isThumb() ? ARM::tTAILJMPdND : ARM::TAILJMPdND);
|
||||||
MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII.get(TCOpcode));
|
MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII.get(TCOpcode));
|
||||||
if (JumpTarget.isGlobal())
|
if (JumpTarget.isGlobal())
|
||||||
MIB.addGlobalAddress(JumpTarget.getGlobal(), JumpTarget.getOffset(),
|
MIB.addGlobalAddress(JumpTarget.getGlobal(), JumpTarget.getOffset(),
|
||||||
@@ -412,10 +412,12 @@ void ARMFrameLowering::emitEpilogue(MachineFunction &MF,
|
|||||||
JumpTarget.getTargetFlags());
|
JumpTarget.getTargetFlags());
|
||||||
}
|
}
|
||||||
} else if (RetOpcode == ARM::TCRETURNri) {
|
} else if (RetOpcode == ARM::TCRETURNri) {
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(ARM::TAILJMPr)).
|
BuildMI(MBB, MBBI, dl,
|
||||||
|
TII.get(STI.isThumb() ? ARM::tTAILJMPr : ARM::TAILJMPr)).
|
||||||
addReg(JumpTarget.getReg(), RegState::Kill);
|
addReg(JumpTarget.getReg(), RegState::Kill);
|
||||||
} else if (RetOpcode == ARM::TCRETURNriND) {
|
} else if (RetOpcode == ARM::TCRETURNriND) {
|
||||||
BuildMI(MBB, MBBI, dl, TII.get(ARM::TAILJMPrND)).
|
BuildMI(MBB, MBBI, dl,
|
||||||
|
TII.get(STI.isThumb() ? ARM::tTAILJMPrND : ARM::TAILJMPrND)).
|
||||||
addReg(JumpTarget.getReg(), RegState::Kill);
|
addReg(JumpTarget.getReg(), RegState::Kill);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1408,11 +1408,7 @@ let isCall = 1,
|
|||||||
|
|
||||||
// Tail calls.
|
// Tail calls.
|
||||||
|
|
||||||
// FIXME: These should probably be xformed into the non-TC versions of the
|
// FIXME: The Thumb versions of these should live in ARMInstrThumb.td
|
||||||
// instructions as part of MC lowering.
|
|
||||||
// FIXME: These seem to be used for both Thumb and ARM instruction selection.
|
|
||||||
// Thumb should have its own version since the instruction is actually
|
|
||||||
// different, even though the mnemonic is the same.
|
|
||||||
let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1 in {
|
let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1 in {
|
||||||
// Darwin versions.
|
// Darwin versions.
|
||||||
let Defs = [R0, R1, R2, R3, R9, R12,
|
let Defs = [R0, R1, R2, R3, R9, R12,
|
||||||
@@ -1426,21 +1422,21 @@ let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1 in {
|
|||||||
def TCRETURNri : PseudoInst<(outs), (ins tcGPR:$dst, variable_ops),
|
def TCRETURNri : PseudoInst<(outs), (ins tcGPR:$dst, variable_ops),
|
||||||
IIC_Br, []>, Requires<[IsDarwin]>;
|
IIC_Br, []>, Requires<[IsDarwin]>;
|
||||||
|
|
||||||
def TAILJMPd : ABXI<0b1010, (outs), (ins brtarget:$dst, variable_ops),
|
def TAILJMPd : ARMPseudoInst<(outs), (ins brtarget:$dst, variable_ops),
|
||||||
IIC_Br, "b\t$dst @ TAILCALL",
|
Size4Bytes, IIC_Br,
|
||||||
[]>, Requires<[IsARM, IsDarwin]>;
|
[]>, Requires<[IsARM, IsDarwin]>;
|
||||||
|
|
||||||
def TAILJMPdt: ABXI<0b1010, (outs), (ins brtarget:$dst, variable_ops),
|
def tTAILJMPd: tPseudoInst<(outs), (ins brtarget:$dst, variable_ops),
|
||||||
IIC_Br, "b.w\t$dst @ TAILCALL",
|
Size4Bytes, IIC_Br,
|
||||||
[]>, Requires<[IsThumb, IsDarwin]>;
|
[]>, Requires<[IsThumb, IsDarwin]>;
|
||||||
|
|
||||||
def TAILJMPr : AXI<(outs), (ins tcGPR:$dst, variable_ops),
|
def TAILJMPr : ARMPseudoInst<(outs), (ins tcGPR:$dst, variable_ops),
|
||||||
BrMiscFrm, IIC_Br, "bx\t$dst @ TAILCALL",
|
Size4Bytes, IIC_Br,
|
||||||
[]>, Requires<[IsDarwin]> {
|
[]>, Requires<[IsARM, IsDarwin]>;
|
||||||
bits<4> dst;
|
|
||||||
let Inst{31-4} = 0b1110000100101111111111110001;
|
def tTAILJMPr : tPseudoInst<(outs), (ins tcGPR:$dst, variable_ops),
|
||||||
let Inst{3-0} = dst;
|
Size4Bytes, IIC_Br,
|
||||||
}
|
[]>, Requires<[IsThumb, IsDarwin]>;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Non-Darwin versions (the difference is R9).
|
// Non-Darwin versions (the difference is R9).
|
||||||
@@ -1455,21 +1451,20 @@ let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1 in {
|
|||||||
def TCRETURNriND : PseudoInst<(outs), (ins tcGPR:$dst, variable_ops),
|
def TCRETURNriND : PseudoInst<(outs), (ins tcGPR:$dst, variable_ops),
|
||||||
IIC_Br, []>, Requires<[IsNotDarwin]>;
|
IIC_Br, []>, Requires<[IsNotDarwin]>;
|
||||||
|
|
||||||
def TAILJMPdND : ABXI<0b1010, (outs), (ins brtarget:$dst, variable_ops),
|
def TAILJMPdND : ARMPseudoInst<(outs), (ins brtarget:$dst, variable_ops),
|
||||||
IIC_Br, "b\t$dst @ TAILCALL",
|
Size4Bytes, IIC_Br,
|
||||||
[]>, Requires<[IsARM, IsNotDarwin]>;
|
[]>, Requires<[IsARM, IsNotDarwin]>;
|
||||||
|
|
||||||
def TAILJMPdNDt : ABXI<0b1010, (outs), (ins brtarget:$dst, variable_ops),
|
def tTAILJMPdND : tPseudoInst<(outs), (ins brtarget:$dst, variable_ops),
|
||||||
IIC_Br, "b.w\t$dst @ TAILCALL",
|
Size4Bytes, IIC_Br,
|
||||||
[]>, Requires<[IsThumb, IsNotDarwin]>;
|
[]>, Requires<[IsThumb, IsNotDarwin]>;
|
||||||
|
|
||||||
def TAILJMPrND : AXI<(outs), (ins tcGPR:$dst, variable_ops),
|
def TAILJMPrND : ARMPseudoInst<(outs), (ins tcGPR:$dst, variable_ops),
|
||||||
BrMiscFrm, IIC_Br, "bx\t$dst @ TAILCALL",
|
Size4Bytes, IIC_Br,
|
||||||
[]>, Requires<[IsNotDarwin]> {
|
[]>, Requires<[IsARM, IsNotDarwin]>;
|
||||||
bits<4> dst;
|
def tTAILJMPrND : tPseudoInst<(outs), (ins tcGPR:$dst, variable_ops),
|
||||||
let Inst{31-4} = 0b1110000100101111111111110001;
|
Size4Bytes, IIC_Br,
|
||||||
let Inst{3-0} = dst;
|
[]>, Requires<[IsThumb, IsNotDarwin]>;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -74,7 +74,7 @@ entry:
|
|||||||
; CHECKT2: t7:
|
; CHECKT2: t7:
|
||||||
; CHECKT2: blxeq _foo
|
; CHECKT2: blxeq _foo
|
||||||
; CHECKT2-NEXT: pop.w
|
; CHECKT2-NEXT: pop.w
|
||||||
; CHECKT2-NEXT: b.w _foo
|
; CHECKT2-NEXT: b _foo
|
||||||
br i1 undef, label %bb, label %bb1.lr.ph
|
br i1 undef, label %bb, label %bb1.lr.ph
|
||||||
|
|
||||||
bb1.lr.ph:
|
bb1.lr.ph:
|
||||||
|
Reference in New Issue
Block a user