]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR middle-end/78726 (Incorrect unsigned arithmetic optimization)
authorJakub Jelinek <jakub@redhat.com>
Fri, 9 Dec 2016 09:21:36 +0000 (10:21 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Fri, 9 Dec 2016 09:21:36 +0000 (10:21 +0100)
PR tree-optimization/78726
* tree-ssa-reassoc.c (make_new_ssa_for_def): Add OPCODE and OP
argument.  For lhs uses in debug stmts, don't replace lhs with
new_lhs, but with a debug temp set to new_lhs opcode op.
(make_new_ssa_for_all_defs): Add OPCODE argument, pass OPCODE and
OP down to make_new_ssa_for_def.
(zero_one_operation): Call make_new_ssa_for_all_defs even when
stmts_to_fix is empty, if *def has not changed yet.  Pass
OPCODE to make_new_ssa_for_all_defs.

* gcc.c-torture/execute/pr78726.c: New test.
* gcc.dg/guality/pr78726.c: New test.

From-SVN: r243476

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/pr78726.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/guality/pr78726.c [new file with mode: 0644]
gcc/tree-ssa-reassoc.c

index e75a77803e5e3e4bf4f2062870de1472afe6c2fe..2ccc00fccae294b367ea92db719d57daeb945d7a 100644 (file)
@@ -1,3 +1,15 @@
+2016-12-09  Jakub Jelinek  <jakub@redhat.com>
+
+       PR tree-optimization/78726
+       * tree-ssa-reassoc.c (make_new_ssa_for_def): Add OPCODE and OP
+       argument.  For lhs uses in debug stmts, don't replace lhs with
+       new_lhs, but with a debug temp set to new_lhs opcode op.
+       (make_new_ssa_for_all_defs): Add OPCODE argument, pass OPCODE and
+       OP down to make_new_ssa_for_def.
+       (zero_one_operation): Call make_new_ssa_for_all_defs even when
+       stmts_to_fix is empty, if *def has not changed yet.  Pass
+       OPCODE to make_new_ssa_for_all_defs.
+
 2016-12-08  Martin Sebor  <msebor@redhat.com>
 
        PR c/78284
index 80166f282a7c684d142041aa9b1465d621d81277..3ea10f27886de39ba35e1de080a8f41b1a390149 100644 (file)
@@ -1,3 +1,9 @@
+2016-12-09  Jakub Jelinek  <jakub@redhat.com>
+
+       PR tree-optimization/78726
+       * gcc.c-torture/execute/pr78726.c: New test.
+       * gcc.dg/guality/pr78726.c: New test.
+
 2016-12-08  Martin Sebor  <msebor@redhat.com>
 
        PR c/78284
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr78726.c b/gcc/testsuite/gcc.c-torture/execute/pr78726.c
new file mode 100644 (file)
index 0000000..9c29234
--- /dev/null
@@ -0,0 +1,23 @@
+/* PR tree-optimization/78726 */
+
+unsigned char b = 36, c = 173;
+unsigned int d;
+
+__attribute__((noinline, noclone)) void
+foo (void)
+{
+  unsigned a = ~b;
+  d = a * c * c + 1023094746U * a;
+}
+
+int
+main ()
+{
+  if (__SIZEOF_INT__ != 4 || __CHAR_BIT__ != 8)
+    return 0;
+  asm volatile ("" : : "g" (&b), "g" (&c) : "memory");
+  foo ();
+  if (d != 799092689U)
+    __builtin_abort ();
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/guality/pr78726.c b/gcc/testsuite/gcc.dg/guality/pr78726.c
new file mode 100644 (file)
index 0000000..dc6b386
--- /dev/null
@@ -0,0 +1,30 @@
+/* PR tree-optimization/78726 */
+/* { dg-do run } */
+/* { dg-options "-g" } */
+
+#include "../nop.h"
+
+unsigned char b = 36, c = 173;
+unsigned int d;
+
+__attribute__((noinline, noclone)) void
+foo (void)
+{
+  unsigned a = ~b;
+  unsigned d1 = a * c;         /* { dg-final { gdb-test 21 "d1" "~36U * 173" } } */
+  unsigned d2 = d1 * c;                /* { dg-final { gdb-test 21 "d2" "~36U * 173 * 173" } } */
+  unsigned d3 = 1023094746 * a;        /* { dg-final { gdb-test 21 "d3" "~36U * 1023094746" } } */
+  d = d2 + d3;
+  unsigned d4 = d1 * 2;        /* { dg-final { gdb-test 21 "d4" "~36U * 173 * 2" } } */
+  unsigned d5 = d2 * 2;                /* { dg-final { gdb-test 21 "d5" "~36U * 173 * 173 * 2" } } */
+  unsigned d6 = d3 * 2;                /* { dg-final { gdb-test 21 "d6" "~36U * 1023094746 * 2" } } */
+  asm (NOP : : : "memory");
+}
+
+int
+main ()
+{
+  asm volatile ("" : : "g" (&b), "g" (&c) : "memory");
+  foo ();
+  return 0;
+}
index f781c5ff28c4f3aee0e7cfd3aae31f403dd28795..b0158368931529ef775c870bd268ff720ba21bc1 100644 (file)
@@ -1153,12 +1153,12 @@ decrement_power (gimple *stmt)
    SSA.  Also return the new SSA.  */
 
 static tree
-make_new_ssa_for_def (gimple *stmt)
+make_new_ssa_for_def (gimple *stmt, enum tree_code opcode, tree op)
 {
   gimple *use_stmt;
   use_operand_p use;
   imm_use_iterator iter;
-  tree new_lhs;
+  tree new_lhs, new_debug_lhs = NULL_TREE;
   tree lhs = gimple_get_lhs (stmt);
 
   new_lhs = make_ssa_name (TREE_TYPE (lhs));
@@ -1167,8 +1167,28 @@ make_new_ssa_for_def (gimple *stmt)
   /* Also need to update GIMPLE_DEBUGs.  */
   FOR_EACH_IMM_USE_STMT (use_stmt, iter, lhs)
     {
+      tree repl = new_lhs;
+      if (is_gimple_debug (use_stmt))
+       {
+         if (new_debug_lhs == NULL_TREE)
+           {
+             new_debug_lhs = make_node (DEBUG_EXPR_DECL);
+             gdebug *def_temp
+               = gimple_build_debug_bind (new_debug_lhs,
+                                          build2 (opcode, TREE_TYPE (lhs),
+                                                  new_lhs, op),
+                                          stmt);
+             DECL_ARTIFICIAL (new_debug_lhs) = 1;
+             TREE_TYPE (new_debug_lhs) = TREE_TYPE (lhs);
+             SET_DECL_MODE (new_debug_lhs, TYPE_MODE (TREE_TYPE (lhs)));
+             gimple_set_uid (def_temp, gimple_uid (stmt));
+             gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
+             gsi_insert_after (&gsi, def_temp, GSI_SAME_STMT);
+           }
+         repl = new_debug_lhs;
+       }
       FOR_EACH_IMM_USE_ON_STMT (use, iter)
-       SET_USE (use, new_lhs);
+       SET_USE (use, repl);
       update_stmt (use_stmt);
     }
   return new_lhs;
@@ -1179,7 +1199,7 @@ make_new_ssa_for_def (gimple *stmt)
    if *DEF is not OP.  */
 
 static void
-make_new_ssa_for_all_defs (tree *def, tree op,
+make_new_ssa_for_all_defs (tree *def, enum tree_code opcode, tree op,
                           vec<gimple *> &stmts_to_fix)
 {
   unsigned i;
@@ -1189,10 +1209,10 @@ make_new_ssa_for_all_defs (tree *def, tree op,
       && TREE_CODE (*def) == SSA_NAME
       && (stmt = SSA_NAME_DEF_STMT (*def))
       && gimple_code (stmt) != GIMPLE_NOP)
-    *def = make_new_ssa_for_def (stmt);
+    *def = make_new_ssa_for_def (stmt, opcode, op);
 
   FOR_EACH_VEC_ELT (stmts_to_fix, i, stmt)
-    make_new_ssa_for_def (stmt);
+    make_new_ssa_for_def (stmt, opcode, op);
 }
 
 /* Find the single immediate use of STMT's LHS, and replace it
@@ -1232,6 +1252,7 @@ propagate_op_to_single_use (tree op, gimple *stmt, tree *def)
 static void
 zero_one_operation (tree *def, enum tree_code opcode, tree op)
 {
+  tree orig_def = *def;
   gimple *stmt = SSA_NAME_DEF_STMT (*def);
   /* PR72835 - Record the stmt chain that has to be updated such that
      we dont use the same LHS when the values computed are different.  */
@@ -1335,8 +1356,8 @@ zero_one_operation (tree *def, enum tree_code opcode, tree op)
     }
   while (1);
 
-  if (stmts_to_fix.length () > 0)
-    make_new_ssa_for_all_defs (def, op, stmts_to_fix);
+  if (stmts_to_fix.length () > 0 || *def == orig_def)
+    make_new_ssa_for_all_defs (def, opcode, op, stmts_to_fix);
 }
 
 /* Returns true if statement S1 dominates statement S2.  Like