aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2014-10-31 20:42:39 +0100
committerJakub Jelinek <jakub@gcc.gnu.org>2014-10-31 20:42:39 +0100
commit73c49bf53abd68081dec20ad8adac0546a8e479b (patch)
tree417f075cb33de7f4237fb474ba35ff9fcd9ec51e
parent62871ba282e75e15af03de75b3e946b745d3c80f (diff)
downloadgcc-73c49bf53abd68081dec20ad8adac0546a8e479b.zip
gcc-73c49bf53abd68081dec20ad8adac0546a8e479b.tar.gz
gcc-73c49bf53abd68081dec20ad8adac0546a8e479b.tar.bz2
re PR rtl-optimization/63659 (wrong code at -O2 and -O3 on x86_64-linux-gnu)
PR rtl-optimization/63659 * ree.c (update_reg_equal_equiv_notes): New function. (combine_set_extension, transform_ifelse): Use it. * gcc.c-torture/execute/pr63659.c: New test. From-SVN: r216985
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/ree.c56
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr63659.c29
4 files changed, 92 insertions, 4 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 4d452e0..6a13083 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2014-10-31 Jakub Jelinek <jakub@redhat.com>
+
+ PR rtl-optimization/63659
+ * ree.c (update_reg_equal_equiv_notes): New function.
+ (combine_set_extension, transform_ifelse): Use it.
+
2014-10-31 Jeff Law <law@redhat.com>
* doc/contrib.texi: Add contribution notes for Balaji Iyer (Cilk+)
diff --git a/gcc/ree.c b/gcc/ree.c
index a89427a..2b44ccc 100644
--- a/gcc/ree.c
+++ b/gcc/ree.c
@@ -274,6 +274,50 @@ typedef struct ext_cand
static int max_insn_uid;
+/* Update or remove REG_EQUAL or REG_EQUIV notes for INSN. */
+
+static bool
+update_reg_equal_equiv_notes (rtx_insn *insn, machine_mode new_mode,
+ machine_mode old_mode, enum rtx_code code)
+{
+ rtx *loc = &REG_NOTES (insn);
+ while (*loc)
+ {
+ enum reg_note kind = REG_NOTE_KIND (*loc);
+ if (kind == REG_EQUAL || kind == REG_EQUIV)
+ {
+ rtx orig_src = XEXP (*loc, 0);
+ /* Update equivalency constants. Recall that RTL constants are
+ sign-extended. */
+ if (GET_CODE (orig_src) == CONST_INT
+ && HOST_BITS_PER_WIDE_INT >= GET_MODE_BITSIZE (new_mode))
+ {
+ if (INTVAL (orig_src) >= 0 || code == SIGN_EXTEND)
+ /* Nothing needed. */;
+ else
+ {
+ /* Zero-extend the negative constant by masking out the
+ bits outside the source mode. */
+ rtx new_const_int
+ = gen_int_mode (INTVAL (orig_src)
+ & GET_MODE_MASK (old_mode),
+ new_mode);
+ if (!validate_change (insn, &XEXP (*loc, 0),
+ new_const_int, true))
+ return false;
+ }
+ loc = &XEXP (*loc, 1);
+ }
+ /* Drop all other notes, they assume a wrong mode. */
+ else if (!validate_change (insn, loc, XEXP (*loc, 1), true))
+ return false;
+ }
+ else
+ loc = &XEXP (*loc, 1);
+ }
+ return true;
+}
+
/* Given a insn (CURR_INSN), an extension candidate for removal (CAND)
and a pointer to the SET rtx (ORIG_SET) that needs to be modified,
this code modifies the SET rtx to a new SET rtx that extends the
@@ -295,6 +339,7 @@ static bool
combine_set_extension (ext_cand *cand, rtx_insn *curr_insn, rtx *orig_set)
{
rtx orig_src = SET_SRC (*orig_set);
+ machine_mode orig_mode = GET_MODE (SET_DEST (*orig_set));
rtx new_set;
rtx cand_pat = PATTERN (cand->insn);
@@ -331,9 +376,8 @@ combine_set_extension (ext_cand *cand, rtx_insn *curr_insn, rtx *orig_set)
{
/* Zero-extend the negative constant by masking out the bits outside
the source mode. */
- machine_mode src_mode = GET_MODE (SET_DEST (*orig_set));
rtx new_const_int
- = gen_int_mode (INTVAL (orig_src) & GET_MODE_MASK (src_mode),
+ = gen_int_mode (INTVAL (orig_src) & GET_MODE_MASK (orig_mode),
GET_MODE (new_reg));
new_set = gen_rtx_SET (VOIDmode, new_reg, new_const_int);
}
@@ -372,7 +416,9 @@ combine_set_extension (ext_cand *cand, rtx_insn *curr_insn, rtx *orig_set)
/* This change is a part of a group of changes. Hence,
validate_change will not try to commit the change. */
- if (validate_change (curr_insn, orig_set, new_set, true))
+ if (validate_change (curr_insn, orig_set, new_set, true)
+ && update_reg_equal_equiv_notes (curr_insn, cand->mode, orig_mode,
+ cand->code))
{
if (dump_file)
{
@@ -422,7 +468,9 @@ transform_ifelse (ext_cand *cand, rtx_insn *def_insn)
ifexpr = gen_rtx_IF_THEN_ELSE (cand->mode, cond, map_srcreg, map_srcreg2);
new_set = gen_rtx_SET (VOIDmode, map_dstreg, ifexpr);
- if (validate_change (def_insn, &PATTERN (def_insn), new_set, true))
+ if (validate_change (def_insn, &PATTERN (def_insn), new_set, true)
+ && update_reg_equal_equiv_notes (def_insn, cand->mode, GET_MODE (dstreg),
+ cand->code))
{
if (dump_file)
{
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 719986c..ac73718 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2014-10-31 Jakub Jelinek <jakub@redhat.com>
+
+ PR rtl-optimization/63659
+ * gcc.c-torture/execute/pr63659.c: New test.
+
2014-10-31 Evgeny Stupachenko <evstupac@gmail.com>
PR target/63534
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr63659.c b/gcc/testsuite/gcc.c-torture/execute/pr63659.c
new file mode 100644
index 0000000..780dc8a
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr63659.c
@@ -0,0 +1,29 @@
+/* PR rtl-optimization/63659 */
+
+int a, b, c, *d = &b, g, h, i;
+unsigned char e;
+char f;
+
+int
+main ()
+{
+ while (a)
+ {
+ for (a = 0; a; a++)
+ for (; c; c++)
+ ;
+ if (i)
+ break;
+ }
+
+ char j = c, k = -1, l;
+ l = g = j >> h;
+ f = l == 0 ? k : k % l;
+ e = 0 ? 0 : f;
+ *d = e;
+
+ if (b != 255)
+ __builtin_abort ();
+
+ return 0;
+}