re PR tree-optimization/71016 (Redundant sign extension with conditional __builtin_clzl)
authorJakub Jelinek <jakub@redhat.com>
Thu, 5 Jan 2017 21:14:19 +0000 (22:14 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Thu, 5 Jan 2017 21:14:19 +0000 (22:14 +0100)
PR tree-optimization/71016
* tree-ssa-phiopt.c (tree_ssa_phiopt_worker): Pass cond_stmt to
factor_out_conditional_conversion.  Formatting fix.
(factor_out_conditional_conversion): Add cond_stmt argument.
If arg1 is INTEGER_CST, punt if new_arg0 is not any operand of
cond_stmt and if arg0_def_stmt is not the only stmt in its bb.
Formatting fix.

* gcc.target/i386/pr71016.c: New test.
* gcc.target/aarch64/pr71016.c: New test.
* gcc.dg/tree-ssa/pr66726-3.c: New test.

From-SVN: r244114

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/tree-ssa/pr66726-3.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/pr71016.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/pr71016.c [new file with mode: 0644]
gcc/tree-ssa-phiopt.c

index 1114d8a5f396752edb1fa724fac75c7790eadf88..8e51cee930bf77991fa1de3520d8b3138cc99551 100644 (file)
@@ -1,3 +1,13 @@
+2017-01-05  Jakub Jelinek  <jakub@redhat.com>
+
+       PR tree-optimization/71016
+       * tree-ssa-phiopt.c (tree_ssa_phiopt_worker): Pass cond_stmt to
+       factor_out_conditional_conversion.  Formatting fix.
+       (factor_out_conditional_conversion): Add cond_stmt argument.
+       If arg1 is INTEGER_CST, punt if new_arg0 is not any operand of
+       cond_stmt and if arg0_def_stmt is not the only stmt in its bb.
+       Formatting fix.
+
 2017-01-05  David Malcolm  <dmalcolm@redhat.com>
 
        * Makefile.in (OBJS): Add read-md.o, read-rtl.o,
index cd205bd7dd4ffcb49f6e0237a20ecb253d4dc39b..e99e399278d9e5c031684383f791c7838625b2ce 100644 (file)
@@ -1,5 +1,10 @@
 2017-01-05  Jakub Jelinek  <jakub@redhat.com>
 
+       PR tree-optimization/71016
+       * gcc.target/i386/pr71016.c: New test.
+       * gcc.target/aarch64/pr71016.c: New test.
+       * gcc.dg/tree-ssa/pr66726-3.c: New test.
+
        PR c++/78931
        * g++.dg/cpp1z/decomp19.C: New test.
 
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr66726-3.c b/gcc/testsuite/gcc.dg/tree-ssa/pr66726-3.c
new file mode 100644 (file)
index 0000000..55c7a14
--- /dev/null
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+/* { dg-final { scan-tree-dump-times "MIN_EXPR" 1 "optimized" } } */
+
+extern unsigned short mode_size[];
+
+int
+oof (int mode)
+{
+  int tem;
+  if (64 < mode_size[mode])
+    tem = 64;
+  else
+    tem = mode_size[mode];
+  return tem;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/pr71016.c b/gcc/testsuite/gcc.target/aarch64/pr71016.c
new file mode 100644 (file)
index 0000000..f50d693
--- /dev/null
@@ -0,0 +1,10 @@
+/* PR tree-optimization/71016 */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { scan-assembler-not "sxtw" } } */
+
+long int
+foo (long int i)
+{
+  return i == 0 ? 17 : __builtin_clzl (i);
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr71016.c b/gcc/testsuite/gcc.target/i386/pr71016.c
new file mode 100644 (file)
index 0000000..d5a89eb
--- /dev/null
@@ -0,0 +1,10 @@
+/* PR tree-optimization/71016 */
+/* { dg-do compile { target lp64 } } */
+/* { dg-options "-O2 -mlzcnt" } */
+/* { dg-final { scan-assembler-not "cltq" } } */
+
+long int
+foo (long int i)
+{
+  return i == 0 ? 17 : __builtin_clzl (i);
+}
index 259f6fe3e39c8b3c8085e3392cbf5aa48d2db0f7..07a226e149c48f9bd61a4ec733156c32c6138879 100644 (file)
@@ -49,7 +49,8 @@ along with GCC; see the file COPYING3.  If not see
 static unsigned int tree_ssa_phiopt_worker (bool, bool);
 static bool conditional_replacement (basic_block, basic_block,
                                     edge, edge, gphi *, tree, tree);
-static gphi *factor_out_conditional_conversion (edge, edge, gphi *, tree, tree);
+static gphi *factor_out_conditional_conversion (edge, edge, gphi *, tree, tree,
+                                               gimple *);
 static int value_replacement (basic_block, basic_block,
                              edge, edge, gimple *, tree, tree);
 static bool minmax_replacement (basic_block, basic_block,
@@ -233,7 +234,7 @@ tree_ssa_phiopt_worker (bool do_store_elim, bool do_hoist_loads)
          continue;
        }
       else if (do_hoist_loads
-                && EDGE_SUCC (bb1, 0)->dest == EDGE_SUCC (bb2, 0)->dest)
+              && EDGE_SUCC (bb1, 0)->dest == EDGE_SUCC (bb2, 0)->dest)
        {
          basic_block bb3 = EDGE_SUCC (bb1, 0)->dest;
 
@@ -313,7 +314,8 @@ tree_ssa_phiopt_worker (bool do_store_elim, bool do_hoist_loads)
          gcc_assert (arg0 != NULL_TREE && arg1 != NULL_TREE);
 
          gphi *newphi = factor_out_conditional_conversion (e1, e2, phi,
-                                                           arg0, arg1);
+                                                           arg0, arg1,
+                                                           cond_stmt);
          if (newphi != NULL)
            {
              phi = newphi;
@@ -402,11 +404,12 @@ replace_phi_edge_with_variable (basic_block cond_block,
 
 /* PR66726: Factor conversion out of COND_EXPR.  If the arguments of the PHI
    stmt are CONVERT_STMT, factor out the conversion and perform the conversion
-   to the result of PHI stmt.  Return the newly-created PHI, if any.  */
+   to the result of PHI stmt.  COND_STMT is the controlling predicate.
+   Return the newly-created PHI, if any.  */
 
 static gphi *
 factor_out_conditional_conversion (edge e0, edge e1, gphi *phi,
-                                  tree arg0, tree arg1)
+                                  tree arg0, tree arg1, gimple *cond_stmt)
 {
   gimple *arg0_def_stmt = NULL, *arg1_def_stmt = NULL, *new_stmt;
   tree new_arg0 = NULL_TREE, new_arg1 = NULL_TREE;
@@ -472,7 +475,31 @@ factor_out_conditional_conversion (edge e0, edge e1, gphi *phi,
          && int_fits_type_p (arg1, TREE_TYPE (new_arg0)))
        {
          if (gimple_assign_cast_p (arg0_def_stmt))
-           new_arg1 = fold_convert (TREE_TYPE (new_arg0), arg1);
+           {
+             /* For the INTEGER_CST case, we are just moving the
+                conversion from one place to another, which can often
+                hurt as the conversion moves further away from the
+                statement that computes the value.  So, perform this
+                only if new_arg0 is an operand of COND_STMT, or
+                if arg0_def_stmt is the only non-debug stmt in
+                its basic block, because then it is possible this
+                could enable further optimizations (minmax replacement
+                etc.).  See PR71016.  */
+             if (new_arg0 != gimple_cond_lhs (cond_stmt)
+                 && new_arg0 != gimple_cond_rhs (cond_stmt)
+                 && gimple_bb (arg0_def_stmt) == e0->src)
+               {
+                 gsi = gsi_for_stmt (arg0_def_stmt);
+                 gsi_prev_nondebug (&gsi);
+                 if (!gsi_end_p (gsi))
+                   return NULL;
+                 gsi = gsi_for_stmt (arg0_def_stmt);
+                 gsi_next_nondebug (&gsi);
+                 if (!gsi_end_p (gsi))
+                   return NULL;
+               }
+             new_arg1 = fold_convert (TREE_TYPE (new_arg0), arg1);
+           }
          else
            return NULL;
        }
@@ -524,7 +551,7 @@ factor_out_conditional_conversion (edge e0, edge e1, gphi *phi,
   /* Create the conversion stmt and insert it.  */
   if (convert_code == VIEW_CONVERT_EXPR)
     temp = fold_build1 (VIEW_CONVERT_EXPR, TREE_TYPE (result), temp);
-  new_stmt = gimple_build_assign (result,  convert_code, temp);
+  new_stmt = gimple_build_assign (result, convert_code, temp);
   gsi = gsi_after_labels (gimple_bb (phi));
   gsi_insert_before (&gsi, new_stmt, GSI_SAME_STMT);