re PR tree-optimization/90106 (builtin sqrt() ignoring libm's sqrt call result)
authorJun Ma <JunMa@linux.alibaba.com>
Thu, 16 May 2019 08:21:17 +0000 (08:21 +0000)
committerJun Ma <junma@gcc.gnu.org>
Thu, 16 May 2019 08:21:17 +0000 (08:21 +0000)
PR tree-optimization/90106
* tree-call-cdce.c (shrink_wrap_one_built_in_call_with_conds): Add
new parameter as new internal function call, also move it to new
basic block.
(use_internal_fn): Pass internal function call to
shrink_wrap_one_built_in_call_with_conds.

gcc/testsuite
* gcc.dg/cdce1.c: Check tailcall code generation after cdce pass.
* gcc.dg/cdce2.c: Likewise.

From-SVN: r271281

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/cdce1.c
gcc/testsuite/gcc.dg/cdce2.c
gcc/tree-call-cdce.c

index 5fd00d9ecc3254b3230f5cbf00fa808c3e9b3cdc..4a891c90048e04983c3bdddf093e075b6f04a71d 100644 (file)
@@ -1,20 +1,11 @@
-2019-05-16  Sebastian Huber  <sebastian.huber@embedded-brains.de>
-
-       * config/arm/t-rtems: Replace ARMv7-M multilibs with Cortex-M
-       multilibs.
-
-2019-05-16  Richard Biener  <rguenther@suse.de>
-
-       PR tree-optimization/90424
-       * tree-ssa.c (non_rewritable_lvalue_p): Handle inserts from
-       aligned subvectors.
-       (execute_update_addresses_taken): Likewise.
-       * tree-cfg.c (verify_gimple_assign_ternary): Likewise.
-
-2019-05-16  Richard Biener  <rguenther@suse.de>
-
-       * gimple-pretty-print.c (dump_ternary_rhs): Dump BIT_INSERT_EXPR
-       as __BIT_INSERT with -gimple.
+2019-05-16  Jun Ma <JunMa@linux.alibaba.com>
+
+       PR tree-optimization/90106
+       * tree-call-cdce.c (shrink_wrap_one_built_in_call_with_conds): Add
+       new parameter as new internal function call, also move it to new
+       basic block.
+       (use_internal_fn): Pass internal function call to
+       shrink_wrap_one_built_in_call_with_conds.
 
 2019-05-15  Jakub Jelinek  <jakub@redhat.com>
 
index 5f01fdf15a8712c33e05e221168dc72163e97d1a..dc4edeffabce1e981aaff245f3e887d6564f2ef9 100644 (file)
@@ -1,3 +1,9 @@
+2019-05-16  Jun Ma <JunMa@linux.alibaba.com>
+
+       PR tree-optimization/90106
+       * gcc.dg/cdce1.c: Check tailcall code generation after cdce pass.
+       * gcc.dg/cdce2.c: Likewise.
+
 2019-05-16  Richard Biener  <rguenther@suse.de>
 
        PR tree-optimization/90424
index b23ad6371126425e77e8128c25caf7e0840bc098..424d80fcdec34ff75439facd4bfa7a9f6f93d5bc 100644 (file)
@@ -1,7 +1,8 @@
 /* { dg-do  run  } */
 /* { dg-options "-O2 -fmath-errno -fdump-tree-cdce-details  -lm" } */
 /* { dg-require-effective-target int32plus } */
-/* { dg-final { scan-tree-dump  "cdce1.c:16: .* function call is shrink-wrapped into error conditions\."  "cdce" } } */
+/* { dg-final { scan-tree-dump  "cdce1.c:17: .* function call is shrink-wrapped into error conditions\."  "cdce" } } */
+/* { dg-final { scan-assembler     "jmp pow" } } */
 /* { dg-require-effective-target large_double } */
 
 #include <stdlib.h>
index 30e7cb1fa0a8c9dc4b0e13fc0c300ef4be950c4e..2af2893549d17ac63bd5bfcf52a237974174eda6 100644 (file)
@@ -1,7 +1,8 @@
 /* { dg-do  run  } */
 /* { dg-skip-if "doubles are floats" { "avr-*-*" } } */
 /* { dg-options "-O2 -fmath-errno -fdump-tree-cdce-details  -lm" } */
-/* { dg-final { scan-tree-dump  "cdce2.c:15: .* function call is shrink-wrapped into error conditions\." "cdce" } } */
+/* { dg-final { scan-tree-dump  "cdce2.c:16: .* function call is shrink-wrapped into error conditions\." "cdce" } } */
+/* { dg-final { scan-assembler "jmp log" } } */
  
 #include <stdlib.h>
 #include <math.h>
index 2e482b37ea25b7571632c297d7a42b2555bd1fd3..9e3372fe56c3d8df26a9a48f7cbdaaf812e0941d 100644 (file)
@@ -93,10 +93,10 @@ along with GCC; see the file COPYING3.  If not see
 
        y = sqrt (x);
      ==>
-       y = IFN_SQRT (x);
        if (__builtin_isless (x, 0))
-           sqrt (x);
-
+         y =  sqrt (x);
+       else
+         y = IFN_SQRT (x);
      In the vast majority of cases we should then never need to call sqrt.
 
    Note that library functions are not supposed to clear errno to zero without
@@ -793,14 +793,16 @@ gen_shrink_wrap_conditions (gcall *bi_call, vec<gimple *> conds,
 }
 
 /* Shrink-wrap BI_CALL so that it is only called when one of the NCONDS
-   conditions in CONDS is false.  */
+   conditions in CONDS is false.  Also move BI_NEWCALL to a new basic block
+   when it is non-null, it is called while all of the CONDS are true.  */
 
 static void
 shrink_wrap_one_built_in_call_with_conds (gcall *bi_call, vec <gimple *> conds,
-                                         unsigned int nconds)
+                                         unsigned int nconds,
+                                         gcall *bi_newcall = NULL)
 {
   gimple_stmt_iterator bi_call_bsi;
-  basic_block bi_call_bb, join_tgt_bb, guard_bb;
+  basic_block bi_call_bb, bi_newcall_bb, join_tgt_bb, guard_bb;
   edge join_tgt_in_edge_from_call, join_tgt_in_edge_fall_thru;
   edge bi_call_in_edge0, guard_bb_in_edge;
   unsigned tn_cond_stmts;
@@ -809,27 +811,26 @@ shrink_wrap_one_built_in_call_with_conds (gcall *bi_call, vec <gimple *> conds,
   gimple *cond_expr_start;
 
   /* The cfg we want to create looks like this:
-
-          [guard n-1]         <- guard_bb (old block)
-            |    \
-            | [guard n-2]                   }
-            |    / \                        }
-            |   /  ...                      } new blocks
-            |  /  [guard 0]                 }
-            | /    /   |                    }
-           [ call ]    |     <- bi_call_bb  }
-            | \        |
-            |  \       |
-            |   [ join ]     <- join_tgt_bb (old iff call must end bb)
-            |
+          [guard n-1]         <- guard_bb (old block)
+            |    \
+            | [guard n-2]                   }
+            |    / \                        }
+            |   /  ...                      } new blocks
+            |  /  [guard 0]                 }
+            | /  /    |                     }
+           [call]     |      <- bi_call_bb  }
+             \    [newcall]  <-bi_newcall_bb}
+              \       |
+                [join]       <- join_tgt_bb (old iff call must end bb)
         possible EH edges (only if [join] is old)
 
      When [join] is new, the immediate dominators for these blocks are:
 
      1. [guard n-1]: unchanged
      2. [call]: [guard n-1]
-     3. [guard m]: [guard m+1] for 0 <= m <= n-2
-     4. [join]: [guard n-1]
+     3. [newcall]: [guard 0]
+     4. [guard m]: [guard m+1] for 0 <= m <= n-2
+     5. [join]: [guard n-1]
 
      We punt for the more complex case case of [join] being old and
      simply free the dominance info.  We also punt on postdominators,
@@ -927,6 +928,47 @@ shrink_wrap_one_built_in_call_with_conds (gcall *bi_call, vec <gimple *> conds,
       edges.quick_push (edge_pair (bi_call_in_edge, guard_bb_in_edge));
     }
 
+  /* Move BI_NEWCALL to new basic block when it is non-null.  */
+  if (bi_newcall)
+    {
+      /* Get bi_newcall_bb by split join_tgt_in_edge_fall_thru edge,
+         and move BI_NEWCALL to bi_newcall_bb.  */
+      bi_newcall_bb = split_edge (join_tgt_in_edge_fall_thru);
+      gimple_stmt_iterator to_gsi = gsi_start_bb (bi_newcall_bb);
+      gimple_stmt_iterator from_gsi = gsi_for_stmt (bi_newcall);
+      gsi_move_before (&from_gsi, &to_gsi);
+      join_tgt_in_edge_fall_thru = EDGE_SUCC (bi_newcall_bb, 0);
+      join_tgt_bb = join_tgt_in_edge_fall_thru->dest;
+
+      tree bi_newcall_lhs = gimple_call_lhs (bi_newcall);
+      tree bi_call_lhs = gimple_call_lhs (bi_call);
+      if (!bi_call_lhs)
+        {
+          bi_call_lhs = copy_ssa_name (bi_newcall_lhs);
+          gimple_call_set_lhs (bi_call, bi_call_lhs);
+          SSA_NAME_DEF_STMT (bi_call_lhs) = bi_call;
+        }
+
+      /* Create phi node for lhs of BI_CALL and BI_NEWCALL.  */
+      gphi *new_phi = create_phi_node (copy_ssa_name (bi_newcall_lhs),
+                                      join_tgt_bb);
+      SSA_NAME_OCCURS_IN_ABNORMAL_PHI (PHI_RESULT (new_phi))
+        = SSA_NAME_OCCURS_IN_ABNORMAL_PHI (bi_newcall_lhs);
+      add_phi_arg (new_phi, bi_call_lhs, join_tgt_in_edge_from_call,
+                   gimple_location (bi_call));
+      add_phi_arg (new_phi, bi_newcall_lhs, join_tgt_in_edge_fall_thru,
+                   gimple_location (bi_newcall));
+
+      /* Replace all use of original return value with result of phi node.  */
+      use_operand_p use_p;
+      gimple *use_stmt;
+      imm_use_iterator iterator;
+      FOR_EACH_IMM_USE_STMT (use_stmt, iterator, bi_newcall_lhs)
+        if (use_stmt != new_phi)
+         FOR_EACH_IMM_USE_ON_STMT (use_p, iterator)
+           SET_USE (use_p, PHI_RESULT (new_phi));
+    }
+
   /* Now update the probability and profile information, processing the
      guards in order of execution.
 
@@ -1030,9 +1072,11 @@ use_internal_fn (gcall *call)
 
   unsigned nconds = 0;
   auto_vec<gimple *, 12> conds;
+  bool is_arg_conds = false;
   if (can_test_argument_range (call))
     {
       gen_shrink_wrap_conditions (call, conds, &nconds);
+      is_arg_conds = true;
       gcc_assert (nconds != 0);
     }
   else
@@ -1082,8 +1126,8 @@ use_internal_fn (gcall *call)
          call = new_call;
        }
     }
-
-  shrink_wrap_one_built_in_call_with_conds (call, conds, nconds);
+  shrink_wrap_one_built_in_call_with_conds (call, conds, nconds,
+                                           is_arg_conds ? new_call : NULL);
 }
 
 /* The top level function for conditional dead code shrink