diff --git a/llvm/lib/Target/ARM/ARMBaseInstrInfo.h b/llvm/lib/Target/ARM/ARMBaseInstrInfo.h --- a/llvm/lib/Target/ARM/ARMBaseInstrInfo.h +++ b/llvm/lib/Target/ARM/ARMBaseInstrInfo.h @@ -377,6 +377,16 @@ /// constructing an outlined call if one exists. Returns 0 otherwise. unsigned findRegisterToSaveLRTo(const outliner::Candidate &C) const; + // Adds an instruction which saves the link register on top of the stack into + /// the MachineBasicBlock \p MBB at position \p It. + void saveLROnStack(MachineBasicBlock &MBB, + MachineBasicBlock::iterator &It) const; + + /// Adds an instruction which restores the link register from the top the + /// stack into the MachineBasicBlock \p MBB at position \p It. + void restoreLRFromStack(MachineBasicBlock &MBB, + MachineBasicBlock::iterator &It) const; + unsigned getInstBundleLength(const MachineInstr &MI) const; int getVLDMDefCycle(const InstrItineraryData *ItinData, diff --git a/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp b/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp --- a/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp +++ b/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp @@ -5624,12 +5624,32 @@ /// | Frame overhead in Bytes | 2 | 4 | /// | Stack fixup required | No | No | /// +-------------------------+--------+-----+ +/// +/// \p MachineOutlinerDefault implies that the function should be called with +/// a save and restore of LR to the stack. +/// +/// That is, +/// +/// I1 Save LR OUTLINED_FUNCTION: +/// I2 --> BL OUTLINED_FUNCTION I1 +/// I3 Restore LR I2 +/// I3 +/// BX LR +/// +/// +-------------------------+--------+-----+ +/// | | Thumb2 | ARM | +/// +-------------------------+--------+-----+ +/// | Call overhead in Bytes | 8 | 12 | +/// | Frame overhead in Bytes | 2 | 4 | +/// | Stack fixup required | Yes | Yes | +/// +-------------------------+--------+-----+ enum MachineOutlinerClass { MachineOutlinerTailCall, MachineOutlinerThunk, MachineOutlinerNoLRSave, - MachineOutlinerRegSave + MachineOutlinerRegSave, + MachineOutlinerDefault }; enum MachineOutlinerMBBFlags { @@ -5647,6 +5667,8 @@ const int FrameNoLRSave; const int CallRegSave; const int FrameRegSave; + const int CallDefault; + const int FrameDefault; OutlinerCosts(const ARMSubtarget &target) : CallTailCall(target.isThumb() ? 4 : 4), @@ -5656,7 +5678,9 @@ CallNoLRSave(target.isThumb() ? 4 : 4), FrameNoLRSave(target.isThumb() ? 4 : 4), CallRegSave(target.isThumb() ? 8 : 12), - FrameRegSave(target.isThumb() ? 2 : 4) {} + FrameRegSave(target.isThumb() ? 2 : 4), + CallDefault(target.isThumb() ? 8 : 12), + FrameDefault(target.isThumb() ? 2 : 4) {} }; unsigned @@ -5749,8 +5773,8 @@ }; OutlinerCosts Costs(Subtarget); - unsigned FrameID = 0; - unsigned NumBytesToCreateFrame = 0; + unsigned FrameID = MachineOutlinerDefault; + unsigned NumBytesToCreateFrame = Costs.FrameDefault; // If the last instruction in any candidate is a terminator, then we should // tail call all of the candidates. @@ -5766,13 +5790,13 @@ SetCandidateCallInfo(MachineOutlinerThunk, Costs.CallThunk); } else { // We need to decide how to emit calls + frames. We can always emit the same - // frame if we don't need to save to the stack. + // frame if we don't need to save to the stack. If we have to save to the + // stack, then we need a different frame. unsigned NumBytesNoStackCalls = 0; std::vector CandidatesWithoutStackFixups; for (outliner::Candidate &C : RepeatedSequenceLocs) { C.initLRU(TRI); - // Is LR available? If so, we don't need a save. if (C.LRU.available(ARM::LR)) { FrameID = MachineOutlinerNoLRSave; @@ -5789,12 +5813,19 @@ C.setCallInfo(MachineOutlinerRegSave, Costs.CallRegSave); CandidatesWithoutStackFixups.push_back(C); } - } - if (!CandidatesWithoutStackFixups.empty()) { - RepeatedSequenceLocs = CandidatesWithoutStackFixups; - } else - return outliner::OutlinedFunction(); + // Is SP used in the sequence at all? If not, we don't have to modify + // the stack, so we are guaranteed to get the same frame. + else if (C.UsedInSequence.available(ARM::SP)) { + NumBytesNoStackCalls += Costs.CallDefault; + C.setCallInfo(MachineOutlinerDefault, Costs.CallDefault); + SetCandidateCallInfo(MachineOutlinerDefault, Costs.CallDefault); + CandidatesWithoutStackFixups.push_back(C); + } + else + return outliner::OutlinedFunction(); + } + RepeatedSequenceLocs = CandidatesWithoutStackFixups; } return outliner::OutlinedFunction(RepeatedSequenceLocs, SequenceSize, @@ -5980,6 +6011,28 @@ return outliner::InstrType::Legal; } +void ARMBaseInstrInfo::saveLROnStack(MachineBasicBlock &MBB, + MachineBasicBlock::iterator &It) const { + unsigned Opc = Subtarget.isThumb() ? ARM::t2STR_PRE : ARM::STR_PRE_IMM; + int Align = -Subtarget.getStackAlignment().value(); + BuildMI(MBB, It, DebugLoc(), get(Opc), ARM::SP) + .addReg(ARM::LR, RegState::Kill) + .addReg(ARM::SP) + .addImm(Align) + .add(predOps(ARMCC::AL)); +} + +void ARMBaseInstrInfo::restoreLRFromStack( + MachineBasicBlock &MBB, MachineBasicBlock::iterator &It) const { + unsigned Opc = Subtarget.isThumb() ? ARM::t2LDR_POST : ARM::LDR_POST_IMM; + MachineInstrBuilder MIB = BuildMI(MBB, It, DebugLoc(), get(Opc), ARM::LR) + .addReg(ARM::SP, RegState::Define) + .addReg(ARM::SP); + if (!Subtarget.isThumb()) + MIB.addReg(0); + MIB.addImm(Subtarget.getStackAlignment().value()).add(predOps(ARMCC::AL)); +} + void ARMBaseInstrInfo::buildOutlinedFrame( MachineBasicBlock &MBB, MachineFunction &MF, const outliner::OutlinedFunction &OF) const { @@ -6041,21 +6094,29 @@ CallMIB.add(predOps(ARMCC::AL)); CallMIB.addGlobalAddress(M.getNamedValue(MF.getName())); + if (C.CallConstructionID == MachineOutlinerNoLRSave || + C.CallConstructionID == MachineOutlinerThunk) { + // No, so just insert the call. + It = MBB.insert(It, CallMIB); + return It; + } + // Can we save to a register? if (C.CallConstructionID == MachineOutlinerRegSave) { unsigned Reg = findRegisterToSaveLRTo(C); assert(Reg != 0 && "No callee-saved register available?"); // Save and restore LR from that register. - if (!MBB.isLiveIn(ARM::LR)) - MBB.addLiveIn(ARM::LR); copyPhysReg(MBB, It, DebugLoc(), Reg, ARM::LR, true); CallPt = MBB.insert(It, CallMIB); copyPhysReg(MBB, It, DebugLoc(), ARM::LR, Reg, true); It--; return CallPt; } - // Insert the call. - It = MBB.insert(It, CallMIB); - return It; + // We have the default case. Save and restore from SP. + saveLROnStack(MBB, It); + CallPt = MBB.insert(It, CallMIB); + restoreLRFromStack(MBB, It); + It--; + return CallPt; } diff --git a/llvm/test/CodeGen/ARM/machine-outliner-default.mir b/llvm/test/CodeGen/ARM/machine-outliner-default.mir new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/ARM/machine-outliner-default.mir @@ -0,0 +1,369 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -mtriple=arm-- -run-pass=machine-outliner -verify-machineinstrs \ +# RUN: %s -o - | FileCheck %s + +--- | + define void @outline_default_arm() #0 { ret void } + define void @outline_default_thumb() #1 { ret void } + define void @outline_default_KO_call_arm() #0 { ret void } + define void @outline_default_KO_call_thumb() #1 { ret void } + define void @outline_default_KO_stack_arm() #0 { ret void } + define void @outline_default_KO_stack_thumb() #0 { ret void } + declare void @bar() + + attributes #0 = { minsize optsize } + attributes #1 = { minsize optsize "target-features"="+armv7-a,+thumb-mode" } +... +--- + +name: outline_default_arm +tracksRegLiveness: true +body: | + ; CHECK-LABEL: name: outline_default_arm + ; CHECK: bb.0: + ; CHECK: liveins: $lr + ; CHECK: early-clobber $sp = STR_PRE_IMM killed $lr, $sp, -8, 14 /* CC::al */, $noreg + ; CHECK: BL @OUTLINED_FUNCTION_0 + ; CHECK: $lr, $sp = LDR_POST_IMM $sp, $noreg, 8, 14 /* CC::al */, $noreg + ; CHECK: bb.1: + ; CHECK: liveins: $lr, $r6, $r7, $r8, $r9, $r10, $r11 + ; CHECK: early-clobber $sp = STR_PRE_IMM killed $lr, $sp, -8, 14 /* CC::al */, $noreg + ; CHECK: BL @OUTLINED_FUNCTION_0 + ; CHECK: $lr, $sp = LDR_POST_IMM $sp, $noreg, 8, 14 /* CC::al */, $noreg + ; CHECK: bb.2: + ; CHECK: liveins: $lr, $r6, $r7, $r8, $r9, $r10, $r11 + ; CHECK: early-clobber $sp = STR_PRE_IMM killed $lr, $sp, -8, 14 /* CC::al */, $noreg + ; CHECK: BL @OUTLINED_FUNCTION_0 + ; CHECK: $lr, $sp = LDR_POST_IMM $sp, $noreg, 8, 14 /* CC::al */, $noreg + ; CHECK: bb.3: + ; CHECK: liveins: $lr, $r6, $r7, $r8, $r9, $r10, $r11 + ; CHECK: $r2 = MOVr $lr, 14 /* CC::al */, $noreg, $noreg + ; CHECK: BX_RET 14 /* CC::al */, $noreg + bb.0: + liveins: $lr + $r0 = MOVi 1, 14, $noreg, $noreg + $r1 = MOVi 1, 14, $noreg, $noreg + $r2 = MOVi 1, 14, $noreg, $noreg + $r3 = MOVi 1, 14, $noreg, $noreg + $r4 = MOVi 1, 14, $noreg, $noreg + $r5 = MOVi 1, 14, $noreg, $noreg + bb.1: + liveins: $lr, $r6, $r7, $r8, $r9, $r10, $r11 + $r0 = MOVi 1, 14, $noreg, $noreg + $r1 = MOVi 1, 14, $noreg, $noreg + $r2 = MOVi 1, 14, $noreg, $noreg + $r3 = MOVi 1, 14, $noreg, $noreg + $r4 = MOVi 1, 14, $noreg, $noreg + $r5 = MOVi 1, 14, $noreg, $noreg + bb.2: + liveins: $lr, $r6, $r7, $r8, $r9, $r10, $r11 + $r0 = MOVi 1, 14, $noreg, $noreg + $r1 = MOVi 1, 14, $noreg, $noreg + $r2 = MOVi 1, 14, $noreg, $noreg + $r3 = MOVi 1, 14, $noreg, $noreg + $r4 = MOVi 1, 14, $noreg, $noreg + $r5 = MOVi 1, 14, $noreg, $noreg + bb.3: + liveins: $lr, $r6, $r7, $r8, $r9, $r10, $r11 + $r2 = MOVr $lr, 14, $noreg, $noreg + BX_RET 14, $noreg +... +--- + +name: outline_default_thumb +tracksRegLiveness: true +body: | + ; CHECK-LABEL: name: outline_default_thumb + ; CHECK: bb.0: + ; CHECK: liveins: $lr + ; CHECK: early-clobber $sp = t2STR_PRE killed $lr, $sp, -8, 14 /* CC::al */, $noreg + ; CHECK: tBL 14 /* CC::al */, $noreg, @OUTLINED_FUNCTION_1 + ; CHECK: $lr, $sp = t2LDR_POST $sp, 8, 14 /* CC::al */, $noreg + ; CHECK: bb.1: + ; CHECK: liveins: $lr, $r4, $r5, $r6, $r7, $r8, $r9, $r10, $r11 + ; CHECK: early-clobber $sp = t2STR_PRE killed $lr, $sp, -8, 14 /* CC::al */, $noreg + ; CHECK: tBL 14 /* CC::al */, $noreg, @OUTLINED_FUNCTION_1 + ; CHECK: $lr, $sp = t2LDR_POST $sp, 8, 14 /* CC::al */, $noreg + ; CHECK: bb.2: + ; CHECK: liveins: $lr, $r4, $r5, $r6, $r7, $r8, $r9, $r10, $r11 + ; CHECK: early-clobber $sp = t2STR_PRE killed $lr, $sp, -8, 14 /* CC::al */, $noreg + ; CHECK: tBL 14 /* CC::al */, $noreg, @OUTLINED_FUNCTION_1 + ; CHECK: $lr, $sp = t2LDR_POST $sp, 8, 14 /* CC::al */, $noreg + ; CHECK: bb.3: + ; CHECK: liveins: $lr, $r4, $r5, $r6, $r7, $r8, $r9, $r10, $r11 + ; CHECK: $r2 = tMOVr $lr, 14 /* CC::al */, $noreg + ; CHECK: tBX_RET 14 /* CC::al */, $noreg + bb.0: + liveins: $lr + $r0 = t2MOVi 1, 14, $noreg, $noreg + $r1 = t2MOVi 1, 14, $noreg, $noreg + $r2 = t2MOVi 1, 14, $noreg, $noreg + $r3 = t2MOVi 1, 14, $noreg, $noreg + bb.1: + liveins: $lr, $r4, $r5, $r6, $r7, $r8, $r9, $r10, $r11 + $r0 = t2MOVi 1, 14, $noreg, $noreg + $r1 = t2MOVi 1, 14, $noreg, $noreg + $r2 = t2MOVi 1, 14, $noreg, $noreg + $r3 = t2MOVi 1, 14, $noreg, $noreg + bb.2: + liveins: $lr, $r4, $r5, $r6, $r7, $r8, $r9, $r10, $r11 + $r0 = t2MOVi 1, 14, $noreg, $noreg + $r1 = t2MOVi 1, 14, $noreg, $noreg + $r2 = t2MOVi 1, 14, $noreg, $noreg + $r3 = t2MOVi 1, 14, $noreg, $noreg + bb.3: + liveins: $lr, $r4, $r5, $r6, $r7, $r8, $r9, $r10, $r11 + $r2 = tMOVr $lr, 14, $noreg + tBX_RET 14, $noreg +... +--- + +name: outline_default_KO_call_arm +tracksRegLiveness: true +body: | + ; CHECK-LABEL: name: outline_default_KO_call_arm + ; CHECK: bb.0: + ; CHECK: liveins: $lr + ; CHECK: BL @bar, implicit-def dead $lr, implicit $sp + ; CHECK: $r0 = MOVi 2, 14 /* CC::al */, $noreg, $noreg + ; CHECK: $r1 = MOVi 2, 14 /* CC::al */, $noreg, $noreg + ; CHECK: $r2 = MOVi 2, 14 /* CC::al */, $noreg, $noreg + ; CHECK: $r3 = MOVi 2, 14 /* CC::al */, $noreg, $noreg + ; CHECK: $r4 = MOVi 2, 14 /* CC::al */, $noreg, $noreg + ; CHECK: bb.1: + ; CHECK: liveins: $lr, $r5, $r6, $r7, $r8, $r9, $r10, $r11 + ; CHECK: BL @bar, implicit-def dead $lr, implicit $sp + ; CHECK: $r0 = MOVi 2, 14 /* CC::al */, $noreg, $noreg + ; CHECK: $r1 = MOVi 2, 14 /* CC::al */, $noreg, $noreg + ; CHECK: $r2 = MOVi 2, 14 /* CC::al */, $noreg, $noreg + ; CHECK: $r3 = MOVi 2, 14 /* CC::al */, $noreg, $noreg + ; CHECK: $r4 = MOVi 2, 14 /* CC::al */, $noreg, $noreg + ; CHECK: bb.2: + ; CHECK: liveins: $lr, $r5, $r6, $r7, $r8, $r9, $r10, $r11 + ; CHECK: BL @bar, implicit-def dead $lr, implicit $sp + ; CHECK: $r0 = MOVi 2, 14 /* CC::al */, $noreg, $noreg + ; CHECK: $r1 = MOVi 2, 14 /* CC::al */, $noreg, $noreg + ; CHECK: $r2 = MOVi 2, 14 /* CC::al */, $noreg, $noreg + ; CHECK: $r3 = MOVi 2, 14 /* CC::al */, $noreg, $noreg + ; CHECK: $r4 = MOVi 2, 14 /* CC::al */, $noreg, $noreg + ; CHECK: bb.3: + ; CHECK: liveins: $lr, $r5, $r6, $r7, $r8, $r9, $r10, $r11 + ; CHECK: $r2 = MOVr $lr, 14 /* CC::al */, $noreg, $noreg + ; CHECK: BX_RET 14 /* CC::al */, $noreg + bb.0: + liveins: $lr + BL @bar, implicit-def dead $lr, implicit $sp + $r0 = MOVi 2, 14, $noreg, $noreg + $r1 = MOVi 2, 14, $noreg, $noreg + $r2 = MOVi 2, 14, $noreg, $noreg + $r3 = MOVi 2, 14, $noreg, $noreg + $r4 = MOVi 2, 14, $noreg, $noreg + bb.1: + liveins: $lr, $r5, $r6, $r7, $r8, $r9, $r10, $r11 + BL @bar, implicit-def dead $lr, implicit $sp + $r0 = MOVi 2, 14, $noreg, $noreg + $r1 = MOVi 2, 14, $noreg, $noreg + $r2 = MOVi 2, 14, $noreg, $noreg + $r3 = MOVi 2, 14, $noreg, $noreg + $r4 = MOVi 2, 14, $noreg, $noreg + bb.2: + liveins: $lr, $r5, $r6, $r7, $r8, $r9, $r10, $r11 + BL @bar, implicit-def dead $lr, implicit $sp + $r0 = MOVi 2, 14, $noreg, $noreg + $r1 = MOVi 2, 14, $noreg, $noreg + $r2 = MOVi 2, 14, $noreg, $noreg + $r3 = MOVi 2, 14, $noreg, $noreg + $r4 = MOVi 2, 14, $noreg, $noreg + bb.3: + liveins: $lr, $r5, $r6, $r7, $r8, $r9, $r10, $r11 + $r2 = MOVr $lr, 14, $noreg, $noreg + BX_RET 14, $noreg +... +--- + +name: outline_default_KO_call_thumb +tracksRegLiveness: true +body: | + ; CHECK-LABEL: name: outline_default_KO_call_thumb + ; CHECK: bb.0: + ; CHECK: liveins: $lr + ; CHECK: tBL 14 /* CC::al */, $noreg, @bar, implicit-def dead $lr, implicit $sp + ; CHECK: $r0 = t2MOVi 2, 14 /* CC::al */, $noreg, $noreg + ; CHECK: $r1 = t2MOVi 2, 14 /* CC::al */, $noreg, $noreg + ; CHECK: $r2 = t2MOVi 2, 14 /* CC::al */, $noreg, $noreg + ; CHECK: bb.1: + ; CHECK: liveins: $lr, $r3, $r4, $r5, $r6, $r7, $r8, $r9, $r10, $r11 + ; CHECK: tBL 14 /* CC::al */, $noreg, @bar, implicit-def dead $lr, implicit $sp + ; CHECK: $r0 = t2MOVi 2, 14 /* CC::al */, $noreg, $noreg + ; CHECK: $r1 = t2MOVi 2, 14 /* CC::al */, $noreg, $noreg + ; CHECK: $r2 = t2MOVi 2, 14 /* CC::al */, $noreg, $noreg + ; CHECK: bb.2: + ; CHECK: liveins: $lr, $r3, $r4, $r5, $r6, $r7, $r8, $r9, $r10, $r11 + ; CHECK: tBL 14 /* CC::al */, $noreg, @bar, implicit-def dead $lr, implicit $sp + ; CHECK: $r0 = t2MOVi 2, 14 /* CC::al */, $noreg, $noreg + ; CHECK: $r1 = t2MOVi 2, 14 /* CC::al */, $noreg, $noreg + ; CHECK: $r2 = t2MOVi 2, 14 /* CC::al */, $noreg, $noreg + ; CHECK: bb.3: + ; CHECK: liveins: $lr, $r3, $r4, $r5, $r6, $r7, $r8, $r9, $r10, $r11 + ; CHECK: $r2 = tMOVr $lr, 14 /* CC::al */, $noreg + ; CHECK: tBX_RET 14 /* CC::al */, $noreg + bb.0: + liveins: $lr + tBL 14, $noreg, @bar, implicit-def dead $lr, implicit $sp + $r0 = t2MOVi 2, 14, $noreg, $noreg + $r1 = t2MOVi 2, 14, $noreg, $noreg + $r2 = t2MOVi 2, 14, $noreg, $noreg + bb.1: + liveins: $lr, $r3, $r4, $r5, $r6, $r7, $r8, $r9, $r10, $r11 + tBL 14, $noreg, @bar, implicit-def dead $lr, implicit $sp + $r0 = t2MOVi 2, 14, $noreg, $noreg + $r1 = t2MOVi 2, 14, $noreg, $noreg + $r2 = t2MOVi 2, 14, $noreg, $noreg + bb.2: + liveins: $lr, $r3, $r4, $r5, $r6, $r7, $r8, $r9, $r10, $r11 + tBL 14, $noreg, @bar, implicit-def dead $lr, implicit $sp + $r0 = t2MOVi 2, 14, $noreg, $noreg + $r1 = t2MOVi 2, 14, $noreg, $noreg + $r2 = t2MOVi 2, 14, $noreg, $noreg + bb.3: + liveins: $lr, $r3, $r4, $r5, $r6, $r7, $r8, $r9, $r10, $r11 + $r2 = tMOVr $lr, 14, $noreg + tBX_RET 14, $noreg +... +--- + +name: outline_default_KO_stack_arm +tracksRegLiveness: true +body: | + ; CHECK-LABEL: name: outline_default_KO_stack_arm + ; CHECK: bb.0: + ; CHECK: liveins: $lr + ; CHECK: $r0 = LDRi12 $sp, 0, 14 /* CC::al */, $noreg + ; CHECK: $r1 = MOVi 3, 14 /* CC::al */, $noreg, $noreg + ; CHECK: $r2 = MOVi 3, 14 /* CC::al */, $noreg, $noreg + ; CHECK: $r3 = MOVi 3, 14 /* CC::al */, $noreg, $noreg + ; CHECK: $r4 = MOVi 3, 14 /* CC::al */, $noreg, $noreg + ; CHECK: $r5 = MOVi 3, 14 /* CC::al */, $noreg, $noreg + ; CHECK: bb.1: + ; CHECK: liveins: $lr, $r6, $r7, $r8, $r9, $r10, $r11 + ; CHECK: $r0 = LDRi12 $sp, 0, 14 /* CC::al */, $noreg + ; CHECK: $r1 = MOVi 3, 14 /* CC::al */, $noreg, $noreg + ; CHECK: $r2 = MOVi 3, 14 /* CC::al */, $noreg, $noreg + ; CHECK: $r3 = MOVi 3, 14 /* CC::al */, $noreg, $noreg + ; CHECK: $r4 = MOVi 3, 14 /* CC::al */, $noreg, $noreg + ; CHECK: $r5 = MOVi 3, 14 /* CC::al */, $noreg, $noreg + ; CHECK: bb.2: + ; CHECK: liveins: $lr, $r5, $r6, $r7, $r8, $r9, $r10, $r11 + ; CHECK: $r0 = LDRi12 $sp, 0, 14 /* CC::al */, $noreg + ; CHECK: $r1 = MOVi 3, 14 /* CC::al */, $noreg, $noreg + ; CHECK: $r2 = MOVi 3, 14 /* CC::al */, $noreg, $noreg + ; CHECK: $r3 = MOVi 3, 14 /* CC::al */, $noreg, $noreg + ; CHECK: $r4 = MOVi 3, 14 /* CC::al */, $noreg, $noreg + ; CHECK: $r5 = MOVi 3, 14 /* CC::al */, $noreg, $noreg + ; CHECK: bb.3: + ; CHECK: liveins: $lr, $r5, $r6, $r7, $r8, $r9, $r10, $r11 + ; CHECK: $r2 = MOVr $lr, 14 /* CC::al */, $noreg, $noreg + ; CHECK: BX_RET 14 /* CC::al */, $noreg + bb.0: + liveins: $lr + $r0 = LDRi12 $sp, 0, 14, $noreg + $r1 = MOVi 3, 14, $noreg, $noreg + $r2 = MOVi 3, 14, $noreg, $noreg + $r3 = MOVi 3, 14, $noreg, $noreg + $r4 = MOVi 3, 14, $noreg, $noreg + $r5 = MOVi 3, 14, $noreg, $noreg + bb.1: + liveins: $lr, $r6, $r7, $r8, $r9, $r10, $r11 + $r0 = LDRi12 $sp, 0, 14, $noreg + $r1 = MOVi 3, 14, $noreg, $noreg + $r2 = MOVi 3, 14, $noreg, $noreg + $r3 = MOVi 3, 14, $noreg, $noreg + $r4 = MOVi 3, 14, $noreg, $noreg + $r5 = MOVi 3, 14, $noreg, $noreg + bb.2: + liveins: $lr, $r5, $r6, $r7, $r8, $r9, $r10, $r11 + $r0 = LDRi12 $sp, 0, 14, $noreg + $r1 = MOVi 3, 14, $noreg, $noreg + $r2 = MOVi 3, 14, $noreg, $noreg + $r3 = MOVi 3, 14, $noreg, $noreg + $r4 = MOVi 3, 14, $noreg, $noreg + $r5 = MOVi 3, 14, $noreg, $noreg + bb.3: + liveins: $lr, $r5, $r6, $r7, $r8, $r9, $r10, $r11 + $r2 = MOVr $lr, 14, $noreg, $noreg + BX_RET 14, $noreg +... +--- + +name: outline_default_KO_stack_thumb +tracksRegLiveness: true +body: | + ; CHECK-LABEL: name: outline_default_KO_stack_thumb + ; CHECK: bb.0: + ; CHECK: liveins: $lr + ; CHECK: $r0 = t2LDRi12 $sp, 0, 14 /* CC::al */, $noreg + ; CHECK: $r1 = t2MOVi 3, 14 /* CC::al */, $noreg, $noreg + ; CHECK: $r2 = t2MOVi 3, 14 /* CC::al */, $noreg, $noreg + ; CHECK: $r3 = t2MOVi 3, 14 /* CC::al */, $noreg, $noreg + ; CHECK: bb.1: + ; CHECK: liveins: $lr, $r4, $r5, $r6, $r7, $r8, $r9, $r10, $r11 + ; CHECK: $r0 = t2LDRi12 $sp, 0, 14 /* CC::al */, $noreg + ; CHECK: $r1 = t2MOVi 3, 14 /* CC::al */, $noreg, $noreg + ; CHECK: $r2 = t2MOVi 3, 14 /* CC::al */, $noreg, $noreg + ; CHECK: $r3 = t2MOVi 3, 14 /* CC::al */, $noreg, $noreg + ; CHECK: bb.2: + ; CHECK: liveins: $lr, $r4, $r5, $r6, $r7, $r8, $r9, $r10, $r11 + ; CHECK: $r0 = t2LDRi12 $sp, 0, 14 /* CC::al */, $noreg + ; CHECK: $r1 = t2MOVi 3, 14 /* CC::al */, $noreg, $noreg + ; CHECK: $r2 = t2MOVi 3, 14 /* CC::al */, $noreg, $noreg + ; CHECK: $r3 = t2MOVi 3, 14 /* CC::al */, $noreg, $noreg + ; CHECK: bb.3: + ; CHECK: liveins: $lr, $r4, $r5, $r6, $r7, $r8, $r9, $r10, $r11 + ; CHECK: $r2 = tMOVr $lr, 14 /* CC::al */, $noreg + ; CHECK: tBX_RET 14 /* CC::al */, $noreg + bb.0: + liveins: $lr + $r0 = t2LDRi12 $sp, 0, 14, $noreg + $r1 = t2MOVi 3, 14, $noreg, $noreg + $r2 = t2MOVi 3, 14, $noreg, $noreg + $r3 = t2MOVi 3, 14, $noreg, $noreg + bb.1: + liveins: $lr, $r4, $r5, $r6, $r7, $r8, $r9, $r10, $r11 + $r0 = t2LDRi12 $sp, 0, 14, $noreg + $r1 = t2MOVi 3, 14, $noreg, $noreg + $r2 = t2MOVi 3, 14, $noreg, $noreg + $r3 = t2MOVi 3, 14, $noreg, $noreg + bb.2: + liveins: $lr, $r4, $r5, $r6, $r7, $r8, $r9, $r10, $r11 + $r0 = t2LDRi12 $sp, 0, 14, $noreg + $r1 = t2MOVi 3, 14, $noreg, $noreg + $r2 = t2MOVi 3, 14, $noreg, $noreg + $r3 = t2MOVi 3, 14, $noreg, $noreg + bb.3: + liveins: $lr, $r4, $r5, $r6, $r7, $r8, $r9, $r10, $r11 + $r2 = tMOVr $lr, 14, $noreg + tBX_RET 14, $noreg + + + ; CHECK-LABEL: name: OUTLINED_FUNCTION_0 + ; CHECK: bb.0: + ; CHECK: liveins: $lr, $r6, $r7, $r8, $r9, $r10, $r11 + ; CHECK: $r0 = MOVi 1, 14 /* CC::al */, $noreg, $noreg + ; CHECK: $r1 = MOVi 1, 14 /* CC::al */, $noreg, $noreg + ; CHECK: $r2 = MOVi 1, 14 /* CC::al */, $noreg, $noreg + ; CHECK: $r3 = MOVi 1, 14 /* CC::al */, $noreg, $noreg + ; CHECK: $r4 = MOVi 1, 14 /* CC::al */, $noreg, $noreg + ; CHECK: $r5 = MOVi 1, 14 /* CC::al */, $noreg, $noreg + ; CHECK: MOVPCLR 14 /* CC::al */, $noreg + + ; CHECK-LABEL: name: OUTLINED_FUNCTION_1 + ; CHECK: bb.0: + ; CHECK: liveins: $lr, $r4, $r5, $r6, $r7, $r8, $r9, $r10, $r11 + ; CHECK: $r0 = t2MOVi 1, 14 /* CC::al */, $noreg, $noreg + ; CHECK: $r1 = t2MOVi 1, 14 /* CC::al */, $noreg, $noreg + ; CHECK: $r2 = t2MOVi 1, 14 /* CC::al */, $noreg, $noreg + ; CHECK: $r3 = t2MOVi 1, 14 /* CC::al */, $noreg, $noreg + ; CHECK: tBX_RET 14 /* CC::al */, $noreg + + + diff --git a/llvm/test/CodeGen/ARM/machine-outliner-lr-regsave.mir b/llvm/test/CodeGen/ARM/machine-outliner-lr-regsave.mir --- a/llvm/test/CodeGen/ARM/machine-outliner-lr-regsave.mir +++ b/llvm/test/CodeGen/ARM/machine-outliner-lr-regsave.mir @@ -28,12 +28,9 @@ ; CHECK: $lr = MOVr killed $r6, 14 /* CC::al */, $noreg, $noreg ; CHECK: bb.2: ; CHECK: liveins: $lr - ; CHECK: $r0 = MOVi 1, 14 /* CC::al */, $noreg, $noreg - ; CHECK: $r1 = MOVi 1, 14 /* CC::al */, $noreg, $noreg - ; CHECK: $r2 = MOVi 1, 14 /* CC::al */, $noreg, $noreg - ; CHECK: $r3 = MOVi 1, 14 /* CC::al */, $noreg, $noreg - ; CHECK: $r4 = MOVi 1, 14 /* CC::al */, $noreg, $noreg - ; CHECK: $r5 = MOVi 1, 14 /* CC::al */, $noreg, $noreg + ; CHECK: early-clobber $sp = STR_PRE_IMM killed $lr, $sp, -8, 14 /* CC::al */, $noreg + ; CHECK: BL @OUTLINED_FUNCTION_1 + ; CHECK: $lr, $sp = LDR_POST_IMM $sp, $noreg, 8, 14 /* CC::al */, $noreg ; CHECK: bb.3: ; CHECK: liveins: $lr, $r0, $r6, $r7, $r8, $r9, $r10, $r11 ; CHECK: $r6 = MOVr killed $lr, 14 /* CC::al */, $noreg, $noreg @@ -98,12 +95,9 @@ ; CHECK: $lr = tMOVr killed $r6, 14 /* CC::al */, $noreg ; CHECK: bb.2: ; CHECK: liveins: $lr - ; CHECK: $r0 = t2MOVi 1, 14 /* CC::al */, $noreg, $noreg - ; CHECK: $r1 = t2MOVi 1, 14 /* CC::al */, $noreg, $noreg - ; CHECK: $r2 = t2MOVi 1, 14 /* CC::al */, $noreg, $noreg - ; CHECK: $r3 = t2MOVi 1, 14 /* CC::al */, $noreg, $noreg - ; CHECK: $r4 = t2MOVi 1, 14 /* CC::al */, $noreg, $noreg - ; CHECK: $r5 = t2MOVi 1, 14 /* CC::al */, $noreg, $noreg + ; CHECK: early-clobber $sp = t2STR_PRE killed $lr, $sp, -8, 14 /* CC::al */, $noreg + ; CHECK: tBL 14 /* CC::al */, $noreg, @OUTLINED_FUNCTION_0 + ; CHECK: $lr, $sp = t2LDR_POST $sp, 8, 14 /* CC::al */, $noreg ; CHECK: bb.3: ; CHECK: liveins: $lr, $r0, $r6, $r7 ; CHECK: $r6 = tMOVr killed $lr, 14 /* CC::al */, $noreg