aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog4
-rw-r--r--gcc/compare-elim.c25
-rw-r--r--gcc/testsuite/ChangeLog3
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr86438.c29
4 files changed, 53 insertions, 8 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 21d9ae7..46ab4e9 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,9 @@
2018-11-09 Alexandre Oliva <aoliva@redhat.com>
+ PR rtl-optimization/86438
+ * compare-elim.c (try_eliminate_compare): Use SET_SRC instead
+ of in_b for the compare if in_b is SET_DEST.
+
PR target/87793
* config/i386/i386.c (ix86_const_not_ok_for_debug_p): Reject
non-toplevel UNSPEC.
diff --git a/gcc/compare-elim.c b/gcc/compare-elim.c
index 50bbaa8..8afbe76 100644
--- a/gcc/compare-elim.c
+++ b/gcc/compare-elim.c
@@ -734,7 +734,7 @@ try_merge_compare (struct comparison *cmp)
static bool
try_eliminate_compare (struct comparison *cmp)
{
- rtx flags, in_a, in_b, cmp_src;
+ rtx flags, in_a, in_b, cmp_a, cmp_b;
if (try_merge_compare (cmp))
return true;
@@ -786,7 +786,7 @@ try_eliminate_compare (struct comparison *cmp)
rtx x = XVECEXP (PATTERN (insn), 0, 0);
if (rtx_equal_p (SET_DEST (x), in_a))
- cmp_src = SET_SRC (x);
+ cmp_a = SET_SRC (x);
/* Also check operations with implicit extensions, e.g.:
[(set (reg:DI)
@@ -800,7 +800,7 @@ try_eliminate_compare (struct comparison *cmp)
&& (GET_CODE (SET_SRC (x)) == ZERO_EXTEND
|| GET_CODE (SET_SRC (x)) == SIGN_EXTEND)
&& GET_MODE (XEXP (SET_SRC (x), 0)) == GET_MODE (in_a))
- cmp_src = XEXP (SET_SRC (x), 0);
+ cmp_a = XEXP (SET_SRC (x), 0);
/* Also check fully redundant comparisons, e.g.:
[(set (reg:SI)
@@ -811,7 +811,7 @@ try_eliminate_compare (struct comparison *cmp)
&& GET_CODE (SET_SRC (x)) == MINUS
&& rtx_equal_p (XEXP (SET_SRC (x), 0), in_a)
&& rtx_equal_p (XEXP (SET_SRC (x), 1), in_b))
- cmp_src = in_a;
+ cmp_a = in_a;
else
return false;
@@ -819,17 +819,26 @@ try_eliminate_compare (struct comparison *cmp)
/* If the source uses addressing modes with side effects, we can't
do the merge because we'd end up with a PARALLEL that has two
instances of that side effect in it. */
- if (side_effects_p (cmp_src))
+ if (side_effects_p (cmp_a))
+ return false;
+
+ if (in_a == in_b)
+ cmp_b = cmp_a;
+ else if (rtx_equal_p (SET_DEST (x), in_b))
+ cmp_b = SET_SRC (x);
+ else
+ cmp_b = in_b;
+ if (side_effects_p (cmp_b))
return false;
/* Determine if we ought to use a different CC_MODE here. */
- flags = maybe_select_cc_mode (cmp, cmp_src, in_b);
+ flags = maybe_select_cc_mode (cmp, cmp_a, cmp_b);
if (flags == NULL)
flags = gen_rtx_REG (cmp->orig_mode, targetm.flags_regnum);
/* Generate a new comparison for installation in the setter. */
- rtx y = copy_rtx (cmp_src);
- y = gen_rtx_COMPARE (GET_MODE (flags), y, in_b);
+ rtx y = copy_rtx (cmp_a);
+ y = gen_rtx_COMPARE (GET_MODE (flags), y, copy_rtx (cmp_b));
y = gen_rtx_SET (flags, y);
/* Canonicalize instruction to:
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 9a7dfc2..6434be0 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,8 @@
2018-11-09 Alexandre Oliva <aoliva@redhat.com>
+ PR rtl-optimization/86438
+ * gcc.dg/torture/pr86438.c: New.
+
PR target/87793
* gcc.dg/pr87793.c: New.
diff --git a/gcc/testsuite/gcc.dg/torture/pr86438.c b/gcc/testsuite/gcc.dg/torture/pr86438.c
new file mode 100644
index 0000000..3e95515
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr86438.c
@@ -0,0 +1,29 @@
+/* { dg-do run } */
+
+typedef unsigned int u32;
+#if __SIZEOF_INT128__
+typedef unsigned long long u64;
+typedef unsigned __int128 u128;
+#else
+typedef unsigned long u64;
+typedef unsigned long long u128;
+#endif
+
+u128 g;
+
+static __attribute__ ((noinline, noclone))
+void check (u64 a, u64 b)
+{
+ if (a != 0 || b != 4)
+ __builtin_abort ();
+}
+
+int
+main (void)
+{
+ u64 d = (g ? 5 : 4);
+ u32 f = __builtin_sub_overflow_p (d, (u128) d, (u64) 0);
+ u128 x = g + f + d;
+ check (x >> (sizeof (u64) * __CHAR_BIT__), x);
+ return 0;
+}