From: Jakub Jelinek Date: Thu, 19 Nov 2015 08:49:59 +0000 (+0100) Subject: re PR rtl-optimization/68376 (wrong code at -O1 and above on x86_64-linux-gnu) X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=dfc3d7a8a25f7235578a4f4547aa95dacf53fcb6;p=gcc.git re PR rtl-optimization/68376 (wrong code at -O1 and above on x86_64-linux-gnu) PR rtl-optimization/68376 * ifcvt.c (noce_try_abs): Disable one_cmpl optimization if encountering x <= 0 ? ~x : x or x > 0 ? ~x : x. * gcc.c-torture/execute/pr68376-1.c: New test. * gcc.c-torture/execute/pr68376-2.c: New test. From-SVN: r230596 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ea632f60c19..5eb06466895 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2015-11-19 Jakub Jelinek + + PR rtl-optimization/68376 + * ifcvt.c (noce_try_abs): Disable one_cmpl optimization if + encountering x <= 0 ? ~x : x or x > 0 ? ~x : x. + 2015-11-19 Richard Biener PR middle-end/68117 diff --git a/gcc/ifcvt.c b/gcc/ifcvt.c index 56e4ed42576..eb5cae5a753 100644 --- a/gcc/ifcvt.c +++ b/gcc/ifcvt.c @@ -2595,12 +2595,49 @@ noce_try_abs (struct noce_if_info *if_info) /* Work around funny ideas get_condition has wrt canonicalization. Note that these rtx constants are known to be CONST_INT, and - therefore imply integer comparisons. */ + therefore imply integer comparisons. + The one_cmpl case is more complicated, as we want to handle + only x < 0 ? ~x : x or x >= 0 ? ~x : x but not + x <= 0 ? ~x : x or x > 0 ? ~x : x, as the latter two + have different result for x == 0. */ if (c == constm1_rtx && GET_CODE (cond) == GT) - ; + { + if (one_cmpl && negate) + return FALSE; + } else if (c == const1_rtx && GET_CODE (cond) == LT) - ; - else if (c != CONST0_RTX (GET_MODE (b))) + { + if (one_cmpl && !negate) + return FALSE; + } + else if (c == CONST0_RTX (GET_MODE (b))) + { + if (one_cmpl) + switch (GET_CODE (cond)) + { + case GT: + if (!negate) + return FALSE; + break; + case GE: + /* >= 0 is the same case as above > -1. */ + if (negate) + return FALSE; + break; + case LT: + if (negate) + return FALSE; + break; + case LE: + /* <= 0 is the same case as above < 1. */ + if (!negate) + return FALSE; + break; + default: + return FALSE; + } + } + else return FALSE; /* Determine what sort of operation this is. */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 8c7746ff729..319d1f3a2d3 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,9 @@ 2015-11-19 Jakub Jelinek + PR rtl-optimization/68376 + * gcc.c-torture/execute/pr68376-1.c: New test. + * gcc.c-torture/execute/pr68376-2.c: New test. + PR target/67770 * gcc.target/i386/pr67770.c: New test. diff --git a/gcc/testsuite/gcc.c-torture/execute/pr68376-1.c b/gcc/testsuite/gcc.c-torture/execute/pr68376-1.c new file mode 100644 index 00000000000..cb52657646c --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr68376-1.c @@ -0,0 +1,24 @@ +/* PR rtl-optimization/68376 */ + +int a, b, c = 1; +signed char d; + +int +main () +{ + for (; a < 1; a++) + for (; b < 1; b++) + { + signed char e = ~d; + if (d < 1) + e = d; + d = e; + if (!c) + __builtin_abort (); + } + + if (d != 0) + __builtin_abort (); + + return 0; +} diff --git a/gcc/testsuite/gcc.c-torture/execute/pr68376-2.c b/gcc/testsuite/gcc.c-torture/execute/pr68376-2.c new file mode 100644 index 00000000000..884571a8923 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr68376-2.c @@ -0,0 +1,41 @@ +/* PR rtl-optimization/68376 */ + +extern void abort (void); + +__attribute__((noinline, noclone)) int +f1 (int x) +{ + return x < 0 ? ~x : x; +} + +__attribute__((noinline, noclone)) int +f2 (int x) +{ + return x < 0 ? x : ~x; +} + +__attribute__((noinline, noclone)) int +f3 (int x) +{ + return x <= 0 ? ~x : x; +} + +__attribute__((noinline, noclone)) int +f4 (int x) +{ + return x <= 0 ? x : ~x; +} + +int +main () +{ + if (f1 (5) != 5 || f1 (-5) != 4 || f1 (0) != 0) + abort (); + if (f2 (5) != -6 || f2 (-5) != -5 || f2 (0) != -1) + abort (); + if (f3 (5) != 5 || f3 (-5) != 4 || f3 (0) != -1) + abort (); + if (f4 (5) != -6 || f4 (-5) != -5 || f4 (0) != 0) + abort (); + return 0; +}