This is a summary of discussions relative to the merge request created by 
Torbjörn Svensson (azoff) <[email protected]> titled
tree-optimization: Fold constant conditional selects [PR124663]
since its creation.

Description: Tested on top of r17-2366-gcfc5aa4ed975c4.
Reg-tested on arm-none-eabi for 14 different targets without any regression.
Reg-tested on x86_64-linux-gnu with some "regressions". What I mean with 
"regressions" is that there are new fails, but they are all related to `tsan` 
and that these tests are unstable/unpredictable. If I run the reference version 
a few times, I get different results.

Ok for trunk, releases/gcc-16 and releases/gcc-15?

--
Fold `(x == CST) ? x : CST` and `(x != CST) ? CST : x` to `CST` for
integral scalar and vector types. This catches cases where earlier
folding has converted bitwise mask expressions into conditional selects,
including ARM MVE predicate-to-vector mask forms.

        PR tree-optimization/124663

gcc/ChangeLog:

        * match.pd: Fold constant conditional selects.

gcc/testsuite/ChangeLog:

        * g++.dg/tree-ssa/pr124663.C: New test.

Signed-off-by: Torbjörn SVENSSON <[email protected]>



The full and up to date discussion can be found at 
https://forge.sourceware.org/gcc/gcc/pulls/193

The merge request has been closed without being merged directly on the forge 
repository.


On 2026-07-19 07:58:06+00:00, Drea Pinski (pinskia) wrote:

So can you generalize it slightly to instead of zero be all constants.
Like (cond (eq @0 CONSTANT_CLASS@1) @0 @1).


On 2026-07-19 16:49:50+00:00, Torbjörn Svensson (azoff) wrote:

@pinskia wrote in 
https://forge.sourceware.org/gcc/gcc/pulls/193#issuecomment-6743:

> So can you generalize it slightly to instead of zero be all constants. Like 
> (cond (eq @0 CONSTANT_CLASS@1) @0 @1).

I tried a few different things and ended up with 

```
     /* A == CST ? A : CST -> CST.  */
         (simplify
          (cnd (eq:c @0 @1) @2 @1)
          (if (ANY_INTEGRAL_TYPE_P (type)
               && CONSTANT_CLASS_P (@1)
               && bitwise_equal_p (@0, @2))
           @1))
        
         /* A != CST ? CST : A -> CST.  */
         (simplify
          (cnd (ne:c @0 @1) @1 @2)
          (if (ANY_INTEGRAL_TYPE_P (type)
               && CONSTANT_CLASS_P (@1)
               && bitwise_equal_p (@0, @2))
           @1)))
```

Is this what you were thinking of?


On 2026-07-19 16:56:22+00:00, Drea Pinski (pinskia) wrote:

@azoff wrote in 
https://forge.sourceware.org/gcc/gcc/pulls/193#issuecomment-6746:

> @pinskia wrote in #193 (comment):
> 
> > So can you generalize it slightly to instead of zero be all constants. Like 
> > (cond (eq @0 CONSTANT_CLASS@1) @0 @1).
> 
> I tried a few different things and ended up with
> 
> ```text
>      /* A == CST ? A : CST -> CST.  */
>        (simplify
>         (cnd (eq:c @0 @1) @2 @1)
>         (if (ANY_INTEGRAL_TYPE_P (type)
>              && CONSTANT_CLASS_P (@1)
>              && bitwise_equal_p (@0, @2))
>          @1))
>       
>        /* A != CST ? CST : A -> CST.  */
>        (simplify
>         (cnd (ne:c @0 @1) @1 @2)
>         (if (ANY_INTEGRAL_TYPE_P (type)
>              && CONSTANT_CLASS_P (@1)
>              && bitwise_equal_p (@0, @2))
>          @1)))
> ```
> 
> Is this what you were thinking of?

Yes but I dont think you need the :c and on the ne/eq as constant class should 
always be last always. Though you might need a convert too. 


On 2026-07-19 17:09:49+00:00, Torbjörn Svensson (azoff) wrote:

@pinskia wrote in 
https://forge.sourceware.org/gcc/gcc/pulls/193#issuecomment-6747:

> @azoff wrote in #193 (comment):
> 
> > @pinskia wrote in #193 (comment):
> > > So can you generalize it slightly to instead of zero be all constants. 
> > > Like (cond (eq @0 CONSTANT_CLASS@1) @0 @1).
> > 
> > 
> > I tried a few different things and ended up with
> > ```text
> >      /* A == CST ? A : CST -> CST.  */
> >      (simplify
> >       (cnd (eq:c @0 @1) @2 @1)
> >       (if (ANY_INTEGRAL_TYPE_P (type)
> >            && CONSTANT_CLASS_P (@1)
> >            && bitwise_equal_p (@0, @2))
> >        @1))
> >     
> >      /* A != CST ? CST : A -> CST.  */
> >      (simplify
> >       (cnd (ne:c @0 @1) @1 @2)
> >       (if (ANY_INTEGRAL_TYPE_P (type)
> >            && CONSTANT_CLASS_P (@1)
> >            && bitwise_equal_p (@0, @2))
> >        @1)))
> > ```
> > 
> > Is this what you were thinking of?
> 
> Yes but I dont think you need the :c and on the ne/eq as constant class 
> should always be last always. Though you might need a convert too.

Are you saying that there is no way to end up with `CST == A ? A : CST` instead 
of `A == CST ? A : CST`? Also, is there any drawback of leaving the `:c` just 
in case?
What other converter are you thinking of?
With the above, the test case that were failing starts to pass on 
arm-none-eabi, so it should be fine as-is, right?


On 2026-07-19 20:15:29+00:00, Drea Pinski (pinskia) wrote:

Try this:
```
 /* A == CST ? A : CST -> CST.  */
         (simplify
          (cnd (eq @0 CONSTANT_CLASS_P@1) (nop_convert? @0) CONSTANT_CLASS_P@2)
          (if (ANY_INTEGRAL_TYPE_P (type)
               && operand_equal_p (@1, @2))
           (convert @1)))
 /* A != CST ? CST : A -> CST.  */
         (simplify
          (cnd (ne @0 CONSTANT_CLASS_P@1) CONSTANT_CLASS_P@2 (nop_convert? @0))
          (if (ANY_INTEGRAL_TYPE_P (type)
               && operand_equal_p (@1, @2))
           (convert @1)))
```

VECTOR_CST should be last due to:
```
bool
tree_swap_operands_p (const_tree arg0, const_tree arg1)
{
  if (CONSTANT_CLASS_P (arg1))
    return false;
  if (CONSTANT_CLASS_P (arg0))
    return true;
```




On 2026-07-19 21:02:53+00:00, Drea Pinski (pinskia) wrote:

Here is a C++ (C++ is required because C front-end does not yet support ?: for 
vectors) testcase you should add:
```
#define vector __attribute__((vector_size(4*sizeof(int))))
void f(vector int *a)
{
  vector int cst = (vector int){1,2,3,4};
  vector int t = (*a == cst);
  *a = (t ? *a : cst);
}
```


On 2026-07-20 06:10:17+00:00, Torbjörn Svensson (azoff) wrote:

I've updated the branch to use your expressions.

I've re-run the reg-test with no difference compared to 
15fe2c8ef344f86c33199ee2a7900c52d29de69e.

@pinskia wrote in 
https://forge.sourceware.org/gcc/gcc/pulls/193#issuecomment-6750:

> Here is a C++ (C++ is required because C front-end does not yet support ?: 
> for vectors) testcase you should add:
> 
> ```text
> #define vector __attribute__((vector_size(4*sizeof(int))))
> void f(vector int *a)
> {
>   vector int cst = (vector int){1,2,3,4};
>   vector int t = (*a == cst);
>   *a = (t ? *a : cst);
> }
> ```

I've also added this test, but I assume that I need to add some more check and 
not just a compile check.

Should I use `/* { dg-final { scan-tree-dump-not "_expr" "forwprop3" } } */` 
again or does it need something different?


On 2026-07-20 06:18:30+00:00, Torbjörn Svensson (azoff) wrote:

@pinskia Please take a look.
The test does fail for an unpatched version of GCC, but pass with the patch.

Should be good to go now, I think.

On 2026-07-23 14:10:03+00:00, Torbjörn Svensson (azoff) 
<[email protected]> requested that Drea Pinski (pinskia) 
<[email protected]> review the code:





On 2026-07-23 18:03:27+00:00, Drea Pinski (pinskia) wrote:

oked on the email list: 
https://gcc.gnu.org/pipermail/gcc-patches/2026-July/724863.html

And already pushed: 
https://gcc.gnu.org/cgit/gcc/commit/?id=3e2b0fcab75527bae01a0e22fe993addcf8475d9

So closing.

Reply via email to