From 3e64f8a4e74cdcaf5920879c86e7e0a827f6ec13 Mon Sep 17 00:00:00 2001 From: Nashe Mncube Date: Thu, 18 Apr 2024 10:53:23 +0100 Subject: [PATCH] [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. --- llvm/lib/Target/AArch64/AArch64InstrInfo.td | 2 +- .../CodeGen/AArch64/mops-register-alias.ll | 21 +++++++++++++++++++ .../AArch64/armv9.3a-mops-register-aliasing.s | 15 +++++++++++++ 3 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 llvm/test/CodeGen/AArch64/mops-register-alias.ll create mode 100644 llvm/test/MC/AArch64/armv9.3a-mops-register-aliasing.s diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td index e1624f70185e1e..3bf90778363c6c 100644 --- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td +++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td @@ -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 { diff --git a/llvm/test/CodeGen/AArch64/mops-register-alias.ll b/llvm/test/CodeGen/AArch64/mops-register-alias.ll new file mode 100644 index 00000000000000..855ab959c4e76b --- /dev/null +++ b/llvm/test/CodeGen/AArch64/mops-register-alias.ll @@ -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" } diff --git a/llvm/test/MC/AArch64/armv9.3a-mops-register-aliasing.s b/llvm/test/MC/AArch64/armv9.3a-mops-register-aliasing.s new file mode 100644 index 00000000000000..109b33857a9d2d --- /dev/null +++ b/llvm/test/MC/AArch64/armv9.3a-mops-register-aliasing.s @@ -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: ^