Another DOM cleanup and a minor improvement to PHI merging
Jeffrey A Law
law@redhat.com
Tue Dec 20 04:11:00 GMT 2005
local_fold will be disappearing shortly from DOM; this patch removes
one of its two uses. Specifically when threading an edge we would
use local_fold to simplify the condition and strip away a subset of
type conversions. Since we do not care about type conversions at all,
we can just fold the condition and strip away all type conversions.
This was bootstrapped and regression tested on i686-pc-linux-gnu
independently of the second patch in this message.
The second part of this checkin is a minor improvement to PHI merging.
We do not currently merge PHIs when the first block dominates the
second block (this restriction makes updating the SSA graph easy).
We can still get the trivial SSA update if the first block dominates
the second and any PHIs in the first block have a single use within
PHIs of the second block.
By merging blocks in this particular case, we're able to thread more
jumps. More importantly, we do so without additional DOM iterations
and sometimes we actually have fewer iterations of DOM.
Bootstrapped and regression tested on i686-pc-linux-gnu.
-------------- next part --------------
* tree-ssa-dom.c (thread_across_edge): Do not use local_fold.
Strip away all type conversions after simplifying the
condition.
* tree-cfgcleanup.c (merge_phi_nodes): Allow merging in some
cases the forwarder block dominates the destination.
Index: gcc/tree-ssa-dom.c
===================================================================
*** gcc/tree-ssa-dom.c (revision 108831)
--- gcc/tree-ssa-dom.c (working copy)
*************** thread_across_edge (struct dom_walk_data
*** 892,900 ****
TREE_OPERAND (COND_EXPR_COND (dummy_cond), 1) = op1;
}
! /* If the conditional folds to an invariant, then we are done,
! otherwise look it up in the hash tables. */
! cached_lhs = local_fold (COND_EXPR_COND (dummy_cond));
if (! is_gimple_min_invariant (cached_lhs))
{
cached_lhs = lookup_avail_expr (dummy_cond, false);
--- 892,905 ----
TREE_OPERAND (COND_EXPR_COND (dummy_cond), 1) = op1;
}
! /* We absolutely do not care about any type conversions
! we only care about a zero/nonzero value. */
! cached_lhs = fold (COND_EXPR_COND (dummy_cond));
! while (TREE_CODE (cached_lhs) == NOP_EXPR
! || TREE_CODE (cached_lhs) == CONVERT_EXPR
! || TREE_CODE (cached_lhs) == NON_LVALUE_EXPR)
! cached_lhs = TREE_OPERAND (cached_lhs, 0);
!
if (! is_gimple_min_invariant (cached_lhs))
{
cached_lhs = lookup_avail_expr (dummy_cond, false);
Index: gcc/tree-cfgcleanup.c
===================================================================
*** gcc/tree-cfgcleanup.c (revision 108831)
--- gcc/tree-cfgcleanup.c (working copy)
*************** merge_phi_nodes (void)
*** 743,748 ****
--- 743,781 ----
nodes at BB. */
*current++ = bb;
}
+ else
+ {
+ tree phi;
+
+ /* BB dominates DEST. There may be many users of the PHI
+ nodes in BB. However, there is still a trivial case we
+ can handle. If the result of every PHI in BB is used
+ only by a PHI in DEST, then we can trivially merge the
+ PHI nodes from BB into DEST. */
+ for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
+ {
+ tree result = PHI_RESULT (phi);
+ int num_uses = num_imm_uses (result);
+ use_operand_p imm_use;
+ tree use_stmt;
+
+ /* If the PHI's result is never used, then we can just
+ ignore it. */
+ if (num_uses == 0)
+ continue;
+
+ /* Get the single use of the result of this PHI node. */
+ if (!single_imm_use (result, &imm_use, &use_stmt)
+ || TREE_CODE (use_stmt) != PHI_NODE
+ || bb_for_stmt (use_stmt) != dest)
+ break;
+ }
+
+ /* If the loop above iterated thorugh all the PHI nodes
+ in BB, then we can merge the PHIs from BB into DEST. */
+ if (!phi)
+ *current++ = bb;
+ }
}
/* Now let's drain WORKLIST. */
More information about the Gcc-patches
mailing list