The following fixes more cases of "lost" PHIs which happen because the block with the loop-closed PHI nodes only get into the SCOP via merge_sese. But if we don't include that we do not handle reductions properly.
Fixed by always including that block in SESE regions. Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk. Richard. 2017-09-20 Richard Biener <rguent...@suse.de> PR tree-optimization/80213 * graphite-scop-detection.c (trivially_empty_bb_p): Labels are allowed in empty BBs as well. (canonicalize_loop_closed_ssa): Also look for other complex edges. (scop_detection::get_sese): Include the loop-closed PHI block in loop SESEs. (scop_detection::merge_sese): Remove code adding extra blocks. (scop_detection::region_has_one_loop): Adjust for get_sese changes. (build_scops): Assert the final returned scop is invalid. Index: gcc/graphite-scop-detection.c =================================================================== --- gcc/graphite-scop-detection.c (revision 253001) +++ gcc/graphite-scop-detection.c (working copy) @@ -261,7 +261,8 @@ trivially_empty_bb_p (basic_block bb) gimple_stmt_iterator gsi; for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) - if (gimple_code (gsi_stmt (gsi)) != GIMPLE_DEBUG) + if (gimple_code (gsi_stmt (gsi)) != GIMPLE_DEBUG + && gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL) return false; return true; @@ -355,7 +356,7 @@ canonicalize_loop_closed_ssa (loop_p loo edge e = single_exit (loop); basic_block bb; - if (!e || e->flags & EDGE_ABNORMAL) + if (!e || (e->flags & EDGE_COMPLEX)) return; bb = e->dest; @@ -674,14 +675,19 @@ scop_detection::get_sese (loop_p loop) if (!loop) return invalid_sese; - if (!loops_state_satisfies_p (LOOPS_HAVE_PREHEADERS)) - return invalid_sese; + edge scop_begin = loop_preheader_edge (loop); edge scop_end = single_exit (loop); - if (!scop_end) + if (!scop_end || (scop_end->flags & EDGE_COMPLEX)) return invalid_sese; - edge scop_begin = loop_preheader_edge (loop); - sese_l s (scop_begin, scop_end); - return s; + /* Include the BB with the loop-closed SSA PHI nodes. + canonicalize_loop_closed_ssa makes sure that is in proper shape. */ + if (! single_pred_p (scop_end->dest) + || ! single_succ_p (scop_end->dest) + || ! trivially_empty_bb_p (scop_end->dest)) + gcc_unreachable (); + scop_end = single_succ_edge (scop_end->dest); + + return sese_l (scop_begin, scop_end); } /* Return the closest dominator with a single entry edge. */ @@ -848,26 +854,6 @@ scop_detection::merge_sese (sese_l first return invalid_sese; } - /* FIXME: We should remove this piece of code once - canonicalize_loop_closed_ssa has been removed, because that function - adds a BB with single exit. */ - if (!trivially_empty_bb_p (get_exit_bb (combined))) - { - /* Find the first empty succ (with single exit) of combined.exit. */ - basic_block imm_succ = combined.exit->dest; - if (single_succ_p (imm_succ) - && single_pred_p (imm_succ) - && trivially_empty_bb_p (imm_succ)) - combined.exit = single_succ_edge (imm_succ); - else - { - DEBUG_PRINT (dp << "[scop-detection-fail] Discarding SCoP because " - << "no single exit (empty succ) for sese exit"; - print_sese (dump_file, combined)); - return invalid_sese; - } - } - /* Analyze all the BBs in new sese. */ if (harmful_loop_in_region (combined)) return invalid_sese; @@ -1027,7 +1013,8 @@ scop_detection::region_has_one_loop (ses return false; /* Otherwise, check whether we have adjacent loops. */ - return begin->dest->loop_father == end->src->loop_father; + return (single_pred_p (end->src) + && begin->dest->loop_father == single_pred (end->src)->loop_father); } /* Add to SCOPS a scop starting at SCOP_BEGIN and ending at SCOP_END. */ @@ -2053,8 +2040,12 @@ build_scops (vec<scop_p> *scops) canonicalize_loop_closed_ssa_form (); + /* ??? We walk the loop tree assuming loop->next is ordered. + This is not so but we'd be free to order it here. */ scop_detection sb; - sb.build_scop_depth (scop_detection::invalid_sese, current_loops->tree_root); + sese_l tem = sb.build_scop_depth (scop_detection::invalid_sese, + current_loops->tree_root); + gcc_assert (! tem); /* Now create scops from the lightweight SESEs. */ vec<sese_l> scops_l = sb.get_scops ();