re PR rtl-optimization/63659 (wrong code at -O2 and -O3 on x86_64-linux-gnu)
authorJakub Jelinek <jakub@redhat.com>
Fri, 31 Oct 2014 19:42:39 +0000 (20:42 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Fri, 31 Oct 2014 19:42:39 +0000 (20:42 +0100)
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

gcc/ChangeLog
gcc/ree.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/pr63659.c [new file with mode: 0644]

index 4d452e07c8028beca876d1d37bfd9e1f66c5ad7e..6a130836fdea0938cbe2837c1ef62970988c4c85 100644 (file)
@@ -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+)
index a89427a399e89ac3d186d4b82c471f30856791fb..2b44ccc6b541dd6ddb43df45e40206d4882e732a 100644 (file)
--- 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)
         {
index 719986cd04562beec6a7d87e4d760857c97efd44..ac737184b549d234aef932e9543214da5a8d45fb 100644 (file)
@@ -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 (file)
index 0000000..780dc8a
--- /dev/null
@@ -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;
+}