forked from OSchip/llvm-project
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:
parent
d181730aa5
commit
6a2e99a46a
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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)>;
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue