Here is the updated patch, which follow UD chain to determine whether iv.base is defined by __gcovx.xxx[] var. It is a lot simpler than adding a tree bit.
regression test and previously failed benchmark in piii mode is ok. Other test is going on. 2014-02-10 Wei Mi <w...@google.com> * tree-ssa-loop-ivopts.c (defined_by_gcov_counter): New. (contains_abnormal_ssa_name_p): Add defined_by_gcov_counter check for ssa name. * testsuite/gcc.dg/profile-generate-4.c: New. Index: tree-ssa-loop-ivopts.c =================================================================== --- tree-ssa-loop-ivopts.c (revision 207019) +++ tree-ssa-loop-ivopts.c (working copy) @@ -705,6 +705,68 @@ idx_contains_abnormal_ssa_name_p (tree b return !abnormal_ssa_name_p (*index); } +/* Return true if the use is defined by a gcov counter var. + It is used to check if an iv candidate is generated for + profiling. For profile generated ssa name, we should not + use it as IV because gcov counter may have data-race for + multithread program, it could involve tricky bug to use + such ssa var in IVOPT. + + To limit patterns to be checked, we list the possible cases + here: + Before PRE, the ssa name used to set __gcov counter is as + follows: + for () { + PROF_edge_counter_1 = __gcov.foo[i]; + PROF_edge_counter_2 = PROF_edge_counter_1 + 1; + __gcov.foo[i] = PROF_edge_counter_2; + } + If PRE works, the loop may be transformed to: + pretmp_1 = __gcov.foo[i]; + for () { + prephitmp_1 = PHI (PROF_edge_counter_2, pretmp_1); + PROF_edge_counter_1 = prephitmp_1; + PROF_edge_counter_2 = PROF_edge_counter_1 + 1; + __gcov.foo[i] = PROF_edge_counter_2; + } + So there are two cases: + case1: If PRE doesn't work, PROF_edge_counter_1 and PROF_edge_counter_2 + are neither induction variables candidates. We don't have to worry + about this case. + case2: If PRE works, the iv candidate base of PROF_edge_counter_1 and + PROF_edge_counter_2 are pretmp_1 or pretmp_1 + 1. pretmp_1 is defined + by __gcov var. + + So this func only has to check case2. For a ssa name which is an iv + candidate, check its base USE and see if it is defined by __gcov var. + Returning true means the ssa name is generated for profiling. */ + +bool +defined_by_gcov_counter (tree use) +{ + gimple stmt; + tree rhs, decl; + const char *name; + + stmt = SSA_NAME_DEF_STMT (use); + if (!is_gimple_assign (stmt)) + return false; + + rhs = gimple_assign_rhs1 (stmt); + if (TREE_CODE (rhs) != ARRAY_REF) + return false; + + decl = TREE_OPERAND (rhs, 0); + if (TREE_CODE (decl) != VAR_DECL) + return false; + + name = IDENTIFIER_POINTER (DECL_NAME (decl)); + if (strncmp (name, "__gcov", 6)) + return false; + + return true; +} + /* Returns true if EXPR contains a ssa name that occurs in an abnormal phi node. */ @@ -721,7 +783,8 @@ contains_abnormal_ssa_name_p (tree expr) codeclass = TREE_CODE_CLASS (code); if (code == SSA_NAME) - return SSA_NAME_OCCURS_IN_ABNORMAL_PHI (expr) != 0; + return SSA_NAME_OCCURS_IN_ABNORMAL_PHI (expr) != 0 + || defined_by_gcov_counter (expr); if (code == INTEGER_CST || is_gimple_min_invariant (expr)) Index: testsuite/gcc.dg/profile-generate-4.c =================================================================== --- testsuite/gcc.dg/profile-generate-4.c (revision 0) +++ testsuite/gcc.dg/profile-generate-4.c (revision 0) @@ -0,0 +1,21 @@ +/* { dg-do compile { target { i?86-*-* x86_64-*-* } } } */ +/* { dg-options "-O2 -fprofile-generate -fno-tree-loop-im -fdump-tree-ivopts-details-blocks" } */ + +/* Because gcov counter related var has data race for multithread program, + compiler should prevent them from affecting program correctness. So + PROF_edge_counter variable should not be used as induction variable, or + else IVOPT may use such variable to compute loop boundary. */ + +void *ptr; +int N; + +void foo(void *t) { + int i; + for (i = 0; i < N; i++) { + t = *(void **)t; + } + ptr = t; +} + +/* { dg-final { scan-tree-dump-times "ssa name PROF_edge_counter" 0 "ivopts"} } */ +/* { dg-final { cleanup-tree-dump "ivopts" } } */