]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
match.pd: x != CST1 ? x + CST2 : CST3 -> x + CST2 [PR112659, PR122996]
authorNetanel Komm <netanelkomm@gmail.com>
Mon, 27 Apr 2026 22:59:37 +0000 (01:59 +0300)
committerAndrew Pinski <andrew.pinski@oss.qualcomm.com>
Tue, 28 Apr 2026 07:59:39 +0000 (00:59 -0700)
This patch extends the conditional addition simplification introduced
in PR 122996 to handle a third constant and uniform vectors. This also
resolves the missing vector addition fold noted in PR 112659.

It simplifies x != CST1 ? x + CST2 : CST3 into x + CST2 when
CST1 + CST2 == CST3.

Bootstrapped and regression tested on x86_64-pc-linux-gnu.

PR tree-optimization/112659
PR tree-optimization/122996

gcc/ChangeLog:

* match.pd: Extend conditional addition pattern to handle
a third constant and uniform vectors.

gcc/testsuite/ChangeLog:

* g++.dg/tree-ssa/cond-add-vec-1.C: New test (positive cases).
* g++.dg/tree-ssa/cond-add-vec-2.C: New test (negative cases).
* gcc.dg/tree-ssa/cond-add-1.c: New test (positive cases).
* gcc.dg/tree-ssa/cond-add-2.c: New test (negative cases).

gcc/match.pd
gcc/testsuite/g++.dg/tree-ssa/cond-add-vec-1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/tree-ssa/cond-add-vec-2.C [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/cond-add-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/cond-add-2.c [new file with mode: 0644]

index 7e6d5bd3af39053255234e93edfe1a8034321e7b..65a2292ecae3944468a8371b4ace5116912857f4 100644 (file)
@@ -5268,11 +5268,20 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
        && expr_no_side_effects_p (@1))
    @2)))
 
-/* x != CST1 ? x + CST2 : 0 -> x + CST2 when CST1 == -CST2.  */
-(simplify
- (cond (ne @0 INTEGER_CST@2) (plus@1 @0 INTEGER_CST@3) integer_zerop)
- (if (wi::to_wide (@2) == -wi::to_wide (@3))
-  @1))
+/* x != CST1 ? x + CST2 : CST3 -> x + CST2 when CST1 + CST2 == CST3.
+   This handles both scalars and uniform vectors.  */
+(for cnd (cond vec_cond)
+ (simplify
+  (cnd (ne @0 uniform_integer_cst_p@1)
+       (plus@2 @0 uniform_integer_cst_p@3)
+       uniform_integer_cst_p@4)
+  (with {
+    tree cst1 = uniform_integer_cst_p (@1);
+    tree cst2 = uniform_integer_cst_p (@3);
+    tree cst3 = uniform_integer_cst_p (@4);
+  }
+  (if (wi::to_wide (cst1) + wi::to_wide (cst2) == wi::to_wide (cst3))
+   @2))))
 
 /* Simplifications of shift and rotates.  */
 
diff --git a/gcc/testsuite/g++.dg/tree-ssa/cond-add-vec-1.C b/gcc/testsuite/g++.dg/tree-ssa/cond-add-vec-1.C
new file mode 100644 (file)
index 0000000..ce5ee51
--- /dev/null
@@ -0,0 +1,36 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wno-psabi -fdump-tree-forwprop1" } */
+
+#define vector4 __attribute__((vector_size(4*sizeof(int))))
+#define vector4_u8 __attribute__((vector_size(4*sizeof(unsigned char))))
+#define vector4_u32 __attribute__((vector_size(4*sizeof(unsigned int))))
+#define vector2_u64 __attribute__((vector_size(2*sizeof(unsigned long))))
+
+void unopt(vector4 int *v) {
+  vector4 int t = *v;
+  vector4 int t1 = t + 8;
+  *v = (t != -8) ? (t1) : (vector4 int){0, 0, 0, 0};
+}
+
+vector2_u64 unsigned long f1 (vector2_u64 unsigned long x) { 
+  return x != (vector2_u64 unsigned long){5, 5}
+        ? x + (vector2_u64 unsigned long){10, 10}
+        : (vector2_u64 unsigned long){15, 15}; 
+}
+
+vector4_u32 unsigned int f2 (vector4_u32 unsigned int x)
+{ 
+  return x != (vector4_u32 unsigned int){20, 20, 20, 20}
+        ? x - (vector4_u32 unsigned int){5, 5, 5, 5}
+        : (vector4_u32 unsigned int){15, 15, 15, 15}; 
+}
+
+vector4_u8 unsigned char
+f3 (vector4_u8 unsigned char x)
+{
+  return x != (vector4_u8 unsigned char){100, 100, 100, 100}
+        ? x + (vector4_u8 unsigned char){166, 166, 166, 166}
+        : (vector4_u8 unsigned char){10, 10, 10, 10};
+}
+
+/* { dg-final { scan-tree-dump-not "VEC_COND_EXPR" "forwprop1" } } */
diff --git a/gcc/testsuite/g++.dg/tree-ssa/cond-add-vec-2.C b/gcc/testsuite/g++.dg/tree-ssa/cond-add-vec-2.C
new file mode 100644 (file)
index 0000000..06c218f
--- /dev/null
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wno-psabi -fdump-tree-forwprop1" } */
+
+#define vector4 __attribute__((vector_size(4*sizeof(int))))
+#define vector2_u64 __attribute__((vector_size(2*sizeof(unsigned long))))
+
+vector4 int g1 (vector4 int x) {
+  vector4 int cst1 = {5, 1};
+  vector4 int cst2 = {10, 2};
+  vector4 int cst3 = {15, 3};
+  return x != cst1 ? x + cst2 : cst3;
+}
+
+vector2_u64 unsigned long g2 (vector2_u64 unsigned long x) { 
+  return x != (vector2_u64 unsigned long){10, 10}
+        ? x + (vector2_u64 unsigned long){20, 20}
+        : (vector2_u64 unsigned long){40, 40}; 
+}
+
+/* { dg-final { scan-tree-dump-times "VEC_COND_EXPR" 2 "forwprop1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/cond-add-1.c b/gcc/testsuite/gcc.dg/tree-ssa/cond-add-1.c
new file mode 100644 (file)
index 0000000..e4e4fc8
--- /dev/null
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+typedef unsigned char u8;
+typedef unsigned short u16;
+typedef unsigned int u32;
+typedef unsigned long u64;
+
+u64 f1 (u64 x) { return x != 5 ? x + 10 : 15; }
+
+u32 f2 (u32 x) { return x != 20 ? x - 5 : 15; }
+
+u16 f3 (u16 x) { return x == 100 ? 150 : x + 50; }
+
+u8  f4 (u8 x)  { return x != 250 ? x + 2 : 252; }
+
+u8  f5 (u8 x) {
+  if (x == 100)
+    return 10;
+  else
+    return x + 166;
+}
+
+/* { dg-final { scan-tree-dump-not "if " "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/cond-add-2.c b/gcc/testsuite/gcc.dg/tree-ssa/cond-add-2.c
new file mode 100644 (file)
index 0000000..c855ec3
--- /dev/null
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+typedef unsigned int u32;
+typedef unsigned long u64;
+
+u64 g1 (u64 x) { return x != 10 ? x + 20 : 40; }
+
+u32 g2 (u32 x) { return x == 100 ? 10 : x + 166; }
+
+/* { dg-final { scan-tree-dump-times "if " 2 "optimized" } } */