diff --git a/gcc/dojump.c b/gcc/dojump.c index 4c7fafe2965..b12bcea7468 100644 --- a/gcc/dojump.c +++ b/gcc/dojump.c @@ -1168,6 +1168,23 @@ do_compare_rtx_and_jump (rtx op0, rtx op1, enum rtx_code code, int unsignedp, profile_probability first_prob = prob.split (cprob); do_compare_rtx_and_jump (op0, op1, first_code, unsignedp, mode, size, NULL, if_true_label, first_prob); + if (orig_code == NE && can_compare_p (UNEQ, mode, ccp_jump)) + { + /* x != y can be split into x unord y || x ltgt y + or x unord y || !(x uneq y). The latter has the + advantage that both comparisons are non-signalling and + so there is a higher chance that the RTL optimizations + merge the two comparisons into just one. */ + code = UNEQ; + prob = prob.invert (); + if (! if_false_label) + { + if (! dummy_label) + dummy_label = gen_label_rtx (); + if_false_label = dummy_label; + } + std::swap (if_false_label, if_true_label); + } } } } diff --git a/gcc/testsuite/gcc.target/i386/pr98212.c b/gcc/testsuite/gcc.target/i386/pr98212.c new file mode 100644 index 00000000000..b8ed0236eec --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr98212.c @@ -0,0 +1,21 @@ +/* PR rtl-optimization/98212 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -msse2 -mfpmath=sse -mno-avx" } */ +/* { dg-final { scan-assembler-times "\tucomiss\t" 2 } } */ +/* { dg-final { scan-assembler-not "\tcomiss\t" } } */ + +void foo (void); + +void +bar (float a, float b) +{ + if (a != b) + foo (); +} + +void +baz (float a, float b) +{ + if (a == b) + foo (); +}