When skimming through the code I noticed the following (chatted on IRC about parts of the changes).
Bootstrap / regtest running on x86_64-unknown-linux-gnu. Will commit tomorrow unless you beat me to that. Richard. 2017-12-04 Richard Biener <rguent...@suse.de> * gimple-loop-interchange.cc (loop_cand::classify_simple_reduction): Simplify. (loop_cand::analyze_iloop_reduction_var): Reject dead reductions. (loop_cand::analyze_oloop_reduction_var): Likewise. Simplify. (tree_loop_interchange::interchange_loops): Properly analyze scalar evolution before instantiating a SCEV. Index: gcc/gimple-loop-interchange.cc =================================================================== --- gcc/gimple-loop-interchange.cc (revision 255383) +++ gcc/gimple-loop-interchange.cc (working copy) @@ -444,50 +444,21 @@ loop_cand::classify_simple_reduction (re if (!bb || bb->loop_father != m_outer) return; - if (!is_gimple_assign (producer)) + if (!gimple_assign_load_p (producer)) return; - code = gimple_assign_rhs_code (producer); - if (get_gimple_rhs_class (code) != GIMPLE_SINGLE_RHS) - return; - - lhs = gimple_assign_lhs (producer); - if (lhs != re->init) - return; - - rhs = gimple_assign_rhs1 (producer); - if (!REFERENCE_CLASS_P (rhs)) - return; - - re->init_ref = rhs; + re->init_ref = gimple_assign_rhs1 (producer); } else if (!CONSTANT_CLASS_P (re->init)) return; - /* Check how reduction variable is used. Note usually reduction variable - is used outside of its defining loop, we don't require that in terms of - loop interchange. */ - if (!re->lcssa_phi) - consumer = single_use_in_loop (re->next, m_loop); - else - consumer = single_use_in_loop (PHI_RESULT (re->lcssa_phi), m_outer); - - if (!consumer || !is_gimple_assign (consumer)) - return; - - code = gimple_assign_rhs_code (consumer); - if (get_gimple_rhs_class (code) != GIMPLE_SINGLE_RHS) - return; - - lhs = gimple_assign_lhs (consumer); - if (!REFERENCE_CLASS_P (lhs)) - return; - - rhs = gimple_assign_rhs1 (consumer); - if (rhs != PHI_RESULT (re->lcssa_phi)) + /* Check how reduction variable is used. */ + consumer = single_use_in_loop (PHI_RESULT (re->lcssa_phi), m_outer); + if (!consumer + || !gimple_store_p (consumer)) return; - re->fini_ref = lhs; + re->fini_ref = gimple_get_lhs (consumer); re->consumer = consumer; /* Simple reduction with constant initializer. */ @@ -608,6 +579,9 @@ loop_cand::analyze_iloop_reduction_var ( else return false; } + if (!lcssa_phi) + return false; + re = XCNEW (struct reduction); re->var = var; re->init = init; @@ -681,15 +655,9 @@ loop_cand::analyze_oloop_reduction_var ( /* Outer loop's reduction should only be used to initialize inner loop's simple reduction. */ - FOR_EACH_IMM_USE_FAST (use_p, iterator, var) - { - stmt = USE_STMT (use_p); - if (is_gimple_debug (stmt)) - continue; - - if (stmt != inner_re->phi) - return false; - } + if (! single_imm_use (var, &use_p, &stmt) + || stmt != inner_re->phi) + return false; /* Check this reduction is correctly used outside of loop via lcssa phi. */ FOR_EACH_IMM_USE_FAST (use_p, iterator, next) @@ -711,6 +679,8 @@ loop_cand::analyze_oloop_reduction_var ( else return false; } + if (!lcssa_phi) + return false; re = XCNEW (struct reduction); re->var = var; @@ -1146,12 +1116,18 @@ tree_loop_interchange::interchange_loops edge instantiate_below = loop_preheader_edge (loop_nest); gsi = gsi_last_bb (loop_preheader_edge (loop_nest)->src); i_niters = number_of_latch_executions (iloop.m_loop); - i_niters = instantiate_scev (instantiate_below, loop_nest, i_niters); + i_niters = analyze_scalar_evolution (loop_outer (iloop.m_loop), i_niters); + i_niters = instantiate_scev (instantiate_below, loop_outer (iloop.m_loop), + i_niters); i_niters = force_gimple_operand_gsi (&gsi, unshare_expr (i_niters), true, NULL_TREE, false, GSI_CONTINUE_LINKING); o_niters = number_of_latch_executions (oloop.m_loop); if (oloop.m_loop != loop_nest) - o_niters = instantiate_scev (instantiate_below, loop_nest, o_niters); + { + o_niters = analyze_scalar_evolution (loop_outer (oloop.m_loop), o_niters); + o_niters = instantiate_scev (instantiate_below, loop_outer (oloop.m_loop), + o_niters); + } o_niters = force_gimple_operand_gsi (&gsi, unshare_expr (o_niters), true, NULL_TREE, false, GSI_CONTINUE_LINKING);