On 5/9/2026 3:24 PM, Richard Sandiford wrote:
Further suggestions?
Jeff
diff --git a/gcc/simplify-rtx.cc b/gcc/simplify-rtx.cc
index ee3d9ec32082..08ae224847b1 100644
--- a/gcc/simplify-rtx.cc
+++ b/gcc/simplify-rtx.cc
@@ -3900,6 +3900,83 @@ simplify_context::simplify_binary_operation_1 (rtx_code
code,
&& negated_ops_p (XEXP (op0, 0), op1))
return simplify_gen_binary (IOR, mode, XEXP (op0, 1), op1);
+ {
+ rtx top0 = op0;
+ rtx top1 = op1;
+ for (int i = 0; i < 2; i++)
+ {
+ /* The outer IOR is commutative so try op0/op1 in their
+ original position and reversed. */
+ if (i == 1)
+ std::swap (top0, top1);
FWIW, it would also work to keep op0 and op1 and do the std::swap
at the end of the loop body. Maybe that would be less error prone
wrt top vs op.
I was originally worried about early exits from the loop and thus I
wanted to leave op0/op1 alone. But the only early exits are returns, so
the state of op0/op1 doesn't matter. I could probably make a case for
either form. I suspect we're more likely to inadvertently use op0/op1
rather than the temporaries than we are to introduce a break in the
loop. Or maybe just put all the stuff into a function to avoid these
worries. I don't offhand think of a strong reason why this all needs to
be inlined.
+
+ /* (ior X (plus/xor X C)) can be simplified into (ior X C) when
+ X and C have no bits in common. */
Maybe s/C/Y/ now that we're not requiring a constant.
Agreed. I'll change that too.
Do you still need the last transformation? I was hoping that
nonzero_bits would return C1 for (and A C1), and so the first test
above would handle it.
I'd hoped for the same, but it was still necessary for some of the H8
cases. Though I did introduce a transient bug while adjusting things.
it's possible I'd tested when I had that transient bug in my tree (which
prevented the first transformation from firing). I'll retest just to be
sure.
Otherwise LGTM FWIW.
It's worth a lot to me. I'll make the two additional adjustments sniff
test and commit.
Thanks!
jeff