summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlaw <law@138bc75d-0d04-0410-961f-82ee72b054a4>2014-01-15 18:13:52 +0000
committerlaw <law@138bc75d-0d04-0410-961f-82ee72b054a4>2014-01-15 18:13:52 +0000
commit92802c6fb22841547067e577a9820d25ccfefd15 (patch)
treee0f2de4b26fbea16dedfb92ad4e491726101c7f8
parentb69fc80ac37d8117944c7c56786c47fb6f5b2f5b (diff)
downloadgcc-92802c6fb22841547067e577a9820d25ccfefd15.tar.gz
PR tree-optimization/59747
* ree.c (find_and_remove_re): Properly handle case where a second eliminated extension requires widening a copy created for elimination of a prior extension. (combine_set_extension): Ensure that the number of hard regs needed for a destination register does not change when we widen it. PR tree-optimization/59747 * gcc.c-torture/execute/pr59747.c: New test. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@206638 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog9
-rw-r--r--gcc/ree.c21
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr59747.c27
4 files changed, 59 insertions, 3 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 1231e88b735..856bd46ac52 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,12 @@
+2014-01-15 Jeff Law <law@redhat.com>
+
+ PR tree-optimization/59747
+ * ree.c (find_and_remove_re): Properly handle case where a second
+ eliminated extension requires widening a copy created for elimination
+ of a prior extension.
+ (combine_set_extension): Ensure that the number of hard regs needed
+ for a destination register does not change when we widen it.
+
2014-01-15 Sebastian Huber <sebastian.huber@embedded-brains.de>
* config.gcc (*-*-rtems*): Add t-rtems to tmake_file.
diff --git a/gcc/ree.c b/gcc/ree.c
index 63cc8cc7c32..19d821ce05a 100644
--- a/gcc/ree.c
+++ b/gcc/ree.c
@@ -297,6 +297,12 @@ combine_set_extension (ext_cand *cand, rtx curr_insn, rtx *orig_set)
else
new_reg = gen_rtx_REG (cand->mode, REGNO (SET_DEST (*orig_set)));
+ /* We're going to be widening the result of DEF_INSN, ensure that doing so
+ doesn't change the number of hard registers needed for the result. */
+ if (HARD_REGNO_NREGS (REGNO (new_reg), cand->mode)
+ != HARD_REGNO_NREGS (REGNO (orig_src), GET_MODE (SET_DEST (*orig_set))))
+ return false;
+
/* Merge constants by directly moving the constant into the register under
some conditions. Recall that RTL constants are sign-extended. */
if (GET_CODE (orig_src) == CONST_INT
@@ -1017,11 +1023,20 @@ find_and_remove_re (void)
for (unsigned int i = 0; i < reinsn_copy_list.length (); i += 2)
{
rtx curr_insn = reinsn_copy_list[i];
+ rtx def_insn = reinsn_copy_list[i + 1];
+
+ /* Use the mode of the destination of the defining insn
+ for the mode of the copy. This is necessary if the
+ defining insn was used to eliminate a second extension
+ that was wider than the first. */
+ rtx sub_rtx = *get_sub_rtx (def_insn);
rtx pat = PATTERN (curr_insn);
- rtx new_reg = gen_rtx_REG (GET_MODE (SET_DEST (pat)),
+ rtx new_dst = gen_rtx_REG (GET_MODE (SET_DEST (sub_rtx)),
REGNO (XEXP (SET_SRC (pat), 0)));
- rtx set = gen_rtx_SET (VOIDmode, new_reg, SET_DEST (pat));
- emit_insn_after (set, reinsn_copy_list[i + 1]);
+ rtx new_src = gen_rtx_REG (GET_MODE (SET_DEST (sub_rtx)),
+ REGNO (SET_DEST (pat)));
+ rtx set = gen_rtx_SET (VOIDmode, new_dst, new_src);
+ emit_insn_after (set, def_insn);
}
/* Delete all useless extensions here in one sweep. */
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 4aadd851e85..dcfb67197f0 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2014-01-15 Jeff Law <law@redhat.com>
+
+ PR tree-optimization/59747
+ * gcc.c-torture/execute/pr59747.c: New test.
+
2014-01-15 H.J. Lu <hongjiu.lu@intel.com>
PR target/59794
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr59747.c b/gcc/testsuite/gcc.c-torture/execute/pr59747.c
new file mode 100644
index 00000000000..d45a9082b81
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr59747.c
@@ -0,0 +1,27 @@
+extern void abort (void);
+extern void exit (int);
+
+int a[6], b, c = 1, d;
+short e;
+
+int __attribute__ ((noinline))
+fn1 (int p)
+{
+ b = a[p];
+}
+
+int
+main ()
+{
+ if (sizeof (long long) != 8)
+ exit (0);
+
+ a[0] = 1;
+ if (c)
+ e--;
+ d = e;
+ long long f = e;
+ if (fn1 ((f >> 56) & 1) != 0)
+ abort ();
+ exit (0);
+}