diff options
Diffstat (limited to 'gcc/tree-ssa-phiprop.cc')
-rw-r--r-- | gcc/tree-ssa-phiprop.cc | 96 |
1 files changed, 50 insertions, 46 deletions
diff --git a/gcc/tree-ssa-phiprop.cc b/gcc/tree-ssa-phiprop.cc index a2e1fb1..897bd58 100644 --- a/gcc/tree-ssa-phiprop.cc +++ b/gcc/tree-ssa-phiprop.cc @@ -99,35 +99,6 @@ struct phiprop_d tree vuse; }; -/* Verify if the value recorded for NAME in PHIVN is still valid at - the start of basic block BB. */ - -static bool -phivn_valid_p (struct phiprop_d *phivn, tree name, basic_block bb) -{ - tree vuse = phivn[SSA_NAME_VERSION (name)].vuse; - gimple *use_stmt; - imm_use_iterator ui2; - bool ok = true; - - /* The def stmts of the virtual uses need to be dominated by bb. */ - gcc_assert (vuse != NULL_TREE); - - FOR_EACH_IMM_USE_STMT (use_stmt, ui2, vuse) - { - /* If BB does not dominate a VDEF, the value is invalid. */ - if ((gimple_vdef (use_stmt) != NULL_TREE - || gimple_code (use_stmt) == GIMPLE_PHI) - && !dominated_by_p (CDI_DOMINATORS, gimple_bb (use_stmt), bb)) - { - ok = false; - break; - } - } - - return ok; -} - /* Insert a new phi node for the dereference of PHI at basic_block BB with the virtual operands from USE_STMT. */ @@ -275,12 +246,13 @@ chk_uses (tree, tree *idx, void *data) <Lx>:; Returns true if a transformation was done and edge insertions need to be committed. Global data PHIVN and N is used to track - past transformation results. We need to be especially careful here + past transformation results. VPHI is the virtual PHI node in BB + if there is one. We need to be especially careful here with aliasing issues as we are moving memory reads. */ static bool -propagate_with_phi (basic_block bb, gphi *phi, struct phiprop_d *phivn, - size_t n, bitmap dce_ssa_names) +propagate_with_phi (basic_block bb, gphi *vphi, gphi *phi, + struct phiprop_d *phivn, size_t n, bitmap dce_ssa_names) { tree ptr = PHI_RESULT (phi); gimple *use_stmt; @@ -298,6 +270,7 @@ propagate_with_phi (basic_block bb, gphi *phi, struct phiprop_d *phivn, && TYPE_MODE (TREE_TYPE (TREE_TYPE (ptr))) == BLKmode)) return false; + tree up_vuse = NULL_TREE; /* Check if we can "cheaply" dereference all phi arguments. */ FOR_EACH_PHI_ARG (arg_p, phi, i, SSA_OP_USE) { @@ -315,14 +288,28 @@ propagate_with_phi (basic_block bb, gphi *phi, struct phiprop_d *phivn, return false; arg = gimple_assign_rhs1 (def_stmt); } - if (TREE_CODE (arg) != ADDR_EXPR - && !(TREE_CODE (arg) == SSA_NAME + if (TREE_CODE (arg) == ADDR_EXPR) + ; + /* When we have an SSA name see if we previously encountered a + dereference of it. */ + else if (TREE_CODE (arg) == SSA_NAME && SSA_NAME_VERSION (arg) < n && phivn[SSA_NAME_VERSION (arg)].value != NULL_TREE && (!type || types_compatible_p - (type, TREE_TYPE (phivn[SSA_NAME_VERSION (arg)].value))) - && phivn_valid_p (phivn, arg, bb))) + (type, TREE_TYPE (phivn[SSA_NAME_VERSION (arg)].value)))) + { + /* The dereference should be under the VUSE that's active in BB. + If the BB has no virtual PHI then record the common "incoming" + vuse. */ + if (vphi) + up_vuse = gimple_phi_arg_def (vphi, phi_arg_index_from_use (arg_p)); + if (!up_vuse) + up_vuse = phivn[SSA_NAME_VERSION (arg)].vuse; + else if (up_vuse != phivn[SSA_NAME_VERSION (arg)].vuse) + return false; + } + else return false; if (!type && TREE_CODE (arg) == SSA_NAME) @@ -372,17 +359,32 @@ propagate_with_phi (basic_block bb, gphi *phi, struct phiprop_d *phivn, && !gimple_has_volatile_ops (use_stmt))) continue; - /* Check if we can move the loads. The def stmt of the virtual use - needs to be in a different basic block dominating bb. When the + /* Check if we can move the loads. This is when the virtual use + is the same as the one active at the start of BB which we know + either from its virtual PHI def or from the common incoming + VUSE. If neither is present make sure the def stmt of the virtual + use is in a different basic block dominating BB. When the def is an edge-inserted one we know it dominates us. */ vuse = gimple_vuse (use_stmt); - def_stmt = SSA_NAME_DEF_STMT (vuse); - if (!SSA_NAME_IS_DEFAULT_DEF (vuse) - && (gimple_bb (def_stmt) == bb - || (gimple_bb (def_stmt) - && !dominated_by_p (CDI_DOMINATORS, - bb, gimple_bb (def_stmt))))) - goto next; + if (vphi) + { + if (vuse != gimple_phi_result (vphi)) + goto next; + } + else if (up_vuse) + { + if (vuse != up_vuse) + goto next; + } + else + { + def_stmt = SSA_NAME_DEF_STMT (vuse); + if (!SSA_NAME_IS_DEFAULT_DEF (vuse) + && (gimple_bb (def_stmt) == bb + || !dominated_by_p (CDI_DOMINATORS, + bb, gimple_bb (def_stmt)))) + goto next; + } /* Found a proper dereference with an aggregate copy. Just insert aggregate copies on the edges instead. */ @@ -535,8 +537,10 @@ pass_phiprop::execute (function *fun) edges avoid blocks with abnormal predecessors. */ if (bb_has_abnormal_pred (bb)) continue; + gphi *vphi = get_virtual_phi (bb); for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi)) - did_something |= propagate_with_phi (bb, gsi.phi (), phivn, n, dce_ssa_names); + did_something |= propagate_with_phi (bb, vphi, gsi.phi (), + phivn, n, dce_ssa_names); } if (did_something) |