From: Netanel Komm Date: Mon, 27 Apr 2026 22:59:37 +0000 (+0300) Subject: match.pd: x != CST1 ? x + CST2 : CST3 -> x + CST2 [PR112659, PR122996] X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5e26bbfbdfa875ef464896bb8768669dd5a9ceb9;p=thirdparty%2Fgcc.git match.pd: x != CST1 ? x + CST2 : CST3 -> x + CST2 [PR112659, PR122996] 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). --- diff --git a/gcc/match.pd b/gcc/match.pd index 7e6d5bd3af3..65a2292ecae 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -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 index 00000000000..ce5ee51be52 --- /dev/null +++ b/gcc/testsuite/g++.dg/tree-ssa/cond-add-vec-1.C @@ -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 index 00000000000..06c218f7751 --- /dev/null +++ b/gcc/testsuite/g++.dg/tree-ssa/cond-add-vec-2.C @@ -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 index 00000000000..e4e4fc8db3e --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/cond-add-1.c @@ -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 index 00000000000..c855ec36556 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/cond-add-2.c @@ -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" } } */