https://gcc.gnu.org/bugzilla/show_bug.cgi?id=122769
--- Comment #5 from Vineet Gupta <vineetg at gcc dot gnu.org> ---
ifcvt: noce_try_cond_zero_arith () currently only handles COND EQ and NE 0.
while the condition we get due to testing sign-bit is GE 0.
It seems we can transform this to EQ 0 with an intermediate SLTI
The patch below fixes the orig test...
+ /* ifcvt/czero has better outcomes with EQ operator, so convert
+ "if (a >= 0)"
+ to
+ "slti a, a, 0"
+ "if (a == 0)". */
+ if (*code == GE
+ && REG_P (*op0)
+ && *op1 == CONST0_RTX (GET_MODE (*op0)))
+ {
+ if (GET_MODE (*op0) == DImode)
+ emit_insn (gen_slt_didi3 (*op0, *op0, *op1));
+ else
+ emit_insn (gen_slt_sisi3 (*op0, *op0, *op1));
+ *code = EQ;
+ return;
+ }
... but trips up when building glibc
error: unrecognizable insn:
(insn 11 10 12 2 (set (reg:SI 165)
(lt:SI (reg:SI 165)
(const_int 0 [0])))
The existing mode iterators in slt pattern are a bit confusing though
(define_insn "@slt<u>_<X:mode><GPR:mode>3"
[(set (match_operand:GPR 0 "register_operand" "= r")
(any_lt:GPR (match_operand:X 1 "register_operand" " r")
(match_operand:X 2 "arith_operand" " rI")))]
""
"slt%i2<u>\t%0,%1,%2"
[(set_attr "type" "slt")
(set_attr "mode" "<X:MODE>")])
specifically "any_lt:GPR"