Skip to content

Commit 3e64f8a

Browse files
authored
[AArch64][CodeGen] Fix illegal register aliasing bug for mops instrs (#88869)
A bug was found where mops instructions were being generated that aliased the source and size registers. This is unpredictable behaviour. This patch uses the earlyclobber constraint on the input source register so that it doesn't alias with the size register. Also a test is introduced which checks affected instructions can't violate this constraint.
1 parent e90bc9c commit 3e64f8a

File tree

3 files changed

+37
-1
lines changed

3 files changed

+37
-1
lines changed

llvm/lib/Target/AArch64/AArch64InstrInfo.td

+1-1
Original file line numberDiff line numberDiff line change
@@ -9486,7 +9486,7 @@ let Predicates = [HasMOPS], Defs = [NZCV], Size = 12, mayStore = 1 in {
94869486
let mayLoad = 0 in {
94879487
def MOPSMemorySetPseudo : Pseudo<(outs GPR64common:$Rd_wb, GPR64:$Rn_wb),
94889488
(ins GPR64common:$Rd, GPR64:$Rn, GPR64:$Rm),
9489-
[], "$Rd = $Rd_wb,$Rn = $Rn_wb">, Sched<[]>;
9489+
[], "$Rd = $Rd_wb,$Rn = $Rn_wb,@earlyclobber $Rn_wb">, Sched<[]>;
94909490
}
94919491
}
94929492
let Predicates = [HasMOPS, HasMTE], Defs = [NZCV], Size = 12, mayLoad = 0, mayStore = 1 in {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
; RUN: llc -O1 -mtriple=aarch64-none-linux-gnu -mattr=+mops -o - %s | FileCheck %s
2+
3+
define void @call_memset_intrinsic() #0 {
4+
; CHECK-LABEL: call_memset_intrinsic:
5+
; CHECK: // %bb.0: // %entry
6+
; CHECK: setp [x{{[0-9]+}}]!, x{{[0-9]+}}!, x{{[0-9]+}}
7+
; CHECK-NOT: setp [x{{[0-9]+}}]!, x[[REG:[0-9]+]]!, x[[REG]]
8+
; CHECK-NEXT: setm [x{{[0-9]+}}]!, x{{[0-9]+}}!, x{{[0-9]+}}
9+
; CHECK-NOT: setm [x{{[0-9]+}}]!, x[[REG:[0-9]+]]!, x[[REG]]
10+
; CHECK-NEXT: sete [x{{[0-9]+}}]!, x{{[0-9]+}}!, x{{[0-9]+}}
11+
; CHECK-NOT: sete [x{{[0-9]+}}]!, x[[REG:[0-9]+]]!, x[[REG]]
12+
entry:
13+
14+
%V0 = alloca [65 x i8], align 1
15+
call void @llvm.memset.p0.i64(ptr noundef nonnull align 1 dereferenceable(64) %V0, i8 64, i64 64, i1 false)
16+
%add.ptr = getelementptr inbounds i8, ptr %V0, i64 64
17+
call void @llvm.memset.p0.i64(ptr noundef nonnull align 1 dereferenceable(64) %add.ptr, i8 64, i64 64, i1 false)
18+
ret void
19+
}
20+
21+
attributes #0 = { "target-cpu"="generic" "target-features"="+mops,+strict-align,+v9.3a" }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// RUN: not llvm-mc -triple aarch64 -mattr=+mops < %s 2>&1 | FileCheck %s
2+
3+
setp [x0]!, x1!, x1
4+
setm [x0]!, x1!, x1
5+
sete [x0]!, x1!, x1
6+
7+
// CHECK: error: invalid SET instruction, source and size registers are the same
8+
// CHECK-NEXT: setp [x0]!, x1!, x1
9+
// CHECK-NEXT: ^
10+
// CHECK-NEXT: error: invalid SET instruction, source and size registers are the same
11+
// CHECK-NEXT: setm [x0]!, x1!, x1
12+
// CHECK-NEXT: ^
13+
// CHECK-NEXT: error: invalid SET instruction, source and size registers are the same
14+
// CHECK-NEXT: sete [x0]!, x1!, x1
15+
// CHECK-NEXT: ^

0 commit comments

Comments
 (0)