| From 26f6fbe2be1dfb6e734ba34b650606cd18a2a4f7 Mon Sep 17 00:00:00 2001 |
| From: David Green <david.green@arm.com> |
| Date: Tue, 14 Dec 2021 12:49:27 +0000 |
| Subject: [PATCH] [ARM] Add AddrModeT2_i8neg addressing mode support for frame |
| lowering. |
| |
| As reported from a failing firefox build, we can sometimes get frame |
| indices with negative offsets from a t2LDRi8. This adds support for |
| them, to prevent the crash. |
| --- |
| llvm/lib/Target/ARM/ARMBaseRegisterInfo.cpp | 4 + |
| llvm/test/CodeGen/ARM/stack_frame_offset.mir | 189 +++++++++++++++++++ |
| 2 files changed, 193 insertions(+) |
| create mode 100644 llvm/test/CodeGen/ARM/stack_frame_offset.mir |
| |
| diff --git a/llvm/lib/Target/ARM/ARMBaseRegisterInfo.cpp b/llvm/lib/Target/ARM/ARMBaseRegisterInfo.cpp |
| index b53efe58e8de..c543d02ff75a 100644 |
| --- a/llvm/lib/Target/ARM/ARMBaseRegisterInfo.cpp |
| +++ b/llvm/lib/Target/ARM/ARMBaseRegisterInfo.cpp |
| @@ -530,6 +530,8 @@ getFrameIndexInstrOffset(const MachineInstr *MI, int Idx) const { |
| unsigned ImmIdx = 0; |
| switch (AddrMode) { |
| case ARMII::AddrModeT2_i8: |
| + case ARMII::AddrModeT2_i8neg: |
| + case ARMII::AddrModeT2_i8pos: |
| case ARMII::AddrModeT2_i12: |
| case ARMII::AddrMode_i12: |
| InstrOffs = MI->getOperand(Idx+1).getImm(); |
| @@ -728,6 +730,8 @@ bool ARMBaseRegisterInfo::isFrameOffsetLegal(const MachineInstr *MI, |
| bool isSigned = true; |
| switch (AddrMode) { |
| case ARMII::AddrModeT2_i8: |
| + case ARMII::AddrModeT2_i8pos: |
| + case ARMII::AddrModeT2_i8neg: |
| case ARMII::AddrModeT2_i12: |
| // i8 supports only negative, and i12 supports only positive, so |
| // based on Offset sign, consider the appropriate instruction |
| diff --git a/llvm/test/CodeGen/ARM/stack_frame_offset.mir b/llvm/test/CodeGen/ARM/stack_frame_offset.mir |
| new file mode 100644 |
| index 000000000000..f2cdb8007e55 |
| --- /dev/null |
| +++ b/llvm/test/CodeGen/ARM/stack_frame_offset.mir |
| @@ -0,0 +1,189 @@ |
| +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py |
| +# RUN: llc -run-pass=prologepilog %s -o - | FileCheck %s |
| + |
| +--- | |
| + target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64" |
| + target triple = "thumbv7m-none-eabi" |
| + |
| + define i32 @testpos() { |
| + entry: |
| + %a = alloca i32, align 4 |
| + call void @other(i32* %a) |
| + %b = load i32, i32* %a, align 4 |
| + ret i32 %b |
| + } |
| + define i32 @testneg4() { |
| + entry: |
| + %a = alloca i32, align 4 |
| + call void @other(i32* %a) |
| + %b = load i32, i32* %a, align 4 |
| + ret i32 %b |
| + } |
| + define i32 @testneg8() { |
| + entry: |
| + %a = alloca i32, align 4 |
| + call void @other(i32* %a) |
| + %b = load i32, i32* %a, align 4 |
| + ret i32 %b |
| + } |
| + |
| + declare void @other(i32*) |
| + |
| +... |
| +--- |
| +name: testpos |
| +tracksRegLiveness: true |
| +frameInfo: |
| + isFrameAddressTaken: false |
| + isReturnAddressTaken: false |
| + hasStackMap: false |
| + hasPatchPoint: false |
| + stackSize: 0 |
| + offsetAdjustment: 0 |
| + maxAlignment: 4 |
| + adjustsStack: true |
| + hasCalls: true |
| + stackProtector: '' |
| + maxCallFrameSize: 0 |
| + cvBytesOfCalleeSavedRegisters: 0 |
| + hasOpaqueSPAdjustment: false |
| + hasVAStart: false |
| + hasMustTailInVarArgFunc: false |
| + hasTailCall: false |
| + localFrameSize: 4 |
| + savePoint: '' |
| + restorePoint: '' |
| +stack: |
| + - { id: 0, name: a, 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: '' } |
| +body: | |
| + bb.0.entry: |
| + ; CHECK-LABEL: name: testpos |
| + ; CHECK: liveins: $r7, $lr |
| + ; CHECK-NEXT: {{ $}} |
| + ; CHECK-NEXT: $sp = frame-setup t2STMDB_UPD $sp, 14 /* CC::al */, $noreg, killed $r7, killed $lr |
| + ; CHECK-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset 8 |
| + ; CHECK-NEXT: frame-setup CFI_INSTRUCTION offset $lr, -4 |
| + ; CHECK-NEXT: frame-setup CFI_INSTRUCTION offset $r7, -8 |
| + ; CHECK-NEXT: $sp = frame-setup tSUBspi $sp, 2, 14 /* CC::al */, $noreg |
| + ; CHECK-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset 16 |
| + ; CHECK-NEXT: renamable $r0 = t2ADDri $sp, 4, 14 /* CC::al */, $noreg, $noreg |
| + ; CHECK-NEXT: tBL 14 /* CC::al */, $noreg, @other, csr_aapcs, implicit-def dead $lr, implicit $sp, implicit $r0, implicit-def $sp |
| + ; CHECK-NEXT: renamable $r0 = t2LDRi12 $sp, 8, 14 /* CC::al */, $noreg :: (dereferenceable load (s32) from %ir.a) |
| + ; CHECK-NEXT: $sp = frame-destroy tADDspi $sp, 2, 14 /* CC::al */, $noreg |
| + ; CHECK-NEXT: $sp = frame-destroy t2LDMIA_RET $sp, 14 /* CC::al */, $noreg, def $r7, def $pc, implicit $r0 |
| + ADJCALLSTACKDOWN 0, 0, 14 /* CC::al */, $noreg, implicit-def dead $sp, implicit $sp |
| + renamable $r0 = t2ADDri %stack.0.a, 0, 14 /* CC::al */, $noreg, $noreg |
| + tBL 14 /* CC::al */, $noreg, @other, csr_aapcs, implicit-def dead $lr, implicit $sp, implicit $r0, implicit-def $sp |
| + ADJCALLSTACKUP 0, -1, 14 /* CC::al */, $noreg, implicit-def dead $sp, implicit $sp |
| + renamable $r0 = t2LDRi12 %stack.0.a, 4, 14 /* CC::al */, $noreg :: (dereferenceable load (s32) from %ir.a) |
| + tBX_RET 14 /* CC::al */, $noreg, implicit $r0 |
| + |
| +... |
| +--- |
| +name: testneg4 |
| +tracksRegLiveness: true |
| +frameInfo: |
| + isFrameAddressTaken: false |
| + isReturnAddressTaken: false |
| + hasStackMap: false |
| + hasPatchPoint: false |
| + stackSize: 0 |
| + offsetAdjustment: 0 |
| + maxAlignment: 4 |
| + adjustsStack: true |
| + hasCalls: true |
| + stackProtector: '' |
| + maxCallFrameSize: 0 |
| + cvBytesOfCalleeSavedRegisters: 0 |
| + hasOpaqueSPAdjustment: false |
| + hasVAStart: false |
| + hasMustTailInVarArgFunc: false |
| + hasTailCall: false |
| + localFrameSize: 4 |
| + savePoint: '' |
| + restorePoint: '' |
| +stack: |
| + - { id: 0, name: a, 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: '' } |
| +body: | |
| + bb.0.entry: |
| + ; CHECK-LABEL: name: testneg4 |
| + ; CHECK: liveins: $r7, $lr |
| + ; CHECK-NEXT: {{ $}} |
| + ; CHECK-NEXT: $sp = frame-setup t2STMDB_UPD $sp, 14 /* CC::al */, $noreg, killed $r7, killed $lr |
| + ; CHECK-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset 8 |
| + ; CHECK-NEXT: frame-setup CFI_INSTRUCTION offset $lr, -4 |
| + ; CHECK-NEXT: frame-setup CFI_INSTRUCTION offset $r7, -8 |
| + ; CHECK-NEXT: $sp = frame-setup tSUBspi $sp, 2, 14 /* CC::al */, $noreg |
| + ; CHECK-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset 16 |
| + ; CHECK-NEXT: renamable $r0 = t2ADDri $sp, 4, 14 /* CC::al */, $noreg, $noreg |
| + ; CHECK-NEXT: tBL 14 /* CC::al */, $noreg, @other, csr_aapcs, implicit-def dead $lr, implicit $sp, implicit $r0, implicit-def $sp |
| + ; CHECK-NEXT: renamable $r0 = t2LDRi12 $sp, 0, 14 /* CC::al */, $noreg :: (dereferenceable load (s32) from %ir.a) |
| + ; CHECK-NEXT: $sp = frame-destroy tADDspi $sp, 2, 14 /* CC::al */, $noreg |
| + ; CHECK-NEXT: $sp = frame-destroy t2LDMIA_RET $sp, 14 /* CC::al */, $noreg, def $r7, def $pc, implicit $r0 |
| + ADJCALLSTACKDOWN 0, 0, 14 /* CC::al */, $noreg, implicit-def dead $sp, implicit $sp |
| + renamable $r0 = t2ADDri %stack.0.a, 0, 14 /* CC::al */, $noreg, $noreg |
| + tBL 14 /* CC::al */, $noreg, @other, csr_aapcs, implicit-def dead $lr, implicit $sp, implicit $r0, implicit-def $sp |
| + ADJCALLSTACKUP 0, -1, 14 /* CC::al */, $noreg, implicit-def dead $sp, implicit $sp |
| + renamable $r0 = t2LDRi8 %stack.0.a, -4, 14 /* CC::al */, $noreg :: (dereferenceable load (s32) from %ir.a) |
| + tBX_RET 14 /* CC::al */, $noreg, implicit $r0 |
| + |
| +... |
| +--- |
| +name: testneg8 |
| +tracksRegLiveness: true |
| +frameInfo: |
| + isFrameAddressTaken: false |
| + isReturnAddressTaken: false |
| + hasStackMap: false |
| + hasPatchPoint: false |
| + stackSize: 0 |
| + offsetAdjustment: 0 |
| + maxAlignment: 4 |
| + adjustsStack: true |
| + hasCalls: true |
| + stackProtector: '' |
| + maxCallFrameSize: 0 |
| + cvBytesOfCalleeSavedRegisters: 0 |
| + hasOpaqueSPAdjustment: false |
| + hasVAStart: false |
| + hasMustTailInVarArgFunc: false |
| + hasTailCall: false |
| + localFrameSize: 4 |
| + savePoint: '' |
| + restorePoint: '' |
| +stack: |
| + - { id: 0, name: a, 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: '' } |
| +body: | |
| + bb.0.entry: |
| + ; CHECK-LABEL: name: testneg8 |
| + ; CHECK: liveins: $r7, $lr |
| + ; CHECK-NEXT: {{ $}} |
| + ; CHECK-NEXT: $sp = frame-setup t2STMDB_UPD $sp, 14 /* CC::al */, $noreg, killed $r7, killed $lr |
| + ; CHECK-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset 8 |
| + ; CHECK-NEXT: frame-setup CFI_INSTRUCTION offset $lr, -4 |
| + ; CHECK-NEXT: frame-setup CFI_INSTRUCTION offset $r7, -8 |
| + ; CHECK-NEXT: $sp = frame-setup tSUBspi $sp, 2, 14 /* CC::al */, $noreg |
| + ; CHECK-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset 16 |
| + ; CHECK-NEXT: renamable $r0 = t2ADDri $sp, 4, 14 /* CC::al */, $noreg, $noreg |
| + ; CHECK-NEXT: tBL 14 /* CC::al */, $noreg, @other, csr_aapcs, implicit-def dead $lr, implicit $sp, implicit $r0, implicit-def $sp |
| + ; CHECK-NEXT: renamable $r0 = t2LDRi8 $sp, -4, 14 /* CC::al */, $noreg :: (dereferenceable load (s32) from %ir.a) |
| + ; CHECK-NEXT: $sp = frame-destroy tADDspi $sp, 2, 14 /* CC::al */, $noreg |
| + ; CHECK-NEXT: $sp = frame-destroy t2LDMIA_RET $sp, 14 /* CC::al */, $noreg, def $r7, def $pc, implicit $r0 |
| + ADJCALLSTACKDOWN 0, 0, 14 /* CC::al */, $noreg, implicit-def dead $sp, implicit $sp |
| + renamable $r0 = t2ADDri %stack.0.a, 0, 14 /* CC::al */, $noreg, $noreg |
| + tBL 14 /* CC::al */, $noreg, @other, csr_aapcs, implicit-def dead $lr, implicit $sp, implicit $r0, implicit-def $sp |
| + ADJCALLSTACKUP 0, -1, 14 /* CC::al */, $noreg, implicit-def dead $sp, implicit $sp |
| + renamable $r0 = t2LDRi8 %stack.0.a, -8, 14 /* CC::al */, $noreg :: (dereferenceable load (s32) from %ir.a) |
| + tBX_RET 14 /* CC::al */, $noreg, implicit $r0 |
| + |
| +... |
| + |
| -- |
| 2.34.1.703.g22d0c6ccf7-goog |
| |