[llvm-branch-commits] [llvm] release/23.x: [ARM][MVE] Match canonical saturating negation patterns (#213085) (PR #213699)
Douglas Yung via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Tue Aug 4 05:32:54 PDT 2026
https://github.com/dyung updated https://github.com/llvm/llvm-project/pull/213699
>From 8ae884c1285b17f0145f084303dbb937c9a37209 Mon Sep 17 00:00:00 2001
From: Ties Stuij <ties.stuij at arm.com>
Date: Mon, 3 Aug 2026 09:35:07 +0100
Subject: [PATCH] [ARM][MVE] Match canonical saturating negation patterns
(#213085)
InstCombine pull request
https://github.com/llvm/llvm-project/pull/194519 canonicalized the
saturating negation idiom to
an llvm.ssub.sat operation. For the ARM backend we only recognized the
original
select and subtract pattern, causing vector absolute values to expand to
VQSUB
plus a compare and select instead of VQABS.
In this patch we teach the VQABS and VQNEG patterns to recognize this
ssub.sat
form.
(cherry picked from commit c99e6752b9f9e1867af88c07ee44f837bc6e4311)
---
llvm/lib/Target/ARM/ARMInstrMVE.td | 9 +++++++++
llvm/test/CodeGen/Thumb2/vqabs.ll | 15 +++------------
llvm/test/CodeGen/Thumb2/vqneg.ll | 9 +++------
3 files changed, 15 insertions(+), 18 deletions(-)
diff --git a/llvm/lib/Target/ARM/ARMInstrMVE.td b/llvm/lib/Target/ARM/ARMInstrMVE.td
index 38f36cb239535..6a94a5615e1c7 100644
--- a/llvm/lib/Target/ARM/ARMInstrMVE.td
+++ b/llvm/lib/Target/ARM/ARMInstrMVE.td
@@ -2568,6 +2568,13 @@ multiclass vqabsneg_pattern<MVEVectorVTInfo VTI, dag int_min, dag int_max,
int_max,
(sub (VTI.Vec zero_vec), (VTI.Vec MQPR:$reg)))))),
(VTI.Vec (vqabs_instruction (VTI.Vec MQPR:$reg)))>;
+ // InstCombine canonicalizes the saturating negate in the expression above
+ // to ssub.sat(0, r).
+ def : Pat<(VTI.Vec (vselect
+ (VTI.Pred (ARMvcmpz (VTI.Vec MQPR:$reg), ARMCCgt)),
+ (VTI.Vec MQPR:$reg),
+ (VTI.Vec (ssubsat (VTI.Vec zero_vec), (VTI.Vec MQPR:$reg))))),
+ (VTI.Vec (vqabs_instruction (VTI.Vec MQPR:$reg)))>;
// Similarly, this tree represents vqneg, i.e. the following vectorized expression:
// r == INT_MIN ? INT_MAX : -r
def : Pat<(VTI.Vec (vselect
@@ -2575,6 +2582,8 @@ multiclass vqabsneg_pattern<MVEVectorVTInfo VTI, dag int_min, dag int_max,
int_max,
(sub (VTI.Vec zero_vec), (VTI.Vec MQPR:$reg)))),
(VTI.Vec (vqneg_instruction (VTI.Vec MQPR:$reg)))>;
+ def : Pat<(VTI.Vec (ssubsat (VTI.Vec zero_vec), (VTI.Vec MQPR:$reg))),
+ (VTI.Vec (vqneg_instruction (VTI.Vec MQPR:$reg)))>;
}
}
diff --git a/llvm/test/CodeGen/Thumb2/vqabs.ll b/llvm/test/CodeGen/Thumb2/vqabs.ll
index f8f4b65a1f7dc..832d85b1095c4 100644
--- a/llvm/test/CodeGen/Thumb2/vqabs.ll
+++ b/llvm/test/CodeGen/Thumb2/vqabs.ll
@@ -52,10 +52,7 @@ entry:
define arm_aapcs_vfpcc <16 x i8> @vqabs_sat_test16(<16 x i8> %A) {
; CHECK-LABEL: vqabs_sat_test16:
; CHECK: @ %bb.0: @ %entry
-; CHECK-NEXT: vmov.i32 q1, #0x0
-; CHECK-NEXT: vcmp.s8 gt, q0, zr
-; CHECK-NEXT: vqsub.s8 q1, q1, q0
-; CHECK-NEXT: vpsel q0, q0, q1
+; CHECK-NEXT: vqabs.s8 q0, q0
; CHECK-NEXT: bx lr
entry:
%0 = icmp sgt <16 x i8> %A, zeroinitializer
@@ -67,10 +64,7 @@ entry:
define arm_aapcs_vfpcc <8 x i16> @vqabs_sat_test8(<8 x i16> %A) {
; CHECK-LABEL: vqabs_sat_test8:
; CHECK: @ %bb.0: @ %entry
-; CHECK-NEXT: vmov.i32 q1, #0x0
-; CHECK-NEXT: vcmp.s16 gt, q0, zr
-; CHECK-NEXT: vqsub.s16 q1, q1, q0
-; CHECK-NEXT: vpsel q0, q0, q1
+; CHECK-NEXT: vqabs.s16 q0, q0
; CHECK-NEXT: bx lr
entry:
%0 = icmp sgt <8 x i16> %A, zeroinitializer
@@ -82,10 +76,7 @@ entry:
define arm_aapcs_vfpcc <4 x i32> @vqabs_sat_test4(<4 x i32> %A) {
; CHECK-LABEL: vqabs_sat_test4:
; CHECK: @ %bb.0: @ %entry
-; CHECK-NEXT: vmov.i32 q1, #0x0
-; CHECK-NEXT: vcmp.s32 gt, q0, zr
-; CHECK-NEXT: vqsub.s32 q1, q1, q0
-; CHECK-NEXT: vpsel q0, q0, q1
+; CHECK-NEXT: vqabs.s32 q0, q0
; CHECK-NEXT: bx lr
entry:
%0 = icmp sgt <4 x i32> %A, zeroinitializer
diff --git a/llvm/test/CodeGen/Thumb2/vqneg.ll b/llvm/test/CodeGen/Thumb2/vqneg.ll
index 4f357d81a5fc5..3a7c227bf4d22 100644
--- a/llvm/test/CodeGen/Thumb2/vqneg.ll
+++ b/llvm/test/CodeGen/Thumb2/vqneg.ll
@@ -46,8 +46,7 @@ entry:
define arm_aapcs_vfpcc <16 x i8> @vqneg_sat_test16(<16 x i8> %A) {
; CHECK-LABEL: vqneg_sat_test16:
; CHECK: @ %bb.0: @ %entry
-; CHECK-NEXT: vmov.i32 q1, #0x0
-; CHECK-NEXT: vqsub.s8 q0, q1, q0
+; CHECK-NEXT: vqneg.s8 q0, q0
; CHECK-NEXT: bx lr
entry:
%0 = tail call <16 x i8> @llvm.ssub.sat.v16i8(<16 x i8> zeroinitializer, <16 x i8> %A)
@@ -57,8 +56,7 @@ entry:
define arm_aapcs_vfpcc <8 x i16> @vqneg_sat_test8(<8 x i16> %A) {
; CHECK-LABEL: vqneg_sat_test8:
; CHECK: @ %bb.0: @ %entry
-; CHECK-NEXT: vmov.i32 q1, #0x0
-; CHECK-NEXT: vqsub.s16 q0, q1, q0
+; CHECK-NEXT: vqneg.s16 q0, q0
; CHECK-NEXT: bx lr
entry:
%0 = tail call <8 x i16> @llvm.ssub.sat.v8i16(<8 x i16> zeroinitializer, <8 x i16> %A)
@@ -68,8 +66,7 @@ entry:
define arm_aapcs_vfpcc <4 x i32> @vqneg_sat_test4(<4 x i32> %A) {
; CHECK-LABEL: vqneg_sat_test4:
; CHECK: @ %bb.0: @ %entry
-; CHECK-NEXT: vmov.i32 q1, #0x0
-; CHECK-NEXT: vqsub.s32 q0, q1, q0
+; CHECK-NEXT: vqneg.s32 q0, q0
; CHECK-NEXT: bx lr
entry:
%0 = tail call <4 x i32> @llvm.ssub.sat.v4i32(<4 x i32> zeroinitializer, <4 x i32> %A)
More information about the llvm-branch-commits
mailing list