[llvm] [AArch64] Add sqneg tablegen patterns (PR #196265)

via llvm-commits llvm-commits at lists.llvm.org
Thu May 7 02:22:41 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-aarch64

Author: David Green (davemgreen)

<details>
<summary>Changes</summary>

This adds some tablegen patterns for sqneg instructions, largely copied from the equivalent MVE patterns. They perform a saturating negation, effectively just protecting against INT_MIN, which is equivalent to a `ssub_sat 0, R`.

---
Full diff: https://github.com/llvm/llvm-project/pull/196265.diff


3 Files Affected:

- (modified) llvm/lib/Target/AArch64/AArch64InstrInfo.td (+18) 
- (modified) llvm/test/CodeGen/AArch64/vqabs.ll (+8-16) 
- (modified) llvm/test/CodeGen/AArch64/vqneg.ll (+8-16) 


``````````diff
diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
index fb54757ea775c..0e23b55821095 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
@@ -6676,6 +6676,24 @@ defm UQXTN  : SIMDTwoScalarMixedBHS<1, 0b10100, "uqxtn", int_aarch64_neon_scalar
 defm USQADD : SIMDTwoScalarBHSDTied< 1, 0b00011, "usqadd", AArch64usqadd,
                                     int_aarch64_neon_usqadd>;
 
+// ssub_sat(0, R) -> sqneg(R)
+def : Pat<(v16i8 (ssubsat immAllZerosV, V128:$reg)),
+          (v16i8 (SQNEGv16i8 V128:$reg))>;
+def : Pat<(v8i16 (ssubsat immAllZerosV, V128:$reg)),
+          (v8i16 (SQNEGv8i16 V128:$reg))>;
+def : Pat<(v4i32 (ssubsat immAllZerosV, V128:$reg)),
+          (v4i32 (SQNEGv4i32 V128:$reg))>;
+def : Pat<(v2i64 (ssubsat immAllZerosV, V128:$reg)),
+          (v2i64 (SQNEGv2i64 V128:$reg))>;
+def : Pat<(v8i8 (ssubsat immAllZerosV, V64:$reg)),
+          (v8i8 (SQNEGv8i8 V64:$reg))>;
+def : Pat<(v4i16 (ssubsat immAllZerosV, V64:$reg)),
+          (v4i16 (SQNEGv4i16 V64:$reg))>;
+def : Pat<(v2i32 (ssubsat immAllZerosV, V64:$reg)),
+          (v2i32 (SQNEGv2i32 V64:$reg))>;
+def : Pat<(v1i64 (ssubsat immAllZerosV, V64:$reg)),
+          (v1i64 (SQNEGv1i64 V64:$reg))>;
+
 // Floating-point conversion patterns.
 multiclass IntegerToFPSIMDScalarPatterns<SDPatternOperator OpN, string INST> {
   let Predicates = [HasFPRCVT] in {
diff --git a/llvm/test/CodeGen/AArch64/vqabs.ll b/llvm/test/CodeGen/AArch64/vqabs.ll
index a05bed23b14e2..7faba50d51e86 100644
--- a/llvm/test/CodeGen/AArch64/vqabs.ll
+++ b/llvm/test/CodeGen/AArch64/vqabs.ll
@@ -89,9 +89,8 @@ entry:
 define <16 x i8> @vqabs_sat_v16i8(<16 x i8> %A) {
 ; CHECK-LABEL: vqabs_sat_v16i8:
 ; CHECK:       // %bb.0: // %entry
-; CHECK-NEXT:    movi v1.2d, #0000000000000000
+; CHECK-NEXT:    sqneg v1.16b, v0.16b
 ; CHECK-NEXT:    cmgt v2.16b, v0.16b, #0
-; CHECK-NEXT:    sqsub v1.16b, v1.16b, v0.16b
 ; CHECK-NEXT:    bif v0.16b, v1.16b, v2.16b
 ; CHECK-NEXT:    ret
 entry:
@@ -104,9 +103,8 @@ entry:
 define <8 x i16> @vqabs_sat_v8i16(<8 x i16> %A) {
 ; CHECK-LABEL: vqabs_sat_v8i16:
 ; CHECK:       // %bb.0: // %entry
-; CHECK-NEXT:    movi v1.2d, #0000000000000000
+; CHECK-NEXT:    sqneg v1.8h, v0.8h
 ; CHECK-NEXT:    cmgt v2.8h, v0.8h, #0
-; CHECK-NEXT:    sqsub v1.8h, v1.8h, v0.8h
 ; CHECK-NEXT:    bif v0.16b, v1.16b, v2.16b
 ; CHECK-NEXT:    ret
 entry:
@@ -119,9 +117,8 @@ entry:
 define <4 x i32> @vqabs_sat_v4i32(<4 x i32> %A) {
 ; CHECK-LABEL: vqabs_sat_v4i32:
 ; CHECK:       // %bb.0: // %entry
-; CHECK-NEXT:    movi v1.2d, #0000000000000000
+; CHECK-NEXT:    sqneg v1.4s, v0.4s
 ; CHECK-NEXT:    cmgt v2.4s, v0.4s, #0
-; CHECK-NEXT:    sqsub v1.4s, v1.4s, v0.4s
 ; CHECK-NEXT:    bif v0.16b, v1.16b, v2.16b
 ; CHECK-NEXT:    ret
 entry:
@@ -134,9 +131,8 @@ entry:
 define <2 x i64> @vqabs_sat_v2i64(<2 x i64> %A) {
 ; CHECK-LABEL: vqabs_sat_v2i64:
 ; CHECK:       // %bb.0: // %entry
-; CHECK-NEXT:    movi v1.2d, #0000000000000000
+; CHECK-NEXT:    sqneg v1.2d, v0.2d
 ; CHECK-NEXT:    cmgt v2.2d, v0.2d, #0
-; CHECK-NEXT:    sqsub v1.2d, v1.2d, v0.2d
 ; CHECK-NEXT:    bif v0.16b, v1.16b, v2.16b
 ; CHECK-NEXT:    ret
 entry:
@@ -149,9 +145,8 @@ entry:
 define <8 x i8> @vqabs_sat_v8i8(<8 x i8> %A) {
 ; CHECK-LABEL: vqabs_sat_v8i8:
 ; CHECK:       // %bb.0: // %entry
-; CHECK-NEXT:    movi v1.2d, #0000000000000000
+; CHECK-NEXT:    sqneg v1.8b, v0.8b
 ; CHECK-NEXT:    cmgt v2.8b, v0.8b, #0
-; CHECK-NEXT:    sqsub v1.8b, v1.8b, v0.8b
 ; CHECK-NEXT:    bif v0.8b, v1.8b, v2.8b
 ; CHECK-NEXT:    ret
 entry:
@@ -164,9 +159,8 @@ entry:
 define <4 x i16> @vqabs_sat_v4i16(<4 x i16> %A) {
 ; CHECK-LABEL: vqabs_sat_v4i16:
 ; CHECK:       // %bb.0: // %entry
-; CHECK-NEXT:    movi v1.2d, #0000000000000000
+; CHECK-NEXT:    sqneg v1.4h, v0.4h
 ; CHECK-NEXT:    cmgt v2.4h, v0.4h, #0
-; CHECK-NEXT:    sqsub v1.4h, v1.4h, v0.4h
 ; CHECK-NEXT:    bif v0.8b, v1.8b, v2.8b
 ; CHECK-NEXT:    ret
 entry:
@@ -179,9 +173,8 @@ entry:
 define <2 x i32> @vqabs_sat_v2i32(<2 x i32> %A) {
 ; CHECK-LABEL: vqabs_sat_v2i32:
 ; CHECK:       // %bb.0: // %entry
-; CHECK-NEXT:    movi v1.2d, #0000000000000000
+; CHECK-NEXT:    sqneg v1.2s, v0.2s
 ; CHECK-NEXT:    cmgt v2.2s, v0.2s, #0
-; CHECK-NEXT:    sqsub v1.2s, v1.2s, v0.2s
 ; CHECK-NEXT:    bif v0.8b, v1.8b, v2.8b
 ; CHECK-NEXT:    ret
 entry:
@@ -194,9 +187,8 @@ entry:
 define <1 x i64> @vqabs_sat_v1i64(<1 x i64> %A) {
 ; CHECK-SD-LABEL: vqabs_sat_v1i64:
 ; CHECK-SD:       // %bb.0: // %entry
-; CHECK-SD-NEXT:    movi v1.2d, #0000000000000000
+; CHECK-SD-NEXT:    sqneg d1, d0
 ; CHECK-SD-NEXT:    cmgt d2, d0, #0
-; CHECK-SD-NEXT:    sqsub d1, d1, d0
 ; CHECK-SD-NEXT:    bif v0.8b, v1.8b, v2.8b
 ; CHECK-SD-NEXT:    ret
 ;
diff --git a/llvm/test/CodeGen/AArch64/vqneg.ll b/llvm/test/CodeGen/AArch64/vqneg.ll
index 7e91ea5a48289..351c8f4bb0db3 100644
--- a/llvm/test/CodeGen/AArch64/vqneg.ll
+++ b/llvm/test/CodeGen/AArch64/vqneg.ll
@@ -73,8 +73,7 @@ entry:
 define <16 x i8> @vqneg_sat_v16i8(<16 x i8> %A) {
 ; CHECK-LABEL: vqneg_sat_v16i8:
 ; CHECK:       // %bb.0: // %entry
-; CHECK-NEXT:    movi v1.2d, #0000000000000000
-; CHECK-NEXT:    sqsub v0.16b, v1.16b, v0.16b
+; CHECK-NEXT:    sqneg v0.16b, v0.16b
 ; CHECK-NEXT:    ret
 entry:
   %0 = tail call <16 x i8> @llvm.ssub.sat.v16i8(<16 x i8> zeroinitializer, <16 x i8> %A)
@@ -84,8 +83,7 @@ entry:
 define <8 x i16> @vqneg_sat_v8i16(<8 x i16> %A) {
 ; CHECK-LABEL: vqneg_sat_v8i16:
 ; CHECK:       // %bb.0: // %entry
-; CHECK-NEXT:    movi v1.2d, #0000000000000000
-; CHECK-NEXT:    sqsub v0.8h, v1.8h, v0.8h
+; CHECK-NEXT:    sqneg v0.8h, v0.8h
 ; CHECK-NEXT:    ret
 entry:
   %0 = tail call <8 x i16> @llvm.ssub.sat.v8i16(<8 x i16> zeroinitializer, <8 x i16> %A)
@@ -95,8 +93,7 @@ entry:
 define <4 x i32> @vqneg_sat_v4i32(<4 x i32> %A) {
 ; CHECK-LABEL: vqneg_sat_v4i32:
 ; CHECK:       // %bb.0: // %entry
-; CHECK-NEXT:    movi v1.2d, #0000000000000000
-; CHECK-NEXT:    sqsub v0.4s, v1.4s, v0.4s
+; CHECK-NEXT:    sqneg v0.4s, v0.4s
 ; CHECK-NEXT:    ret
 entry:
   %0 = tail call <4 x i32> @llvm.ssub.sat.v4i32(<4 x i32> zeroinitializer, <4 x i32> %A)
@@ -106,8 +103,7 @@ entry:
 define <2 x i64> @vqneg_sat_v2i64(<2 x i64> %A) {
 ; CHECK-LABEL: vqneg_sat_v2i64:
 ; CHECK:       // %bb.0: // %entry
-; CHECK-NEXT:    movi v1.2d, #0000000000000000
-; CHECK-NEXT:    sqsub v0.2d, v1.2d, v0.2d
+; CHECK-NEXT:    sqneg v0.2d, v0.2d
 ; CHECK-NEXT:    ret
 entry:
   %0 = tail call <2 x i64> @llvm.ssub.sat.v2i64(<2 x i64> zeroinitializer, <2 x i64> %A)
@@ -117,8 +113,7 @@ entry:
 define <8 x i8> @vqneg_sat_v8i8(<8 x i8> %A) {
 ; CHECK-LABEL: vqneg_sat_v8i8:
 ; CHECK:       // %bb.0: // %entry
-; CHECK-NEXT:    movi v1.2d, #0000000000000000
-; CHECK-NEXT:    sqsub v0.8b, v1.8b, v0.8b
+; CHECK-NEXT:    sqneg v0.8b, v0.8b
 ; CHECK-NEXT:    ret
 entry:
   %0 = tail call <8 x i8> @llvm.ssub.sat.v8i8(<8 x i8> zeroinitializer, <8 x i8> %A)
@@ -128,8 +123,7 @@ entry:
 define <4 x i16> @vqneg_sat_v4i16(<4 x i16> %A) {
 ; CHECK-LABEL: vqneg_sat_v4i16:
 ; CHECK:       // %bb.0: // %entry
-; CHECK-NEXT:    movi v1.2d, #0000000000000000
-; CHECK-NEXT:    sqsub v0.4h, v1.4h, v0.4h
+; CHECK-NEXT:    sqneg v0.4h, v0.4h
 ; CHECK-NEXT:    ret
 entry:
   %0 = tail call <4 x i16> @llvm.ssub.sat.v4i16(<4 x i16> zeroinitializer, <4 x i16> %A)
@@ -139,8 +133,7 @@ entry:
 define <2 x i32> @vqneg_sat_v2i32(<2 x i32> %A) {
 ; CHECK-LABEL: vqneg_sat_v2i32:
 ; CHECK:       // %bb.0: // %entry
-; CHECK-NEXT:    movi v1.2d, #0000000000000000
-; CHECK-NEXT:    sqsub v0.2s, v1.2s, v0.2s
+; CHECK-NEXT:    sqneg v0.2s, v0.2s
 ; CHECK-NEXT:    ret
 entry:
   %0 = tail call <2 x i32> @llvm.ssub.sat.v2i32(<2 x i32> zeroinitializer, <2 x i32> %A)
@@ -150,8 +143,7 @@ entry:
 define <1 x i64> @vqneg_sat_v1i64(<1 x i64> %A) {
 ; CHECK-SD-LABEL: vqneg_sat_v1i64:
 ; CHECK-SD:       // %bb.0: // %entry
-; CHECK-SD-NEXT:    movi v1.2d, #0000000000000000
-; CHECK-SD-NEXT:    sqsub d0, d1, d0
+; CHECK-SD-NEXT:    sqneg d0, d0
 ; CHECK-SD-NEXT:    ret
 ;
 ; CHECK-GI-LABEL: vqneg_sat_v1i64:

``````````

</details>


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


More information about the llvm-commits mailing list