Commit 5486a996 by Jun Ma Committed by Jun Ma

re PR tree-optimization/90106 (builtin sqrt() ignoring libm's sqrt call result)

	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
parent fd893bf1
2019-05-16 Sebastian Huber <sebastian.huber@embedded-brains.de> 2019-05-16 Jun Ma <JunMa@linux.alibaba.com>
* config/arm/t-rtems: Replace ARMv7-M multilibs with Cortex-M PR tree-optimization/90106
multilibs. * 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
2019-05-16 Richard Biener <rguenther@suse.de> basic block.
(use_internal_fn): Pass internal function call to
PR tree-optimization/90424 shrink_wrap_one_built_in_call_with_conds.
* 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-15 Jakub Jelinek <jakub@redhat.com> 2019-05-15 Jakub Jelinek <jakub@redhat.com>
......
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> 2019-05-16 Richard Biener <rguenther@suse.de>
PR tree-optimization/90424 PR tree-optimization/90424
......
/* { dg-do run } */ /* { dg-do run } */
/* { dg-options "-O2 -fmath-errno -fdump-tree-cdce-details -lm" } */ /* { dg-options "-O2 -fmath-errno -fdump-tree-cdce-details -lm" } */
/* { dg-require-effective-target int32plus } */ /* { 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 } */ /* { dg-require-effective-target large_double } */
#include <stdlib.h> #include <stdlib.h>
......
/* { dg-do run } */ /* { dg-do run } */
/* { dg-skip-if "doubles are floats" { "avr-*-*" } } */ /* { dg-skip-if "doubles are floats" { "avr-*-*" } } */
/* { dg-options "-O2 -fmath-errno -fdump-tree-cdce-details -lm" } */ /* { 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 <stdlib.h>
#include <math.h> #include <math.h>
......
...@@ -93,10 +93,10 @@ along with GCC; see the file COPYING3. If not see ...@@ -93,10 +93,10 @@ along with GCC; see the file COPYING3. If not see
y = sqrt (x); y = sqrt (x);
==> ==>
y = IFN_SQRT (x);
if (__builtin_isless (x, 0)) 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. 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 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, ...@@ -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 /* 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 static void
shrink_wrap_one_built_in_call_with_conds (gcall *bi_call, vec <gimple *> conds, 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; 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 join_tgt_in_edge_from_call, join_tgt_in_edge_fall_thru;
edge bi_call_in_edge0, guard_bb_in_edge; edge bi_call_in_edge0, guard_bb_in_edge;
unsigned tn_cond_stmts; unsigned tn_cond_stmts;
...@@ -809,27 +811,26 @@ shrink_wrap_one_built_in_call_with_conds (gcall *bi_call, vec <gimple *> conds, ...@@ -809,27 +811,26 @@ shrink_wrap_one_built_in_call_with_conds (gcall *bi_call, vec <gimple *> conds,
gimple *cond_expr_start; gimple *cond_expr_start;
/* The cfg we want to create looks like this: /* The cfg we want to create looks like this:
[guard n-1] <- guard_bb (old block)
[guard n-1] <- guard_bb (old block) | \
| \ | [guard n-2] }
| [guard n-2] } | / \ }
| / \ } | / ... } new blocks
| / ... } new blocks | / [guard 0] }
| / [guard 0] } | / / | }
| / / | } [call] | <- bi_call_bb }
[ call ] | <- bi_call_bb } \ [newcall] <-bi_newcall_bb}
| \ | \ |
| \ | [join] <- join_tgt_bb (old iff call must end bb)
| [ join ] <- join_tgt_bb (old iff call must end bb)
|
possible EH edges (only if [join] is old) possible EH edges (only if [join] is old)
When [join] is new, the immediate dominators for these blocks are: When [join] is new, the immediate dominators for these blocks are:
1. [guard n-1]: unchanged 1. [guard n-1]: unchanged
2. [call]: [guard n-1] 2. [call]: [guard n-1]
3. [guard m]: [guard m+1] for 0 <= m <= n-2 3. [newcall]: [guard 0]
4. [join]: [guard n-1] 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 We punt for the more complex case case of [join] being old and
simply free the dominance info. We also punt on postdominators, 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, ...@@ -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)); 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 /* Now update the probability and profile information, processing the
guards in order of execution. guards in order of execution.
...@@ -1030,9 +1072,11 @@ use_internal_fn (gcall *call) ...@@ -1030,9 +1072,11 @@ use_internal_fn (gcall *call)
unsigned nconds = 0; unsigned nconds = 0;
auto_vec<gimple *, 12> conds; auto_vec<gimple *, 12> conds;
bool is_arg_conds = false;
if (can_test_argument_range (call)) if (can_test_argument_range (call))
{ {
gen_shrink_wrap_conditions (call, conds, &nconds); gen_shrink_wrap_conditions (call, conds, &nconds);
is_arg_conds = true;
gcc_assert (nconds != 0); gcc_assert (nconds != 0);
} }
else else
...@@ -1082,8 +1126,8 @@ use_internal_fn (gcall *call) ...@@ -1082,8 +1126,8 @@ use_internal_fn (gcall *call)
call = new_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 /* The top level function for conditional dead code shrink
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment