[backport gcc-4.8/trunk r193187 to fix final_scan_insn on m68k/cc0 targets ] From: Andreas Schwab Subject: [PATCH] Fix final_scan_insn to handle all comparisons in non-jump and cmove insn Date: Sat, 03 Nov 2012 14:16:25 +0100 List-Archive: final_scan_insn didn't handle the IEEE-aware compares in a non-jump/cmove insn, causing wrong code if it was generated with swapped operands (CC_REVERSED set). Tested on m68k-linux. Andreas. * final.c (final_scan_insn) [HAVE_cc0]: Handle all comparison codes in non-jump and cmove insn. testsuite/ * gcc.dg/torture/fp-compare.c: New testcase. --- gcc-4.7.2/gcc/final.c.~1~ 2011-12-13 14:41:12.000000000 +0100 +++ gcc-4.7.2/gcc/final.c 2012-11-03 16:55:08.000000000 +0100 @@ -2566,36 +2566,19 @@ final_scan_insn (rtx insn, FILE *file, i else_rtx = const0_rtx; } - switch (GET_CODE (cond_rtx)) + if (COMPARISON_P (cond_rtx) + && XEXP (cond_rtx, 0) == cc0_rtx) { - case GTU: - case GT: - case LTU: - case LT: - case GEU: - case GE: - case LEU: - case LE: - case EQ: - case NE: - { - int result; - if (XEXP (cond_rtx, 0) != cc0_rtx) - break; - result = alter_cond (cond_rtx); - if (result == 1) - validate_change (insn, &SET_SRC (set), then_rtx, 0); - else if (result == -1) - validate_change (insn, &SET_SRC (set), else_rtx, 0); - else if (result == 2) - INSN_CODE (insn) = -1; - if (SET_DEST (set) == SET_SRC (set)) - delete_insn (insn); - } - break; - - default: - break; + int result; + result = alter_cond (cond_rtx); + if (result == 1) + validate_change (insn, &SET_SRC (set), then_rtx, 0); + else if (result == -1) + validate_change (insn, &SET_SRC (set), else_rtx, 0); + else if (result == 2) + INSN_CODE (insn) = -1; + if (SET_DEST (set) == SET_SRC (set)) + delete_insn (insn); } } --- gcc-4.7.2/gcc/testsuite/gcc.dg/torture/fp-compare.c.~1~ 1970-01-01 01:00:00.000000000 +0100 +++ gcc-4.7.2/gcc/testsuite/gcc.dg/torture/fp-compare.c 2012-11-03 16:55:08.000000000 +0100 @@ -0,0 +1,23 @@ +/* { dg-do run } */ +/* Check that find_scan_insn properly handles swapped FP comparisons. */ +static double x; +static int exit_code; + +void __attribute__ ((noinline)) +check_int (int a, int b) +{ + exit_code += (a != b); +} + +int +main (void) +{ + x = 0.0; + asm ("" : "+m" (x)); + check_int (__builtin_isgreater (x, 1.0), 0); + check_int (__builtin_isgreaterequal (x, 1.0), 0); + check_int (__builtin_isless (x, 1.0), 1); + check_int (__builtin_islessequal (x, 1.0), 1); + check_int (__builtin_islessgreater (x, 1.0), 1); + return exit_code; +}