diff --git a/lib/Target/ARM/ARMISelLowering.cpp b/lib/Target/ARM/ARMISelLowering.cpp index cb3d923351f..50ac5e9c69d 100644 --- a/lib/Target/ARM/ARMISelLowering.cpp +++ b/lib/Target/ARM/ARMISelLowering.cpp @@ -555,10 +555,10 @@ SDOperand ARMTargetLowering::LowerCALL(SDOperand Op, SelectionDAG &DAG) { CallOpc = (isDirect || Subtarget->hasV5TOps()) ? ARMISD::CALL : ARMISD::CALL_NOLINK; } - if (CallOpc == ARMISD::CALL_NOLINK) { - // On CALL_NOLINK we must move PC to LR + if (CallOpc == ARMISD::CALL_NOLINK && !Subtarget->isThumb()) { + // implicit def LR - LR mustn't be allocated as GRP:$dst of CALL_NOLINK Chain = DAG.getCopyToReg(Chain, ARM::LR, - DAG.getRegister(ARM::PC, MVT::i32), InFlag); + DAG.getNode(ISD::UNDEF, MVT::i32), InFlag); InFlag = Chain.getValue(1); } diff --git a/lib/Target/ARM/ARMInstrInfo.td b/lib/Target/ARM/ARMInstrInfo.td index 201f65c7f5a..36d2e4a0460 100644 --- a/lib/Target/ARM/ARMInstrInfo.td +++ b/lib/Target/ARM/ARMInstrInfo.td @@ -370,6 +370,8 @@ class AI3 pattern> : I; class AI4 pattern> : I; +class AIx2 pattern> + : I; class AI1x2 pattern> : I; @@ -546,9 +548,9 @@ let isCall = 1, noResults = 1, [(ARMcall GPR:$dst)]>, Requires<[IsARM, HasV5T]>; let Uses = [LR] in { // ARMv4T - def BX : AI<(ops GPR:$dst, variable_ops), - "bx $dst", - [(ARMcall_nolink GPR:$dst)]>; + def BX : AIx2<(ops GPR:$dst, variable_ops), + "mov lr, pc\n\tbx $dst", + [(ARMcall_nolink GPR:$dst)]>; } } diff --git a/lib/Target/ARM/ARMInstrThumb.td b/lib/Target/ARM/ARMInstrThumb.td index a1f03bd1726..3c7cd03ee75 100644 --- a/lib/Target/ARM/ARMInstrThumb.td +++ b/lib/Target/ARM/ARMInstrThumb.td @@ -189,12 +189,10 @@ let isCall = 1, noResults = 1, def tBLXr : TI<(ops GPR:$dst, variable_ops), "blx $dst", [(ARMtcall GPR:$dst)]>, Requires<[HasV5T]>; - let Uses = [LR] in { - // ARMv4T - def tBX : TI<(ops GPR:$dst, variable_ops), - "bx $dst", + // ARMv4T + def tBX : TIx2<(ops GPR:$dst, variable_ops), + "cpy lr, pc\n\tbx $dst", [(ARMcall_nolink GPR:$dst)]>; - } } let isBranch = 1, isTerminator = 1, isBarrier = 1 in {