diff --git a/lib/Target/ARM/ARMBaseInstrInfo.cpp b/lib/Target/ARM/ARMBaseInstrInfo.cpp index 6fe7c2c8c6a..7b35a06b945 100644 --- a/lib/Target/ARM/ARMBaseInstrInfo.cpp +++ b/lib/Target/ARM/ARMBaseInstrInfo.cpp @@ -643,6 +643,13 @@ ARMBaseInstrInfo::copyRegToReg(MachineBasicBlock &MBB, DebugLoc DL = DebugLoc::getUnknownLoc(); if (I != MBB.end()) DL = I->getDebugLoc(); + // tGPR is used sometimes in ARM instructions that need to avoid using + // certain registers. Just treat it as GPR here. + if (DestRC == ARM::tGPRRegisterClass) + DestRC = ARM::GPRRegisterClass; + if (SrcRC == ARM::tGPRRegisterClass) + SrcRC = ARM::GPRRegisterClass; + if (DestRC != SrcRC) { if (DestRC->getSize() != SrcRC->getSize()) return false; diff --git a/lib/Target/ARM/ARMInstrInfo.td b/lib/Target/ARM/ARMInstrInfo.td index 1c6f78ac8bf..a021388994f 100644 --- a/lib/Target/ARM/ARMInstrInfo.td +++ b/lib/Target/ARM/ARMInstrInfo.td @@ -828,9 +828,10 @@ let isCall = 1, } // ARMv4T - def BX : ABXIx2<(outs), (ins GPR:$func, variable_ops), + // Note: Restrict $func to the tGPR regclass to prevent it being in LR. + def BX : ABXIx2<(outs), (ins tGPR:$func, variable_ops), IIC_Br, "mov\tlr, pc\n\tbx\t$func", - [(ARMcall_nolink GPR:$func)]>, + [(ARMcall_nolink tGPR:$func)]>, Requires<[IsARM, IsNotDarwin]> { let Inst{7-4} = 0b0001; let Inst{19-8} = 0b111111111111; @@ -865,9 +866,10 @@ let isCall = 1, } // ARMv4T - def BXr9 : ABXIx2<(outs), (ins GPR:$func, variable_ops), + // Note: Restrict $func to the tGPR regclass to prevent it being in LR. + def BXr9 : ABXIx2<(outs), (ins tGPR:$func, variable_ops), IIC_Br, "mov\tlr, pc\n\tbx\t$func", - [(ARMcall_nolink GPR:$func)]>, Requires<[IsARM, IsDarwin]> { + [(ARMcall_nolink tGPR:$func)]>, Requires<[IsARM, IsDarwin]> { let Inst{7-4} = 0b0001; let Inst{19-8} = 0b111111111111; let Inst{27-20} = 0b00010010; diff --git a/test/CodeGen/ARM/call.ll b/test/CodeGen/ARM/call.ll index 3dd66ae71df..c60b75b574a 100644 --- a/test/CodeGen/ARM/call.ll +++ b/test/CodeGen/ARM/call.ll @@ -20,3 +20,17 @@ define void @g.upgrd.1() { %tmp.upgrd.2 = tail call i32 %tmp( ) ; [#uses=0] ret void } + +define i32* @m_231b(i32, i32, i32*, i32*, i32*) nounwind { +; CHECKV4: m_231b +; CHECKV4: bx r{{.*}} +BB0: + %5 = inttoptr i32 %0 to i32* ; [#uses=1] + %t35 = volatile load i32* %5 ; [#uses=1] + %6 = inttoptr i32 %t35 to i32** ; [#uses=1] + %7 = getelementptr i32** %6, i32 86 ; [#uses=1] + %8 = load i32** %7 ; [#uses=1] + %9 = bitcast i32* %8 to i32* (i32, i32*, i32, i32*, i32*, i32*)* ; [#uses=1] + %10 = call i32* %9(i32 %0, i32* null, i32 %1, i32* %2, i32* %3, i32* %4) ; [#uses=1] + ret i32* %10 +}