From: Yvan Roux Date: Tue, 19 Jan 2021 09:07:56 +0000 (+0100) Subject: [ARM][MachineOutliner] Add stack fixup feature X-Git-Tag: llvmorg-13-init~855 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=244ad228f34363b508cd1096c99d8f1bbe999d85;p=platform%2Fupstream%2Fllvm.git [ARM][MachineOutliner] Add stack fixup feature This patch handles cases where we have to save/restore the link register into the stack and and load/store instruction which use the stack are part of the outlined region. It checks that there will be no overflow introduced by the new offset and fixup these instructions accordingly. Differential Revision: https://reviews.llvm.org/D92934 --- diff --git a/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp b/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp index 143bf66..112eb59 100644 --- a/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp +++ b/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp @@ -5914,6 +5914,112 @@ outliner::OutlinedFunction ARMBaseInstrInfo::getOutliningCandidateInfo( NumBytesToCreateFrame, FrameID); } +bool ARMBaseInstrInfo::checkAndUpdateStackOffset(MachineInstr *MI, + int64_t Fixup, + bool Updt) const { + int SPIdx = MI->findRegisterUseOperandIdx(ARM::SP); + unsigned AddrMode = (MI->getDesc().TSFlags & ARMII::AddrModeMask); + if (SPIdx < 0) + // No SP operand + return true; + else if (SPIdx != 1 && (AddrMode != ARMII::AddrModeT2_i8s4 || SPIdx != 2)) + // If SP is not the base register we can't do much + return false; + + // 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; + + 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(); @@ -6125,6 +6231,19 @@ ARMBaseInstrInfo::getOutliningType(MachineBasicBlock::iterator &MIT, 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; } @@ -6140,6 +6259,12 @@ ARMBaseInstrInfo::getOutliningType(MachineBasicBlock::iterator &MIT, return outliner::InstrType::Legal; } +void ARMBaseInstrInfo::fixupPostOutline(MachineBasicBlock &MBB) const { + for (MachineInstr &MI : MBB) { + 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; @@ -6275,6 +6400,12 @@ void ARMBaseInstrInfo::buildOutlinedFrame( 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); @@ -6289,6 +6420,15 @@ void ARMBaseInstrInfo::buildOutlinedFrame( // 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( @@ -6345,6 +6485,8 @@ MachineBasicBlock::iterator ARMBaseInstrInfo::insertOutlinedCall( 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/lib/Target/ARM/ARMBaseInstrInfo.h b/llvm/lib/Target/ARM/ARMBaseInstrInfo.h index b14f7e4..1b843c4 100644 --- a/llvm/lib/Target/ARM/ARMBaseInstrInfo.h +++ b/llvm/lib/Target/ARM/ARMBaseInstrInfo.h @@ -404,6 +404,16 @@ private: /// after the LR is was restored from a register. 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; diff --git a/llvm/test/CodeGen/ARM/machine-outliner-default.mir b/llvm/test/CodeGen/ARM/machine-outliner-default.mir index 9db4207..fa5119c 100644 --- a/llvm/test/CodeGen/ARM/machine-outliner-default.mir +++ b/llvm/test/CodeGen/ARM/machine-outliner-default.mir @@ -5,8 +5,6 @@ --- | 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 } declare void @bar() attributes #0 = { minsize optsize } @@ -113,121 +111,6 @@ body: | liveins: $lr, $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: diff --git a/llvm/test/CodeGen/ARM/machine-outliner-no-lr-save.mir b/llvm/test/CodeGen/ARM/machine-outliner-no-lr-save.mir index 678633d..71a7d4d 100644 --- 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 @@ body: | ... --- -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 @@ body: | 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 index 0000000..1f8745c --- /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 index 0000000..7d9b195 --- /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/tools/UpdateTestChecks/update_llc_test_checks/Inputs/arm_generated_funcs.ll b/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/arm_generated_funcs.ll index cdc7d3b..bae66d4 100644 --- a/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/arm_generated_funcs.ll +++ b/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/arm_generated_funcs.ll @@ -1,6 +1,4 @@ ; RUN: llc -enable-machine-outliner -mtriple=arm-unknown-linux < %s | FileCheck %s -; -; NOTE: Machine outliner runs, but doesn't do anything. @x = global i32 0, align 4 define dso_local i32 @check_boundaries() #0 { 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 index ddf87ee..de5571f 100644 --- 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 @@ -1,6 +1,5 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --include-generated-funcs ; RUN: llc -enable-machine-outliner -mtriple=arm-unknown-linux < %s | FileCheck %s -; NOTE: Machine outliner runs, but doesn't do anything. @x = global i32 0, align 4 define dso_local i32 @check_boundaries() #0 { @@ -76,14 +75,9 @@ attributes #0 = { noredzone nounwind ssp uwtable "frame-pointer"="all" } ; 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 +87,9 @@ attributes #0 = { noredzone nounwind ssp uwtable "frame-pointer"="all" } ; 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 +123,15 @@ attributes #0 = { noredzone nounwind ssp uwtable "frame-pointer"="all" } ; 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 index 316e774..4f62338 100644 --- 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 @@ -1,7 +1,5 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc -enable-machine-outliner -mtriple=arm-unknown-linux < %s | FileCheck %s -; -; NOTE: Machine outliner runs, but doesn't do anything. @x = global i32 0, align 4 define dso_local i32 @check_boundaries() #0 { @@ -18,14 +16,9 @@ define dso_local i32 @check_boundaries() #0 { ; 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 +28,9 @@ define dso_local i32 @check_boundaries() #0 { ; 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