On 05 Jan 2007 07:18:47 -0800, Ian Lance Taylor <[EMAIL PROTECTED]> wrote:
Andrew Haley <[EMAIL PROTECTED]> writes:> It appears that memory references to arrays aren't being hoisted out > of loops: in this test case, gcc 3.4 doesn't touch memory at all in > the loop, but 4.3pre (and 4.2, etc) does. > > Here's the test case: > > void foo(int *a) > { int i; > for (i = 0; i < 1000000; i++) > a[0] += a[1]; > } At the tree level, the problem is that the assignment to a[0] is seen as aliasing a[1]. This causes the use of a[1] to look like a USE of an SMT, and the assignment to a[0] to look like a DEF of the same SMT. So in tree-ssa-loop-im.c the statements look like they are not loop invariant. I don't know we can do better with our current aliasing representation. Unless we decide to do some sort of array SRA.
Well, we don't treat it like an array because it doesn't look like one. You have a couple options here: If you change create_overlap_variables in tree-ssa-alias.c to do SFT's for small arrays, the testcase should just work. Alternatively, you could teach tree PRE's load motion to go past using just the VUSE/VDEF's to determine where loads are killed, and it will do this for you. That code is being reworked right now as part of some work i'm doing on a branch (gcc-pre-vn branch, it's just a dump of my VN rewrite tree, which is why it's not in svn.html), so if you wanted to take this approach, let me know.
Or perhaps we could make the loop invariant motion pass more complicated: when it sees a use or assignment of a memory tag, it could explicitly check all the other uses/assignments in the loop and see if they conflict. I don't really know how often this would pay off, though.
Array accesses are one of the only places we get seriously confused very easily. There are places where load motion at the tree level is currently more conservative than it needs to be, but the amount of loads we fail to move as a result is nowhere near as high (percentage wise) as those due to array accesses.
