diff --git a/lib/Target/ARM/ARMAsmPrinter.cpp b/lib/Target/ARM/ARMAsmPrinter.cpp index e1a2cc57abf..478c2468381 100644 --- a/lib/Target/ARM/ARMAsmPrinter.cpp +++ b/lib/Target/ARM/ARMAsmPrinter.cpp @@ -945,6 +945,16 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) { unsigned Opc = MI->getOpcode(); switch (Opc) { default: break; + case ARM::LDMIA_RET: { + // LDMIA_RET is just a normal LDMIA_UPD instruction that targets PC and as + // such has additional code-gen properties and scheduling information. + // To emit it, we just construct as normal and set the opcode to LDMIA_UPD. + MCInst TmpInst; + LowerARMMachineInstrToMCInst(MI, TmpInst, *this); + TmpInst.setOpcode(ARM::LDMIA_UPD); + OutStreamer.EmitInstruction(TmpInst); + return; + } case ARM::t2ADDrSPi: case ARM::t2ADDrSPi12: case ARM::t2SUBrSPi: diff --git a/lib/Target/ARM/ARMInstrInfo.td b/lib/Target/ARM/ARMInstrInfo.td index 2bfe11c955e..bb40e39903b 100644 --- a/lib/Target/ARM/ARMInstrInfo.td +++ b/lib/Target/ARM/ARMInstrInfo.td @@ -1928,16 +1928,10 @@ def : MnemonicAlias<"stm", "stmia">; // FIXME: Should pc be an implicit operand like PICADD, etc? let isReturn = 1, isTerminator = 1, isBarrier = 1, mayLoad = 1, hasExtraDefRegAllocReq = 1, isCodeGenOnly = 1 in -// FIXME: Should be a pseudo-instruction. -def LDMIA_RET : AXI4<(outs GPR:$wb), (ins GPR:$Rn, pred:$p, - reglist:$regs, variable_ops), - IndexModeUpd, LdStMulFrm, IIC_iLoad_mBr, - "ldmia${p}\t$Rn!, $regs", - "$Rn = $wb", []> { - let Inst{24-23} = 0b01; // Increment After - let Inst{21} = 1; // Writeback - let Inst{20} = 1; // Load -} +def LDMIA_RET : ARMPseudoInst<(outs GPR:$wb), (ins GPR:$Rn, pred:$p, + reglist:$regs, variable_ops), + Size4Bytes, IIC_iLoad_mBr, []>, + RegConstraint<"$Rn = $wb">; //===----------------------------------------------------------------------===// // Move Instructions. diff --git a/test/CodeGen/ARM/2010-03-18-ldm-rtrn.ll b/test/CodeGen/ARM/2010-03-18-ldm-rtrn.ll index d9e1a1486a3..fee86008ad7 100644 --- a/test/CodeGen/ARM/2010-03-18-ldm-rtrn.ll +++ b/test/CodeGen/ARM/2010-03-18-ldm-rtrn.ll @@ -6,7 +6,7 @@ define i32 @bar(i32 %a) nounwind { entry: %0 = tail call i32 @foo(i32 %a) nounwind ; [#uses=1] %1 = add nsw i32 %0, 3 ; [#uses=1] -; CHECK: ldmia sp!, {r11, pc} +; CHECK: pop {r11, pc} ; V4: pop ; V4-NEXT: mov pc, lr ret i32 %1 diff --git a/test/CodeGen/ARM/2010-10-25-ifcvt-ldm.ll b/test/CodeGen/ARM/2010-10-25-ifcvt-ldm.ll index 163c9b030ec..32d350e9c8b 100644 --- a/test/CodeGen/ARM/2010-10-25-ifcvt-ldm.ll +++ b/test/CodeGen/ARM/2010-10-25-ifcvt-ldm.ll @@ -4,9 +4,9 @@ ; was being treated as an instruction count. ; CHECK: push -; CHECK: ldmia -; CHECK: ldmia -; CHECK: ldmia +; CHECK: pop +; CHECK: pop +; CHECK: pop define i32 @test(i32 %x) { entry: diff --git a/test/CodeGen/ARM/2010-11-29-PrologueBug.ll b/test/CodeGen/ARM/2010-11-29-PrologueBug.ll index 8d7541feae9..e3c18cefd51 100644 --- a/test/CodeGen/ARM/2010-11-29-PrologueBug.ll +++ b/test/CodeGen/ARM/2010-11-29-PrologueBug.ll @@ -10,7 +10,7 @@ entry: ; ARM: bl _foo ; ARM: bl _foo ; ARM: bl _foo -; ARM: ldmia sp!, {r7, pc} +; ARM: pop {r7, pc} ; THUMB2: t: ; THUMB2: push diff --git a/test/CodeGen/ARM/bx_fold.ll b/test/CodeGen/ARM/bx_fold.ll index 09f1aae0a9f..5533038fb82 100644 --- a/test/CodeGen/ARM/bx_fold.ll +++ b/test/CodeGen/ARM/bx_fold.ll @@ -24,7 +24,7 @@ bb1: ; preds = %bb, %entry bb18: ; preds = %bb1 ; CHECK-NOT: bx -; CHECK: ldmia sp! +; CHECK: pop ret void } diff --git a/test/CodeGen/ARM/code-placement.ll b/test/CodeGen/ARM/code-placement.ll index 036598fc060..91ef6592522 100644 --- a/test/CodeGen/ARM/code-placement.ll +++ b/test/CodeGen/ARM/code-placement.ll @@ -72,7 +72,7 @@ bb2.preheader: ; preds = %bb3, %bb.nph15 br i1 %4, label %bb1, label %bb3 ; CHECK: LBB1_[[RET]]: @ %bb5 -; CHECK: ldmia sp! +; CHECK: pop bb5: ; preds = %bb3, %entry %sum.1.lcssa = phi i32 [ 0, %entry ], [ %sum.0.lcssa, %bb3 ] ; [#uses=1] ret i32 %sum.1.lcssa diff --git a/test/CodeGen/ARM/ifcvt10.ll b/test/CodeGen/ARM/ifcvt10.ll index 75428ac2165..18f87bfc2e7 100644 --- a/test/CodeGen/ARM/ifcvt10.ll +++ b/test/CodeGen/ARM/ifcvt10.ll @@ -9,9 +9,9 @@ entry: ; CHECK: t: ; CHECK: vpop {d8} ; CHECK-NOT: vpopne -; CHECK: ldmia sp!, {r7, pc} +; CHECK: pop {r7, pc} ; CHECK: vpop {d8} -; CHECK: ldmia sp!, {r7, pc} +; CHECK: pop {r7, pc} br i1 undef, label %if.else, label %if.then if.then: ; preds = %entry diff --git a/test/CodeGen/ARM/ifcvt5.ll b/test/CodeGen/ARM/ifcvt5.ll index bca2ae346a6..3615055f8b2 100644 --- a/test/CodeGen/ARM/ifcvt5.ll +++ b/test/CodeGen/ARM/ifcvt5.ll @@ -11,7 +11,7 @@ entry: define i32 @t1(i32 %a, i32 %b) { ; CHECK: t1: -; CHECK: ldmialt sp!, {r7, pc} +; CHECK: poplt {r7, pc} entry: %tmp1 = icmp sgt i32 %a, 10 ; [#uses=1] br i1 %tmp1, label %cond_true, label %UnifiedReturnBlock diff --git a/test/CodeGen/ARM/ifcvt6.ll b/test/CodeGen/ARM/ifcvt6.ll index 5edf32fd1af..23276576855 100644 --- a/test/CodeGen/ARM/ifcvt6.ll +++ b/test/CodeGen/ARM/ifcvt6.ll @@ -3,7 +3,7 @@ define void @foo(i32 %X, i32 %Y) { entry: ; CHECK: cmpne -; CHECK: ldmiahi sp! +; CHECK: pophi %tmp1 = icmp ult i32 %X, 4 ; [#uses=1] %tmp4 = icmp eq i32 %Y, 0 ; [#uses=1] %tmp7 = or i1 %tmp4, %tmp1 ; [#uses=1] diff --git a/test/CodeGen/ARM/ifcvt7.ll b/test/CodeGen/ARM/ifcvt7.ll index 62e13557cfd..476ed4d47c6 100644 --- a/test/CodeGen/ARM/ifcvt7.ll +++ b/test/CodeGen/ARM/ifcvt7.ll @@ -6,7 +6,7 @@ define fastcc i32 @CountTree(%struct.quad_struct* %tree) { ; CHECK: cmpeq ; CHECK: moveq -; CHECK: ldmiaeq sp! +; CHECK: popeq entry: br label %tailrecurse diff --git a/test/CodeGen/ARM/ifcvt8.ll b/test/CodeGen/ARM/ifcvt8.ll index 5fdfc4ea680..ca9a5c63cda 100644 --- a/test/CodeGen/ARM/ifcvt8.ll +++ b/test/CodeGen/ARM/ifcvt8.ll @@ -5,7 +5,7 @@ declare void @abort() define fastcc void @t(%struct.SString* %word, i8 signext %c) { -; CHECK: ldmiane sp! +; CHECK: popne entry: %tmp1 = icmp eq %struct.SString* %word, null ; [#uses=1] br i1 %tmp1, label %cond_true, label %cond_false diff --git a/test/CodeGen/ARM/ldm.ll b/test/CodeGen/ARM/ldm.ll index 2f1b85ebbb0..db78fd06ab2 100644 --- a/test/CodeGen/ARM/ldm.ll +++ b/test/CodeGen/ARM/ldm.ll @@ -5,9 +5,9 @@ define i32 @t1() { ; CHECK: t1: -; CHECK: ldmia +; CHECK: pop ; V4T: t1: -; V4T: ldmia +; V4T: pop %tmp = load i32* getelementptr ([0 x i32]* @X, i32 0, i32 0) ; [#uses=1] %tmp3 = load i32* getelementptr ([0 x i32]* @X, i32 0, i32 1) ; [#uses=1] %tmp4 = tail call i32 @f1( i32 %tmp, i32 %tmp3 ) ; [#uses=1] @@ -16,9 +16,9 @@ define i32 @t1() { define i32 @t2() { ; CHECK: t2: -; CHECK: ldmia +; CHECK: pop ; V4T: t2: -; V4T: ldmia +; V4T: pop %tmp = load i32* getelementptr ([0 x i32]* @X, i32 0, i32 2) ; [#uses=1] %tmp3 = load i32* getelementptr ([0 x i32]* @X, i32 0, i32 3) ; [#uses=1] %tmp5 = load i32* getelementptr ([0 x i32]* @X, i32 0, i32 4) ; [#uses=1] @@ -29,7 +29,7 @@ define i32 @t2() { define i32 @t3() { ; CHECK: t3: ; CHECK: ldmib -; CHECK: ldmia sp! +; CHECK: pop ; V4T: t3: ; V4T: ldmib ; V4T: pop