------- Comment #7 from matz at gcc dot gnu dot org 2008-02-12 15:36 ------- The immediate problem is that the solution iterates between two orders. On my machine (i686) it all happen around basic block 231. The even iterations (after 128 iterations) the var-track info for bb 231 starts with:
Basic block 231: IN: Stack adjustment: 0 Reg 0: i+0 i_cycle+0 Reg 1: i+0 the odd iterations it's: Basic block 231: IN: Stack adjustment: 0 Reg 0: i_cycle+0 i+0 Reg 1: i+0 so the problem is in the hardreg->expr association. One time hardreg 0 contains i_cycle and i, the other time it contains i and i_cycle. That's of course completely equivalent, but leads to subtle differences in the the OUT set (for some yet unknown reason, I think probably _there_ the actual problem lies). The cause for these different IN sets is that the reg0 info isn't the join (i.e. intersection) but the union of information from the predecessors. Predecessor A has "reg0: i" in OUT, predecessor B has "reg0: i_cycle" in OUT. (Note: reg0 never contains both i and i_cycle in any OUT set). The code in vt_find_locations() does a _union_ of the information of the predecessors, i.e. it joins not only the common parts of the info but also the differences. The joining happens via linked lists, hence it is inherently dependend on the order the elements are seen. This and the problem that equivalent but differently ordered INs lead to different OUT sets, together with the fact that 231 is a loop basic block (i.e. feeds itself), leads to the oscillation. The fix I had in mind is to perhaps stabilize all this by not unioning but intersecting the predecessors OUT sets. This actually makes more sense, as surely if reg0 contain "i" at the end on block A, and "i_cycle" at the end of block B, it clearly has indeterminate value at the join point of both blocks, except if "i" and "i_cycle" somehow are equivalent. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=35065