[backport from gcc-4.7/trunk ] gcc/ 2011-11-10 Richard Guenther PR tree-optimization/51070 * tree-loop-distribution.c (generate_builtin): Do not replace the loop with a builtin if the partition contains statements which results are used outside of the loop. (pass_loop_distribution): Verify and collect. gcc/testsuite/ 2011-11-10 Richard Guenther PR tree-optimization/51070 * gcc.dg/torture/pr51070.c: New testcase. --- gcc-4.6.2/gcc/testsuite/gcc.dg/torture/pr51070.c.~1~ 1970-01-01 01:00:00.000000000 +0100 +++ gcc-4.6.2/gcc/testsuite/gcc.dg/torture/pr51070.c 2011-11-19 14:57:56.000000000 +0100 @@ -0,0 +1,34 @@ +/* { dg-do compile } */ + +int +func_4 (int si1, int si2) +{ + return si1; +} + +int +func_14 (int left, int right) +{ + return 1; +} + +int +func_37 (int left, int right) +{ + return left; +} + +int g_92[1024]; +int g_95[1024]; +int g_224; +int g_352[1024]; +int +func_9 () +{ + for (; g_224; g_224 += 1) + { + g_95[0] = func_4 (func_37 (g_92[g_224], 0), 0); + g_92[g_224] = 0, g_352[g_224] = func_14 (0, 0); + } + return 0; +} --- gcc-4.6.2/gcc/tree-loop-distribution.c.~1~ 2011-05-11 15:07:54.000000000 +0200 +++ gcc-4.6.2/gcc/tree-loop-distribution.c 2011-11-19 14:59:12.000000000 +0100 @@ -63,6 +63,48 @@ static bitmap remaining_stmts; predecessor a node that writes to memory. */ static bitmap upstream_mem_writes; +/* Returns true when DEF is an SSA_NAME defined in LOOP and used after + the LOOP. */ + +static bool +ssa_name_has_uses_outside_loop_p (tree def, loop_p loop) +{ + imm_use_iterator imm_iter; + use_operand_p use_p; + + FOR_EACH_IMM_USE_FAST (use_p, imm_iter, def) + if (loop != loop_containing_stmt (USE_STMT (use_p))) + return true; + + return false; +} + +/* Returns true when STMT defines a scalar variable used after the + loop. */ + +static bool +stmt_has_scalar_dependences_outside_loop (gimple stmt) +{ + tree name; + + switch (gimple_code (stmt)) + { + case GIMPLE_ASSIGN: + name = gimple_assign_lhs (stmt); + break; + + case GIMPLE_PHI: + name = gimple_phi_result (stmt); + break; + + default: + return false; + } + + return TREE_CODE (name) == SSA_NAME + && ssa_name_has_uses_outside_loop_p (name, loop_containing_stmt (stmt)); +} + /* Update the PHI nodes of NEW_LOOP. NEW_LOOP is a duplicate of ORIG_LOOP. */ @@ -332,10 +374,18 @@ generate_builtin (struct loop *loop, bit { gimple stmt = gsi_stmt (bsi); - if (gimple_code (stmt) != GIMPLE_LABEL - && !is_gimple_debug (stmt) - && bitmap_bit_p (partition, x++) - && is_gimple_assign (stmt) + if (gimple_code (stmt) == GIMPLE_LABEL + || is_gimple_debug (stmt)) + continue; + + if (!bitmap_bit_p (partition, x++)) + continue; + + /* If the stmt has uses outside of the loop fail. */ + if (stmt_has_scalar_dependences_outside_loop (stmt)) + goto end; + + if (is_gimple_assign (stmt) && !is_gimple_reg (gimple_assign_lhs (stmt))) { /* Don't generate the builtins when there are more than @@ -826,48 +876,6 @@ fuse_partitions_with_similar_memory_acce } } -/* Returns true when DEF is an SSA_NAME defined in LOOP and used after - the LOOP. */ - -static bool -ssa_name_has_uses_outside_loop_p (tree def, loop_p loop) -{ - imm_use_iterator imm_iter; - use_operand_p use_p; - - FOR_EACH_IMM_USE_FAST (use_p, imm_iter, def) - if (loop != loop_containing_stmt (USE_STMT (use_p))) - return true; - - return false; -} - -/* Returns true when STMT defines a scalar variable used after the - loop. */ - -static bool -stmt_has_scalar_dependences_outside_loop (gimple stmt) -{ - tree name; - - switch (gimple_code (stmt)) - { - case GIMPLE_ASSIGN: - name = gimple_assign_lhs (stmt); - break; - - case GIMPLE_PHI: - name = gimple_phi_result (stmt); - break; - - default: - return false; - } - - return TREE_CODE (name) == SSA_NAME - && ssa_name_has_uses_outside_loop_p (name, loop_containing_stmt (stmt)); -} - /* Returns true when STMT will be code generated in a partition of RDG different than PART and that will not be code generated as a builtin. */ @@ -1313,6 +1321,8 @@ struct gimple_opt_pass pass_loop_distrib 0, /* properties_provided */ 0, /* properties_destroyed */ 0, /* todo_flags_start */ - TODO_dump_func /* todo_flags_finish */ + TODO_dump_func + | TODO_ggc_collect + | TODO_verify_ssa /* todo_flags_finish */ } };