Skip to content

Commit 7c959b3

Browse files
committed
[AArch64] Fix range check for STGPostIndex
When generating function epilogues using AArch64 stack tagging, we can fold an SP update into the tag-setting loop. The loop tags 32 bytes at a time using ST2G, so the final SP update might be done either by a post indexed STG which tags the final 16 bytes of the tagged region, or by an ADD/SUB instruction after the loop. However, we were only considering the range of the ADD/SUB instructions when deciding whether to do this, and the valid immediate range for STG is slightly lower when the offset is positive.
1 parent da334d3 commit 7c959b3

File tree

2 files changed

+17
-6
lines changed

2 files changed

+17
-6
lines changed

llvm/lib/Target/AArch64/AArch64FrameLowering.cpp

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4393,10 +4393,20 @@ bool canMergeRegUpdate(MachineBasicBlock::iterator II, unsigned Reg,
43934393
int64_t Offset = MI.getOperand(2).getImm() << Shift;
43944394
if (MI.getOpcode() == AArch64::SUBXri)
43954395
Offset = -Offset;
4396-
int64_t AbsPostOffset = std::abs(Offset - Size);
4397-
const int64_t kMaxOffset =
4398-
0xFFF; // Max encoding for unshifted ADDXri / SUBXri
4399-
if (AbsPostOffset <= kMaxOffset && AbsPostOffset % 16 == 0) {
4396+
int64_t PostOffset = Offset - Size;
4397+
// TagStoreEdit::emitLoop might emit either an ADD/SUB after the loop, or
4398+
// an STGPostIndex which does the last 16 bytes of tag write. Which one is
4399+
// chosen depends on the alignment of the loop size, but the difference
4400+
// between the valid ranges for the two instructions is small, so we
4401+
// conservatively assume that it could be either case here.
4402+
//
4403+
// Max offset of STGPostIndex, minus the 16 byte tag write folded into that
4404+
// instruction.
4405+
const int64_t kMaxOffset = 4080 - 16;
4406+
// Max offset of SUBXri.
4407+
const int64_t kMinOffset = -4095;
4408+
if (PostOffset <= kMaxOffset && PostOffset >= kMinOffset &&
4409+
PostOffset % 16 == 0) {
44004410
*TotalOffset = Offset;
44014411
return true;
44024412
}

llvm/test/CodeGen/AArch64/stack-tagging-epilogue-fold.mir

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,9 @@ body: |
5353
; CHECK-NEXT: renamable $x10 = COPY renamable $x9
5454
; CHECK-NEXT: dead early-clobber renamable $x11, dead early-clobber renamable $x10 = STGloop_wback 4080, killed renamable $x10, implicit-def dead $nzcv
5555
; CHECK-NEXT: ST2Gi renamable $x8, renamable $x8, 0
56-
; CHECK-NEXT: dead early-clobber $x8, early-clobber $sp = frame-destroy STGloop_wback 4096, $sp, implicit-def $nzcv
57-
; CHECK-NEXT: $sp = frame-destroy STGPostIndex $sp, $sp, 256
56+
; CHECK-NEXT: $x9 = ADDXri $sp, 0, 0
57+
; CHECK-NEXT: dead early-clobber $x8, dead early-clobber $x9 = STGloop_wback 4112, $x9, implicit-def $nzcv
58+
; CHECK-NEXT: $sp = frame-destroy ADDXri $sp, 2, 12
5859
; CHECK-NEXT: early-clobber $sp, $fp = frame-destroy LDRXpost $sp, 16 :: (load (s64) from %stack.5)
5960
; CHECK-NEXT: RET_ReallyLR
6061
/* Prologue */

0 commit comments

Comments
 (0)