[llvm] [AArch64][GlobalISel] Add test coverage for saturating mul. NFC (PR #217154)
David Green via llvm-commits
llvm-commits at lists.llvm.org
Tue Aug 18 15:46:19 PDT 2026
https://github.com/davemgreen created https://github.com/llvm/llvm-project/pull/217154
None
>From af37c9e2b4bd86924b1f456be7a81763e7b73400 Mon Sep 17 00:00:00 2001
From: David Green <david.green at arm.com>
Date: Tue, 18 Aug 2026 23:46:07 +0100
Subject: [PATCH] [AArch64][GlobalISel] Add test coverage for saturating mul.
NFC
---
.../CodeGen/AArch64/saturating-vec-smull.ll | 266 ++++++++++++++----
1 file changed, 208 insertions(+), 58 deletions(-)
diff --git a/llvm/test/CodeGen/AArch64/saturating-vec-smull.ll b/llvm/test/CodeGen/AArch64/saturating-vec-smull.ll
index b81493580ecce..24f89fa0e85c3 100644
--- a/llvm/test/CodeGen/AArch64/saturating-vec-smull.ll
+++ b/llvm/test/CodeGen/AArch64/saturating-vec-smull.ll
@@ -1,16 +1,30 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
-; RUN: llc -mtriple=aarch64-none-elf < %s | FileCheck %s
+; RUN: llc -mtriple=aarch64-none-elf < %s | FileCheck %s --check-prefixes=CHECK,CHECK-SD
+; RUN: llc -mtriple=aarch64-none-elf -global-isel -global-isel-abort=2 2>&1 < %s | FileCheck %s --check-prefixes=CHECK,CHECK-GI
+; CHECK-GI: warning: Instruction selection used fallback path for extend_to_illegal_type
define <2 x i16> @saturating_2xi16(<2 x i16> %a, <2 x i16> %b) {
-; CHECK-LABEL: saturating_2xi16:
-; CHECK: // %bb.0:
-; CHECK-NEXT: shl v0.2s, v0.2s, #16
-; CHECK-NEXT: shl v1.2s, v1.2s, #16
-; CHECK-NEXT: sshr v0.2s, v0.2s, #16
-; CHECK-NEXT: sshr v1.2s, v1.2s, #16
-; CHECK-NEXT: sqdmulh v0.2s, v1.2s, v0.2s
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: saturating_2xi16:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: shl v0.2s, v0.2s, #16
+; CHECK-SD-NEXT: shl v1.2s, v1.2s, #16
+; CHECK-SD-NEXT: sshr v0.2s, v0.2s, #16
+; CHECK-SD-NEXT: sshr v1.2s, v1.2s, #16
+; CHECK-SD-NEXT: sqdmulh v0.2s, v1.2s, v0.2s
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: saturating_2xi16:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: shl v0.2s, v0.2s, #16
+; CHECK-GI-NEXT: shl v1.2s, v1.2s, #16
+; CHECK-GI-NEXT: sshr v0.2s, v0.2s, #16
+; CHECK-GI-NEXT: sshr v1.2s, v1.2s, #16
+; CHECK-GI-NEXT: mul v0.2s, v1.2s, v0.2s
+; CHECK-GI-NEXT: movi v1.2s, #127, msl #8
+; CHECK-GI-NEXT: sshr v0.2s, v0.2s, #15
+; CHECK-GI-NEXT: smin v0.2s, v0.2s, v1.2s
+; CHECK-GI-NEXT: ret
%as = sext <2 x i16> %a to <2 x i32>
%bs = sext <2 x i16> %b to <2 x i32>
%m = mul <2 x i32> %bs, %as
@@ -21,10 +35,19 @@ define <2 x i16> @saturating_2xi16(<2 x i16> %a, <2 x i16> %b) {
}
define <4 x i16> @saturating_4xi16(<4 x i16> %a, <4 x i16> %b) {
-; CHECK-LABEL: saturating_4xi16:
-; CHECK: // %bb.0:
-; CHECK-NEXT: sqdmulh v0.4h, v1.4h, v0.4h
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: saturating_4xi16:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: sqdmulh v0.4h, v1.4h, v0.4h
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: saturating_4xi16:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: smull v0.4s, v1.4h, v0.4h
+; CHECK-GI-NEXT: movi v1.4s, #127, msl #8
+; CHECK-GI-NEXT: sshr v0.4s, v0.4s, #15
+; CHECK-GI-NEXT: smin v0.4s, v0.4s, v1.4s
+; CHECK-GI-NEXT: xtn v0.4h, v0.4s
+; CHECK-GI-NEXT: ret
%as = sext <4 x i16> %a to <4 x i32>
%bs = sext <4 x i16> %b to <4 x i32>
%m = mul <4 x i32> %bs, %as
@@ -35,10 +58,22 @@ define <4 x i16> @saturating_4xi16(<4 x i16> %a, <4 x i16> %b) {
}
define <8 x i16> @saturating_8xi16(<8 x i16> %a, <8 x i16> %b) {
-; CHECK-LABEL: saturating_8xi16:
-; CHECK: // %bb.0:
-; CHECK-NEXT: sqdmulh v0.8h, v1.8h, v0.8h
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: saturating_8xi16:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: sqdmulh v0.8h, v1.8h, v0.8h
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: saturating_8xi16:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: smull v3.4s, v1.4h, v0.4h
+; CHECK-GI-NEXT: smull2 v0.4s, v1.8h, v0.8h
+; CHECK-GI-NEXT: movi v2.4s, #127, msl #8
+; CHECK-GI-NEXT: sshr v1.4s, v3.4s, #15
+; CHECK-GI-NEXT: sshr v0.4s, v0.4s, #15
+; CHECK-GI-NEXT: smin v1.4s, v1.4s, v2.4s
+; CHECK-GI-NEXT: smin v0.4s, v0.4s, v2.4s
+; CHECK-GI-NEXT: uzp1 v0.8h, v1.8h, v0.8h
+; CHECK-GI-NEXT: ret
%as = sext <8 x i16> %a to <8 x i32>
%bs = sext <8 x i16> %b to <8 x i32>
%m = mul <8 x i32> %bs, %as
@@ -49,10 +84,21 @@ define <8 x i16> @saturating_8xi16(<8 x i16> %a, <8 x i16> %b) {
}
define <2 x i32> @saturating_2xi32(<2 x i32> %a, <2 x i32> %b) {
-; CHECK-LABEL: saturating_2xi32:
-; CHECK: // %bb.0:
-; CHECK-NEXT: sqdmulh v0.2s, v1.2s, v0.2s
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: saturating_2xi32:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: sqdmulh v0.2s, v1.2s, v0.2s
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: saturating_2xi32:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: smull v0.2d, v1.2s, v0.2s
+; CHECK-GI-NEXT: adrp x8, .LCPI3_0
+; CHECK-GI-NEXT: ldr q1, [x8, :lo12:.LCPI3_0]
+; CHECK-GI-NEXT: sshr v0.2d, v0.2d, #31
+; CHECK-GI-NEXT: cmgt v2.2d, v1.2d, v0.2d
+; CHECK-GI-NEXT: bif v0.16b, v1.16b, v2.16b
+; CHECK-GI-NEXT: xtn v0.2s, v0.2d
+; CHECK-GI-NEXT: ret
%as = sext <2 x i32> %a to <2 x i64>
%bs = sext <2 x i32> %b to <2 x i64>
%m = mul <2 x i64> %bs, %as
@@ -63,10 +109,25 @@ define <2 x i32> @saturating_2xi32(<2 x i32> %a, <2 x i32> %b) {
}
define <4 x i32> @saturating_4xi32(<4 x i32> %a, <4 x i32> %b) {
-; CHECK-LABEL: saturating_4xi32:
-; CHECK: // %bb.0:
-; CHECK-NEXT: sqdmulh v0.4s, v1.4s, v0.4s
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: saturating_4xi32:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: sqdmulh v0.4s, v1.4s, v0.4s
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: saturating_4xi32:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: smull v2.2d, v1.2s, v0.2s
+; CHECK-GI-NEXT: smull2 v0.2d, v1.4s, v0.4s
+; CHECK-GI-NEXT: adrp x8, .LCPI4_0
+; CHECK-GI-NEXT: sshr v1.2d, v2.2d, #31
+; CHECK-GI-NEXT: sshr v0.2d, v0.2d, #31
+; CHECK-GI-NEXT: ldr q2, [x8, :lo12:.LCPI4_0]
+; CHECK-GI-NEXT: cmgt v3.2d, v2.2d, v1.2d
+; CHECK-GI-NEXT: cmgt v4.2d, v2.2d, v0.2d
+; CHECK-GI-NEXT: bif v1.16b, v2.16b, v3.16b
+; CHECK-GI-NEXT: bif v0.16b, v2.16b, v4.16b
+; CHECK-GI-NEXT: uzp1 v0.4s, v1.4s, v0.4s
+; CHECK-GI-NEXT: ret
%as = sext <4 x i32> %a to <4 x i64>
%bs = sext <4 x i32> %b to <4 x i64>
%m = mul <4 x i64> %bs, %as
@@ -77,11 +138,35 @@ define <4 x i32> @saturating_4xi32(<4 x i32> %a, <4 x i32> %b) {
}
define <8 x i32> @saturating_8xi32(<8 x i32> %a, <8 x i32> %b) {
-; CHECK-LABEL: saturating_8xi32:
-; CHECK: // %bb.0:
-; CHECK-NEXT: sqdmulh v1.4s, v3.4s, v1.4s
-; CHECK-NEXT: sqdmulh v0.4s, v2.4s, v0.4s
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: saturating_8xi32:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: sqdmulh v1.4s, v3.4s, v1.4s
+; CHECK-SD-NEXT: sqdmulh v0.4s, v2.4s, v0.4s
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: saturating_8xi32:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: smull v4.2d, v2.2s, v0.2s
+; CHECK-GI-NEXT: smull2 v0.2d, v2.4s, v0.4s
+; CHECK-GI-NEXT: adrp x8, .LCPI5_0
+; CHECK-GI-NEXT: smull v2.2d, v3.2s, v1.2s
+; CHECK-GI-NEXT: smull2 v1.2d, v3.4s, v1.4s
+; CHECK-GI-NEXT: ldr q3, [x8, :lo12:.LCPI5_0]
+; CHECK-GI-NEXT: sshr v4.2d, v4.2d, #31
+; CHECK-GI-NEXT: sshr v0.2d, v0.2d, #31
+; CHECK-GI-NEXT: sshr v2.2d, v2.2d, #31
+; CHECK-GI-NEXT: sshr v1.2d, v1.2d, #31
+; CHECK-GI-NEXT: cmgt v5.2d, v3.2d, v4.2d
+; CHECK-GI-NEXT: cmgt v6.2d, v3.2d, v0.2d
+; CHECK-GI-NEXT: cmgt v7.2d, v3.2d, v2.2d
+; CHECK-GI-NEXT: cmgt v16.2d, v3.2d, v1.2d
+; CHECK-GI-NEXT: bif v4.16b, v3.16b, v5.16b
+; CHECK-GI-NEXT: bif v0.16b, v3.16b, v6.16b
+; CHECK-GI-NEXT: bif v2.16b, v3.16b, v7.16b
+; CHECK-GI-NEXT: bif v1.16b, v3.16b, v16.16b
+; CHECK-GI-NEXT: uzp1 v0.4s, v4.4s, v0.4s
+; CHECK-GI-NEXT: uzp1 v1.4s, v2.4s, v1.4s
+; CHECK-GI-NEXT: ret
%as = sext <8 x i32> %a to <8 x i64>
%bs = sext <8 x i32> %b to <8 x i64>
%m = mul <8 x i64> %bs, %as
@@ -92,11 +177,21 @@ define <8 x i32> @saturating_8xi32(<8 x i32> %a, <8 x i32> %b) {
}
define <2 x i64> @saturating_2xi32_2xi64(<2 x i32> %a, <2 x i32> %b) {
-; CHECK-LABEL: saturating_2xi32_2xi64:
-; CHECK: // %bb.0:
-; CHECK-NEXT: sqdmulh v0.2s, v1.2s, v0.2s
-; CHECK-NEXT: sshll v0.2d, v0.2s, #0
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: saturating_2xi32_2xi64:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: sqdmulh v0.2s, v1.2s, v0.2s
+; CHECK-SD-NEXT: sshll v0.2d, v0.2s, #0
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: saturating_2xi32_2xi64:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: smull v0.2d, v1.2s, v0.2s
+; CHECK-GI-NEXT: adrp x8, .LCPI6_0
+; CHECK-GI-NEXT: ldr q1, [x8, :lo12:.LCPI6_0]
+; CHECK-GI-NEXT: sshr v0.2d, v0.2d, #31
+; CHECK-GI-NEXT: cmgt v2.2d, v1.2d, v0.2d
+; CHECK-GI-NEXT: bif v0.16b, v1.16b, v2.16b
+; CHECK-GI-NEXT: ret
%as = sext <2 x i32> %a to <2 x i64>
%bs = sext <2 x i32> %b to <2 x i64>
%m = mul <2 x i64> %bs, %as
@@ -106,15 +201,56 @@ define <2 x i64> @saturating_2xi32_2xi64(<2 x i32> %a, <2 x i32> %b) {
}
define <6 x i16> @saturating_6xi16(<6 x i16> %a, <6 x i16> %b) {
-; CHECK-LABEL: saturating_6xi16:
-; CHECK: // %bb.0:
-; CHECK-NEXT: smull2 v2.4s, v1.8h, v0.8h
-; CHECK-NEXT: movi v3.4s, #127, msl #8
-; CHECK-NEXT: sqdmulh v0.4h, v1.4h, v0.4h
-; CHECK-NEXT: sshr v2.4s, v2.4s, #15
-; CHECK-NEXT: smin v1.4s, v2.4s, v3.4s
-; CHECK-NEXT: xtn2 v0.8h, v1.4s
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: saturating_6xi16:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: smull2 v2.4s, v1.8h, v0.8h
+; CHECK-SD-NEXT: movi v3.4s, #127, msl #8
+; CHECK-SD-NEXT: sqdmulh v0.4h, v1.4h, v0.4h
+; CHECK-SD-NEXT: sshr v2.4s, v2.4s, #15
+; CHECK-SD-NEXT: smin v1.4s, v2.4s, v3.4s
+; CHECK-SD-NEXT: xtn2 v0.8h, v1.4s
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: saturating_6xi16:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: smov w8, v1.h[0]
+; CHECK-GI-NEXT: smov w9, v0.h[0]
+; CHECK-GI-NEXT: smov w10, v1.h[1]
+; CHECK-GI-NEXT: smov w11, v0.h[1]
+; CHECK-GI-NEXT: smov w12, v1.h[2]
+; CHECK-GI-NEXT: movi v2.4s, #127, msl #8
+; CHECK-GI-NEXT: fmov s3, w8
+; CHECK-GI-NEXT: fmov s4, w9
+; CHECK-GI-NEXT: smov w8, v0.h[2]
+; CHECK-GI-NEXT: smov w9, v1.h[3]
+; CHECK-GI-NEXT: sshll2 v1.4s, v1.8h, #0
+; CHECK-GI-NEXT: mov v3.s[1], w10
+; CHECK-GI-NEXT: mov v4.s[1], w11
+; CHECK-GI-NEXT: smov w10, v0.h[3]
+; CHECK-GI-NEXT: sshll2 v0.4s, v0.8h, #0
+; CHECK-GI-NEXT: mov v3.s[2], w12
+; CHECK-GI-NEXT: mov v4.s[2], w8
+; CHECK-GI-NEXT: mul v0.2s, v1.2s, v0.2s
+; CHECK-GI-NEXT: movi v1.2s, #127, msl #8
+; CHECK-GI-NEXT: mov v3.s[3], w9
+; CHECK-GI-NEXT: mov v4.s[3], w10
+; CHECK-GI-NEXT: sshr v0.2s, v0.2s, #15
+; CHECK-GI-NEXT: smin v0.2s, v0.2s, v1.2s
+; CHECK-GI-NEXT: mul v3.4s, v3.4s, v4.4s
+; CHECK-GI-NEXT: sshr v3.4s, v3.4s, #15
+; CHECK-GI-NEXT: smin v2.4s, v3.4s, v2.4s
+; CHECK-GI-NEXT: mov w8, v2.s[1]
+; CHECK-GI-NEXT: mov w9, v2.s[2]
+; CHECK-GI-NEXT: mov w10, v2.s[3]
+; CHECK-GI-NEXT: mov v2.h[1], w8
+; CHECK-GI-NEXT: fmov w8, s0
+; CHECK-GI-NEXT: mov v2.h[2], w9
+; CHECK-GI-NEXT: mov w9, v0.s[1]
+; CHECK-GI-NEXT: mov v2.h[3], w10
+; CHECK-GI-NEXT: mov v2.h[4], w8
+; CHECK-GI-NEXT: mov v2.h[5], w9
+; CHECK-GI-NEXT: mov v0.16b, v2.16b
+; CHECK-GI-NEXT: ret
%as = sext <6 x i16> %a to <6 x i32>
%bs = sext <6 x i16> %b to <6 x i32>
%m = mul <6 x i32> %bs, %as
@@ -199,20 +335,34 @@ define <2 x i11> @illegal_source(<2 x i11> %a, <2 x i11> %b) {
ret <2 x i11> %t
}
define <1 x i16> @saturating_1xi16(<1 x i16> %a, <1 x i16> %b) {
-; CHECK-LABEL: saturating_1xi16:
-; CHECK: // %bb.0:
-; CHECK-NEXT: zip1 v0.4h, v0.4h, v0.4h
-; CHECK-NEXT: zip1 v1.4h, v1.4h, v0.4h
-; CHECK-NEXT: shl v0.2s, v0.2s, #16
-; CHECK-NEXT: sshr v0.2s, v0.2s, #16
-; CHECK-NEXT: shl v1.2s, v1.2s, #16
-; CHECK-NEXT: sshr v1.2s, v1.2s, #16
-; CHECK-NEXT: mul v0.2s, v1.2s, v0.2s
-; CHECK-NEXT: movi v1.2s, #127, msl #8
-; CHECK-NEXT: sshr v0.2s, v0.2s, #15
-; CHECK-NEXT: smin v0.2s, v0.2s, v1.2s
-; CHECK-NEXT: xtn v0.4h, v0.4s
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: saturating_1xi16:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: zip1 v0.4h, v0.4h, v0.4h
+; CHECK-SD-NEXT: zip1 v1.4h, v1.4h, v0.4h
+; CHECK-SD-NEXT: shl v0.2s, v0.2s, #16
+; CHECK-SD-NEXT: sshr v0.2s, v0.2s, #16
+; CHECK-SD-NEXT: shl v1.2s, v1.2s, #16
+; CHECK-SD-NEXT: sshr v1.2s, v1.2s, #16
+; CHECK-SD-NEXT: mul v0.2s, v1.2s, v0.2s
+; CHECK-SD-NEXT: movi v1.2s, #127, msl #8
+; CHECK-SD-NEXT: sshr v0.2s, v0.2s, #15
+; CHECK-SD-NEXT: smin v0.2s, v0.2s, v1.2s
+; CHECK-SD-NEXT: xtn v0.4h, v0.4s
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: saturating_1xi16:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: // kill: def $d0 killed $d0 def $q0
+; CHECK-GI-NEXT: // kill: def $d1 killed $d1 def $q1
+; CHECK-GI-NEXT: smov w8, v0.h[0]
+; CHECK-GI-NEXT: smov w9, v1.h[0]
+; CHECK-GI-NEXT: mul w8, w9, w8
+; CHECK-GI-NEXT: mov w9, #32767 // =0x7fff
+; CHECK-GI-NEXT: asr w8, w8, #15
+; CHECK-GI-NEXT: cmp w8, w9
+; CHECK-GI-NEXT: csel w8, w8, w9, lt
+; CHECK-GI-NEXT: fmov s0, w8
+; CHECK-GI-NEXT: ret
%as = sext <1 x i16> %a to <1 x i32>
%bs = sext <1 x i16> %b to <1 x i32>
%m = mul <1 x i32> %bs, %as
More information about the llvm-commits
mailing list