https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91384
--- Comment #8 from Uroš Bizjak <ubizjak at gmail dot com> --- (In reply to Jakub Jelinek from comment #1) > Started with r223689. Though, generally that change looks like a useful > GIMPLE canonicalization. How about we amend the above change to: diff --git a/gcc/match.pd b/gcc/match.pd index 43bacb4f68e..1370ba7302d 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -4506,6 +4506,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (cmp (negate @0) CONSTANT_CLASS_P@1) (if (FLOAT_TYPE_P (TREE_TYPE (@0)) || (ANY_INTEGRAL_TYPE_P (TREE_TYPE (@0)) + && integer_nonzerop (@0) && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0)))) (with { tree tem = const_unop (NEGATE_EXPR, TREE_TYPE (@0), @1); } (if (tem && !TREE_OVERFLOW (tem)) so we simplify (cmp (negate @0) CONSTANT_CLASS_P@1)) only for non-zero integer arguments. For the original testcase, the compare is eliminated: test: negl %edi pushq %r12 movl %edi, %r12d je .L2 call foo movl %r12d, %eax popq %r12 ret .L2: call bar movl %r12d, %eax popq %r12 ret Please also note that for the slightly changed original testcase: --cut here-- void f1 (void); void f2 (void); void foo (int a) { int r = -a; if (r) f1 (); else f2 (); } --cut here-- combine RTL pass manages to remove the negation without problems: Trying 6 -> 7: 6: {r84:SI=-r85:SI;clobber flags:CC;} REG_DEAD r85:SI REG_UNUSED flags:CC 7: flags:CCZ=cmp(r84:SI,0) REG_DEAD r84:SI Successfully matched this instruction: (set (reg:CCZ 17 flags) (compare:CCZ (reg:SI 85) (const_int 0 [0]))) so the compilation (-O2) results in the same assembly: foo: testl %edi, %edi je .L2 jmp f1 .L2: jmp f2