[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