Skip to content

Commit 7d72525

Browse files
authored
[AArch64] Fix STG instruction being moved past memcpy (llvm#117191)
When merging STG instructions used for AArch64 stack tagging, we were stopping on reaching a load or store instruction, but not calls, so it was possible for an STG to be moved past a call to memcpy. This test case (reduced from fuzzer-generated C code) was the result of StackColoring merging allocas A and B into one stack slot, and StackSafetyAnalysis proving that B does not need tagging, so we end up with tagged and untagged objects in the same stack slot. The tagged object (A) is live first, so it is important that it's memory is restored to the background tag before it gets reused to hold B.
1 parent 4dafb09 commit 7d72525

File tree

2 files changed

+104
-1
lines changed

2 files changed

+104
-1
lines changed

llvm/lib/Target/AArch64/AArch64FrameLowering.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -4585,7 +4585,7 @@ MachineBasicBlock::iterator tryMergeAdjacentSTG(MachineBasicBlock::iterator II,
45854585
break;
45864586

45874587
// Reject anything that may alias the collected instructions.
4588-
if (MI.mayLoadOrStore() || MI.hasUnmodeledSideEffects())
4588+
if (MI.mayLoadOrStore() || MI.hasUnmodeledSideEffects() || MI.isCall())
45894589
break;
45904590
}
45914591

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 5
2+
# RUN: llc -mtriple=aarch64 -mattr=+mte -run-pass=prologepilog %s -o - | FileCheck %s
3+
--- |
4+
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32"
5+
target triple = "aarch64-unknown-none-elf"
6+
7+
@glob = global [8 x i32] zeroinitializer, align 4
8+
9+
declare dso_local void @F78(ptr %B)
10+
11+
define void @F55() sanitize_memtag "target-features"="+mte,+strict-align" {
12+
entry:
13+
%basetag = call ptr @llvm.aarch64.irg.sp(i64 0)
14+
%A = alloca i32, i32 8, align 16
15+
%A.tag = call ptr @llvm.aarch64.tagp.p0(ptr %A, ptr %basetag, i64 0)
16+
%B = alloca i32, i32 8, align 4
17+
%C = alloca i32, i32 8, align 16
18+
%C.tag = call ptr @llvm.aarch64.tagp.p0(ptr %C, ptr %basetag, i64 1)
19+
call void @llvm.aarch64.settag(ptr %C.tag, i64 32)
20+
call void @F56(ptr %C.tag)
21+
call void @llvm.lifetime.start.p0(i64 32, ptr %A)
22+
call void @llvm.aarch64.settag(ptr %A.tag, i64 32)
23+
call void @F56(ptr %A.tag)
24+
call void @llvm.aarch64.settag(ptr %A, i64 32)
25+
call void @llvm.lifetime.end.p0(i64 32, ptr %A)
26+
call void @llvm.lifetime.start.p0(i64 32, ptr %A)
27+
call void @llvm.memcpy.p0.p0.i64(ptr align 4 %A, ptr align 4 @glob, i64 32, i1 false)
28+
call void @F78(ptr %A)
29+
call void @llvm.lifetime.end.p0(i64 32, ptr %A)
30+
call void @llvm.aarch64.settag(ptr %C, i64 32)
31+
ret void
32+
}
33+
34+
declare void @F56(ptr)
35+
...
36+
---
37+
name: F55
38+
frameInfo:
39+
adjustsStack: true
40+
stack:
41+
- { id: 0, name: A, type: default, offset: 0, size: 32, alignment: 16,
42+
stack-id: default, callee-saved-register: '', callee-saved-restored: true,
43+
local-offset: -32, debug-info-variable: '', debug-info-expression: '',
44+
debug-info-location: '' }
45+
- { id: 2, name: C, type: default, offset: 0, size: 32, alignment: 16,
46+
stack-id: default, callee-saved-register: '', callee-saved-restored: true,
47+
local-offset: -64, debug-info-variable: '', debug-info-expression: '',
48+
debug-info-location: '' }
49+
body: |
50+
bb.0.entry:
51+
; CHECK-LABEL: name: F55
52+
; CHECK: liveins: $x19, $lr
53+
; CHECK-NEXT: {{ $}}
54+
; CHECK-NEXT: frame-setup EMITMTETAGGED
55+
; CHECK-NEXT: $sp = frame-setup SUBXri $sp, 80, 0
56+
; CHECK-NEXT: frame-setup STPXi killed $lr, killed $x19, $sp, 8 :: (store (s64) into %stack.3), (store (s64) into %stack.2)
57+
; CHECK-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset 80
58+
; CHECK-NEXT: frame-setup CFI_INSTRUCTION offset $w19, -8
59+
; CHECK-NEXT: frame-setup CFI_INSTRUCTION offset $w30, -16
60+
; CHECK-NEXT: renamable $x0 = IRGstack $sp, $xzr
61+
; CHECK-NEXT: renamable $x19 = TAGPstack $x0, 2, renamable $x0, 1
62+
; CHECK-NEXT: ST2Gi renamable $x0, renamable $x0, 0 :: (store (s256) into %ir.C.tag, align 16)
63+
; CHECK-NEXT: BL @F56, csr_aarch64_aapcs, implicit-def dead $lr, implicit $sp, implicit $x0, implicit-def $sp
64+
; CHECK-NEXT: ST2Gi renamable $x19, renamable $x19, 0 :: (store (s256) into %ir.A.tag, align 16)
65+
; CHECK-NEXT: $x0 = COPY killed renamable $x19
66+
; CHECK-NEXT: BL @F56, csr_aarch64_aapcs, implicit-def dead $lr, implicit $sp, implicit $x0, implicit-def $sp
67+
; CHECK-NEXT: ST2Gi $sp, $sp, 2 :: (store (s256) into %ir.A, align 16)
68+
; CHECK-NEXT: renamable $x1 = LOADgot target-flags(aarch64-got) @glob
69+
; CHECK-NEXT: $x0 = ADDXri $sp, 32, 0
70+
; CHECK-NEXT: dead $w2 = MOVi32imm 32, implicit-def $x2
71+
; CHECK-NEXT: BL &memcpy, csr_aarch64_aapcs, implicit-def dead $lr, implicit $sp, implicit $x0, implicit $x1, implicit $x2, implicit-def $sp, implicit-def dead $x0
72+
; CHECK-NEXT: $x0 = ADDXri $sp, 32, 0
73+
; CHECK-NEXT: BL @F78, csr_aarch64_aapcs, implicit-def dead $lr, implicit $sp, implicit $x0, implicit-def $sp
74+
; CHECK-NEXT: ST2Gi $sp, $sp, 0 :: (store (s256) into %ir.C, align 16)
75+
; CHECK-NEXT: $sp = frame-destroy ADDXri $sp, 64, 0
76+
; CHECK-NEXT: early-clobber $sp, $lr, $x19 = frame-destroy LDPXpost $sp, 2 :: (load (s64) from %stack.3), (load (s64) from %stack.2)
77+
; CHECK-NEXT: RET_ReallyLR
78+
renamable $x0 = IRGstack $sp, $xzr
79+
renamable $x19 = TAGPstack %stack.0.A, 0, renamable $x0, 1
80+
ST2Gi renamable $x0, renamable $x0, 0 :: (store (s256) into %ir.C.tag, align 16)
81+
ADJCALLSTACKDOWN 0, 0, implicit-def dead $sp, implicit $sp
82+
BL @F56, csr_aarch64_aapcs, implicit-def dead $lr, implicit $sp, implicit $x0, implicit-def $sp
83+
ADJCALLSTACKUP 0, 0, implicit-def dead $sp, implicit $sp
84+
ST2Gi renamable $x19, renamable $x19, 0 :: (store (s256) into %ir.A.tag, align 16)
85+
ADJCALLSTACKDOWN 0, 0, implicit-def dead $sp, implicit $sp
86+
$x0 = COPY killed renamable $x19
87+
BL @F56, csr_aarch64_aapcs, implicit-def dead $lr, implicit $sp, implicit $x0, implicit-def $sp
88+
ADJCALLSTACKUP 0, 0, implicit-def dead $sp, implicit $sp
89+
ST2Gi $sp, %stack.0.A, 0 :: (store (s256) into %ir.A, align 16)
90+
ADJCALLSTACKDOWN 0, 0, implicit-def dead $sp, implicit $sp
91+
renamable $x1 = LOADgot target-flags(aarch64-got) @glob
92+
$x0 = ADDXri %stack.0.A, 0, 0
93+
dead $w2 = MOVi32imm 32, implicit-def $x2
94+
BL &memcpy, csr_aarch64_aapcs, implicit-def dead $lr, implicit $sp, implicit $x0, implicit $x1, implicit $x2, implicit-def $sp, implicit-def dead $x0
95+
ADJCALLSTACKUP 0, 0, implicit-def dead $sp, implicit $sp
96+
ADJCALLSTACKDOWN 0, 0, implicit-def dead $sp, implicit $sp
97+
$x0 = ADDXri %stack.0.A, 0, 0
98+
BL @F78, csr_aarch64_aapcs, implicit-def dead $lr, implicit $sp, implicit $x0, implicit-def $sp
99+
ADJCALLSTACKUP 0, 0, implicit-def dead $sp, implicit $sp
100+
ST2Gi $sp, %stack.2.C, 0 :: (store (s256) into %ir.C, align 16)
101+
RET_ReallyLR
102+
103+
...

0 commit comments

Comments
 (0)