Skip to content

Commit b09c575

Browse files
committed
[AArch64] Add Defs=[NZCV] to MTE loop pseudos.
The `STGloop` family of pseudo-instructions all expand to a loop which iterates over a region of memory setting all its MTE tags to a given value. The loop writes to the flags in order to check termination. But the unexpanded pseudo-instructions were not marked as modifying the flags. Therefore it was possible for one to end up in a location where the flags were live, and then the loop would corrupt them. We spotted the effect of this in a libc++ test involving a lot of complicated inlining, and haven't been able to construct a smaller test case that demonstrates actual incorrect output code. So my test here is just checking that `implicit-def $nzcv` shows up on the pseudo-instructions as they're output from isel. Reviewed By: DavidSpickett Differential Revision: https://reviews.llvm.org/D158262
1 parent 7549cde commit b09c575

File tree

2 files changed

+60
-1
lines changed

2 files changed

+60
-1
lines changed

llvm/lib/Target/AArch64/AArch64InstrInfo.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2259,7 +2259,7 @@ def : Pat<(int_aarch64_irg_sp i64:$Rm), (IRGstack SP, i64:$Rm)>;
22592259

22602260
// Large STG to be expanded into a loop. $sz is the size, $Rn is start address.
22612261
// $Rn_wback is one past the end of the range. $Rm is the loop counter.
2262-
let isCodeGenOnly=1, mayStore=1 in {
2262+
let isCodeGenOnly=1, mayStore=1, Defs=[NZCV] in {
22632263
def STGloop_wback
22642264
: Pseudo<(outs GPR64common:$Rm, GPR64sp:$Rn_wback), (ins i64imm:$sz, GPR64sp:$Rn),
22652265
[], "$Rn = $Rn_wback,@earlyclobber $Rn_wback,@earlyclobber $Rm" >,
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
; RUN: llc -O2 -print-after-isel -mtriple=aarch64-linux-gnu %s -o /dev/null 2>&1 | FileCheck %s --check-prefixes=CHECK
2+
3+
; This test function includes a 256-byte buffer. We expect it to require its
4+
; MTE tags to be set to a useful value on entry, and cleared again on exit. At
5+
; the time of writing this test, the pseudo-instructions chosen are
6+
; STGloop_wback and STGloop respectively, but if different pseudos are selected
7+
; in future, that's not a problem. The important thing is that both should
8+
; include that implicit-def of $nzcv, because these pseudo-instructions will
9+
; expand into loops that use the flags for their termination tests.
10+
11+
; CHECK: STGloop_wback 256, {{.*}}, implicit-def dead $nzcv
12+
; CHECK: STGloop 256, {{.*}}, implicit-def dead $nzcv
13+
14+
define i32 @foo(i32 noundef %0) #0 {
15+
%2 = alloca i32, align 4
16+
%3 = alloca [256 x i8], align 1
17+
%4 = alloca i64, align 8
18+
%5 = alloca i32, align 4
19+
%6 = alloca i64, align 8
20+
store i32 %0, ptr %2, align 4
21+
%7 = load i32, ptr %2, align 4
22+
%8 = getelementptr inbounds [256 x i8], ptr %3, i64 0, i64 0
23+
%9 = call i64 @read(i32 noundef %7, ptr noundef %8, i64 noundef 256)
24+
store i64 %9, ptr %4, align 8
25+
store i32 0, ptr %5, align 4
26+
store i64 0, ptr %6, align 8
27+
br label %10
28+
29+
10: ; preds = %21, %1
30+
%11 = load i64, ptr %6, align 8
31+
%12 = load i64, ptr %4, align 8
32+
%13 = icmp ult i64 %11, %12
33+
br i1 %13, label %14, label %24
34+
35+
14: ; preds = %10
36+
%15 = load i64, ptr %6, align 8
37+
%16 = getelementptr inbounds [256 x i8], ptr %3, i64 0, i64 %15
38+
%17 = load i8, ptr %16, align 1
39+
%18 = zext i8 %17 to i32
40+
%19 = load i32, ptr %5, align 4
41+
%20 = add nsw i32 %19, %18
42+
store i32 %20, ptr %5, align 4
43+
br label %21
44+
45+
21: ; preds = %14
46+
%22 = load i64, ptr %6, align 8
47+
%23 = add i64 %22, 1
48+
store i64 %23, ptr %6, align 8
49+
br label %10
50+
51+
24: ; preds = %10
52+
%25 = load i32, ptr %5, align 4
53+
%26 = srem i32 %25, 251
54+
ret i32 %26
55+
}
56+
57+
declare i64 @read(i32 noundef, ptr noundef, i64 noundef)
58+
59+
attributes #0 = { sanitize_memtag "target-features"="+mte" }

0 commit comments

Comments
 (0)