[llvm] [AArch64] Define constructive EXT_ZZZI pseudo instruction (PR #152552)

Gaƫtan Bossu via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 11 06:32:07 PDT 2025


================
@@ -0,0 +1,91 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 5
+# RUN: llc -mtriple=aarch64 -mattr=+sve -run-pass=aarch64-expand-pseudo -verify-machineinstrs %s -o - | FileCheck %s
+
+# Test the expansion of constructive ternary operations into their
+# destructive counterparts.
+
+
+# EXT_ZZZI
+
+---
+name:            test_ext_zzzi_unique
+body:             |
+  bb.0:
+    ; CHECK-LABEL: name: test_ext_zzzi_unique
+    ; CHECK: BUNDLE implicit-def $z2, implicit-def $q2, implicit-def $d2, implicit-def $s2, implicit-def $h2, implicit-def $b2, implicit-def $b2_hi, implicit-def $h2_hi, implicit-def $s2_hi, implicit-def $d2_hi, implicit-def $q2_hi, implicit $z0, implicit killed $z1 {
+    ; CHECK-NEXT:   $z2 = MOVPRFX_ZZ $z0
+    ; CHECK-NEXT:   $z2 = EXT_ZZI internal killed $z2, killed $z1, 1
+    ; CHECK-NEXT: }
+    ; CHECK-NEXT: RET undef $lr, implicit killed $z2
+    $z2 = EXT_ZZZI killed $z0, killed $z1, 1
+    RET_ReallyLR implicit killed $z2
+...
+
+# Here the destination register is the same as the second operand,
+# we cannot use movprfx.
+---
+name:            test_ext_zzzi_not_unique
+body:             |
+  bb.0:
+    ; CHECK-LABEL: name: test_ext_zzzi_not_unique
+    ; CHECK: BUNDLE implicit-def $z2, implicit-def $q2, implicit-def $d2, implicit-def $s2, implicit-def $h2, implicit-def $b2, implicit-def $b2_hi, implicit-def $h2_hi, implicit-def $s2_hi, implicit-def $d2_hi, implicit-def $q2_hi, implicit $z0 {
+    ; CHECK-NEXT:   $z2 = ORR_ZZZ $z0, $z0
+    ; CHECK-NEXT:   $z2 = EXT_ZZI internal killed $z2, internal killed $z2, 1
+    ; CHECK-NEXT: }
+    ; CHECK-NEXT: RET undef $lr, implicit killed $z2
+    $z2 = EXT_ZZZI killed $z0, killed $z2, 1
----------------
gbossu wrote:

This is the typical trap when re-writing two-address instructions, and I fell into it head first :(

I don't think there is an easy way around that other than convincing the register allocator to give different registers to the two inputs.

I also think the existing lowering of `DestructiveBinary` pseudo instructions is unsafe for the same reason. This can be seen in the `test_bic_zpzz_not_unique_regs` test case where the incoming value of `z2` is overwritten. I'll probably open a PR to disable `DestructiveBinary` pseudos for now.

For the `EXT` case, I'll probably go with @paulwalker-arm 's suggestion and create a variant of `EXT` that takes a single Z input.

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


More information about the llvm-commits mailing list