https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108292

--- Comment #5 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
Though, it seems the REG_EQUAL note is also wrong on the cmov10.c testcase
which went with the commit (again, exact opposite).

Seems we have multiple cases where this REG_EQUAL note is newly added.
One is x != 0 ? -1 : y, negate_cc_compare_p is true and code overridden to EQ
and ct/cf swapped.
So, the note is then (neg (eq x const0_rtx)).
Another one is x == 0 ? y : -1, negate_cc_compare_p is true, code, ct and cf
unchanged.
The note is then (neg (eq x const0_rtx)) too.
The sequence emitted for both of these cases is neg{l,q} x; sbb{l,q} tmp, tmp,
which sets tmp to 0 if x == 0 and to -1 if x != 0.  So the right note would be
IMNSHO
(neg (ne x const0_rtx)) for both of the above cases.
Another case is the sign_bit_compare_p case, which happens for (signed)
x >= 0 ? y : z
x < 0 ? y : z
x > -1 ? y : z
x <= -1 ? y : z
The code handling those cases is:
              if (code == GT || code == GE)
                code = reverse_condition (code);
              else
                {
                  std::swap (ct, cf);
                  diff = ct - cf;
                }
              tmp = emit_store_flag (tmp, code, op0, op1, VOIDmode, 0, -1);
In that case emit_store_flag sets tmp to (code op0 op1) ? -1 : 0 so I think
(neg (code op0 op1)) is the right REG_EQUAL note for it.
The last case is when ix86_expand_carry_flag_compare returns true.
This is when LTU/GEU comparisons are used or something which can be turned into
one,
e.g. x == 0 or x != 0 turned into x < 1U or x >= 1U.

Now, the code below the addition of the new REG_EQUAL note assumes that the
comparison
set tmp to 0 if true and to -1 if false (which can be seen e.g. from diff == 1
&& ct == 0 case not adding any further instructions).  So the REG_EQUAL note
should be IMHO
gen_rtx_NEG (mode, gen_rtx_fmt_ee (reverse_condition (code), mode, op0, op1))
rather than gen_rtx_NEG (mode, gen_rtx_fmt_ee (code, mode, op0, op1))
for the cases where std::swap (ct, cf); has not been done (with the original
code, not the adjusted one).  For the sign_bit_compare_p case that matches the
above analysis that
it is handled correctly, as we reverse_condition iff swap isn't done.
For the negate_cc_compare_p case I think it matches the analysis too that it is
always wrong and should be always NE.

Reply via email to