https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118012
--- Comment #6 from Georg-Johann Lay <gjl at gcc dot gnu.org> ---
(In reply to Andrew Pinski from comment #5)
> /* Expand X*Y as X&-Y when Y must be zero or one. */
> ...
> if (bit0_p || bit1_p)
> {
> bool speed = optimize_insn_for_speed_p ();
> int cost = add_cost (speed, mode) + neg_cost (speed, mode);
> struct algorithm algorithm;
> enum mult_variant variant;
> if (CONST_INT_P (op1)
> ? !choose_mult_variant (mode, INTVAL (op1),
> &algorithm, &variant, cost)
> : cost < mul_cost (speed, mode))
>
>
> Note this should have a debug print in dump_file but that is a different
> story.
>
> So maybe we are not doing the right costs here.
That place just replaces a multiplication by some other tricks like negate +
bit_and on the extended mode. I don't see how tweaking the costs there would
give a branch-on-bit around the target operation (bit_xor in the example).
You cannot roll back that in the backend by, say, a combine pattern that yould
read
(xor:HI (and:HI (neg:HI (sign_extract:HI (subreg:QI (reg:HI) 0)
(const_int 1)
(const_int 0))))
(reg:HI))
> Or we should have another choice of how to expand `a * onezero` into
> `onezero ? a : 0`
The propblem is that this is just the preparation for the 2nd xor operand to be
0u (when the bit is 0) or -1u (when the bit is 1). What you want is a branch
depending on the bit, avoiding the 2nd operand altogether. Just do
if (bit == 0)
goto skip;
c ^= a;
skip:;
instead of:
// Do crazy things to coax bit == 1 into some operand coax and then
c ^= coax;
I don't see where the payload operation (the c ^= a) is in the expr.cc code
from above, it's just setting up coax.
And this doesn't only occur with bit == 1 but also with bit == 0.
And this doesn't only occur wihh bit_xor but also with bit_ior and plus.