diff --git a/llvm/lib/Target/ARM/ARMFrameLowering.cpp b/llvm/lib/Target/ARM/ARMFrameLowering.cpp --- a/llvm/lib/Target/ARM/ARMFrameLowering.cpp +++ b/llvm/lib/Target/ARM/ARMFrameLowering.cpp @@ -2238,18 +2238,20 @@ (Subtarget.createAAPCSFrameChain() && MF.getFrameInfo().hasCalls()); } -// Thumb1 may require a spill when storing to a frame index through FP, for -// cases where FP is a high register (R11). This scans the function for cases -// where this may happen. +// Thumb1 may require a spill when storing to a frame index through FP (or any +// access with execute-only), for cases where FP is a high register (R11). This +// scans the function for cases where this may happen. static bool canSpillOnFrameIndexAccess(const MachineFunction &MF, const TargetFrameLowering &TFI) { const ARMFunctionInfo *AFI = MF.getInfo(); if (!AFI->isThumb1OnlyFunction()) return false; + const ARMSubtarget &STI = MF.getSubtarget(); for (const auto &MBB : MF) for (const auto &MI : MBB) - if (MI.getOpcode() == ARM::tSTRspi || MI.getOpcode() == ARM::tSTRi) + if (MI.getOpcode() == ARM::tSTRspi || MI.getOpcode() == ARM::tSTRi || + STI.genExecuteOnly()) for (const auto &Op : MI.operands()) if (Op.isFI()) { Register Reg; @@ -2532,18 +2534,19 @@ CS1Spilled = true; } - // This is true when we inserted a spill for a callee-save GPR which is - // not otherwise used by the function. This guaranteees it is possible - // to scavenge a register to hold the address of a stack slot. On Thumb1, - // the register must be a valid operand to tSTRi, i.e. r4-r7. For other - // subtargets, this is any GPR, i.e. r4-r11 or lr. + // This is the number of extra spills inserted for callee-save GPRs which + // would not otherwise be used by the function. When greater than zero it + // guaranteees that it is possible to scavenge a register to hold the + // address of a stack slot. On Thumb1, the register must be a valid operand + // to tSTRi, i.e. r4-r7. For other subtargets, this is any GPR, i.e. r4-r11 + // or lr. // // If we don't insert a spill, we instead allocate an emergency spill // slot, which can be used by scavenging to spill an arbitrary register. // // We currently don't try to figure out whether any specific instruction // requires scavening an additional register. - bool ExtraCSSpill = false; + unsigned NumExtraCSSpill = 0; if (AFI->isThumb1OnlyFunction()) { // For Thumb1-only targets, we need some low registers when we save and @@ -2652,7 +2655,7 @@ CS1Spilled = true; assert(!MRI.isReserved(Reg) && "Should not be reserved"); if (Reg != ARM::LR && !MRI.isPhysRegUsed(Reg)) - ExtraCSSpill = true; + NumExtraCSSpill++; UnspilledCS1GPRs.erase(llvm::find(UnspilledCS1GPRs, Reg)); if (Reg == ARM::LR) LRSpilled = true; @@ -2678,7 +2681,7 @@ ForceLRSpill = false; if (!MRI.isReserved(ARM::LR) && !MRI.isPhysRegUsed(ARM::LR) && !AFI->isThumb1OnlyFunction()) - ExtraCSSpill = true; + NumExtraCSSpill++; } // If stack and double are 8-byte aligned and we are spilling an odd number @@ -2701,7 +2704,7 @@ << " to make up alignment\n"); if (!MRI.isReserved(Reg) && !MRI.isPhysRegUsed(Reg) && !(Reg == ARM::LR && AFI->isThumb1OnlyFunction())) - ExtraCSSpill = true; + NumExtraCSSpill++; break; } } @@ -2711,18 +2714,26 @@ LLVM_DEBUG(dbgs() << "Spilling " << printReg(Reg, TRI) << " to make up alignment\n"); if (!MRI.isReserved(Reg) && !MRI.isPhysRegUsed(Reg)) - ExtraCSSpill = true; + NumExtraCSSpill++; } } - // Estimate if we might need to scavenge a register at some point in order + // Estimate if we might need to scavenge registers at some point in order // to materialize a stack offset. If so, either spill one additional // callee-saved register or reserve a special spill slot to facilitate // register scavenging. Thumb1 needs a spill slot for stack pointer // adjustments and for frame index accesses when FP is high register, // even when the frame itself is small. - if (!ExtraCSSpill && - (BigFrameOffsets || canSpillOnFrameIndexAccess(MF, *this))) { + unsigned RegsNeeded = 0; + if (BigFrameOffsets || canSpillOnFrameIndexAccess(MF, *this)) { + RegsNeeded++; + // With thumb1 execute-only we may need an additional register for saving + // and restoring the CPSR. + if (AFI->isThumb1OnlyFunction() && STI.genExecuteOnly() && !STI.useMovt()) + RegsNeeded++; + } + + if (RegsNeeded > NumExtraCSSpill) { // If any non-reserved CS register isn't spilled, just spill one or two // extra. That should take care of it! unsigned NumExtras = TargetAlign.value() / 4; @@ -2749,10 +2760,10 @@ for (unsigned Reg : Extras) { SavedRegs.set(Reg); if (!MRI.isPhysRegUsed(Reg)) - ExtraCSSpill = true; + NumExtraCSSpill++; } } - if (!ExtraCSSpill && RS) { + while ((RegsNeeded > NumExtraCSSpill) && RS) { // Reserve a slot closest to SP or frame pointer. LLVM_DEBUG(dbgs() << "Reserving emergency spill slot\n"); const TargetRegisterClass &RC = ARM::GPRRegClass; @@ -2760,6 +2771,7 @@ Align Alignment = TRI->getSpillAlign(RC); RS->addScavengingFrameIndex( MFI.CreateStackObject(Size, Alignment, false)); + --RegsNeeded; } } } diff --git a/llvm/lib/Target/ARM/ThumbRegisterInfo.cpp b/llvm/lib/Target/ARM/ThumbRegisterInfo.cpp --- a/llvm/lib/Target/ARM/ThumbRegisterInfo.cpp +++ b/llvm/lib/Target/ARM/ThumbRegisterInfo.cpp @@ -173,9 +173,60 @@ .addReg(LdReg, RegState::Kill) .setMIFlags(MIFlags); } else if (ST.genExecuteOnly()) { - unsigned XOInstr = ST.useMovt() ? ARM::t2MOVi32imm : ARM::tMOVi32imm; - BuildMI(MBB, MBBI, dl, TII.get(XOInstr), LdReg) - .addImm(NumBytes).setMIFlags(MIFlags); + if (ST.useMovt()) { + BuildMI(MBB, MBBI, dl, TII.get(ARM::t2MOVi32imm ), LdReg) + .addImm(NumBytes) + .setMIFlags(MIFlags); + } else if (!CanChangeCC) { + // tMOVi32imm is lowered to a sequence of flag-setting instructions, so + // if CPSR is live we need to save and restore CPSR around it. + // TODO Try inserting the tMOVi32imm at an earlier point, where CPSR is + // dead. + bool LiveCpsr = false, CpsrWrite = false; + auto isCpsr = [](auto &MO) { return MO.getReg() == ARM::CPSR; }; + for (auto Iter = MBBI; Iter != MBB.instr_end(); ++Iter) { + // If CPSR is used after this instruction (and there's not a def before + // that) then CPSR is live. + if (any_of(Iter->all_uses(), isCpsr)) { + LiveCpsr = true; + break; + } + if (any_of(Iter->all_defs(), isCpsr)) { + CpsrWrite = true; + break; + } + } + // If there's no use or def of CPSR then it may be live if it's a + // live-out value. + auto liveOutIsCpsr = [](auto &Out) { return Out.PhysReg == ARM::CPSR; }; + if (!LiveCpsr && !CpsrWrite) + LiveCpsr = any_of(MBB.liveouts(), liveOutIsCpsr); + + Register CPSRSaveReg; + unsigned APSREncoding; + if (LiveCpsr) { + CPSRSaveReg = MF.getRegInfo().createVirtualRegister(&ARM::tGPRRegClass); + APSREncoding = + ARMSysReg::lookupMClassSysRegByName("apsr_nzcvq")->Encoding; + BuildMI(MBB, MBBI, dl, TII.get(ARM::t2MRS_M), CPSRSaveReg) + .addImm(APSREncoding) + .add(predOps(ARMCC::AL)) + .addReg(ARM::CPSR, RegState::Implicit); + } + BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVi32imm), LdReg) + .addImm(NumBytes) + .setMIFlags(MIFlags); + if (LiveCpsr) { + BuildMI(MBB, MBBI, dl, TII.get(ARM::t2MSR_M)) + .addImm(APSREncoding) + .addReg(CPSRSaveReg, RegState::Kill) + .add(predOps(ARMCC::AL)); + } + } else { + BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVi32imm), LdReg) + .addImm(NumBytes) + .setMIFlags(MIFlags); + } } else MRI.emitLoadConstPool(MBB, MBBI, dl, LdReg, 0, NumBytes, ARMCC::AL, 0, MIFlags); diff --git a/llvm/test/CodeGen/ARM/execute-only-save-cpsr.mir b/llvm/test/CodeGen/ARM/execute-only-save-cpsr.mir new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/ARM/execute-only-save-cpsr.mir @@ -0,0 +1,441 @@ +# RUN: llc -run-pass=prologepilog %s -o - | FileCheck %s +# Tests to check that CPSR is saved and restored if live when we emit tMOVi32imm +# to resolve a frame offset. + +--- | + target triple = "thumbv6m-arm-none-eabi" + + define void @test_def_in_block(i32 %x) #0 { + entry: + %var = alloca i32, align 4 + %dummy = alloca [2048 x i8], align 1 + %cmp = icmp eq i32 %x, 0 + store i32 %x, ptr %var, align 4 + br i1 %cmp, label %if.then, label %if.end + + if.then: + br label %if.end + + if.end: + ret void + } + + define void @test_live_in(i32 %x) #0 { + entry: + %var = alloca i32, align 4 + %dummy = alloca [2048 x i8], align 1 + %cmp = icmp eq i32 %x, 0 + br i1 %cmp, label %if.then, label %if.end + + if.then: + store i32 %x, ptr %var, align 4 + %cmp1 = icmp slt i32 %x, 0 + br i1 %cmp1, label %if.then2, label %if.end + + if.then2: + br label %if.end + + if.end: + ret void + } + + define void @test_live_out(i32 %x) #0 { + entry: + %var = alloca i32, align 4 + %dummy = alloca [2048 x i8], align 1 + %cmp = icmp eq i32 %x, 0 + store i32 %x, ptr %var, align 4 + br label %if.then + + if.then: + br i1 %cmp, label %if.then2, label %if.end + + if.then2: + br label %if.end + + if.end: + ret void + } + + define void @test_live_out_def_after_mov(i32 %x) #0 { + entry: + %var = alloca i32, align 4 + %dummy = alloca [2048 x i8], align 1 + store i32 %x, ptr %var, align 4 + %cmp = icmp eq i32 %x, 0 + br label %if.then + + if.then: + br i1 %cmp, label %if.then2, label %if.end + + if.then2: + br label %if.end + + if.end: + ret void + } + + attributes #0 = { "target-features"="+execute-only" } +... +--- +name: test_def_in_block +alignment: 2 +exposesReturnsTwice: false +legalized: false +regBankSelected: false +selected: false +failedISel: false +tracksRegLiveness: true +hasWinCFI: false +callsEHReturn: false +callsUnwindInit: false +hasEHCatchret: false +hasEHScopes: false +hasEHFunclets: false +isOutlined: false +debugInstrRef: false +failsVerification: false +tracksDebugUserValues: false +registers: [] +liveins: + - { reg: '$r0', virtual-reg: '' } +frameInfo: + isFrameAddressTaken: false + isReturnAddressTaken: false + hasStackMap: false + hasPatchPoint: false + stackSize: 0 + offsetAdjustment: 0 + maxAlignment: 4 + adjustsStack: false + hasCalls: false + stackProtector: '' + functionContext: '' + maxCallFrameSize: 0 + cvBytesOfCalleeSavedRegisters: 0 + hasOpaqueSPAdjustment: false + hasVAStart: false + hasMustTailInVarArgFunc: false + hasTailCall: false + localFrameSize: 2052 + savePoint: '' + restorePoint: '' +fixedStack: [] +stack: + - { id: 0, name: var, type: default, offset: 0, size: 4, alignment: 4, + stack-id: default, callee-saved-register: '', callee-saved-restored: true, + local-offset: -4, debug-info-variable: '', debug-info-expression: '', + debug-info-location: '' } + - { id: 1, name: dummy, type: default, offset: 0, size: 2048, alignment: 1, + stack-id: default, callee-saved-register: '', callee-saved-restored: true, + local-offset: -2052, debug-info-variable: '', debug-info-expression: '', + debug-info-location: '' } +entry_values: [] +callSites: [] +debugValueSubstitutions: [] +constants: [] +machineFunctionInfo: {} +body: | + bb.0.entry: + successors: %bb.1(0x40000000), %bb.2(0x40000000) + liveins: $r0 + + ; CHECK-LABEL: name: test_def_in_block + ; CHECK-LABEL: bb.0.entry: + ; CHECK: tCMPi8 renamable $r0, 0, 14 /* CC::al */, $noreg, implicit-def $cpsr + ; CHECK-NEXT: $r2 = t2MRS_M 2048, 14 /* CC::al */, $noreg, implicit $cpsr + ; CHECK-NEXT: $r1 = tMOVi32imm 2048, implicit-def $cpsr + ; CHECK-NEXT: t2MSR_M 2048, killed $r2, 14 /* CC::al */, $noreg, implicit-def $cpsr + ; CHECK-NEXT: $r1 = tADDhirr $r1, killed $sp, 14 /* CC::al */, $noreg + ; CHECK-NEXT: tSTRi renamable $r0, killed $r1, 0, 14 /* CC::al */, $noreg :: (store (s32) into %ir.var) + + tCMPi8 renamable $r0, 0, 14 /* CC::al */, $noreg, implicit-def $cpsr + tSTRspi renamable $r0, %stack.0.var, 0, 14 /* CC::al */, $noreg :: (store (s32) into %ir.var) + tBcc %bb.1, 1 /* CC::ne */, killed $cpsr + tB %bb.2, 14 /* CC::al */, $noreg + + bb.1.if.then: + successors: %bb.2(0x80000000) + + tB %bb.2, 14 /* CC::al */, $noreg + + bb.2.if.end: + tBX_RET 14 /* CC::al */, $noreg + +... +--- +name: test_live_in +alignment: 2 +exposesReturnsTwice: false +legalized: false +regBankSelected: false +selected: false +failedISel: false +tracksRegLiveness: true +hasWinCFI: false +callsEHReturn: false +callsUnwindInit: false +hasEHCatchret: false +hasEHScopes: false +hasEHFunclets: false +isOutlined: false +debugInstrRef: false +failsVerification: false +tracksDebugUserValues: false +registers: [] +liveins: + - { reg: '$r0', virtual-reg: '' } +frameInfo: + isFrameAddressTaken: false + isReturnAddressTaken: false + hasStackMap: false + hasPatchPoint: false + stackSize: 0 + offsetAdjustment: 0 + maxAlignment: 4 + adjustsStack: false + hasCalls: false + stackProtector: '' + functionContext: '' + maxCallFrameSize: 0 + cvBytesOfCalleeSavedRegisters: 0 + hasOpaqueSPAdjustment: false + hasVAStart: false + hasMustTailInVarArgFunc: false + hasTailCall: false + localFrameSize: 2052 + savePoint: '' + restorePoint: '' +fixedStack: [] +stack: + - { id: 0, name: var, type: default, offset: 0, size: 4, alignment: 4, + stack-id: default, callee-saved-register: '', callee-saved-restored: true, + local-offset: -4, debug-info-variable: '', debug-info-expression: '', + debug-info-location: '' } + - { id: 1, name: dummy, type: default, offset: 0, size: 2048, alignment: 1, + stack-id: default, callee-saved-register: '', callee-saved-restored: true, + local-offset: -2052, debug-info-variable: '', debug-info-expression: '', + debug-info-location: '' } +entry_values: [] +callSites: [] +debugValueSubstitutions: [] +constants: [] +machineFunctionInfo: {} +body: | + bb.0.entry: + successors: %bb.1(0x40000000), %bb.3(0x40000000) + liveins: $r0 + + tCMPi8 renamable $r0, 0, 14 /* CC::al */, $noreg, implicit-def $cpsr + tBcc %bb.3, 1 /* CC::ne */, $cpsr + tB %bb.1, 14 /* CC::al */, $noreg + + bb.1.if.then: + successors: %bb.2(0x40000000), %bb.3(0x40000000) + liveins: $r0, $cpsr + + ; CHECK-LABEL: name: test_live_in + ; CHECK-LABEL: bb.1.if.then: + ; CHECK: $r2 = t2MRS_M 2048, 14 /* CC::al */, $noreg, implicit $cpsr + ; CHECK-NEXT: $r1 = tMOVi32imm 2048, implicit-def $cpsr + ; CHECK-NEXT: t2MSR_M 2048, killed $r2, 14 /* CC::al */, $noreg, implicit-def $cpsr + ; CHECK-NEXT: $r1 = tADDhirr $r1, killed $sp, 14 /* CC::al */, $noreg + ; CHECK-NEXT: tSTRi renamable $r0, killed $r1, 0, 14 /* CC::al */, $noreg :: (store (s32) into %ir.var) + + tSTRspi renamable $r0, %stack.0.var, 0, 14 /* CC::al */, $noreg :: (store (s32) into %ir.var) + tBcc %bb.3, 5 /* CC::pl */, killed $cpsr + tB %bb.2, 14 /* CC::al */, $noreg + + bb.2.if.then2: + successors: %bb.3(0x80000000) + + tB %bb.3, 14 /* CC::al */, $noreg + + bb.3.if.end: + tBX_RET 14 /* CC::al */, $noreg + +... +--- +name: test_live_out +alignment: 2 +exposesReturnsTwice: false +legalized: false +regBankSelected: false +selected: false +failedISel: false +tracksRegLiveness: true +hasWinCFI: false +callsEHReturn: false +callsUnwindInit: false +hasEHCatchret: false +hasEHScopes: false +hasEHFunclets: false +isOutlined: false +debugInstrRef: false +failsVerification: false +tracksDebugUserValues: false +registers: [] +liveins: + - { reg: '$r0', virtual-reg: '' } +frameInfo: + isFrameAddressTaken: false + isReturnAddressTaken: false + hasStackMap: false + hasPatchPoint: false + stackSize: 0 + offsetAdjustment: 0 + maxAlignment: 4 + adjustsStack: false + hasCalls: false + stackProtector: '' + functionContext: '' + maxCallFrameSize: 0 + cvBytesOfCalleeSavedRegisters: 0 + hasOpaqueSPAdjustment: false + hasVAStart: false + hasMustTailInVarArgFunc: false + hasTailCall: false + localFrameSize: 2052 + savePoint: '' + restorePoint: '' +fixedStack: [] +stack: + - { id: 0, name: var, type: default, offset: 0, size: 4, alignment: 4, + stack-id: default, callee-saved-register: '', callee-saved-restored: true, + local-offset: -4, debug-info-variable: '', debug-info-expression: '', + debug-info-location: '' } + - { id: 1, name: dummy, type: default, offset: 0, size: 2048, alignment: 1, + stack-id: default, callee-saved-register: '', callee-saved-restored: true, + local-offset: -2052, debug-info-variable: '', debug-info-expression: '', + debug-info-location: '' } +entry_values: [] +callSites: [] +debugValueSubstitutions: [] +constants: [] +machineFunctionInfo: {} +body: | + bb.0.entry: + successors: %bb.1(0x40000000) + liveins: $r0 + + ; CHECK-LABEL: name: test_live_out + ; CHECK-LABEL: bb.0.entry: + ; CHECK: tCMPi8 renamable $r0, 0, 14 /* CC::al */, $noreg, implicit-def $cpsr + ; CHECK-NEXT: $r2 = t2MRS_M 2048, 14 /* CC::al */, $noreg, implicit $cpsr + ; CHECK-NEXT: $r1 = tMOVi32imm 2048, implicit-def $cpsr + ; CHECK-NEXT: t2MSR_M 2048, killed $r2, 14 /* CC::al */, $noreg, implicit-def $cpsr + ; CHECK-NEXT: $r1 = tADDhirr $r1, killed $sp, 14 /* CC::al */, $noreg + ; CHECK-NEXT: tSTRi renamable $r0, killed $r1, 0, 14 /* CC::al */, $noreg :: (store (s32) into %ir.var) + + tCMPi8 renamable $r0, 0, 14 /* CC::al */, $noreg, implicit-def $cpsr + tSTRspi renamable $r0, %stack.0.var, 0, 14 /* CC::al */, $noreg :: (store (s32) into %ir.var) + tB %bb.1, 14 /* CC::al */, $noreg + + bb.1.if.then: + successors: %bb.2(0x40000000), %bb.3(0x40000000) + liveins: $cpsr + + tBcc %bb.3, 5 /* CC::pl */, killed $cpsr + tB %bb.2, 14 /* CC::al */, $noreg + + bb.2.if.then2: + successors: %bb.3(0x80000000) + + tB %bb.3, 14 /* CC::al */, $noreg + + bb.3.if.end: + tBX_RET 14 /* CC::al */, $noreg + +... +--- +name: test_live_out_def_after_mov +alignment: 2 +exposesReturnsTwice: false +legalized: false +regBankSelected: false +selected: false +failedISel: false +tracksRegLiveness: true +hasWinCFI: false +callsEHReturn: false +callsUnwindInit: false +hasEHCatchret: false +hasEHScopes: false +hasEHFunclets: false +isOutlined: false +debugInstrRef: false +failsVerification: false +tracksDebugUserValues: false +registers: [] +liveins: + - { reg: '$r0', virtual-reg: '' } +frameInfo: + isFrameAddressTaken: false + isReturnAddressTaken: false + hasStackMap: false + hasPatchPoint: false + stackSize: 0 + offsetAdjustment: 0 + maxAlignment: 4 + adjustsStack: false + hasCalls: false + stackProtector: '' + functionContext: '' + maxCallFrameSize: 0 + cvBytesOfCalleeSavedRegisters: 0 + hasOpaqueSPAdjustment: false + hasVAStart: false + hasMustTailInVarArgFunc: false + hasTailCall: false + localFrameSize: 2052 + savePoint: '' + restorePoint: '' +fixedStack: [] +stack: + - { id: 0, name: var, type: default, offset: 0, size: 4, alignment: 4, + stack-id: default, callee-saved-register: '', callee-saved-restored: true, + local-offset: -4, debug-info-variable: '', debug-info-expression: '', + debug-info-location: '' } + - { id: 1, name: dummy, type: default, offset: 0, size: 2048, alignment: 1, + stack-id: default, callee-saved-register: '', callee-saved-restored: true, + local-offset: -2052, debug-info-variable: '', debug-info-expression: '', + debug-info-location: '' } +entry_values: [] +callSites: [] +debugValueSubstitutions: [] +constants: [] +machineFunctionInfo: {} +body: | + bb.0.entry: + successors: %bb.1(0x40000000) + liveins: $r0 + + ; Here the live-out cpsr is defined after the tMOVi32imm, so cpsr doesn't + ; need to be saved. + ; CHECK-LABEL: name: test_live_out + ; CHECK-LABEL: bb.0.entry: + ; CHECK: $r1 = tMOVi32imm 2048, implicit-def $cpsr + ; CHECK-NEXT: $r1 = tADDhirr $r1, killed $sp, 14 /* CC::al */, $noreg + ; CHECK-NEXT: tSTRi renamable $r0, killed $r1, 0, 14 /* CC::al */, $noreg :: (store (s32) into %ir.var) + ; CHECK-NEXT: tCMPi8 renamable $r0, 0, 14 /* CC::al */, $noreg, implicit-def $cpsr + + tSTRspi renamable $r0, %stack.0.var, 0, 14 /* CC::al */, $noreg :: (store (s32) into %ir.var) + tCMPi8 renamable $r0, 0, 14 /* CC::al */, $noreg, implicit-def $cpsr + tB %bb.1, 14 /* CC::al */, $noreg + + bb.1.if.then: + successors: %bb.2(0x40000000), %bb.3(0x40000000) + liveins: $cpsr + + tBcc %bb.3, 5 /* CC::pl */, killed $cpsr + tB %bb.2, 14 /* CC::al */, $noreg + + bb.2.if.then2: + successors: %bb.3(0x80000000) + + tB %bb.3, 14 /* CC::al */, $noreg + + bb.3.if.end: + tBX_RET 14 /* CC::al */, $noreg + +... diff --git a/llvm/test/CodeGen/ARM/large-stack.ll b/llvm/test/CodeGen/ARM/large-stack.ll --- a/llvm/test/CodeGen/ARM/large-stack.ll +++ b/llvm/test/CodeGen/ARM/large-stack.ll @@ -36,7 +36,7 @@ ; CHECK-NEXT: lsls [[REG]], [[REG]], #0x8 ; CHECK-NEXT: adds [[REG]], #0xff ; CHECK-NEXT: lsls [[REG]], [[REG]], #0x8 -; CHECK-NEXT: adds [[REG]], #0xf0 +; CHECK-NEXT: adds [[REG]], #0xf4 %retval = alloca i32, align 4 %tmp = alloca i32, align 4 %a = alloca [u0x30000001 x i8], align 16 @@ -45,7 +45,7 @@ ; CHECK: movs [[REG:r[0-9]+]], #0x30 ; CHECK-NEXT: lsls [[REG]], [[REG]], #0x18 ; CHECK-NEXT: add [[REG]], sp -; CHECK-NEXT: str {{r[0-9]+}}, [[[REG]], #0x8] +; CHECK-NEXT: str {{r[0-9]+}}, [[[REG]], #0x4] %tmp1 = load i32, ptr %tmp ret i32 %tmp1 }