[llvm] [AArch64][CodeGen] Don't try to compute stack addresses in xzr (PR #213009)

Simon Tatham via llvm-commits llvm-commits at lists.llvm.org
Fri Jul 31 01:14:31 PDT 2026


================
@@ -0,0 +1,149 @@
+# RUN: llc -mtriple=aarch64 -O1 -run-pass=aarch64-cond-br-tuning %s -o - \
+# RUN:   | FileCheck %s
+# RUN: llc -mtriple=aarch64 -O1 %s -o - -verify-machineinstrs
+
+# Source: an llvm-reduced version of fuzzer-generated compiler input in
+# https://github.com/llvm/llvm-project/issues/212528
+#
+# The point of this test is to ensure we don't generate an add instruction
+# involving a stack slot with xzr as the destination, e.g.
+#
+#   $xzr = ADDSXri %stack.0, 0, 0, implicit-def $nzcv
+#
+# because in this case, since there are SVE registers on the stack, that would
+# expand to a sequence of instructions such as
+#
+#    $xzr = ADDXri $sp, 12, 0
+#    $xzr = ADDVL_XXI $xzr, 1, implicit $vg
+#    $xzr = ADDSXri $xzr, 0, 0, implicit-def $nzcv
+#
+# and none of those is a legal AArch64 instruction (ADD and ADDVL can't target
+# xzr at all, and ADDS can't use it as an input). Also, if they were legal,
+# they wouldn't compute the intended value, since the results of the first two
+# instructions would be thrown away.
+#
+# We check the output of the phase that could have generated this unwanted
+# ADDS, and also check that the full code generation passes
+# -verify-machineinstrs.
+
+--- |
+  ; ModuleID = '<stdin>'
+  source_filename = "<stdin>"
+  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"
+  target triple = "aarch64"
+  
+  define void @launch(i1 %0, ptr %g28, ptr %g10) #0 {
+    %2 = alloca i8, align 4
+    br label %3
+  
+  3:                                                ; preds = %8, %6, %1
+    %4 = phi <2 x i8> [ zeroinitializer, %1 ], [ %5, %8 ], [ zeroinitializer, %6 ]
+    %5 = xor <2 x i8> %4, splat (i8 1)
+    br i1 %0, label %8, label %6
+  
+  6:                                                ; preds = %3
+    %7 = extractelement <2 x i8> %4, i64 0
+    store <4 x i16> splat (i16 1), ptr %g28, align 8
+    br label %3
+  
+  8:                                                ; preds = %3
+    %9 = call ptr @f20()
+    store i8 0, ptr %g10, align 4
+    %10 = icmp eq ptr null, %2
+    br i1 %10, label %3, label %11
+  
+  11:                                               ; preds = %8
+    ret void
+  }
+  
+  declare ptr @f20() #1
+  
+  attributes #0 = { "frame-pointer"="non-leaf-no-reserve" "target-features"="+sve,+armv9a" }
+  attributes #1 = { "target-features"="+armv9a" }
+...
+---
+name:            launch
+alignment:       4
+tracksRegLiveness: true
+noPhis:          false
+isSSA:           true
+noVRegs:         false
+hasFakeUses:     false
+registers:
+  - { id: 0, class: fpr64 }
+  - { id: 1, class: fpr64 }
+  - { id: 2, class: gpr32 }
+  - { id: 3, class: gpr64common }
+  - { id: 4, class: gpr64common }
+  - { id: 5, class: gpr32 }
+  - { id: 6, class: fpr64 }
+  - { id: 7, class: fpr128 }
+  - { id: 8, class: zpr }
+  - { id: 9, class: zpr }
+  - { id: 10, class: zpr }
+  - { id: 11, class: fpr64 }
+  - { id: 12, class: fpr64 }
+  - { id: 13, class: fpr128 }
+  - { id: 14, class: gpr64all }
+  - { id: 15, class: gpr32 }
+  - { id: 16, class: gpr64common }
----------------
statham-arm wrote:

This is already the result of both `llvm-reduce` and `--simplify-mir`!

I think in particular that the presence of an SVE register in the stack frame is important, because it's what causes the add-to-frame-index to expand into multiple instructions. Otherwise it would do the thing I said in the comment (before I cut it down just now): a _simple_ add-to-frame-index turns into just `add xN, sp, #M`, and in that simple form, it _is_ legal and correct to replace `xN` with `xzr`.

https://github.com/llvm/llvm-project/pull/213009


More information about the llvm-commits mailing list