Skip to content

Commit

Permalink
[AArch64][CodeGen] Fix illegal register aliasing bug for mops instrs (l…
Browse files Browse the repository at this point in the history
…lvm#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.
  • Loading branch information
nasherm authored Apr 18, 2024
1 parent e90bc9c commit 3e64f8a
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 1 deletion.
2 changes: 1 addition & 1 deletion llvm/lib/Target/AArch64/AArch64InstrInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -9486,7 +9486,7 @@ let Predicates = [HasMOPS], Defs = [NZCV], Size = 12, mayStore = 1 in {
let mayLoad = 0 in {
def MOPSMemorySetPseudo : Pseudo<(outs GPR64common:$Rd_wb, GPR64:$Rn_wb),
(ins GPR64common:$Rd, GPR64:$Rn, GPR64:$Rm),
[], "$Rd = $Rd_wb,$Rn = $Rn_wb">, Sched<[]>;
[], "$Rd = $Rd_wb,$Rn = $Rn_wb,@earlyclobber $Rn_wb">, Sched<[]>;
}
}
let Predicates = [HasMOPS, HasMTE], Defs = [NZCV], Size = 12, mayLoad = 0, mayStore = 1 in {
Expand Down
21 changes: 21 additions & 0 deletions llvm/test/CodeGen/AArch64/mops-register-alias.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
; RUN: llc -O1 -mtriple=aarch64-none-linux-gnu -mattr=+mops -o - %s | FileCheck %s

define void @call_memset_intrinsic() #0 {
; CHECK-LABEL: call_memset_intrinsic:
; CHECK: // %bb.0: // %entry
; CHECK: setp [x{{[0-9]+}}]!, x{{[0-9]+}}!, x{{[0-9]+}}
; CHECK-NOT: setp [x{{[0-9]+}}]!, x[[REG:[0-9]+]]!, x[[REG]]
; CHECK-NEXT: setm [x{{[0-9]+}}]!, x{{[0-9]+}}!, x{{[0-9]+}}
; CHECK-NOT: setm [x{{[0-9]+}}]!, x[[REG:[0-9]+]]!, x[[REG]]
; CHECK-NEXT: sete [x{{[0-9]+}}]!, x{{[0-9]+}}!, x{{[0-9]+}}
; CHECK-NOT: sete [x{{[0-9]+}}]!, x[[REG:[0-9]+]]!, x[[REG]]
entry:

%V0 = alloca [65 x i8], align 1
call void @llvm.memset.p0.i64(ptr noundef nonnull align 1 dereferenceable(64) %V0, i8 64, i64 64, i1 false)
%add.ptr = getelementptr inbounds i8, ptr %V0, i64 64
call void @llvm.memset.p0.i64(ptr noundef nonnull align 1 dereferenceable(64) %add.ptr, i8 64, i64 64, i1 false)
ret void
}

attributes #0 = { "target-cpu"="generic" "target-features"="+mops,+strict-align,+v9.3a" }
15 changes: 15 additions & 0 deletions llvm/test/MC/AArch64/armv9.3a-mops-register-aliasing.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// RUN: not llvm-mc -triple aarch64 -mattr=+mops < %s 2>&1 | FileCheck %s

setp [x0]!, x1!, x1
setm [x0]!, x1!, x1
sete [x0]!, x1!, x1

// CHECK: error: invalid SET instruction, source and size registers are the same
// CHECK-NEXT: setp [x0]!, x1!, x1
// CHECK-NEXT: ^
// CHECK-NEXT: error: invalid SET instruction, source and size registers are the same
// CHECK-NEXT: setm [x0]!, x1!, x1
// CHECK-NEXT: ^
// CHECK-NEXT: error: invalid SET instruction, source and size registers are the same
// CHECK-NEXT: sete [x0]!, x1!, x1
// CHECK-NEXT: ^

0 comments on commit 3e64f8a

Please sign in to comment.