There are two basic errors in the computation - the first is when min_cost is never adjusted it remains at UINT_MAX (happens when all PHI arguments are not defined in any loop). Second is if the PHI argument is not defined in the same loop as the PHI - then we accumulate the cost of already invariant stmts (inconsistently with the LIM cost modelling).
Bootstrap and regtest running on x86_64-unknown-linux-gnu. Richard. 2014-06-16 Richard Biener <rguent...@suse.de> * tree-ssa-loop-im.c (determine_max_movement): Adjust cost of PHI node moving. * gcc.dg/tree-ssa/ssa-lim-12.c: New testcase. Index: gcc/tree-ssa-loop-im.c =================================================================== *** gcc/tree-ssa-loop-im.c (revision 211698) --- gcc/tree-ssa-loop-im.c (working copy) *************** determine_max_movement (gimple stmt, boo *** 729,742 **** } if (!add_dependency (val, lim_data, loop, false)) return false; ! def_data = get_lim_data (SSA_NAME_DEF_STMT (val)); ! if (def_data) { ! min_cost = MIN (min_cost, def_data->cost); ! total_cost += def_data->cost; } } lim_data->cost += min_cost; if (gimple_phi_num_args (stmt) > 1) --- 732,752 ---- } if (!add_dependency (val, lim_data, loop, false)) return false; ! ! gimple def_stmt = SSA_NAME_DEF_STMT (val); ! if (gimple_bb (def_stmt) ! && gimple_bb (def_stmt)->loop_father == loop) { ! def_data = get_lim_data (def_stmt); ! if (def_data) ! { ! min_cost = MIN (min_cost, def_data->cost); ! total_cost += def_data->cost; ! } } } + min_cost = MIN (min_cost, total_cost); lim_data->cost += min_cost; if (gimple_phi_num_args (stmt) > 1) Index: gcc/testsuite/gcc.dg/tree-ssa/ssa-lim-12.c =================================================================== *** gcc/testsuite/gcc.dg/tree-ssa/ssa-lim-12.c (revision 0) --- gcc/testsuite/gcc.dg/tree-ssa/ssa-lim-12.c (working copy) *************** *** 0 **** --- 1,27 ---- + /* { dg-do compile } */ + /* { dg-options "-O -fdump-tree-lim1" } */ + + int a[1024]; + + void foo (int x, int z) + { + int i; + int y = -x; + for (i = 0; i < 1024; ++i) + a[i] = x ? y : z; + } + + void bar (int x, int z) + { + int j; + for (j = 0; j < 1024; ++j) + { + int i; + int y = -j + z; + for (i = 0; i < 1024; ++i) + a[i] = x ? y : j; + } + } + + /* { dg-final { scan-tree-dump-times "!= 0 ? " 2 "lim1" } } */ + /* { dg-final { cleanup-tree-dump "lim1" } } */