[llvm] [GlobalISel][AArch64] Allow vector ptr to int unmerges (PR #115228)

David Green via llvm-commits llvm-commits at lists.llvm.org
Wed Nov 6 14:32:50 PST 2024


https://github.com/davemgreen created https://github.com/llvm/llvm-project/pull/115228

Vector pointer -> scalar integer unmerges are already legal. This loosens the verifier check for vector-of-pointers -> vectors.

>From cb34bb28e8af526cfb45e04467d6468605003585 Mon Sep 17 00:00:00 2001
From: David Green <david.green at arm.com>
Date: Wed, 6 Nov 2024 22:31:17 +0000
Subject: [PATCH] [GlobalISel][AArch64] Allow vector ptr to int unmerges

Vector pointer -> scalar integer unmerges are already legal. This loosens the
verifier check for vector-of-pointers -> vectors.
---
 llvm/lib/CodeGen/MachineVerifier.cpp          |   4 +-
 llvm/test/CodeGen/AArch64/getelementptr.ll    | 478 ++++++++++++++++++
 .../MachineVerifier/test_g_unmerge_values.mir |   5 +
 3 files changed, 486 insertions(+), 1 deletion(-)
 create mode 100644 llvm/test/CodeGen/AArch64/getelementptr.ll

diff --git a/llvm/lib/CodeGen/MachineVerifier.cpp b/llvm/lib/CodeGen/MachineVerifier.cpp
index e2c09fe25d55cd..10369928f7a05b 100644
--- a/llvm/lib/CodeGen/MachineVerifier.cpp
+++ b/llvm/lib/CodeGen/MachineVerifier.cpp
@@ -1487,7 +1487,9 @@ void MachineVerifier::verifyPreISelGenericInstruction(const MachineInstr *MI) {
     LLT SrcTy = MRI->getType(MI->getOperand(NumDsts).getReg());
     if (DstTy.isVector()) {
       // This case is the converse of G_CONCAT_VECTORS.
-      if (!SrcTy.isVector() || SrcTy.getScalarType() != DstTy.getScalarType() ||
+      if (!SrcTy.isVector() ||
+          (SrcTy.getScalarType() != DstTy.getScalarType() &&
+           !SrcTy.isPointerVector()) ||
           SrcTy.isScalableVector() != DstTy.isScalableVector() ||
           SrcTy.getSizeInBits() != NumDsts * DstTy.getSizeInBits())
         report("G_UNMERGE_VALUES source operand does not match vector "
diff --git a/llvm/test/CodeGen/AArch64/getelementptr.ll b/llvm/test/CodeGen/AArch64/getelementptr.ll
new file mode 100644
index 00000000000000..91a98dfa91aca6
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/getelementptr.ll
@@ -0,0 +1,478 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; RUN: llc -mtriple=aarch64 -verify-machineinstrs %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-SD
+; RUN: llc -mtriple=aarch64 -global-isel -global-isel-abort=2 -verify-machineinstrs %s -o - 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK-GI
+
+define ptr @s(ptr %p, i32 %q) {
+; CHECK-LABEL: s:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    add x0, x0, w1, sxtw #2
+; CHECK-NEXT:    ret
+  %d = getelementptr i32, ptr %p, i32 %q
+  ret ptr %d
+}
+
+define <2 x ptr> @v2(<2 x ptr> %p, i32 %q) {
+; CHECK-SD-LABEL: v2:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    dup v1.2s, w0
+; CHECK-SD-NEXT:    sshll v1.2d, v1.2s, #2
+; CHECK-SD-NEXT:    add v0.2d, v0.2d, v1.2d
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: v2:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    dup v1.2s, w0
+; CHECK-GI-NEXT:    adrp x8, .LCPI1_0
+; CHECK-GI-NEXT:    ldr q2, [x8, :lo12:.LCPI1_0]
+; CHECK-GI-NEXT:    fmov x9, d2
+; CHECK-GI-NEXT:    mov x11, v2.d[1]
+; CHECK-GI-NEXT:    sshll v1.2d, v1.2s, #0
+; CHECK-GI-NEXT:    fmov x8, d1
+; CHECK-GI-NEXT:    mov x10, v1.d[1]
+; CHECK-GI-NEXT:    mul x8, x8, x9
+; CHECK-GI-NEXT:    mul x9, x10, x11
+; CHECK-GI-NEXT:    mov v1.d[0], x8
+; CHECK-GI-NEXT:    mov v1.d[1], x9
+; CHECK-GI-NEXT:    add v0.2d, v0.2d, v1.2d
+; CHECK-GI-NEXT:    ret
+  %d = getelementptr i32, <2 x ptr> %p, i32 %q
+  ret <2 x ptr> %d
+}
+
+define <3 x ptr> @v3(<3 x ptr> %p, i32 %q) {
+; CHECK-LABEL: v3:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    dup v3.2s, w0
+; CHECK-NEXT:    // kill: def $d0 killed $d0 def $q0
+; CHECK-NEXT:    // kill: def $d1 killed $d1 def $q1
+; CHECK-NEXT:    mov w8, #2 // =0x2
+; CHECK-NEXT:    mov v0.d[1], v1.d[0]
+; CHECK-NEXT:    sshll v1.2d, v3.2s, #2
+; CHECK-NEXT:    fmov s3, w0
+; CHECK-NEXT:    sshll v3.2d, v3.2s, #0
+; CHECK-NEXT:    add v0.2d, v0.2d, v1.2d
+; CHECK-NEXT:    fmov d1, x8
+; CHECK-NEXT:    ushl d3, d3, d1
+; CHECK-NEXT:    ext v1.16b, v0.16b, v0.16b, #8
+; CHECK-NEXT:    // kill: def $d0 killed $d0 killed $q0
+; CHECK-NEXT:    // kill: def $d1 killed $d1 killed $q1
+; CHECK-NEXT:    add d2, d2, d3
+; CHECK-NEXT:    ret
+  %d = getelementptr i32, <3 x ptr> %p, i32 %q
+  ret <3 x ptr> %d
+}
+
+define <4 x ptr> @v4(<4 x ptr> %p, i32 %q) {
+; CHECK-SD-LABEL: v4:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    dup v2.2s, w0
+; CHECK-SD-NEXT:    sshll v2.2d, v2.2s, #2
+; CHECK-SD-NEXT:    add v0.2d, v0.2d, v2.2d
+; CHECK-SD-NEXT:    add v1.2d, v1.2d, v2.2d
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: v4:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    dup v2.2s, w0
+; CHECK-GI-NEXT:    adrp x8, .LCPI3_0
+; CHECK-GI-NEXT:    ldr q3, [x8, :lo12:.LCPI3_0]
+; CHECK-GI-NEXT:    fmov x8, d3
+; CHECK-GI-NEXT:    mov x12, v3.d[1]
+; CHECK-GI-NEXT:    sshll v2.2d, v2.2s, #0
+; CHECK-GI-NEXT:    fmov x9, d2
+; CHECK-GI-NEXT:    mov x11, v2.d[1]
+; CHECK-GI-NEXT:    mul x10, x9, x8
+; CHECK-GI-NEXT:    mul x8, x9, x8
+; CHECK-GI-NEXT:    mul x9, x11, x12
+; CHECK-GI-NEXT:    mov v2.d[0], x10
+; CHECK-GI-NEXT:    mov v3.d[0], x8
+; CHECK-GI-NEXT:    mov v2.d[1], x9
+; CHECK-GI-NEXT:    mov v3.d[1], x9
+; CHECK-GI-NEXT:    add v0.2d, v0.2d, v2.2d
+; CHECK-GI-NEXT:    add v1.2d, v1.2d, v3.2d
+; CHECK-GI-NEXT:    ret
+  %d = getelementptr i32, <4 x ptr> %p, i32 %q
+  ret <4 x ptr> %d
+}
+
+define <2 x ptr> @v2b(ptr %p, <2 x i32> %q) {
+; CHECK-SD-LABEL: v2b:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    sshll v0.2d, v0.2s, #2
+; CHECK-SD-NEXT:    dup v1.2d, x0
+; CHECK-SD-NEXT:    add v0.2d, v1.2d, v0.2d
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: v2b:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI4_0
+; CHECK-GI-NEXT:    sshll v0.2d, v0.2s, #0
+; CHECK-GI-NEXT:    ldr q1, [x8, :lo12:.LCPI4_0]
+; CHECK-GI-NEXT:    fmov x8, d0
+; CHECK-GI-NEXT:    fmov x9, d1
+; CHECK-GI-NEXT:    mov x10, v0.d[1]
+; CHECK-GI-NEXT:    mov x11, v1.d[1]
+; CHECK-GI-NEXT:    dup v1.2d, x0
+; CHECK-GI-NEXT:    mul x8, x8, x9
+; CHECK-GI-NEXT:    mul x9, x10, x11
+; CHECK-GI-NEXT:    mov v0.d[0], x8
+; CHECK-GI-NEXT:    mov v0.d[1], x9
+; CHECK-GI-NEXT:    add v0.2d, v1.2d, v0.2d
+; CHECK-GI-NEXT:    ret
+  %d = getelementptr i32, ptr %p, <2 x i32> %q
+  ret <2 x ptr> %d
+}
+
+define <3 x ptr> @v3b(ptr %p, <3 x i32> %q) {
+; CHECK-LABEL: v3b:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    dup v1.2d, x0
+; CHECK-NEXT:    sshll v2.2d, v0.2s, #2
+; CHECK-NEXT:    mov w8, #2 // =0x2
+; CHECK-NEXT:    sshll2 v3.2d, v0.4s, #0
+; CHECK-NEXT:    add v0.2d, v1.2d, v2.2d
+; CHECK-NEXT:    fmov d1, x8
+; CHECK-NEXT:    ushl d2, d3, d1
+; CHECK-NEXT:    fmov d3, x0
+; CHECK-NEXT:    ext v1.16b, v0.16b, v0.16b, #8
+; CHECK-NEXT:    // kill: def $d0 killed $d0 killed $q0
+; CHECK-NEXT:    // kill: def $d1 killed $d1 killed $q1
+; CHECK-NEXT:    add d2, d3, d2
+; CHECK-NEXT:    ret
+  %d = getelementptr i32, ptr %p, <3 x i32> %q
+  ret <3 x ptr> %d
+}
+
+define <4 x ptr> @v4b(ptr %p, <4 x i32> %q) {
+; CHECK-SD-LABEL: v4b:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    sshll2 v1.2d, v0.4s, #2
+; CHECK-SD-NEXT:    dup v2.2d, x0
+; CHECK-SD-NEXT:    sshll v0.2d, v0.2s, #2
+; CHECK-SD-NEXT:    add v1.2d, v2.2d, v1.2d
+; CHECK-SD-NEXT:    add v0.2d, v2.2d, v0.2d
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: v4b:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI6_0
+; CHECK-GI-NEXT:    sshll v1.2d, v0.2s, #0
+; CHECK-GI-NEXT:    sshll2 v0.2d, v0.4s, #0
+; CHECK-GI-NEXT:    ldr q2, [x8, :lo12:.LCPI6_0]
+; CHECK-GI-NEXT:    fmov x8, d2
+; CHECK-GI-NEXT:    fmov x9, d1
+; CHECK-GI-NEXT:    fmov x12, d0
+; CHECK-GI-NEXT:    mov x10, v2.d[1]
+; CHECK-GI-NEXT:    mov x11, v1.d[1]
+; CHECK-GI-NEXT:    mov x13, v0.d[1]
+; CHECK-GI-NEXT:    dup v2.2d, x0
+; CHECK-GI-NEXT:    mul x9, x9, x8
+; CHECK-GI-NEXT:    mul x8, x12, x8
+; CHECK-GI-NEXT:    mul x11, x11, x10
+; CHECK-GI-NEXT:    mov v0.d[0], x9
+; CHECK-GI-NEXT:    mul x10, x13, x10
+; CHECK-GI-NEXT:    mov v1.d[0], x8
+; CHECK-GI-NEXT:    mov v0.d[1], x11
+; CHECK-GI-NEXT:    mov v1.d[1], x10
+; CHECK-GI-NEXT:    add v0.2d, v2.2d, v0.2d
+; CHECK-GI-NEXT:    add v1.2d, v2.2d, v1.2d
+; CHECK-GI-NEXT:    ret
+  %d = getelementptr i32, ptr %p, <4 x i32> %q
+  ret <4 x ptr> %d
+}
+
+
+define ptr @s_10(ptr %p, i32 %q) {
+; CHECK-LABEL: s_10:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    add x0, x0, #40
+; CHECK-NEXT:    ret
+  %d = getelementptr i32, ptr %p, i32 10
+  ret ptr %d
+}
+
+define <2 x ptr> @v2_10(<2 x ptr> %p, i32 %q) {
+; CHECK-SD-LABEL: v2_10:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    mov w8, #40 // =0x28
+; CHECK-SD-NEXT:    dup v1.2d, x8
+; CHECK-SD-NEXT:    add v0.2d, v0.2d, v1.2d
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: v2_10:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI8_0
+; CHECK-GI-NEXT:    ldr q1, [x8, :lo12:.LCPI8_0]
+; CHECK-GI-NEXT:    add v0.2d, v0.2d, v1.2d
+; CHECK-GI-NEXT:    ret
+  %d = getelementptr i32, <2 x ptr> %p, i32 10
+  ret <2 x ptr> %d
+}
+
+define <3 x ptr> @v3_10(<3 x ptr> %p, i32 %q) {
+; CHECK-LABEL: v3_10:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    // kill: def $d0 killed $d0 def $q0
+; CHECK-NEXT:    // kill: def $d1 killed $d1 def $q1
+; CHECK-NEXT:    mov w8, #40 // =0x28
+; CHECK-NEXT:    mov v0.d[1], v1.d[0]
+; CHECK-NEXT:    dup v3.2d, x8
+; CHECK-NEXT:    add d2, d2, d3
+; CHECK-NEXT:    add v0.2d, v0.2d, v3.2d
+; CHECK-NEXT:    ext v1.16b, v0.16b, v0.16b, #8
+; CHECK-NEXT:    // kill: def $d0 killed $d0 killed $q0
+; CHECK-NEXT:    // kill: def $d1 killed $d1 killed $q1
+; CHECK-NEXT:    ret
+  %d = getelementptr i32, <3 x ptr> %p, i32 10
+  ret <3 x ptr> %d
+}
+
+define <4 x ptr> @v4_10(<4 x ptr> %p, i32 %q) {
+; CHECK-SD-LABEL: v4_10:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    mov w8, #40 // =0x28
+; CHECK-SD-NEXT:    dup v2.2d, x8
+; CHECK-SD-NEXT:    add v0.2d, v0.2d, v2.2d
+; CHECK-SD-NEXT:    add v1.2d, v1.2d, v2.2d
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: v4_10:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI10_0
+; CHECK-GI-NEXT:    ldr q2, [x8, :lo12:.LCPI10_0]
+; CHECK-GI-NEXT:    add v0.2d, v0.2d, v2.2d
+; CHECK-GI-NEXT:    add v1.2d, v1.2d, v2.2d
+; CHECK-GI-NEXT:    ret
+  %d = getelementptr i32, <4 x ptr> %p, i32 10
+  ret <4 x ptr> %d
+}
+
+define <2 x ptr> @v2b_10(ptr %p, <2 x i32> %q) {
+; CHECK-SD-LABEL: v2b_10:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    mov w8, #40 // =0x28
+; CHECK-SD-NEXT:    dup v0.2d, x0
+; CHECK-SD-NEXT:    dup v1.2d, x8
+; CHECK-SD-NEXT:    add v0.2d, v0.2d, v1.2d
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: v2b_10:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    movi v0.2s, #10
+; CHECK-GI-NEXT:    adrp x8, .LCPI11_0
+; CHECK-GI-NEXT:    ldr q1, [x8, :lo12:.LCPI11_0]
+; CHECK-GI-NEXT:    fmov x9, d1
+; CHECK-GI-NEXT:    mov x11, v1.d[1]
+; CHECK-GI-NEXT:    dup v1.2d, x0
+; CHECK-GI-NEXT:    sshll v0.2d, v0.2s, #0
+; CHECK-GI-NEXT:    fmov x8, d0
+; CHECK-GI-NEXT:    mov x10, v0.d[1]
+; CHECK-GI-NEXT:    mul x8, x8, x9
+; CHECK-GI-NEXT:    mul x9, x10, x11
+; CHECK-GI-NEXT:    mov v0.d[0], x8
+; CHECK-GI-NEXT:    mov v0.d[1], x9
+; CHECK-GI-NEXT:    add v0.2d, v1.2d, v0.2d
+; CHECK-GI-NEXT:    ret
+  %d = getelementptr i32, ptr %p, <2 x i32> <i32 10, i32 10>
+  ret <2 x ptr> %d
+}
+
+define <3 x ptr> @v3b_10(ptr %p, <3 x i32> %q) {
+; CHECK-LABEL: v3b_10:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    mov w8, #40 // =0x28
+; CHECK-NEXT:    dup v0.2d, x0
+; CHECK-NEXT:    fmov d3, x0
+; CHECK-NEXT:    dup v2.2d, x8
+; CHECK-NEXT:    add v0.2d, v0.2d, v2.2d
+; CHECK-NEXT:    add d2, d3, d2
+; CHECK-NEXT:    ext v1.16b, v0.16b, v0.16b, #8
+; CHECK-NEXT:    // kill: def $d0 killed $d0 killed $q0
+; CHECK-NEXT:    // kill: def $d1 killed $d1 killed $q1
+; CHECK-NEXT:    ret
+  %d = getelementptr i32, ptr %p, <3 x i32> <i32 10, i32 10, i32 10>
+  ret <3 x ptr> %d
+}
+
+define <4 x ptr> @v4b_10(ptr %p, <4 x i32> %q) {
+; CHECK-SD-LABEL: v4b_10:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    mov w8, #40 // =0x28
+; CHECK-SD-NEXT:    dup v0.2d, x0
+; CHECK-SD-NEXT:    dup v1.2d, x8
+; CHECK-SD-NEXT:    add v0.2d, v0.2d, v1.2d
+; CHECK-SD-NEXT:    mov v1.16b, v0.16b
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: v4b_10:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    movi v0.2s, #10
+; CHECK-GI-NEXT:    adrp x8, .LCPI13_0
+; CHECK-GI-NEXT:    dup v2.2d, x0
+; CHECK-GI-NEXT:    ldr q1, [x8, :lo12:.LCPI13_0]
+; CHECK-GI-NEXT:    fmov x8, d1
+; CHECK-GI-NEXT:    mov x12, v1.d[1]
+; CHECK-GI-NEXT:    sshll v0.2d, v0.2s, #0
+; CHECK-GI-NEXT:    fmov x9, d0
+; CHECK-GI-NEXT:    mov x11, v0.d[1]
+; CHECK-GI-NEXT:    mul x10, x9, x8
+; CHECK-GI-NEXT:    mul x8, x9, x8
+; CHECK-GI-NEXT:    mul x9, x11, x12
+; CHECK-GI-NEXT:    mov v0.d[0], x10
+; CHECK-GI-NEXT:    mov v1.d[0], x8
+; CHECK-GI-NEXT:    mov v0.d[1], x9
+; CHECK-GI-NEXT:    mov v1.d[1], x9
+; CHECK-GI-NEXT:    add v0.2d, v2.2d, v0.2d
+; CHECK-GI-NEXT:    add v1.2d, v2.2d, v1.2d
+; CHECK-GI-NEXT:    ret
+  %d = getelementptr i32, ptr %p, <4 x i32> <i32 10, i32 10, i32 10, i32 10>
+  ret <4 x ptr> %d
+}
+
+
+define ptr @s_m10(ptr %p, i32 %q) {
+; CHECK-LABEL: s_m10:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    sub x0, x0, #40
+; CHECK-NEXT:    ret
+  %d = getelementptr i32, ptr %p, i32 -10
+  ret ptr %d
+}
+
+define <2 x ptr> @v2_m10(<2 x ptr> %p, i32 %q) {
+; CHECK-SD-LABEL: v2_m10:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    mov x8, #-40 // =0xffffffffffffffd8
+; CHECK-SD-NEXT:    dup v1.2d, x8
+; CHECK-SD-NEXT:    add v0.2d, v0.2d, v1.2d
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: v2_m10:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI15_0
+; CHECK-GI-NEXT:    ldr q1, [x8, :lo12:.LCPI15_0]
+; CHECK-GI-NEXT:    add v0.2d, v0.2d, v1.2d
+; CHECK-GI-NEXT:    ret
+  %d = getelementptr i32, <2 x ptr> %p, i32 -10
+  ret <2 x ptr> %d
+}
+
+define <3 x ptr> @v3_m10(<3 x ptr> %p, i32 %q) {
+; CHECK-LABEL: v3_m10:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    // kill: def $d0 killed $d0 def $q0
+; CHECK-NEXT:    // kill: def $d1 killed $d1 def $q1
+; CHECK-NEXT:    mov x8, #-40 // =0xffffffffffffffd8
+; CHECK-NEXT:    mov v0.d[1], v1.d[0]
+; CHECK-NEXT:    dup v3.2d, x8
+; CHECK-NEXT:    add d2, d2, d3
+; CHECK-NEXT:    add v0.2d, v0.2d, v3.2d
+; CHECK-NEXT:    ext v1.16b, v0.16b, v0.16b, #8
+; CHECK-NEXT:    // kill: def $d0 killed $d0 killed $q0
+; CHECK-NEXT:    // kill: def $d1 killed $d1 killed $q1
+; CHECK-NEXT:    ret
+  %d = getelementptr i32, <3 x ptr> %p, i32 -10
+  ret <3 x ptr> %d
+}
+
+define <4 x ptr> @v4_m10(<4 x ptr> %p, i32 %q) {
+; CHECK-SD-LABEL: v4_m10:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    mov x8, #-40 // =0xffffffffffffffd8
+; CHECK-SD-NEXT:    dup v2.2d, x8
+; CHECK-SD-NEXT:    add v0.2d, v0.2d, v2.2d
+; CHECK-SD-NEXT:    add v1.2d, v1.2d, v2.2d
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: v4_m10:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    adrp x8, .LCPI17_0
+; CHECK-GI-NEXT:    ldr q2, [x8, :lo12:.LCPI17_0]
+; CHECK-GI-NEXT:    add v0.2d, v0.2d, v2.2d
+; CHECK-GI-NEXT:    add v1.2d, v1.2d, v2.2d
+; CHECK-GI-NEXT:    ret
+  %d = getelementptr i32, <4 x ptr> %p, i32 -10
+  ret <4 x ptr> %d
+}
+
+define <2 x ptr> @v2b_m10(ptr %p, <2 x i32> %q) {
+; CHECK-SD-LABEL: v2b_m10:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    mov x8, #-40 // =0xffffffffffffffd8
+; CHECK-SD-NEXT:    dup v1.2d, x0
+; CHECK-SD-NEXT:    dup v0.2d, x8
+; CHECK-SD-NEXT:    add v0.2d, v1.2d, v0.2d
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: v2b_m10:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    mvni v0.2s, #9
+; CHECK-GI-NEXT:    adrp x8, .LCPI18_0
+; CHECK-GI-NEXT:    ldr q1, [x8, :lo12:.LCPI18_0]
+; CHECK-GI-NEXT:    sshll v0.2d, v0.2s, #0
+; CHECK-GI-NEXT:    fmov x9, d1
+; CHECK-GI-NEXT:    mov x11, v1.d[1]
+; CHECK-GI-NEXT:    dup v1.2d, x0
+; CHECK-GI-NEXT:    fmov x8, d0
+; CHECK-GI-NEXT:    mov x10, v0.d[1]
+; CHECK-GI-NEXT:    mul x8, x8, x9
+; CHECK-GI-NEXT:    mul x9, x10, x11
+; CHECK-GI-NEXT:    mov v0.d[0], x8
+; CHECK-GI-NEXT:    mov v0.d[1], x9
+; CHECK-GI-NEXT:    add v0.2d, v1.2d, v0.2d
+; CHECK-GI-NEXT:    ret
+  %d = getelementptr i32, ptr %p, <2 x i32> <i32 -10, i32 -10>
+  ret <2 x ptr> %d
+}
+
+define <3 x ptr> @v3b_m10(ptr %p, <3 x i32> %q) {
+; CHECK-LABEL: v3b_m10:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    mov x8, #-40 // =0xffffffffffffffd8
+; CHECK-NEXT:    dup v0.2d, x0
+; CHECK-NEXT:    fmov d3, x0
+; CHECK-NEXT:    dup v2.2d, x8
+; CHECK-NEXT:    add v0.2d, v0.2d, v2.2d
+; CHECK-NEXT:    add d2, d3, d2
+; CHECK-NEXT:    ext v1.16b, v0.16b, v0.16b, #8
+; CHECK-NEXT:    // kill: def $d0 killed $d0 killed $q0
+; CHECK-NEXT:    // kill: def $d1 killed $d1 killed $q1
+; CHECK-NEXT:    ret
+  %d = getelementptr i32, ptr %p, <3 x i32> <i32 -10, i32 -10, i32 -10>
+  ret <3 x ptr> %d
+}
+
+define <4 x ptr> @v4b_m10(ptr %p, <4 x i32> %q) {
+; CHECK-SD-LABEL: v4b_m10:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    mov x8, #-40 // =0xffffffffffffffd8
+; CHECK-SD-NEXT:    dup v1.2d, x0
+; CHECK-SD-NEXT:    dup v0.2d, x8
+; CHECK-SD-NEXT:    add v0.2d, v1.2d, v0.2d
+; CHECK-SD-NEXT:    mov v1.16b, v0.16b
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: v4b_m10:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    mvni v0.2s, #9
+; CHECK-GI-NEXT:    adrp x8, .LCPI20_0
+; CHECK-GI-NEXT:    dup v2.2d, x0
+; CHECK-GI-NEXT:    ldr q1, [x8, :lo12:.LCPI20_0]
+; CHECK-GI-NEXT:    sshll v0.2d, v0.2s, #0
+; CHECK-GI-NEXT:    fmov x8, d1
+; CHECK-GI-NEXT:    mov x12, v1.d[1]
+; CHECK-GI-NEXT:    fmov x9, d0
+; CHECK-GI-NEXT:    mov x11, v0.d[1]
+; CHECK-GI-NEXT:    mul x10, x9, x8
+; CHECK-GI-NEXT:    mul x8, x9, x8
+; CHECK-GI-NEXT:    mul x9, x11, x12
+; CHECK-GI-NEXT:    mov v0.d[0], x10
+; CHECK-GI-NEXT:    mov v1.d[0], x8
+; CHECK-GI-NEXT:    mov v0.d[1], x9
+; CHECK-GI-NEXT:    mov v1.d[1], x9
+; CHECK-GI-NEXT:    add v0.2d, v2.2d, v0.2d
+; CHECK-GI-NEXT:    add v1.2d, v2.2d, v1.2d
+; CHECK-GI-NEXT:    ret
+  %d = getelementptr i32, ptr %p, <4 x i32> <i32 -10, i32 -10, i32 -10, i32 -10>
+  ret <4 x ptr> %d
+}
diff --git a/llvm/test/MachineVerifier/test_g_unmerge_values.mir b/llvm/test/MachineVerifier/test_g_unmerge_values.mir
index d16854890f7d88..4e5a2b2c2792bb 100644
--- a/llvm/test/MachineVerifier/test_g_unmerge_values.mir
+++ b/llvm/test/MachineVerifier/test_g_unmerge_values.mir
@@ -30,4 +30,9 @@ body: |
 
     ; CHECK: Bad machine code: G_UNMERGE_VALUES scalar source operand does not match scalar destination operands
     %17:_(s32), %18:_(s32), %19:_(s32) = G_UNMERGE_VALUES %14
+
+    ; CHECK-NOT: Bad machine code
+    %20:_(<4 x p0>) = IMPLICIT_DEF
+    %21:_(<2 x s64>), %22:_(<2 x s64>) = G_UNMERGE_VALUES %20
+    %23:_(s64), %24:_(s64), %25:_(s64), %26:_(s64) = G_UNMERGE_VALUES %20
 ...



More information about the llvm-commits mailing list