Mercurial > hg > CbC > CbC_gcc
diff gcc/tree-ssa-threadedge.c @ 145:1830386684a0
gcc-9.2.0
author | anatofuz |
---|---|
date | Thu, 13 Feb 2020 11:34:05 +0900 |
parents | 84e7813d76e9 |
children |
line wrap: on
line diff
--- a/gcc/tree-ssa-threadedge.c Thu Oct 25 07:37:49 2018 +0900 +++ b/gcc/tree-ssa-threadedge.c Thu Feb 13 11:34:05 2020 +0900 @@ -1,5 +1,5 @@ /* SSA Jump Threading - Copyright (C) 2005-2018 Free Software Foundation, Inc. + Copyright (C) 2005-2020 Free Software Foundation, Inc. Contributed by Jeff Law <law@redhat.com> This file is part of GCC. @@ -31,7 +31,6 @@ #include "gimple-iterator.h" #include "tree-cfg.h" #include "tree-ssa-threadupdate.h" -#include "params.h" #include "tree-ssa-scopedtables.h" #include "tree-ssa-threadedge.h" #include "tree-ssa-dom.h" @@ -140,7 +139,7 @@ tree dst = gimple_phi_result (phi); /* If the desired argument is not the same as this PHI's result - and it is set by a PHI in E->dest, then we can not thread + and it is set by a PHI in E->dest, then we cannot thread through E->dest. */ if (src != dst && TREE_CODE (src) == SSA_NAME @@ -165,8 +164,8 @@ /* Get an empty new VR we can pass to update_value_range and save away in the VR stack. */ vr_values *vr_values = evrp_range_analyzer->get_vr_values (); - value_range *new_vr = vr_values->allocate_value_range (); - *new_vr = value_range (); + value_range_equiv *new_vr = vr_values->allocate_value_range_equiv (); + new (new_vr) value_range_equiv (); /* There are three cases to consider: @@ -181,9 +180,9 @@ if (TREE_CODE (src) == SSA_NAME) new_vr->deep_copy (vr_values->get_value_range (src)); else if (TREE_CODE (src) == INTEGER_CST) - set_value_range_to_value (new_vr, src, NULL); + new_vr->set (src); else - set_value_range_to_varying (new_vr); + new_vr->set_varying (TREE_TYPE (src)); /* This is a temporary range for DST, so push it. */ evrp_range_analyzer->push_value_range (dst, new_vr); @@ -234,7 +233,7 @@ gimple_stmt_iterator gsi; int max_stmt_count; - max_stmt_count = PARAM_VALUE (PARAM_MAX_JUMP_THREAD_DUPLICATION_STMTS); + max_stmt_count = param_max_jump_thread_duplication_stmts; /* Walk through each statement in the block recording equivalences we discover. Note any equivalences we discover are context @@ -253,13 +252,13 @@ continue; /* If the statement has volatile operands, then we assume we - can not thread through this block. This is overly + cannot thread through this block. This is overly conservative in some ways. */ if (gimple_code (stmt) == GIMPLE_ASM && gimple_asm_volatile_p (as_a <gasm *> (stmt))) return NULL; - /* If the statement is a unique builtin, we can not thread + /* If the statement is a unique builtin, we cannot thread through here. */ if (gimple_code (stmt) == GIMPLE_CALL && gimple_call_internal_p (stmt) @@ -275,7 +274,7 @@ killed due to threading, grow the max count accordingly. */ if (max_stmt_count - == PARAM_VALUE (PARAM_MAX_JUMP_THREAD_DUPLICATION_STMTS)) + == param_max_jump_thread_duplication_stmts) { max_stmt_count += estimate_threading_killed_stmts (e->dest); if (dump_file) @@ -331,6 +330,7 @@ { tree fndecl = gimple_call_fndecl (stmt); if (fndecl + && fndecl_built_in_p (fndecl, BUILT_IN_NORMAL) && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_OBJECT_SIZE || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CONSTANT_P)) continue; @@ -906,7 +906,7 @@ tree cond; /* The key property of these blocks is that they need not be duplicated - when threading. Thus they can not have visible side effects such + when threading. Thus they cannot have visible side effects such as PHI nodes. */ if (!gsi_end_p (gsi_start_phis (bb))) return false; @@ -1157,6 +1157,68 @@ return 0; } +/* There are basic blocks look like: + <P0> + p0 = a CMP b ; or p0 = (INT) (a CMP b) + goto <X>; + + <P1> + p1 = c CMP d + goto <X>; + + <X> + # phi = PHI <p0 (P0), p1 (P1)> + if (phi != 0) goto <Y>; else goto <Z>; + + Then, edge (P0,X) or (P1,X) could be marked as EDGE_START_JUMP_THREAD + And edge (X,Y), (X,Z) is EDGE_COPY_SRC_JOINER_BLOCK + + Return true if E is (P0,X) or (P1,X) */ + +bool +edge_forwards_cmp_to_conditional_jump_through_empty_bb_p (edge e) +{ + /* See if there is only one stmt which is gcond. */ + gcond *gs; + if (!(gs = safe_dyn_cast<gcond *> (last_and_only_stmt (e->dest)))) + return false; + + /* See if gcond's cond is "(phi !=/== 0/1)" in the basic block. */ + tree cond = gimple_cond_lhs (gs); + enum tree_code code = gimple_cond_code (gs); + tree rhs = gimple_cond_rhs (gs); + if (TREE_CODE (cond) != SSA_NAME + || (code != NE_EXPR && code != EQ_EXPR) + || (!integer_onep (rhs) && !integer_zerop (rhs))) + return false; + gphi *phi = dyn_cast <gphi *> (SSA_NAME_DEF_STMT (cond)); + if (phi == NULL || gimple_bb (phi) != e->dest) + return false; + + /* Check if phi's incoming value is CMP. */ + gassign *def; + tree value = PHI_ARG_DEF_FROM_EDGE (phi, e); + if (TREE_CODE (value) != SSA_NAME + || !has_single_use (value) + || !(def = dyn_cast <gassign *> (SSA_NAME_DEF_STMT (value)))) + return false; + + /* Or if it is (INT) (a CMP b). */ + if (CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def))) + { + value = gimple_assign_rhs1 (def); + if (TREE_CODE (value) != SSA_NAME + || !has_single_use (value) + || !(def = dyn_cast<gassign *> (SSA_NAME_DEF_STMT (value)))) + return false; + } + + if (TREE_CODE_CLASS (gimple_assign_rhs_code (def)) != tcc_comparison) + return false; + + return true; +} + /* We are exiting E->src, see if E->dest ends with a conditional jump which has a known value when reached via E. @@ -1261,7 +1323,7 @@ /* If E->dest has abnormal outgoing edges, then there's no guarantee we can safely redirect any of the edges. Just punt those cases. */ FOR_EACH_EDGE (taken_edge, ei, e->dest->succs) - if (taken_edge->flags & EDGE_ABNORMAL) + if (taken_edge->flags & EDGE_COMPLEX) { const_and_copies->pop_to_marker (); avail_exprs_stack->pop_to_marker (); @@ -1299,7 +1361,6 @@ x = new jump_thread_edge (taken_edge, EDGE_COPY_SRC_JOINER_BLOCK); path->safe_push (x); - found = false; found = thread_around_empty_blocks (taken_edge, dummy_cond, avail_exprs_stack, @@ -1317,10 +1378,12 @@ /* If we were able to thread through a successor of E->dest, then record the jump threading opportunity. */ - if (found) + if (found + || edge_forwards_cmp_to_conditional_jump_through_empty_bb_p (e)) { - propagate_threaded_block_debug_into (path->last ()->e->dest, - taken_edge->dest); + if (taken_edge->dest != path->last ()->e->dest) + propagate_threaded_block_debug_into (path->last ()->e->dest, + taken_edge->dest); register_jump_thread (path); } else