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).

llvm-svn: 127637
This commit is contained in:
Jim Grosbach 2011-03-15 00:30:40 +00:00
parent 2139d3148f
commit 3af6fe66b9
4 changed files with 72 additions and 32 deletions

View File

@ -1707,6 +1707,49 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) {
}
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
// on ARMv5. Lower them now to "normal" instructions, since all the
// restrictions are already satisfied.

View File

@ -400,8 +400,8 @@ void ARMFrameLowering::emitEpilogue(MachineFunction &MF,
// Jump to label or value in register.
if (RetOpcode == ARM::TCRETURNdi || RetOpcode == ARM::TCRETURNdiND) {
unsigned TCOpcode = (RetOpcode == ARM::TCRETURNdi)
? (STI.isThumb() ? ARM::TAILJMPdt : ARM::TAILJMPd)
: (STI.isThumb() ? ARM::TAILJMPdNDt : ARM::TAILJMPdND);
? (STI.isThumb() ? ARM::tTAILJMPd : ARM::TAILJMPd)
: (STI.isThumb() ? ARM::tTAILJMPdND : ARM::TAILJMPdND);
MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII.get(TCOpcode));
if (JumpTarget.isGlobal())
MIB.addGlobalAddress(JumpTarget.getGlobal(), JumpTarget.getOffset(),
@ -412,10 +412,12 @@ void ARMFrameLowering::emitEpilogue(MachineFunction &MF,
JumpTarget.getTargetFlags());
}
} 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);
} 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);
}

View File

@ -1408,11 +1408,7 @@ let isCall = 1,
// Tail calls.
// FIXME: These should probably be xformed into the non-TC versions of the
// 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.
// FIXME: The Thumb versions of these should live in ARMInstrThumb.td
let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1 in {
// Darwin versions.
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),
IIC_Br, []>, Requires<[IsDarwin]>;
def TAILJMPd : ABXI<0b1010, (outs), (ins brtarget:$dst, variable_ops),
IIC_Br, "b\t$dst @ TAILCALL",
def TAILJMPd : ARMPseudoInst<(outs), (ins brtarget:$dst, variable_ops),
Size4Bytes, IIC_Br,
[]>, Requires<[IsARM, IsDarwin]>;
def TAILJMPdt: ABXI<0b1010, (outs), (ins brtarget:$dst, variable_ops),
IIC_Br, "b.w\t$dst @ TAILCALL",
def tTAILJMPd: tPseudoInst<(outs), (ins brtarget:$dst, variable_ops),
Size4Bytes, IIC_Br,
[]>, Requires<[IsThumb, IsDarwin]>;
def TAILJMPr : AXI<(outs), (ins tcGPR:$dst, variable_ops),
BrMiscFrm, IIC_Br, "bx\t$dst @ TAILCALL",
[]>, Requires<[IsDarwin]> {
bits<4> dst;
let Inst{31-4} = 0b1110000100101111111111110001;
let Inst{3-0} = dst;
}
def TAILJMPr : ARMPseudoInst<(outs), (ins tcGPR:$dst, variable_ops),
Size4Bytes, IIC_Br,
[]>, Requires<[IsARM, IsDarwin]>;
def tTAILJMPr : tPseudoInst<(outs), (ins tcGPR:$dst, variable_ops),
Size4Bytes, IIC_Br,
[]>, Requires<[IsThumb, IsDarwin]>;
}
// 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),
IIC_Br, []>, Requires<[IsNotDarwin]>;
def TAILJMPdND : ABXI<0b1010, (outs), (ins brtarget:$dst, variable_ops),
IIC_Br, "b\t$dst @ TAILCALL",
def TAILJMPdND : ARMPseudoInst<(outs), (ins brtarget:$dst, variable_ops),
Size4Bytes, IIC_Br,
[]>, Requires<[IsARM, IsNotDarwin]>;
def TAILJMPdNDt : ABXI<0b1010, (outs), (ins brtarget:$dst, variable_ops),
IIC_Br, "b.w\t$dst @ TAILCALL",
def tTAILJMPdND : tPseudoInst<(outs), (ins brtarget:$dst, variable_ops),
Size4Bytes, IIC_Br,
[]>, Requires<[IsThumb, IsNotDarwin]>;
def TAILJMPrND : AXI<(outs), (ins tcGPR:$dst, variable_ops),
BrMiscFrm, IIC_Br, "bx\t$dst @ TAILCALL",
[]>, Requires<[IsNotDarwin]> {
bits<4> dst;
let Inst{31-4} = 0b1110000100101111111111110001;
let Inst{3-0} = dst;
}
def TAILJMPrND : ARMPseudoInst<(outs), (ins tcGPR:$dst, variable_ops),
Size4Bytes, IIC_Br,
[]>, Requires<[IsARM, IsNotDarwin]>;
def tTAILJMPrND : tPseudoInst<(outs), (ins tcGPR:$dst, variable_ops),
Size4Bytes, IIC_Br,
[]>, Requires<[IsThumb, IsNotDarwin]>;
}
}

View File

@ -74,7 +74,7 @@ entry:
; CHECKT2: t7:
; CHECKT2: blxeq _foo
; CHECKT2-NEXT: pop.w
; CHECKT2-NEXT: b.w _foo
; CHECKT2-NEXT: b _foo
br i1 undef, label %bb, label %bb1.lr.ph
bb1.lr.ph: