From e6503e0a45efcea6a0cdc5aeab165e084b0eb624 Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Mon, 19 Oct 2015 14:00:28 +0000 Subject: re PR tree-optimization/67975 (Failure to optimise equality between two call sequences) 2015-10-19 Richard Biener PR tree-optimization/67975 * tree-cfg.h (extract_true_false_controlled_edges): Declare. * tree-cfg.c (extract_true_false_controlled_edges): Split out core worker from ... * tree-ssa-loop-im.c (extract_true_false_args_from_phi): ... here. * tree-ssa-sccvn.c (vn_phi_compute_hash): Hash number of args instead of block number for PHIs with two or one args. (vn_phi_eq): Compare edge predicates of PHIs that are in different blocks. * gcc.dg/tree-ssa/ssa-fre-50.c: New testcase. From-SVN: r228971 --- gcc/tree-cfg.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) (limited to 'gcc/tree-cfg.c') diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c index 735ac46..5bf546e 100644 --- a/gcc/tree-cfg.c +++ b/gcc/tree-cfg.c @@ -8532,6 +8532,75 @@ extract_true_false_edges_from_block (basic_block b, } } + +/* From a controlling predicate in the immediate dominator DOM of + PHIBLOCK determine the edges into PHIBLOCK that are chosen if the + predicate evaluates to true and false and store them to + *TRUE_CONTROLLED_EDGE and *FALSE_CONTROLLED_EDGE if + they are non-NULL. Returns true if the edges can be determined, + else return false. */ + +bool +extract_true_false_controlled_edges (basic_block dom, basic_block phiblock, + edge *true_controlled_edge, + edge *false_controlled_edge) +{ + basic_block bb = phiblock; + edge true_edge, false_edge, tem; + edge e0 = NULL, e1 = NULL; + + /* We have to verify that one edge into the PHI node is dominated + by the true edge of the predicate block and the other edge + dominated by the false edge. This ensures that the PHI argument + we are going to take is completely determined by the path we + take from the predicate block. + We can only use BB dominance checks below if the destination of + the true/false edges are dominated by their edge, thus only + have a single predecessor. */ + extract_true_false_edges_from_block (dom, &true_edge, &false_edge); + tem = EDGE_PRED (bb, 0); + if (tem == true_edge + || (single_pred_p (true_edge->dest) + && (tem->src == true_edge->dest + || dominated_by_p (CDI_DOMINATORS, + tem->src, true_edge->dest)))) + e0 = tem; + else if (tem == false_edge + || (single_pred_p (false_edge->dest) + && (tem->src == false_edge->dest + || dominated_by_p (CDI_DOMINATORS, + tem->src, false_edge->dest)))) + e1 = tem; + else + return false; + tem = EDGE_PRED (bb, 1); + if (tem == true_edge + || (single_pred_p (true_edge->dest) + && (tem->src == true_edge->dest + || dominated_by_p (CDI_DOMINATORS, + tem->src, true_edge->dest)))) + e0 = tem; + else if (tem == false_edge + || (single_pred_p (false_edge->dest) + && (tem->src == false_edge->dest + || dominated_by_p (CDI_DOMINATORS, + tem->src, false_edge->dest)))) + e1 = tem; + else + return false; + if (!e0 || !e1) + return false; + + if (true_controlled_edge) + *true_controlled_edge = e0; + if (false_controlled_edge) + *false_controlled_edge = e1; + + return true; +} + + + /* Emit return warnings. */ namespace { -- cgit v1.1