Deduplicate ARM call-related instructions.

We had special instructions for iOS because r9 is call-clobbered, but
that is represented dynamically by the register mask operands now, so
there is no need for the pseudo-instructions.

llvm-svn: 154144
This commit is contained in:
Jakob Stoklund Olesen 2012-04-06 00:04:58 +00:00
parent d181730aa5
commit 6a2e99a46a
6 changed files with 24 additions and 145 deletions

View File

@ -1266,7 +1266,6 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) {
}
// Darwin call instructions are just normal call instructions with different
// clobber semantics (they clobber R9).
case ARM::BXr9_CALL:
case ARM::BX_CALL: {
{
MCInst TmpInst;
@ -1288,7 +1287,6 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) {
}
return;
}
case ARM::tBXr9_CALL:
case ARM::tBX_CALL: {
{
MCInst TmpInst;
@ -1311,7 +1309,6 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) {
}
return;
}
case ARM::BMOVPCRXr9_CALL:
case ARM::BMOVPCRX_CALL: {
{
MCInst TmpInst;
@ -1339,7 +1336,6 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) {
}
return;
}
case ARM::BMOVPCBr9_CALL:
case ARM::BMOVPCB_CALL: {
{
MCInst TmpInst;
@ -1367,7 +1363,6 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) {
}
return;
}
case ARM::t2BMOVPCBr9_CALL:
case ARM::t2BMOVPCB_CALL: {
{
MCInst TmpInst;

View File

@ -836,9 +836,7 @@ void ARMCodeEmitter::emitPseudoInstruction(const MachineInstr &MI) {
default:
llvm_unreachable("ARMCodeEmitter::emitPseudoInstruction");
case ARM::BX_CALL:
case ARM::BMOVPCRX_CALL:
case ARM::BXr9_CALL:
case ARM::BMOVPCRXr9_CALL: {
case ARM::BMOVPCRX_CALL: {
// First emit mov lr, pc
unsigned Binary = 0x01a0e00f;
Binary |= II->getPredicate(&MI) << ARMII::CondShift;

View File

@ -2111,13 +2111,10 @@ bool ARMFastISel::SelectRet(const Instruction *I) {
}
unsigned ARMFastISel::ARMSelectCallOp(const GlobalValue *GV) {
// iOS needs the r9 versions of the opcodes.
bool isiOS = Subtarget->isTargetIOS();
if (isThumb2) {
return isiOS ? ARM::tBLr9 : ARM::tBL;
return ARM::tBL;
} else {
return isiOS ? ARM::BLr9 : ARM::BL;
return ARM::BL;
}
}
@ -2176,8 +2173,7 @@ bool ARMFastISel::ARMEmitLibcall(const Instruction *I, RTLIB::Libcall Call) {
if (!ProcessCallArgs(Args, ArgRegs, ArgVTs, ArgFlags, RegArgs, CC, NumBytes))
return false;
// Issue the call, BLr9 for iOS, BL otherwise.
// TODO: Turn this into the table of arm call ops.
// Issue the call.
MachineInstrBuilder MIB;
unsigned CallOpc = ARMSelectCallOp(NULL);
if (isThumb2)
@ -2302,8 +2298,7 @@ bool ARMFastISel::SelectCall(const Instruction *I,
if (!ProcessCallArgs(Args, ArgRegs, ArgVTs, ArgFlags, RegArgs, CC, NumBytes))
return false;
// Issue the call, BLr9 for iOS, BL otherwise.
// TODO: Turn this into the table of arm call ops.
// Issue the call.
MachineInstrBuilder MIB;
unsigned CallOpc = ARMSelectCallOp(GV);
// Explicitly adding the predicate here.

View File

@ -1908,7 +1908,7 @@ let isCall = 1,
def BL : ABXI<0b1011, (outs), (ins bl_target:$func, variable_ops),
IIC_Br, "bl\t$func",
[(ARMcall tglobaladdr:$func)]>,
Requires<[IsARM, IsNotIOS]> {
Requires<[IsARM]> {
let Inst{31-28} = 0b1110;
bits<24> func;
let Inst{23-0} = func;
@ -1918,7 +1918,7 @@ let isCall = 1,
def BL_pred : ABI<0b1011, (outs), (ins bl_target:$func, variable_ops),
IIC_Br, "bl", "\t$func",
[(ARMcall_pred tglobaladdr:$func)]>,
Requires<[IsARM, IsNotIOS]> {
Requires<[IsARM]> {
bits<24> func;
let Inst{23-0} = func;
let DecoderMethod = "DecodeBranchImmInstruction";
@ -1928,7 +1928,7 @@ let isCall = 1,
def BLX : AXI<(outs), (ins GPR:$func, variable_ops), BrMiscFrm,
IIC_Br, "blx\t$func",
[(ARMcall GPR:$func)]>,
Requires<[IsARM, HasV5T, IsNotIOS]> {
Requires<[IsARM, HasV5T]> {
bits<4> func;
let Inst{31-4} = 0b1110000100101111111111110011;
let Inst{3-0} = func;
@ -1937,7 +1937,7 @@ let isCall = 1,
def BLX_pred : AI<(outs), (ins GPR:$func, variable_ops), BrMiscFrm,
IIC_Br, "blx", "\t$func",
[(ARMcall_pred GPR:$func)]>,
Requires<[IsARM, HasV5T, IsNotIOS]> {
Requires<[IsARM, HasV5T]> {
bits<4> func;
let Inst{27-4} = 0b000100101111111111110011;
let Inst{3-0} = func;
@ -1947,67 +1947,19 @@ let isCall = 1,
// Note: Restrict $func to the tGPR regclass to prevent it being in LR.
def BX_CALL : ARMPseudoInst<(outs), (ins tGPR:$func, variable_ops),
8, IIC_Br, [(ARMcall_nolink tGPR:$func)]>,
Requires<[IsARM, HasV4T, IsNotIOS]>;
Requires<[IsARM, HasV4T]>;
// ARMv4
def BMOVPCRX_CALL : ARMPseudoInst<(outs), (ins tGPR:$func, variable_ops),
8, IIC_Br, [(ARMcall_nolink tGPR:$func)]>,
Requires<[IsARM, NoV4T, IsNotIOS]>;
Requires<[IsARM, NoV4T]>;
// mov lr, pc; b if callee is marked noreturn to avoid confusing the
// return stack predictor.
def BMOVPCB_CALL : ARMPseudoInst<(outs),
(ins bl_target:$func, variable_ops),
8, IIC_Br, [(ARMcall_nolink tglobaladdr:$func)]>,
Requires<[IsARM, IsNotIOS]>;
}
let isCall = 1,
// On IOS R9 is call-clobbered.
// R7 is marked as a use to prevent frame-pointer assignments from being
// moved above / below calls.
Defs = [LR], Uses = [R7, SP] in {
def BLr9 : ARMPseudoExpand<(outs), (ins bl_target:$func, variable_ops),
4, IIC_Br,
[(ARMcall tglobaladdr:$func)], (BL bl_target:$func)>,
Requires<[IsARM, IsIOS]>;
def BLr9_pred : ARMPseudoExpand<(outs),
(ins bl_target:$func, pred:$p, variable_ops),
4, IIC_Br,
[(ARMcall_pred tglobaladdr:$func)],
(BL_pred bl_target:$func, pred:$p)>,
Requires<[IsARM, IsIOS]>;
// ARMv5T and above
def BLXr9 : ARMPseudoExpand<(outs), (ins GPR:$func, variable_ops),
4, IIC_Br,
[(ARMcall GPR:$func)],
(BLX GPR:$func)>,
Requires<[IsARM, HasV5T, IsIOS]>;
def BLXr9_pred: ARMPseudoExpand<(outs), (ins GPR:$func, pred:$p,variable_ops),
4, IIC_Br,
[(ARMcall_pred GPR:$func)],
(BLX_pred GPR:$func, pred:$p)>,
Requires<[IsARM, HasV5T, IsIOS]>;
// ARMv4T
// Note: Restrict $func to the tGPR regclass to prevent it being in LR.
def BXr9_CALL : ARMPseudoInst<(outs), (ins tGPR:$func, variable_ops),
8, IIC_Br, [(ARMcall_nolink tGPR:$func)]>,
Requires<[IsARM, HasV4T, IsIOS]>;
// ARMv4
def BMOVPCRXr9_CALL : ARMPseudoInst<(outs), (ins tGPR:$func, variable_ops),
8, IIC_Br, [(ARMcall_nolink tGPR:$func)]>,
Requires<[IsARM, NoV4T, IsIOS]>;
// mov lr, pc; b if callee is marked noreturn to avoid confusing the
// return stack predictor.
def BMOVPCBr9_CALL : ARMPseudoInst<(outs),(ins bl_target:$func, variable_ops),
8, IIC_Br, [(ARMcall_nolink tglobaladdr:$func)]>,
Requires<[IsARM, IsIOS]>;
Requires<[IsARM]>;
}
let isBranch = 1, isTerminator = 1 in {
@ -4898,15 +4850,9 @@ def : ARMPat<(ARMtcret (i32 texternalsym:$dst)),
// Direct calls
def : ARMPat<(ARMcall texternalsym:$func), (BL texternalsym:$func)>,
Requires<[IsARM, IsNotIOS]>;
def : ARMPat<(ARMcall texternalsym:$func), (BLr9 texternalsym:$func)>,
Requires<[IsARM, IsIOS]>;
Requires<[IsARM]>;
def : ARMPat<(ARMcall_nolink texternalsym:$func),
(BMOVPCB_CALL texternalsym:$func)>,
Requires<[IsARM, IsNotIOS]>;
def : ARMPat<(ARMcall_nolink texternalsym:$func),
(BMOVPCBr9_CALL texternalsym:$func)>,
Requires<[IsARM, IsIOS]>;
(BMOVPCB_CALL texternalsym:$func)>, Requires<[IsARM]>;
// zextload i1 -> zextload i8
def : ARMPat<(zextloadi1 addrmode_imm12:$addr), (LDRBi12 addrmode_imm12:$addr)>;

View File

@ -416,14 +416,13 @@ let isReturn = 1, isTerminator = 1, isBarrier = 1 in {
// prevent stack-pointer assignments that appear immediately before calls from
// potentially appearing dead.
let isCall = 1,
// On non-IOS platforms R9 is callee-saved.
Defs = [LR], Uses = [SP] in {
// Also used for Thumb2
def tBL : TIx2<0b11110, 0b11, 1,
(outs), (ins pred:$p, t_bltarget:$func, variable_ops), IIC_Br,
"bl${p}\t$func",
[(ARMtcall tglobaladdr:$func)]>,
Requires<[IsThumb, IsNotIOS]> {
Requires<[IsThumb]> {
bits<22> func;
let Inst{26} = func{21};
let Inst{25-16} = func{20-11};
@ -437,7 +436,7 @@ let isCall = 1,
(outs), (ins pred:$p, t_blxtarget:$func, variable_ops), IIC_Br,
"blx${p}\t$func",
[(ARMcall tglobaladdr:$func)]>,
Requires<[IsThumb, HasV5T, IsNotIOS]> {
Requires<[IsThumb, HasV5T]> {
bits<21> func;
let Inst{25-16} = func{20-11};
let Inst{13} = 1;
@ -450,7 +449,7 @@ let isCall = 1,
def tBLXr : TI<(outs), (ins pred:$p, GPR:$func, variable_ops), IIC_Br,
"blx${p}\t$func",
[(ARMtcall GPR:$func)]>,
Requires<[IsThumb, HasV5T, IsNotIOS]>,
Requires<[IsThumb, HasV5T]>,
T1Special<{1,1,1,?}> { // A6.2.3 & A8.6.24;
bits<4> func;
let Inst{6-3} = func;
@ -461,37 +460,7 @@ let isCall = 1,
def tBX_CALL : tPseudoInst<(outs), (ins tGPR:$func, variable_ops),
4, IIC_Br,
[(ARMcall_nolink tGPR:$func)]>,
Requires<[IsThumb, IsThumb1Only, IsNotIOS]>;
}
let isCall = 1,
// On IOS R9 is call-clobbered.
// R7 is marked as a use to prevent frame-pointer assignments from being
// moved above / below calls.
Defs = [LR], Uses = [R7, SP] in {
// Also used for Thumb2
def tBLr9 : tPseudoExpand<(outs), (ins pred:$p, t_bltarget:$func, variable_ops),
4, IIC_Br, [(ARMtcall tglobaladdr:$func)],
(tBL pred:$p, t_bltarget:$func)>,
Requires<[IsThumb, IsIOS]>;
// ARMv5T and above, also used for Thumb2
def tBLXi_r9 : tPseudoExpand<(outs), (ins pred:$p, t_blxtarget:$func, variable_ops),
4, IIC_Br, [(ARMcall tglobaladdr:$func)],
(tBLXi pred:$p, t_blxtarget:$func)>,
Requires<[IsThumb, HasV5T, IsIOS]>;
// Also used for Thumb2
def tBLXr_r9 : tPseudoExpand<(outs), (ins pred:$p, GPR:$func, variable_ops),
2, IIC_Br, [(ARMtcall GPR:$func)],
(tBLXr pred:$p, GPR:$func)>,
Requires<[IsThumb, HasV5T, IsIOS]>;
// ARMv4T
def tBXr9_CALL : tPseudoInst<(outs), (ins tGPR:$func, variable_ops),
4, IIC_Br,
[(ARMcall_nolink tGPR:$func)]>,
Requires<[IsThumb, IsThumb1Only, IsIOS]>;
Requires<[IsThumb, IsThumb1Only]>;
}
let isBranch = 1, isTerminator = 1, isBarrier = 1 in {
@ -1318,20 +1287,14 @@ def : T1Pat<(ARMWrapperJT tjumptable:$dst, imm:$id),
// Direct calls
def : T1Pat<(ARMtcall texternalsym:$func), (tBL texternalsym:$func)>,
Requires<[IsThumb, IsNotIOS]>;
def : T1Pat<(ARMtcall texternalsym:$func), (tBLr9 texternalsym:$func)>,
Requires<[IsThumb, IsIOS]>;
Requires<[IsThumb]>;
def : Tv5Pat<(ARMcall texternalsym:$func), (tBLXi texternalsym:$func)>,
Requires<[IsThumb, HasV5T, IsNotIOS]>;
def : Tv5Pat<(ARMcall texternalsym:$func), (tBLXi_r9 texternalsym:$func)>,
Requires<[IsThumb, HasV5T, IsIOS]>;
Requires<[IsThumb, HasV5T]>;
// Indirect calls to ARM routines
def : Tv5Pat<(ARMcall GPR:$dst), (tBLXr GPR:$dst)>,
Requires<[IsThumb, HasV5T, IsNotIOS]>;
def : Tv5Pat<(ARMcall GPR:$dst), (tBLXr_r9 GPR:$dst)>,
Requires<[IsThumb, HasV5T, IsIOS]>;
Requires<[IsThumb, HasV5T]>;
// zextload i1 -> zextload i8
def : T1Pat<(zextloadi1 t_addrmode_rrs1:$addr),

View File

@ -3276,37 +3276,19 @@ let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1 in {
Requires<[IsThumb2, IsIOS]>;
}
let isCall = 1,
// On non-IOS platforms R9 is callee-saved.
Defs = [LR], Uses = [SP] in {
let isCall = 1, Defs = [LR], Uses = [SP] in {
// mov lr, pc; b if callee is marked noreturn to avoid confusing the
// return stack predictor.
def t2BMOVPCB_CALL : tPseudoInst<(outs),
(ins t_bltarget:$func, variable_ops),
6, IIC_Br, [(ARMcall_nolink tglobaladdr:$func)]>,
Requires<[IsThumb, IsNotIOS]>;
}
let isCall = 1,
// On IOS R9 is call-clobbered.
// R7 is marked as a use to prevent frame-pointer assignments from being
// moved above / below calls.
Defs = [LR], Uses = [R7, SP] in {
// mov lr, pc; b if callee is marked noreturn to avoid confusing the
// return stack predictor.
def t2BMOVPCBr9_CALL : tPseudoInst<(outs),
(ins t_bltarget:$func, variable_ops),
6, IIC_Br, [(ARMcall_nolink tglobaladdr:$func)]>,
Requires<[IsThumb, IsIOS]>;
Requires<[IsThumb]>;
}
// Direct calls
def : T2Pat<(ARMcall_nolink texternalsym:$func),
(t2BMOVPCB_CALL texternalsym:$func)>,
Requires<[IsThumb, IsNotIOS]>;
def : T2Pat<(ARMcall_nolink texternalsym:$func),
(t2BMOVPCBr9_CALL texternalsym:$func)>,
Requires<[IsThumb, IsIOS]>;
Requires<[IsThumb]>;
// IT block
let Defs = [ITSTATE] in