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.