On 1/7/2026 3:06 PM, Andrew Pinski wrote:
Yes afterwards, the sink happens. And pushed ` y_3(D) << 2`/`_1 +
z_4(D)` into the branch.
And then uncprop changes `0(2)` into `y_3(D)(2)` in the PHI (sometimes
that is better; sometimes that is worse; for riscv with zicond it is
usually worse because ifcvt does not always convert back into 0).
In general uncprop should be profitable as it reduces the number of
constant initializations created by conditional equivalences.
Essentially it replaces a constant zero with an object known to have the
value zero on the appropriate path.
RTL cse/gcse/cprop all know how to handle conditional equivalences and
should push the 0 value back in. It's also the cas that the zicond code
knows how to handle cases where both arms are pseudos, but one of the
arms is also used in the test and as a result we know its going to have
the value zero in the context we care about.
I wonder if keeping `(lshift @0 @4)` as being compared to 0 if that
would be better, it would at least keep one expression out of the
branch.
Dunno. I'd probably need to see before/after RTL and assembly code.
With the pattern I sent this is the 'optimized' dump I get:
long int frob (long int x, long int y, long int z)
{
long int ret;
long int _1;
_Bool _7;
long int _8;
;; basic block 2, loop depth 0, count 1073741824 (estimated locally,
freq 1.0000), maybe hot
;; prev block 0, next block 1, flags: (NEW, REACHABLE, VISITED)
;; pred: ENTRY [always] count:1073741824 (estimated locally,
freq 1.0000) (FALLTHRU,EXECUTABLE)
_1 = y_3(D) << 2;
ret_5 = _1 + z_4(D);
_7 = y_3(D) == 0;
_8 = _7 ? 0 : ret_5;
# VUSE <.MEM_6(D)>
return _8;
;; succ: EXIT [always] count:1073741824 (estimated locally,
freq 1.0000) (EXECUTABLE) test.c:8:10
I'm not sure why we're having this difference given that the patterns
are quite similar.
Because when you have a cond_expr in the output of a match pattern, we
don't recreate an if/else branches.
In the pattern without the cond_expr, the sink pass sinks the other
expressions. While here we have an explicit COND_EXPR rather than
control flow.
The big question is, can ifcvt on the rtl level recover the first way
into the second way; I think currently it does not but I have not
fully looked; so we might to need help it on the gimple level (for GCC
17 though).
I would generally expect the form above to eventually collapse down to
something ifcvt can convert using zicond.
Jeff