summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2016-01-26 11:12:03 +0000
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2016-01-26 11:12:03 +0000
commitf7fc06e7ab0ca1bf1e9f9bcd6a0cf34ff99c7659 (patch)
tree13dabb40608100e7283aa3ad638031f8b5807728
parentd1dae58758fd7baf64f7dd3bd435037bcd15eda5 (diff)
downloadgcc-f7fc06e7ab0ca1bf1e9f9bcd6a0cf34ff99c7659.tar.gz
PR target/69442
* combine.c (combine_instructions): For REG_EQUAL note with SET_DEST being ZERO_EXTRACT, also temporarily set SET_DEST to the underlying register. * doc/rtl.texi (REG_EQUAL): Document the behavior of REG_EQUAL/REG_EQUIV notes if SET_DEST is ZERO_EXTRACT. * gcc.dg/pr69442.c: New test. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@232819 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog9
-rw-r--r--gcc/combine.c15
-rw-r--r--gcc/doc/rtl.texi6
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.dg/pr69442.c23
5 files changed, 51 insertions, 7 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 70e5fd61f3b..17f9b2b8217 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,12 @@
+2016-01-26 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/69442
+ * combine.c (combine_instructions): For REG_EQUAL note with
+ SET_DEST being ZERO_EXTRACT, also temporarily set SET_DEST
+ to the underlying register.
+ * doc/rtl.texi (REG_EQUAL): Document the behavior of
+ REG_EQUAL/REG_EQUIV notes if SET_DEST is ZERO_EXTRACT.
+
2016-01-26 Roger Ferrer Ibáñez <rofirrim@gmail.com>
PR target/67896
diff --git a/gcc/combine.c b/gcc/combine.c
index 2f913dd8ea9..858552ddc3f 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -1454,15 +1454,21 @@ combine_instructions (rtx_insn *f, unsigned int nregs)
&& ! unmentioned_reg_p (note, SET_SRC (set))
&& (GET_MODE (note) == VOIDmode
? SCALAR_INT_MODE_P (GET_MODE (SET_DEST (set)))
- : GET_MODE (SET_DEST (set)) == GET_MODE (note)))
+ : (GET_MODE (SET_DEST (set)) == GET_MODE (note)
+ && (GET_CODE (SET_DEST (set)) != ZERO_EXTRACT
+ || (GET_MODE (XEXP (SET_DEST (set), 0))
+ == GET_MODE (note))))))
{
/* Temporarily replace the set's source with the
contents of the REG_EQUAL note. The insn will
be deleted or recognized by try_combine. */
- rtx orig = SET_SRC (set);
+ rtx orig_src = SET_SRC (set);
+ rtx orig_dest = SET_DEST (set);
+ if (GET_CODE (SET_DEST (set)) == ZERO_EXTRACT)
+ SET_DEST (set) = XEXP (SET_DEST (set), 0);
SET_SRC (set) = note;
i2mod = temp;
- i2mod_old_rhs = copy_rtx (orig);
+ i2mod_old_rhs = copy_rtx (orig_src);
i2mod_new_rhs = copy_rtx (note);
next = try_combine (insn, i2mod, NULL, NULL,
&new_direct_jump_p,
@@ -1473,7 +1479,8 @@ combine_instructions (rtx_insn *f, unsigned int nregs)
statistics_counter_event (cfun, "insn-with-note combine", 1);
goto retry;
}
- SET_SRC (set) = orig;
+ SET_SRC (set) = orig_src;
+ SET_DEST (set) = orig_dest;
}
}
diff --git a/gcc/doc/rtl.texi b/gcc/doc/rtl.texi
index e44ef53d851..1b3f47e3573 100644
--- a/gcc/doc/rtl.texi
+++ b/gcc/doc/rtl.texi
@@ -3915,9 +3915,9 @@ indicates that that register will be equal to @var{op} at run time; the
scope of this equivalence differs between the two types of notes. The
value which the insn explicitly copies into the register may look
different from @var{op}, but they will be equal at run time. If the
-output of the single @code{set} is a @code{strict_low_part} expression,
-the note refers to the register that is contained in @code{SUBREG_REG}
-of the @code{subreg} expression.
+output of the single @code{set} is a @code{strict_low_part} or
+@code{zero_extract} expression, the note refers to the register that
+is contained in its first operand.
For @code{REG_EQUIV}, the register is equivalent to @var{op} throughout
the entire function, and could validly be replaced in all its
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index ae150baa578..67bc4e4cf57 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2016-01-26 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/69442
+ * gcc.dg/pr69442.c: New test.
+
2016-01-26 Roger Ferrer Ibáñez <rofirrim@gmail.com>
PR target/67896
diff --git a/gcc/testsuite/gcc.dg/pr69442.c b/gcc/testsuite/gcc.dg/pr69442.c
new file mode 100644
index 00000000000..ee75f92951a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr69442.c
@@ -0,0 +1,23 @@
+/* PR target/69442 */
+/* { dg-do run } */
+/* { dg-options "-Og" } */
+
+unsigned long long __attribute__ ((noinline, noclone))
+foo (unsigned int x, unsigned long long y)
+{
+ x |= 0xffff;
+ y -= 0xffULL;
+ y %= 0xffff0000ffffffe7ULL;
+ return x + y;
+}
+
+int
+main ()
+{
+ if (sizeof (unsigned long long) * __CHAR_BIT__ != 64)
+ return 0;
+
+ if (foo (0, 0) != 0xffff0000ff19ULL)
+ __builtin_abort ();
+ return 0;
+}