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 @@ -396,6 +396,17 @@ void emitCFIForLRRestoreFromReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator It) const; + /// \brief Sets the offsets on outlined instructions in \p MBB which use SP + /// so that they will be valid post-outlining. + /// + /// \param MBB A \p MachineBasicBlock in an outlined function. + void fixupPostOutline(MachineBasicBlock &MBB) const; + + /// Returns true if the machine instruction offset can handle the stack fixup + /// and updates it if requested. + bool checkAndUpdateStackOffset(MachineInstr *MI, int64_t Fixup, + bool Updt) 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 @@ -5815,37 +5815,161 @@ 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(); - } + } - // Does every candidate's MBB contain a call? If so, then we might have a - // call in the range. - if (FlagsSetInAll & MachineOutlinerMBBFlags::HasCalls) { - // check if the range contains a call. These require a save + restore of - // the link register. - if (std::any_of(FirstCand.front(), FirstCand.back(), - [](const MachineInstr &MI) { return MI.isCall(); })) - NumBytesToCreateFrame += Costs.SaveRestoreLROnStack; - - // Handle the last instruction separately. If it is tail call, then the - // last instruction is a call, we don't want to save + restore in this - // case. However, it could be possible that the last instruction is a - // call without it being valid to tail call this sequence. We should - // consider this as well. - else if (FrameID != MachineOutlinerThunk && - FrameID != MachineOutlinerTailCall && FirstCand.back()->isCall()) - NumBytesToCreateFrame += Costs.SaveRestoreLROnStack; + // If we outline this, we need to modify the stack. Pretend we don't + // outline this by saving all of its bytes. + else + NumBytesNoStackCalls += SequenceSize; } - RepeatedSequenceLocs = CandidatesWithoutStackFixups; + + // If there are no places where we have to save LR, then note that we don't + // have to update the stack. Otherwise, give every candidate the default + // call type. + if (NumBytesNoStackCalls <= + RepeatedSequenceLocs.size() * Costs.CallDefault) { + RepeatedSequenceLocs = CandidatesWithoutStackFixups; + FrameID = MachineOutlinerNoLRSave; + } else + SetCandidateCallInfo(MachineOutlinerDefault, Costs.CallDefault); + } + + // Does every candidate's MBB contain a call? If so, then we might have a + // call in the range. + if (FlagsSetInAll & MachineOutlinerMBBFlags::HasCalls) { + // check if the range contains a call. These require a save + restore of + // the link register. + if (std::any_of(FirstCand.front(), FirstCand.back(), + [](const MachineInstr &MI) { return MI.isCall(); })) + NumBytesToCreateFrame += Costs.SaveRestoreLROnStack; + + // Handle the last instruction separately. If it is tail call, then the + // last instruction is a call, we don't want to save + restore in this + // case. However, it could be possible that the last instruction is a + // call without it being valid to tail call this sequence. We should + // consider this as well. + else if (FrameID != MachineOutlinerThunk && + FrameID != MachineOutlinerTailCall && FirstCand.back()->isCall()) + NumBytesToCreateFrame += Costs.SaveRestoreLROnStack; } return outliner::OutlinedFunction(RepeatedSequenceLocs, SequenceSize, NumBytesToCreateFrame, FrameID); } +bool ARMBaseInstrInfo::checkAndUpdateStackOffset(MachineInstr *MI, + int64_t Fixup, + bool Updt) const { + int SPIdx = MI->findRegisterUseOperandIdx(ARM::SP); + if (SPIdx < 0) + // No SP operand + return true; + + unsigned AddrMode = (MI->getDesc().TSFlags & ARMII::AddrModeMask); + + // Stack might be involved but addressing mode doesn't handle any offset. + // Rq: AddrModeT1_[1|2|4] don't operate on SP + if (AddrMode == ARMII::AddrMode1 // Arithmetic instructions + || AddrMode == ARMII::AddrMode4 // Load/Store Multiple + || AddrMode == ARMII::AddrMode6 // Neon Load/Store Multiple + || AddrMode == ARMII::AddrModeT2_so // SP can't be used as based register + || AddrMode == ARMII::AddrModeT2_pc // PCrel access + || AddrMode == ARMII::AddrMode2 // Used by PRE and POST indexed LD/ST + || AddrMode == ARMII::AddrModeNone) + return false; + + // If SP is not the base register we can't do much + if (SPIdx != 1) { + if (AddrMode != ARMII::AddrModeT2_i8s4) + return false; + else if (SPIdx != 2) + return false; + } + + unsigned NumOps = MI->getDesc().getNumOperands(); + unsigned ImmIdx = NumOps - 3; + + const MachineOperand &Offset = MI->getOperand(ImmIdx); + assert(Offset.isImm() && "Is not an immediate"); + int64_t OffVal = Offset.getImm(); + + if (OffVal < 0) + // Don't override data if the are below SP. + return false; + + unsigned NumBits = 0; + unsigned Scale = 1; + + switch (AddrMode) { + case ARMII::AddrMode3: + if (ARM_AM::getAM3Op(OffVal) == ARM_AM::sub) + return false; + OffVal = ARM_AM::getAM3Offset(OffVal); + NumBits = 8; + break; + case ARMII::AddrMode5: + if (ARM_AM::getAM5Op(OffVal) == ARM_AM::sub) + return false; + OffVal = ARM_AM::getAM5Offset(OffVal); + NumBits = 8; + Scale = 4; + break; + case ARMII::AddrMode5FP16: + if (ARM_AM::getAM5FP16Op(OffVal) == ARM_AM::sub) + return false; + OffVal = ARM_AM::getAM5FP16Offset(OffVal); + NumBits = 8; + Scale = 2; + break; + case ARMII::AddrModeT2_i8: + NumBits = 8; + break; + case ARMII::AddrModeT2_i8s4: + case ARMII::AddrModeT2_ldrex: + NumBits = 8; + Scale = 4; + break; + case ARMII::AddrModeT2_i12: + case ARMII::AddrMode_i12: + NumBits = 12; + break; + case ARMII::AddrModeT2_i7: + NumBits = 7; + break; + case ARMII::AddrModeT2_i7s2: + NumBits = 7; + Scale = 2; + break; + case ARMII::AddrModeT2_i7s4: + NumBits = 7; + Scale = 4; + break; + case ARMII::AddrModeT1_s: // SP-relative LD/ST + NumBits = 8; + Scale = 4; + break; + default: + llvm_unreachable("Unsupported addressing mode!"); + } + // Make sure the offset is encodable for instructions that scale the + // immediate. + if (((OffVal * Scale + Fixup) & (Scale - 1)) != 0) + return false; + + OffVal += Fixup / Scale; + + unsigned Mask = (1 << NumBits) - 1; + + if (OffVal <= Mask) { + if (Updt) + MI->getOperand(ImmIdx).setImm(OffVal); + return true; + } + + return false; +} + bool ARMBaseInstrInfo::isFunctionSafeToOutlineFrom( MachineFunction &MF, bool OutlineFromLinkOnceODRs) const { const Function &F = MF.getFunction(); @@ -6055,6 +6179,19 @@ if (!MightNeedStackFixUp) return outliner::InstrType::Legal; + // Any modification of SP will break our code to save/restore LR. + // FIXME: We could handle some instructions which add a constant offset to + // SP, with a bit more work. + if (MI.modifiesRegister(ARM::SP, TRI)) + return outliner::InstrType::Illegal; + + // At this point, we have a stack instruction that we might need to fix up. + // up. We'll handle it if it's a load or store. + if (checkAndUpdateStackOffset(&MI, Subtarget.getStackAlignment().value(), + false)) + return outliner::InstrType::Legal; + + // We can't fix it up, so don't outline it. return outliner::InstrType::Illegal; } @@ -6070,6 +6207,14 @@ return outliner::InstrType::Legal; } +void ARMBaseInstrInfo::fixupPostOutline(MachineBasicBlock &MBB) const { + for (MachineInstr &MI : MBB) { + if (!MI.mayLoadOrStore()) + continue; + checkAndUpdateStackOffset(&MI, Subtarget.getStackAlignment().value(), true); + } +} + void ARMBaseInstrInfo::saveLROnStack(MachineBasicBlock &MBB, MachineBasicBlock::iterator It) const { unsigned Opc = Subtarget.isThumb() ? ARM::t2STR_PRE : ARM::STR_PRE_IMM; @@ -6205,6 +6350,12 @@ saveLROnStack(MBB, It); emitCFIForLRSaveOnStack(MBB, It); + // Fix up the instructions in the range, since we're going to modify the + // stack. + assert(OF.FrameConstructionID != MachineOutlinerDefault && + "Can only fix up stack references once"); + fixupPostOutline(MBB); + // Insert a restore before the terminator for the function. Restore LR. restoreLRFromStack(MBB, Et); emitCFIForLRRestoreFromStack(MBB, Et); @@ -6219,6 +6370,15 @@ // current feature set. BuildMI(MBB, MBB.end(), DebugLoc(), get(Subtarget.getReturnOpcode())) .add(predOps(ARMCC::AL)); + + // Did we have to modify the stack by saving the link register? + if (OF.FrameConstructionID != MachineOutlinerDefault && + OF.Candidates[0].CallConstructionID != MachineOutlinerDefault) + return; + + // We modified the stack. + // Walk over the basic block and fix up all the stack accesses. + fixupPostOutline(MBB); } MachineBasicBlock::iterator ARMBaseInstrInfo::insertOutlinedCall( @@ -6275,6 +6435,8 @@ return CallPt; } // We have the default case. Save and restore from SP. + if (!MBB.isLiveIn(ARM::LR)) + MBB.addLiveIn(ARM::LR); saveLROnStack(MBB, It); if (!AFI.isLRSpilled()) emitCFIForLRSaveOnStack(MBB, It); diff --git a/llvm/test/CodeGen/ARM/machine-outliner-calls.mir b/llvm/test/CodeGen/ARM/machine-outliner-calls.mir --- a/llvm/test/CodeGen/ARM/machine-outliner-calls.mir +++ b/llvm/test/CodeGen/ARM/machine-outliner-calls.mir @@ -88,15 +88,15 @@ ; CHECK: frame-setup CFI_INSTRUCTION def_cfa_offset 8 ; CHECK: frame-setup CFI_INSTRUCTION offset $lr, -4 ; CHECK: frame-setup CFI_INSTRUCTION offset $r7, -8 - ; CHECK: tBL 14 /* CC::al */, $noreg, @OUTLINED_FUNCTION_3 + ; CHECK: tBL 14 /* CC::al */, $noreg, @OUTLINED_FUNCTION_4 ; CHECK: bb.1: - ; CHECK: tBL 14 /* CC::al */, $noreg, @OUTLINED_FUNCTION_3 + ; CHECK: tBL 14 /* CC::al */, $noreg, @OUTLINED_FUNCTION_4 ; CHECK: bb.2: - ; CHECK: tBL 14 /* CC::al */, $noreg, @OUTLINED_FUNCTION_3 + ; CHECK: tBL 14 /* CC::al */, $noreg, @OUTLINED_FUNCTION_4 ; CHECK: bb.3: - ; CHECK: tBL 14 /* CC::al */, $noreg, @OUTLINED_FUNCTION_3 + ; CHECK: tBL 14 /* CC::al */, $noreg, @OUTLINED_FUNCTION_4 ; CHECK: bb.4: - ; CHECK: tBL 14 /* CC::al */, $noreg, @OUTLINED_FUNCTION_3 + ; CHECK: tBL 14 /* CC::al */, $noreg, @OUTLINED_FUNCTION_4 ; CHECK: bb.5: ; CHECK: $sp = frame-destroy t2LDMIA_RET $sp, 14 /* CC::al */, $noreg, def $r7, def $pc bb.0: @@ -139,12 +139,14 @@ ; CHECK: frame-setup CFI_INSTRUCTION def_cfa_offset 8 ; CHECK: frame-setup CFI_INSTRUCTION offset $lr, -4 ; CHECK: frame-setup CFI_INSTRUCTION offset $r4, -8 - ; CHECK: BL @OUTLINED_FUNCTION_2 + ; CHECK: BL @OUTLINED_FUNCTION_1 ; CHECK: bb.1: - ; CHECK: BL @OUTLINED_FUNCTION_2 + ; CHECK: BL @OUTLINED_FUNCTION_1 ; CHECK: bb.2: - ; CHECK: BL @OUTLINED_FUNCTION_2 + ; CHECK: BL @OUTLINED_FUNCTION_1 ; CHECK: bb.3: + ; CHECK: BL @OUTLINED_FUNCTION_1 + ; CHECK: bb.4: ; CHECK: $sp = frame-destroy LDMIA_UPD $sp, 14 /* CC::al */, $noreg, def $r4, def $lr ; CHECK: BX_RET 14 /* CC::al */, $noreg bb.0: @@ -172,6 +174,14 @@ $r4 = MOVi 2, 14, $noreg, $noreg BL @bar, implicit-def dead $lr, implicit $sp bb.3: + 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 + BL @bar, implicit-def dead $lr, implicit $sp + bb.4: BX_RET 14, $noreg ... --- @@ -186,12 +196,14 @@ ; CHECK: frame-setup CFI_INSTRUCTION def_cfa_offset 8 ; CHECK: frame-setup CFI_INSTRUCTION offset $lr, -4 ; CHECK: frame-setup CFI_INSTRUCTION offset $r7, -8 - ; CHECK: tBL 14 /* CC::al */, $noreg, @OUTLINED_FUNCTION_4 + ; CHECK: tBL 14 /* CC::al */, $noreg, @OUTLINED_FUNCTION_3 ; CHECK: bb.1: - ; CHECK: tBL 14 /* CC::al */, $noreg, @OUTLINED_FUNCTION_4 + ; CHECK: tBL 14 /* CC::al */, $noreg, @OUTLINED_FUNCTION_3 ; CHECK: bb.2: - ; CHECK: tBL 14 /* CC::al */, $noreg, @OUTLINED_FUNCTION_4 + ; CHECK: tBL 14 /* CC::al */, $noreg, @OUTLINED_FUNCTION_3 ; CHECK: bb.3: + ; CHECK: tBL 14 /* CC::al */, $noreg, @OUTLINED_FUNCTION_3 + ; CHECK: bb.4: ; CHECK: $sp = frame-destroy t2LDMIA_RET $sp, 14 /* CC::al */, $noreg, def $r7, def $pc bb.0: tBL 14, $noreg, @bar, implicit-def dead $lr, implicit $sp @@ -212,6 +224,12 @@ $r2 = t2MOVi 2, 14, $noreg, $noreg tBL 14, $noreg, @bar, implicit-def dead $lr, implicit $sp bb.3: + 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 + tBL 14, $noreg, @bar, implicit-def dead $lr, implicit $sp + bb.4: tBX_RET 14, $noreg ... --- @@ -227,19 +245,19 @@ ; CHECK: frame-setup CFI_INSTRUCTION offset $lr, -4 ; CHECK: frame-setup CFI_INSTRUCTION offset $r4, -8 ; CHECK: BL @"\01mcount", csr_aapcs, implicit-def dead $lr, implicit $sp - ; CHECK: BL @OUTLINED_FUNCTION_1 + ; CHECK: BL @OUTLINED_FUNCTION_2 ; CHECK: bb.1: ; CHECK: BL @"\01mcount", csr_aapcs, implicit-def dead $lr, implicit $sp - ; CHECK: BL @OUTLINED_FUNCTION_1 + ; CHECK: BL @OUTLINED_FUNCTION_2 ; CHECK: bb.2: ; CHECK: BL @"\01mcount", csr_aapcs, implicit-def dead $lr, implicit $sp - ; CHECK: BL @OUTLINED_FUNCTION_1 + ; CHECK: BL @OUTLINED_FUNCTION_2 ; CHECK: bb.3: ; CHECK: BL @"\01mcount", csr_aapcs, implicit-def dead $lr, implicit $sp - ; CHECK: BL @OUTLINED_FUNCTION_1 + ; CHECK: BL @OUTLINED_FUNCTION_2 ; CHECK: bb.4: ; CHECK: BL @"\01mcount", csr_aapcs, implicit-def dead $lr, implicit $sp - ; CHECK: BL @OUTLINED_FUNCTION_1 + ; CHECK: BL @OUTLINED_FUNCTION_2 ; CHECK: bb.5: ; CHECK: $sp = frame-destroy LDMIA_UPD $sp, 14 /* CC::al */, $noreg, def $r4, def $lr ; CHECK: BX_RET 14 /* CC::al */, $noreg @@ -307,16 +325,6 @@ ; CHECK-LABEL: name: OUTLINED_FUNCTION_1 ; CHECK: bb.0: - ; CHECK: liveins: $r11, $r10, $r9, $r8, $r7, $r6, $r5, $d15, $d14, $d13, $d12, $d11, $d10, $d9, $d8 - ; CHECK: $r0 = MOVi 3, 14 /* CC::al */, $noreg, $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: MOVPCLR 14 /* CC::al */, $noreg - - ; CHECK-LABEL: name: OUTLINED_FUNCTION_2 - ; CHECK: bb.0: ; CHECK: liveins: $r11, $r10, $r9, $r8, $r7, $r6, $r5, $d15, $d14, $d13, $d12, $d11, $d10, $d9, $d8, $lr ; CHECK: early-clobber $sp = STR_PRE_IMM killed $lr, $sp, -8, 14 /* CC::al */, $noreg ; CHECK: frame-setup CFI_INSTRUCTION def_cfa_offset 8 @@ -330,6 +338,16 @@ ; CHECK: $lr, $sp = LDR_POST_IMM $sp, $noreg, 8, 14 /* CC::al */, $noreg ; CHECK: TAILJMPd @bar, implicit $sp + ; CHECK-LABEL: name: OUTLINED_FUNCTION_2 + ; CHECK: bb.0: + ; CHECK: liveins: $r11, $r10, $r9, $r8, $r7, $r6, $r5, $d15, $d14, $d13, $d12, $d11, $d10, $d9, $d8 + ; CHECK: $r0 = MOVi 3, 14 /* CC::al */, $noreg, $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: MOVPCLR 14 /* CC::al */, $noreg + ; CHECK-LABEL: name: OUTLINED_FUNCTION_3 ; CHECK: bb.0: ; CHECK: liveins: $r11, $r10, $r9, $r8, $r6, $r5, $r4, $d15, $d14, $d13, $d12, $d11, $d10, $d9, $d8, $lr @@ -337,11 +355,11 @@ ; CHECK: frame-setup CFI_INSTRUCTION def_cfa_offset 8 ; CHECK: frame-setup CFI_INSTRUCTION offset $lr, -8 ; CHECK: tBL 14 /* CC::al */, $noreg, @bar, implicit-def dead $lr, implicit $sp - ; 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: $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: $lr, $sp = t2LDR_POST $sp, 8, 14 /* CC::al */, $noreg - ; CHECK: tBX_RET 14 /* CC::al */, $noreg + ; CHECK: tTAILJMPdND @bar, 14 /* CC::al */, $noreg, implicit $sp ; CHECK-LABEL: name: OUTLINED_FUNCTION_4 ; CHECK: bb.0: @@ -350,11 +368,11 @@ ; CHECK: frame-setup CFI_INSTRUCTION def_cfa_offset 8 ; CHECK: frame-setup CFI_INSTRUCTION offset $lr, -8 ; 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: $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: $lr, $sp = t2LDR_POST $sp, 8, 14 /* CC::al */, $noreg - ; CHECK: tTAILJMPdND @bar, 14 /* CC::al */, $noreg, implicit $sp + ; CHECK: tBX_RET 14 /* CC::al */, $noreg diff --git a/llvm/test/CodeGen/ARM/machine-outliner-default.mir b/llvm/test/CodeGen/ARM/machine-outliner-default.mir --- a/llvm/test/CodeGen/ARM/machine-outliner-default.mir +++ b/llvm/test/CodeGen/ARM/machine-outliner-default.mir @@ -5,8 +5,8 @@ --- | define void @outline_default_arm() #0 { ret void } define void @outline_default_thumb() #1 { ret void } - define void @outline_default_KO_stack_arm() #0 { ret void } - define void @outline_default_KO_stack_thumb() #0 { ret void } + define void @outline_default_OK_stack_arm() #0 { ret void } + define void @outline_default_OK_stack_thumb() #1 { ret void } declare void @bar() attributes #0 = { minsize optsize } @@ -21,17 +21,17 @@ ; 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: BL @OUTLINED_FUNCTION_2 ; 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: BL @OUTLINED_FUNCTION_2 ; 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: BL @OUTLINED_FUNCTION_2 ; 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 @@ -75,17 +75,17 @@ ; 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: tBL 14 /* CC::al */, $noreg, @OUTLINED_FUNCTION_3 ; 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: tBL 14 /* CC::al */, $noreg, @OUTLINED_FUNCTION_3 ; 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: tBL 14 /* CC::al */, $noreg, @OUTLINED_FUNCTION_3 ; 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 @@ -116,34 +116,25 @@ ... --- -name: outline_default_KO_stack_arm +name: outline_default_OK_stack_arm tracksRegLiveness: true body: | - ; CHECK-LABEL: name: outline_default_KO_stack_arm + ; CHECK-LABEL: name: outline_default_OK_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: 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.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: 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.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: 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, $r5, $r6, $r7, $r8, $r9, $r10, $r11 ; CHECK: $r2 = MOVr $lr, 14 /* CC::al */, $noreg, $noreg @@ -179,30 +170,27 @@ ... --- -name: outline_default_KO_stack_thumb +name: outline_default_OK_stack_thumb tracksRegLiveness: true body: | - ; CHECK-LABEL: name: outline_default_KO_stack_thumb + ; CHECK-LABEL: name: outline_default_OK_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: 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.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: liveins: $lr, $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_0 + ; 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: $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: liveins: $lr, $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_0 + ; 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: liveins: $lr, $r6, $r7, $r8, $r9, $r10, $r11 ; CHECK: $r2 = tMOVr $lr, 14 /* CC::al */, $noreg ; CHECK: tBX_RET 14 /* CC::al */, $noreg bb.0: @@ -211,20 +199,26 @@ $r1 = t2MOVi 3, 14, $noreg, $noreg $r2 = t2MOVi 3, 14, $noreg, $noreg $r3 = t2MOVi 3, 14, $noreg, $noreg + $r4 = t2MOVi 3, 14, $noreg, $noreg + $r5 = t2MOVi 3, 14, $noreg, $noreg bb.1: - liveins: $lr, $r4, $r5, $r6, $r7, $r8, $r9, $r10, $r11 + liveins: $lr, $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 + $r4 = t2MOVi 3, 14, $noreg, $noreg + $r5 = t2MOVi 3, 14, $noreg, $noreg bb.2: - liveins: $lr, $r4, $r5, $r6, $r7, $r8, $r9, $r10, $r11 + liveins: $lr, $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 + $r4 = t2MOVi 3, 14, $noreg, $noreg + $r5 = t2MOVi 3, 14, $noreg, $noreg bb.3: - liveins: $lr, $r4, $r5, $r6, $r7, $r8, $r9, $r10, $r11 + liveins: $lr, $r6, $r7, $r8, $r9, $r10, $r11 $r2 = tMOVr $lr, 14, $noreg tBX_RET 14, $noreg @@ -232,6 +226,28 @@ ; CHECK-LABEL: name: OUTLINED_FUNCTION_0 ; CHECK: bb.0: ; CHECK: liveins: $lr, $r6, $r7, $r8, $r9, $r10, $r11 + ; CHECK: $r0 = t2LDRi12 $sp, 8, 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: $r4 = t2MOVi 3, 14 /* CC::al */, $noreg, $noreg + ; CHECK: $r5 = t2MOVi 3, 14 /* CC::al */, $noreg, $noreg + ; CHECK: tBX_RET 14 /* CC::al */, $noreg + + ; CHECK-LABEL: name: OUTLINED_FUNCTION_1 + ; CHECK: bb.0: + ; CHECK: liveins: $lr, $r11, $r6, $r7, $r8, $r9, $r10 + ; CHECK: $r0 = LDRi12 $sp, 8, 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: MOVPCLR 14 /* CC::al */, $noreg + + ; CHECK-LABEL: name: OUTLINED_FUNCTION_2 + ; 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 @@ -240,7 +256,7 @@ ; CHECK: $r5 = MOVi 1, 14 /* CC::al */, $noreg, $noreg ; CHECK: MOVPCLR 14 /* CC::al */, $noreg - ; CHECK-LABEL: name: OUTLINED_FUNCTION_1 + ; CHECK-LABEL: name: OUTLINED_FUNCTION_3 ; CHECK: bb.0: ; CHECK: liveins: $lr, $r4, $r5, $r6, $r7, $r8, $r9, $r10, $r11 ; CHECK: $r0 = t2MOVi 1, 14 /* CC::al */, $noreg, $noreg diff --git a/llvm/test/CodeGen/ARM/machine-outliner-no-lr-save.mir b/llvm/test/CodeGen/ARM/machine-outliner-no-lr-save.mir --- a/llvm/test/CodeGen/ARM/machine-outliner-no-lr-save.mir +++ b/llvm/test/CodeGen/ARM/machine-outliner-no-lr-save.mir @@ -4,9 +4,7 @@ --- | define void @outline_no_save_ok_arm() #0 { ret void } - define void @outline_no_save_ko_arm() #0 { ret void } define void @outline_no_save_ok_thumb() #1 { ret void } - define void @outline_no_save_ko_thumb() #1 { ret void } declare void @foo() @@ -42,33 +40,6 @@ ... --- -name: outline_no_save_ko_arm -tracksRegLiveness: true -body: | - ; CHECK-LABEL: name: outline_no_save_ko_arm - ; CHECK-NOT: OUTLINED_FUNCTION - bb.0: - liveins: $lr - $r2 = MOVi 2, 14, $noreg, $noreg - $r2 = MOVi 2, 14, $noreg, $noreg - $r2 = MOVi 2, 14, $noreg, $noreg - $r2 = MOVi 2, 14, $noreg, $noreg - $r3 = LDRi12 $sp, 8, 14, $noreg - $r2 = MOVr $lr, 14, $noreg, $noreg - bb.1: - $r2 = MOVi 2, 14, $noreg, $noreg - $r2 = MOVi 2, 14, $noreg, $noreg - $r2 = MOVi 2, 14, $noreg, $noreg - $r2 = MOVi 2, 14, $noreg, $noreg - $r3 = LDRi12 $sp, 8, 14, $noreg - $r4 = MOVi 4, 14, $noreg, $noreg - BL @foo - bb.2: - liveins: $lr - BX_RET 14, $noreg -... ---- - name: outline_no_save_ok_thumb tracksRegLiveness: true body: | @@ -93,33 +64,6 @@ t2STRi12 $r2, $sp, 0, 14, $noreg bb.2: tBX_RET 14, $noreg -... ---- - -name: outline_no_save_ko_thumb -tracksRegLiveness: true -body: | - ; CHECK-LABEL: name: outline_no_save_ko_thumb - ; CHECK-NOT: OUTLINED_FUNCTION - bb.0: - liveins: $lr - $r2 = t2MOVi 2, 14, $noreg, $noreg - $r2 = t2MOVi 2, 14, $noreg, $noreg - $r2 = t2MOVi 2, 14, $noreg, $noreg - $r2 = t2MOVi 2, 14, $noreg, $noreg - t2STRi12 $r2, $sp, 0, 14, $noreg - $r2 = tMOVr $lr, 14, $noreg - bb.1: - $r2 = t2MOVi 2, 14, $noreg, $noreg - $r2 = t2MOVi 2, 14, $noreg, $noreg - $r2 = t2MOVi 2, 14, $noreg, $noreg - $r2 = t2MOVi 2, 14, $noreg, $noreg - t2STRi12 $r2, $sp, 0, 14, $noreg - $r4 = t2MOVi 3, 14, $noreg, $noreg - tBL 14, $noreg, @foo - bb.2: - liveins: $lr, $r0, $r6, $r7, $r8, $r9, $r10, $r11 - tBX_RET 14, $noreg ; CHECK-LABEL: name: OUTLINED_FUNCTION_0 ; CHECK: bb.0: diff --git a/llvm/test/CodeGen/ARM/machine-outliner-stack-fixup-arm.mir b/llvm/test/CodeGen/ARM/machine-outliner-stack-fixup-arm.mir new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/ARM/machine-outliner-stack-fixup-arm.mir @@ -0,0 +1,186 @@ +# RUN: llc -mtriple=armv7-- -run-pass=prologepilog -run-pass=machine-outliner \ +# RUN: -verify-machineinstrs %s -o - | FileCheck %s + +--- | + define void @CheckAddrMode_i12() { ret void } + define void @CheckAddrMode3() { ret void } + define void @CheckAddrMode5() { ret void } + define void @CheckAddrMode5FP16() { ret void } + define void @foo() { ret void } + +... +--- + +name: CheckAddrMode_i12 +tracksRegLiveness: true +body: | + bb.0: + liveins: $r0 + ; CHECK-LABEL: name: CheckAddrMode_i12 + ; CHECK: $r1 = MOVr killed $r0, 14 /* CC::al */, $noreg, $noreg + ; CHECK-NEXT: BL @OUTLINED_FUNCTION_[[I12:[0-9]+]] + ; CHECK-NEXT: $r6 = LDRi12 $sp, 4088, 14 /* CC::al */, $noreg + $r1 = MOVr killed $r0, 14, $noreg, $noreg + BL @foo, implicit-def dead $lr, implicit $sp + $r1 = LDRi12 $sp, 0, 14, $noreg + $r2 = LDRi12 $sp, 8, 14, $noreg + $r5 = LDRi12 $sp, 4086, 14, $noreg + $r6 = LDRi12 $sp, 4088, 14, $noreg + BL @foo, implicit-def dead $lr, implicit $sp + $r1 = LDRi12 $sp, 0, 14, $noreg + $r2 = LDRi12 $sp, 8, 14, $noreg + $r5 = LDRi12 $sp, 4086, 14, $noreg + $r6 = LDRi12 $sp, 4088, 14, $noreg + BL @foo, implicit-def dead $lr, implicit $sp + $r1 = LDRi12 $sp, 0, 14, $noreg + $r2 = LDRi12 $sp, 8, 14, $noreg + $r5 = LDRi12 $sp, 4086, 14, $noreg + $r6 = LDRi12 $sp, 4088, 14, $noreg + BX_RET 14, $noreg +... +--- + +name: CheckAddrMode3 +tracksRegLiveness: true +body: | + bb.0: + liveins: $r1 + ; CHECK-LABEL: name: CheckAddrMode3 + ; CHECK: $r0 = MOVr killed $r1, 14 /* CC::al */, $noreg, $noreg + ; CHECK-NEXT: BL @OUTLINED_FUNCTION_[[I3:[0-9]+]] + ; CHECK-NEXT: $r6 = LDRSH $sp, $noreg, 248, 14 /* CC::al */, $noreg + $r0 = MOVr killed $r1, 14, $noreg, $noreg + BL @foo, implicit-def dead $lr, implicit $sp + $r1 = LDRSH $sp, $noreg, 0, 14, $noreg + $r2 = LDRSH $sp, $noreg, 8, 14, $noreg + $r5 = LDRSH $sp, $noreg, 247, 14, $noreg + $r6 = LDRSH $sp, $noreg, 248, 14, $noreg + BL @foo, implicit-def dead $lr, implicit $sp + $r1 = LDRSH $sp, $noreg, 0, 14, $noreg + $r2 = LDRSH $sp, $noreg, 8, 14, $noreg + $r5 = LDRSH $sp, $noreg, 247, 14, $noreg + $r6 = LDRSH $sp, $noreg, 248, 14, $noreg + BL @foo, implicit-def dead $lr, implicit $sp + $r1 = LDRSH $sp, $noreg, 0, 14, $noreg + $r2 = LDRSH $sp, $noreg, 8, 14, $noreg + $r5 = LDRSH $sp, $noreg, 247, 14, $noreg + $r6 = LDRSH $sp, $noreg, 248, 14, $noreg + BX_RET 14, $noreg +... +--- + +name: CheckAddrMode5 +tracksRegLiveness: true +body: | + bb.0: + liveins: $r2 + ; CHECK-LABEL: name: CheckAddrMode5 + ; CHECK: $r0 = MOVr killed $r2, 14 /* CC::al */, $noreg, $noreg + ; CHECK-NEXT: BL @OUTLINED_FUNCTION_[[I5:[0-9]+]] + ; CHECK-NEXT: $d5 = VLDRD $sp, 254, 14 /* CC::al */, $noreg + $r0 = MOVr killed $r2, 14, $noreg, $noreg + BL @foo, implicit-def dead $lr, implicit $sp + $d0 = VLDRD $sp, 0, 14, $noreg + $d1 = VLDRD $sp, 8, 14, $noreg + $d4 = VLDRD $sp, 253, 14, $noreg + $d5 = VLDRD $sp, 254, 14, $noreg + BL @foo, implicit-def dead $lr, implicit $sp + $d0 = VLDRD $sp, 0, 14, $noreg + $d1 = VLDRD $sp, 8, 14, $noreg + $d4 = VLDRD $sp, 253, 14, $noreg + $d5 = VLDRD $sp, 254, 14, $noreg + BL @foo, implicit-def dead $lr, implicit $sp + $d0 = VLDRD $sp, 0, 14, $noreg + $d1 = VLDRD $sp, 8, 14, $noreg + $d4 = VLDRD $sp, 253, 14, $noreg + $d5 = VLDRD $sp, 254, 14, $noreg + BL @foo, implicit-def dead $lr, implicit $sp + $d0 = VLDRD $sp, 0, 14, $noreg + $d1 = VLDRD $sp, 8, 14, $noreg + $d4 = VLDRD $sp, 253, 14, $noreg + $d5 = VLDRD $sp, 254, 14, $noreg + BX_RET 14, $noreg +... +--- + +name: CheckAddrMode5FP16 +tracksRegLiveness: true +body: | + bb.0: + liveins: $r3 + ; CHECK-LABEL: name: CheckAddrMode5FP16 + ; CHECK: $r0 = MOVr killed $r3, 14 /* CC::al */, $noreg, $noreg + ; CHECK-NEXT: BL @OUTLINED_FUNCTION_[[I5FP16:[0-9]+]] + ; CHECK-NEXT: $s6 = VLDRH $sp, 252, 14, $noreg + $r0 = MOVr killed $r3, 14, $noreg, $noreg + BL @foo, implicit-def dead $lr, implicit $sp + $s1 = VLDRH $sp, 0, 14, $noreg + $s2 = VLDRH $sp, 8, 14, $noreg + $s5 = VLDRH $sp, 240, 14, $noreg + $s6 = VLDRH $sp, 252, 14, $noreg + BL @foo, implicit-def dead $lr, implicit $sp + $s1 = VLDRH $sp, 0, 14, $noreg + $s2 = VLDRH $sp, 8, 14, $noreg + $s5 = VLDRH $sp, 240, 14, $noreg + $s6 = VLDRH $sp, 252, 14, $noreg + BL @foo, implicit-def dead $lr, implicit $sp + $s1 = VLDRH $sp, 0, 14, $noreg + $s2 = VLDRH $sp, 8, 14, $noreg + $s5 = VLDRH $sp, 240, 14, $noreg + $s6 = VLDRH $sp, 252, 14, $noreg + BL @foo, implicit-def dead $lr, implicit $sp + $s1 = VLDRH $sp, 0, 14, $noreg + $s2 = VLDRH $sp, 8, 14, $noreg + $s5 = VLDRH $sp, 240, 14, $noreg + $s6 = VLDRH $sp, 252, 14, $noreg + BX_RET 14, $noreg +... +--- + +name: foo +tracksRegLiveness: true +body: | + bb.0: + liveins: $lr + + BX_RET 14, $noreg + + ;CHECK: name: OUTLINED_FUNCTION_[[I5]] + ;CHECK: early-clobber $sp = STR_PRE_IMM killed $lr, $sp, -8, 14 /* CC::al */, $noreg + ;CHECK-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset 8 + ;CHECK-NEXT: frame-setup CFI_INSTRUCTION offset $lr, -8 + ;CHECK-NEXT: BL @foo, implicit-def dead $lr, implicit $sp + ;CHECK-NEXT: $d0 = VLDRD $sp, 2, 14 /* CC::al */, $noreg + ;CHECK-NEXT: $d1 = VLDRD $sp, 10, 14 /* CC::al */, $noreg + ;CHECK-NEXT: $d4 = VLDRD $sp, 255, 14 /* CC::al */, $noreg + ;CHECK-NEXT: $lr, $sp = LDR_POST_IMM $sp, $noreg, 8, 14 /* CC::al */, $noreg + + ;CHECK: name: OUTLINED_FUNCTION_[[I5FP16]] + ;CHECK: early-clobber $sp = STR_PRE_IMM killed $lr, $sp, -8, 14 /* CC::al */, $noreg + ;CHECK-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset 8 + ;CHECK-NEXT: frame-setup CFI_INSTRUCTION offset $lr, -8 + ;CHECK-NEXT: BL @foo, implicit-def dead $lr, implicit $sp + ;CHECK-NEXT: $s1 = VLDRH $sp, 4, 14, $noreg + ;CHECK-NEXT: $s2 = VLDRH $sp, 12, 14, $noreg + ;CHECK-NEXT: $s5 = VLDRH $sp, 244, 14, $noreg + ;CHECK-NEXT: $lr, $sp = LDR_POST_IMM $sp, $noreg, 8, 14 /* CC::al */, $noreg + + ;CHECK: name: OUTLINED_FUNCTION_[[I12]] + ;CHECK: early-clobber $sp = STR_PRE_IMM killed $lr, $sp, -8, 14 /* CC::al */, $noreg + ;CHECK-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset 8 + ;CHECK-NEXT: frame-setup CFI_INSTRUCTION offset $lr, -8 + ;CHECK-NEXT: BL @foo, implicit-def dead $lr, implicit $sp + ;CHECK-NEXT: $r1 = LDRi12 $sp, 8, 14 /* CC::al */, $noreg + ;CHECK-NEXT: $r2 = LDRi12 $sp, 16, 14 /* CC::al */, $noreg + ;CHECK-NEXT: $r5 = LDRi12 $sp, 4094, 14 /* CC::al */, $noreg + ;CHECK-NEXT: $lr, $sp = LDR_POST_IMM $sp, $noreg, 8, 14 /* CC::al */, $noreg + + ;CHECK: name: OUTLINED_FUNCTION_[[I3]] + ;CHECK: early-clobber $sp = STR_PRE_IMM killed $lr, $sp, -8, 14 /* CC::al */, $noreg + ;CHECK-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset 8 + ;CHECK-NEXT: frame-setup CFI_INSTRUCTION offset $lr, -8 + ;CHECK-NEXT: BL @foo, implicit-def dead $lr, implicit $sp + ;CHECK-NEXT: $r1 = LDRSH $sp, $noreg, 8, 14 /* CC::al */, $noreg + ;CHECK-NEXT: $r2 = LDRSH $sp, $noreg, 16, 14 /* CC::al */, $noreg + ;CHECK-NEXT: $r5 = LDRSH $sp, $noreg, 255, 14 /* CC::al */, $noreg + ;CHECK-NEXT: $lr, $sp = LDR_POST_IMM $sp, $noreg, 8, 14 /* CC::al */, $noreg diff --git a/llvm/test/CodeGen/ARM/machine-outliner-stack-fixup-thumb.mir b/llvm/test/CodeGen/ARM/machine-outliner-stack-fixup-thumb.mir new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/ARM/machine-outliner-stack-fixup-thumb.mir @@ -0,0 +1,231 @@ +# RUN: llc -mtriple=thumbv7-- -run-pass=prologepilog \ +# RUN: -run-pass=machine-outliner %s -o - | FileCheck %s + +--- | + define void @CheckAddrModeT2_i12() { ret void } + define void @CheckAddrModeT2_i8() { ret void } + define void @CheckAddrModeT2_i8s4() { ret void } + define void @CheckAddrModeT2_ldrex() { ret void } + define void @CheckAddrModeT1_s() { ret void } + define void @foo() { ret void } + +... +--- + +name: CheckAddrModeT2_i12 +tracksRegLiveness: true + +body: | + bb.0: + liveins: $r1 + ;CHECK-LABEL: name: CheckAddrModeT2_i12 + ;CHECK: $r0 = tMOVr killed $r1, 14 /* CC::al */, $noreg + ;CHECK-NEXT: tBL 14 /* CC::al */, $noreg, @OUTLINED_FUNCTION_[[I12:[0-9]+]] + ;CHECK-NEXT: $r0 = t2LDRi12 $sp, 4088, 14 /* CC::al */, $noreg + $r0 = tMOVr killed $r1, 14, $noreg + tBL 14, $noreg, @foo, implicit-def dead $lr, implicit $sp + $r0 = t2LDRi12 $sp, 0, 14, $noreg + $r0 = t2LDRi12 $sp, 4, 14, $noreg + $r0 = t2LDRi12 $sp, 4086, 14, $noreg + $r0 = t2LDRi12 $sp, 4088, 14, $noreg + tBL 14, $noreg, @foo, implicit-def dead $lr, implicit $sp + $r0 = t2LDRi12 $sp, 0, 14, $noreg + $r0 = t2LDRi12 $sp, 4, 14, $noreg + $r0 = t2LDRi12 $sp, 4086, 14, $noreg + $r0 = t2LDRi12 $sp, 4088, 14, $noreg + tBL 14, $noreg, @foo, implicit-def dead $lr, implicit $sp + $r0 = t2LDRi12 $sp, 0, 14, $noreg + $r0 = t2LDRi12 $sp, 4, 14, $noreg + $r0 = t2LDRi12 $sp, 4086, 14, $noreg + $r0 = t2LDRi12 $sp, 4088, 14, $noreg + BX_RET 14, $noreg +... +--- + +name: CheckAddrModeT2_i8 +tracksRegLiveness: true + +body: | + bb.0: + liveins: $r1 + ;CHECK-LABEL: name: CheckAddrModeT2_i8 + ;CHECK: $r0 = tMOVr $r1, 14 /* CC::al */, $noreg + ;CHECK-NEXT: tBL 14 /* CC::al */, $noreg, @OUTLINED_FUNCTION_[[I8:[0-9]+]] + ;CHECK-NEXT: t2STRHi8 $r0, $sp, 248, 14 /* CC::al */, $noreg + $r0 = tMOVr $r1, 14, $noreg + tBL 14, $noreg, @foo, implicit-def dead $lr, implicit $sp + t2STRHi8 $r0, $sp, 0, 14, $noreg + t2STRHi8 $r0, $sp, 4, 14, $noreg + t2STRHi8 $r0, $sp, 247, 14, $noreg + t2STRHi8 $r0, $sp, 248, 14, $noreg + tBL 14, $noreg, @foo, implicit-def dead $lr, implicit $sp + t2STRHi8 $r0, $sp, 0, 14, $noreg + t2STRHi8 $r0, $sp, 4, 14, $noreg + t2STRHi8 $r0, $sp, 247, 14, $noreg + t2STRHi8 $r0, $sp, 248, 14, $noreg + tBL 14, $noreg, @foo, implicit-def dead $lr, implicit $sp + t2STRHi8 $r0, $sp, 0, 14, $noreg + t2STRHi8 $r0, $sp, 4, 14, $noreg + t2STRHi8 $r0, $sp, 247, 14, $noreg + t2STRHi8 $r0, $sp, 248, 14, $noreg + BX_RET 14, $noreg +... +--- + +name: CheckAddrModeT2_i8s4 +tracksRegLiveness: true + +body: | + bb.0: + liveins: $r1 + ;CHECK-LABEL: name: CheckAddrModeT2_i8s4 + ;CHECK: $r0 = tMOVr $r1, 14 /* CC::al */, $noreg + ;CHECK-NEXT: tBL 14 /* CC::al */, $noreg, @OUTLINED_FUNCTION_[[I8S4:[0-9]+]] + ;CHECK-NEXT: t2STRDi8 $r0, $r1, $sp, 254, 14 /* CC::al */, $noreg + $r0 = tMOVr $r1, 14, $noreg + tBL 14, $noreg, @foo, implicit-def dead $lr, implicit $sp + t2STRDi8 $r0, $r1, $sp, 0, 14, $noreg + t2STRDi8 $r0, $r1, $sp, 8, 14, $noreg + t2STRDi8 $r0, $r1, $sp, 253, 14, $noreg + t2STRDi8 $r0, $r1, $sp, 254, 14, $noreg + tBL 14, $noreg, @foo, implicit-def dead $lr, implicit $sp + t2STRDi8 $r0, $r1, $sp, 0, 14, $noreg + t2STRDi8 $r0, $r1, $sp, 8, 14, $noreg + t2STRDi8 $r0, $r1, $sp, 253, 14, $noreg + t2STRDi8 $r0, $r1, $sp, 254, 14, $noreg + tBL 14, $noreg, @foo, implicit-def dead $lr, implicit $sp + t2STRDi8 $r0, $r1, $sp, 0, 14, $noreg + t2STRDi8 $r0, $r1, $sp, 8, 14, $noreg + t2STRDi8 $r0, $r1, $sp, 253, 14, $noreg + t2STRDi8 $r0, $r1, $sp, 254, 14, $noreg + BX_RET 14, $noreg +... +--- + +name: CheckAddrModeT2_ldrex +tracksRegLiveness: true + +body: | + bb.0: + liveins: $r1 + ;CHECK-LABEL: name: CheckAddrModeT2_ldrex + ;CHECK: $r0 = tMOVr $r1, 14 /* CC::al */, $noreg + ;CHECK-NEXT: tBL 14 /* CC::al */, $noreg, @OUTLINED_FUNCTION_[[LDREX:[0-9]+]] + ;CHECK-NEXT: $r1 = t2LDREX $sp, 254, 14 /* CC::al */, $noreg + $r0 = tMOVr $r1, 14, $noreg + tBL 14, $noreg, @foo, implicit-def dead $lr, implicit $sp + $r1 = t2LDREX $sp, 0, 14, $noreg + $r1 = t2LDREX $sp, 8, 14, $noreg + $r1 = t2LDREX $sp, 253, 14, $noreg + $r1 = t2LDREX $sp, 254, 14, $noreg + tBL 14, $noreg, @foo, implicit-def dead $lr, implicit $sp + $r1 = t2LDREX $sp, 0, 14, $noreg + $r1 = t2LDREX $sp, 8, 14, $noreg + $r1 = t2LDREX $sp, 253, 14, $noreg + $r1 = t2LDREX $sp, 254, 14, $noreg + tBL 14, $noreg, @foo, implicit-def dead $lr, implicit $sp + $r1 = t2LDREX $sp, 0, 14, $noreg + $r1 = t2LDREX $sp, 8, 14, $noreg + $r1 = t2LDREX $sp, 253, 14, $noreg + $r1 = t2LDREX $sp, 254, 14, $noreg + tBL 14, $noreg, @foo, implicit-def dead $lr, implicit $sp + $r1 = t2LDREX $sp, 0, 14, $noreg + $r1 = t2LDREX $sp, 8, 14, $noreg + $r1 = t2LDREX $sp, 253, 14, $noreg + $r1 = t2LDREX $sp, 254, 14, $noreg + BX_RET 14, $noreg +... +--- + +name: CheckAddrModeT1_s +tracksRegLiveness: true + +body: | + bb.0: + liveins: $r0, $r1 + ;CHECK-LABEL: name: CheckAddrModeT1_s + ;CHECK: $r0 = tMOVr $r1, 14 /* CC::al */, $noreg + ;CHECK-NEXT: tBL 14 /* CC::al */, $noreg, @OUTLINED_FUNCTION_[[T1_S:[0-9]+]] + ;CHECK-NEXT: tSTRspi $r0, $sp, 254, 14 /* CC::al */, $noreg + $r0 = tMOVr $r1, 14, $noreg + tBL 14, $noreg, @foo, implicit-def dead $lr, implicit $sp + tSTRspi $r0, $sp, 0, 14, $noreg + tSTRspi $r0, $sp, 4, 14, $noreg + tSTRspi $r0, $sp, 253, 14, $noreg + tSTRspi $r0, $sp, 254, 14, $noreg + tBL 14, $noreg, @foo, implicit-def dead $lr, implicit $sp + tSTRspi $r0, $sp, 0, 14, $noreg + tSTRspi $r0, $sp, 4, 14, $noreg + tSTRspi $r0, $sp, 253, 14, $noreg + tSTRspi $r0, $sp, 254, 14, $noreg + tBL 14, $noreg, @foo, implicit-def dead $lr, implicit $sp + tSTRspi $r0, $sp, 0, 14, $noreg + tSTRspi $r0, $sp, 4, 14, $noreg + tSTRspi $r0, $sp, 253, 14, $noreg + tSTRspi $r0, $sp, 254, 14, $noreg + tBL 14, $noreg, @foo, implicit-def dead $lr, implicit $sp + tSTRspi $r0, $sp, 0, 14, $noreg + tSTRspi $r0, $sp, 4, 14, $noreg + tSTRspi $r0, $sp, 253, 14, $noreg + tSTRspi $r0, $sp, 254, 14, $noreg + BX_RET 14, $noreg +... +--- + +name: foo +tracksRegLiveness: true +body: | + bb.0: + liveins: $lr + + BX_RET 14, $noreg + + ;CHECK: name: OUTLINED_FUNCTION_[[LDREX]] + ;CHECK: early-clobber $sp = t2STR_PRE killed $lr, $sp, -8, 14 /* CC::al */, $noreg + ;CHECK-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset 8 + ;CHECK-NEXT: frame-setup CFI_INSTRUCTION offset $lr, -8 + ;CHECK-NEXT: tBL 14 /* CC::al */, $noreg, @foo, implicit-def dead $lr, implicit $sp + ;CHECK-NEXT: $r1 = t2LDREX $sp, 2, 14 /* CC::al */, $noreg + ;CHECK-NEXT: $r1 = t2LDREX $sp, 10, 14 /* CC::al */, $noreg + ;CHECK-NEXT: $r1 = t2LDREX $sp, 255, 14 /* CC::al */, $noreg + ;CHECK-NEXT: $lr, $sp = t2LDR_POST $sp, 8, 14 /* CC::al */, $noreg + + ;CHECK: name: OUTLINED_FUNCTION_[[I8]] + ;CHECK: early-clobber $sp = t2STR_PRE killed $lr, $sp, -8, 14 /* CC::al */, $noreg + ;CHECK-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset 8 + ;CHECK-NEXT: frame-setup CFI_INSTRUCTION offset $lr, -8 + ;CHECK-NEXT: tBL 14 /* CC::al */, $noreg, @foo, implicit-def dead $lr, implicit $sp + ;CHECK-NEXT: t2STRHi8 $r0, $sp, 8, 14 /* CC::al */, $noreg + ;CHECK-NEXT: t2STRHi8 $r0, $sp, 12, 14 /* CC::al */, $noreg + ;CHECK-NEXT: t2STRHi8 $r0, $sp, 255, 14 /* CC::al */, $noreg + ;CHECK-NEXT: $lr, $sp = t2LDR_POST $sp, 8, 14 /* CC::al */, $noreg + + ;CHECK: name: OUTLINED_FUNCTION_[[I8S4]] + ;CHECK: early-clobber $sp = t2STR_PRE killed $lr, $sp, -8, 14 /* CC::al */, $noreg + ;CHECK-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset 8 + ;CHECK-NEXT: frame-setup CFI_INSTRUCTION offset $lr, -8 + ;CHECK-NEXT: tBL 14 /* CC::al */, $noreg, @foo, implicit-def dead $lr, implicit $sp + ;CHECK-NEXT: t2STRDi8 $r0, $r1, $sp, 2, 14 /* CC::al */, $noreg + ;CHECK-NEXT: t2STRDi8 $r0, $r1, $sp, 10, 14 /* CC::al */, $noreg + ;CHECK-NEXT: t2STRDi8 $r0, $r1, $sp, 255, 14 /* CC::al */, $noreg + ;CHECK-NEXT: $lr, $sp = t2LDR_POST $sp, 8, 14 /* CC::al */, $noreg + + ;CHECK: name: OUTLINED_FUNCTION_[[I12]] + ;CHECK: early-clobber $sp = t2STR_PRE killed $lr, $sp, -8, 14 /* CC::al */, $noreg + ;CHECK-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset 8 + ;CHECK-NEXT: frame-setup CFI_INSTRUCTION offset $lr, -8 + ;CHECK-NEXT: tBL 14 /* CC::al */, $noreg, @foo, implicit-def dead $lr, implicit $sp + ;CHECK-NEXT: $r0 = t2LDRi12 $sp, 8, 14 /* CC::al */, $noreg + ;CHECK-NEXT: $r0 = t2LDRi12 $sp, 12, 14 /* CC::al */, $noreg + ;CHECK-NEXT: $r0 = t2LDRi12 $sp, 4094, 14 /* CC::al */, $noreg + ;CHECK-NEXT: $lr, $sp = t2LDR_POST $sp, 8, 14 /* CC::al */, $noreg + + ;CHECK: name: OUTLINED_FUNCTION_[[T1_S]] + ;CHECK: early-clobber $sp = t2STR_PRE killed $lr, $sp, -8, 14 /* CC::al */, $noreg + ;CHECK-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset 8 + ;CHECK-NEXT: frame-setup CFI_INSTRUCTION offset $lr, -8 + ;CHECK-NEXT: tBL 14 /* CC::al */, $noreg, @foo, implicit-def dead $lr, implicit $sp + ;CHECK-NEXT: tSTRspi $r0, $sp, 2, 14 /* CC::al */, $noreg + ;CHECK-NEXT: tSTRspi $r0, $sp, 6, 14 /* CC::al */, $noreg + ;CHECK-NEXT: tSTRspi $r0, $sp, 255, 14 /* CC::al */, $noreg + ;CHECK-NEXT: $lr, $sp = t2LDR_POST $sp, 8, 14 /* CC::al */, $noreg diff --git a/llvm/test/CodeGen/ARM/machine-outliner-stack-use.mir b/llvm/test/CodeGen/ARM/machine-outliner-stack-use.mir new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/ARM/machine-outliner-stack-use.mir @@ -0,0 +1,71 @@ +# RUN: llc -mtriple=arm-- -run-pass=machine-outliner -verify-machineinstrs \ +# RUN: %s -o - | FileCheck %s + +--- | + define void @fun_1() #0 { ret void } + define void @fun_2() #0 { ret void } + + attributes #0 = { minsize optsize } +... +--- + +name: fun_1 +tracksRegLiveness: true +body: | + bb.0: + ; CHECK-LABEL: name: fun_1 + ; CHECK: early-clobber $sp = STR_PRE_IMM killed $lr, $sp, -8, 14 /* CC::al */, $noreg + ; CHECK-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset 8 + ; CHECK-NEXT: frame-setup CFI_INSTRUCTION offset $lr, -8 + ; CHECK-NEXT: BL @OUTLINED_FUNCTION_0 + ; CHECK-NEXT: $lr, $sp = LDR_POST_IMM $sp, $noreg, 8, 14 /* CC::al */, $noreg + ; CHECK-NEXT: frame-destroy CFI_INSTRUCTION def_cfa_offset 0 + ; CHECK-NEXT: frame-destroy CFI_INSTRUCTION restore $lr + $r0 = MOVi 1, 14, $noreg, $noreg + $r0 = MOVi 1, 14, $noreg, $noreg + $r0 = LDRi12 $sp, 0, 14, $noreg + $r0 = LDRi12 $sp, 0, 14, $noreg + $r0 = LDRi12 $sp, 0, 14, $noreg + $r0 = MOVi 1, 14, $noreg, $noreg + $r0 = LDRi12 $sp, 0, 14, $noreg + $r0 = MOVi 1, 14, $noreg, $noreg + bb.1: + liveins: $lr, $r0, $r1, $r2, $r3, $r4, $r5, $r6, $r7, $r8, $r9, $r10, $r11 + $r2 = MOVr $lr, 14, $noreg, $noreg + BX_RET 14, $noreg +... +--- + +name: fun_2 +tracksRegLiveness: true +body: | + bb.0: + ; CHECK-LABEL: name: fun_2 + ; CHECK: early-clobber $sp = STR_PRE_IMM killed $lr, $sp, -8, 14 /* CC::al */, $noreg + ; CHECK-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset 8 + ; CHECK-NEXT: frame-setup CFI_INSTRUCTION offset $lr, -8 + ; CHECK-NEXT: BL @OUTLINED_FUNCTION_0 + ; CHECK-NEXT: $lr, $sp = LDR_POST_IMM $sp, $noreg, 8, 14 /* CC::al */, $noreg + ; CHECK-NEXT: frame-destroy CFI_INSTRUCTION def_cfa_offset 0 + ; CHECK-NEXT: frame-destroy CFI_INSTRUCTION restore $lr + $r0 = MOVi 1, 14, $noreg, $noreg + $r0 = MOVi 1, 14, $noreg, $noreg + $r0 = LDRi12 $sp, 0, 14, $noreg + $r0 = LDRi12 $sp, 0, 14, $noreg + $r0 = LDRi12 $sp, 0, 14, $noreg + $r0 = MOVi 1, 14, $noreg, $noreg + $r0 = LDRi12 $sp, 0, 14, $noreg + $r0 = MOVi 1, 14, $noreg, $noreg + bb.1: + BX_RET 14, $noreg + + ;CHECK: name: OUTLINED_FUNCTION_0 + ;CHECK: $r0 = MOVi 1, 14 /* CC::al */, $noreg, $noreg + ;CHECK-NEXT: $r0 = MOVi 1, 14 /* CC::al */, $noreg, $noreg + ;CHECK-NEXT: $r0 = LDRi12 $sp, 8, 14 /* CC::al */, $noreg + ;CHECK-NEXT: $r0 = LDRi12 $sp, 8, 14 /* CC::al */, $noreg + ;CHECK-NEXT: $r0 = LDRi12 $sp, 8, 14 /* CC::al */, $noreg + ;CHECK-NEXT: $r0 = MOVi 1, 14 /* CC::al */, $noreg, $noreg + ;CHECK-NEXT: $r0 = LDRi12 $sp, 8, 14 /* CC::al */, $noreg + ;CHECK-NEXT: $r0 = MOVi 1, 14 /* CC::al */, $noreg, $noreg + ;CHECK-NEXT: MOVPCLR 14 /* CC::al */, $noreg diff --git a/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/arm_generated_funcs.ll.generated.expected b/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/arm_generated_funcs.ll.generated.expected --- a/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/arm_generated_funcs.ll.generated.expected +++ b/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/arm_generated_funcs.ll.generated.expected @@ -76,14 +76,9 @@ ; CHECK-NEXT: str r0, [sp, #4] ; CHECK-NEXT: b .LBB0_3 ; CHECK-NEXT: .LBB0_2: -; CHECK-NEXT: mov r0, #2 -; CHECK-NEXT: str r0, [sp, #8] -; CHECK-NEXT: mov r0, #1 -; CHECK-NEXT: str r0, [sp, #12] -; CHECK-NEXT: mov r0, #3 -; CHECK-NEXT: str r0, [sp, #4] -; CHECK-NEXT: mov r0, #4 -; CHECK-NEXT: str r0, [sp] +; CHECK-NEXT: mov r1, lr +; CHECK-NEXT: bl OUTLINED_FUNCTION_0 +; CHECK-NEXT: mov lr, r1 ; CHECK-NEXT: .LBB0_3: ; CHECK-NEXT: ldr r0, [sp, #12] ; CHECK-NEXT: cmp r0, #0 @@ -93,14 +88,9 @@ ; CHECK-NEXT: str r0, [sp, #4] ; CHECK-NEXT: b .LBB0_6 ; CHECK-NEXT: .LBB0_5: -; CHECK-NEXT: mov r0, #2 -; CHECK-NEXT: str r0, [sp, #8] -; CHECK-NEXT: mov r0, #1 -; CHECK-NEXT: str r0, [sp, #12] -; CHECK-NEXT: mov r0, #3 -; CHECK-NEXT: str r0, [sp, #4] -; CHECK-NEXT: mov r0, #4 -; CHECK-NEXT: str r0, [sp] +; CHECK-NEXT: mov r1, lr +; CHECK-NEXT: bl OUTLINED_FUNCTION_0 +; CHECK-NEXT: mov lr, r1 ; CHECK-NEXT: .LBB0_6: ; CHECK-NEXT: mov r0, #0 ; CHECK-NEXT: add sp, sp, #20 @@ -134,3 +124,15 @@ ; CHECK-NEXT: @ %bb.1: ; CHECK-NEXT: .LCPI1_0: ; CHECK-NEXT: .long x +; +; CHECK-LABEL: OUTLINED_FUNCTION_0: +; CHECK: @ %bb.0: +; CHECK-NEXT: mov r0, #2 +; CHECK-NEXT: str r0, [sp, #8] +; CHECK-NEXT: mov r0, #1 +; CHECK-NEXT: str r0, [sp, #12] +; CHECK-NEXT: mov r0, #3 +; CHECK-NEXT: str r0, [sp, #4] +; CHECK-NEXT: mov r0, #4 +; CHECK-NEXT: str r0, [sp] +; CHECK-NEXT: mov pc, lr diff --git a/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/arm_generated_funcs.ll.nogenerated.expected b/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/arm_generated_funcs.ll.nogenerated.expected --- a/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/arm_generated_funcs.ll.nogenerated.expected +++ b/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/arm_generated_funcs.ll.nogenerated.expected @@ -18,14 +18,9 @@ ; CHECK-NEXT: str r0, [sp, #4] ; CHECK-NEXT: b .LBB0_3 ; CHECK-NEXT: .LBB0_2: -; CHECK-NEXT: mov r0, #2 -; CHECK-NEXT: str r0, [sp, #8] -; CHECK-NEXT: mov r0, #1 -; CHECK-NEXT: str r0, [sp, #12] -; CHECK-NEXT: mov r0, #3 -; CHECK-NEXT: str r0, [sp, #4] -; CHECK-NEXT: mov r0, #4 -; CHECK-NEXT: str r0, [sp] +; CHECK-NEXT: mov r1, lr +; CHECK-NEXT: bl OUTLINED_FUNCTION_0 +; CHECK-NEXT: mov lr, r1 ; CHECK-NEXT: .LBB0_3: ; CHECK-NEXT: ldr r0, [sp, #12] ; CHECK-NEXT: cmp r0, #0 @@ -35,14 +30,9 @@ ; CHECK-NEXT: str r0, [sp, #4] ; CHECK-NEXT: b .LBB0_6 ; CHECK-NEXT: .LBB0_5: -; CHECK-NEXT: mov r0, #2 -; CHECK-NEXT: str r0, [sp, #8] -; CHECK-NEXT: mov r0, #1 -; CHECK-NEXT: str r0, [sp, #12] -; CHECK-NEXT: mov r0, #3 -; CHECK-NEXT: str r0, [sp, #4] -; CHECK-NEXT: mov r0, #4 -; CHECK-NEXT: str r0, [sp] +; CHECK-NEXT: mov r1, lr +; CHECK-NEXT: bl OUTLINED_FUNCTION_0 +; CHECK-NEXT: mov lr, r1 ; CHECK-NEXT: .LBB0_6: ; CHECK-NEXT: mov r0, #0 ; CHECK-NEXT: add sp, sp, #20