------- Comment #6 from steven at gcc dot gnu dot org 2010-01-02 00:42 ------- Working with "gcc (GCC) 4.5.0 20090808 (experimental) [trunk revision 150579]", I looked at what loop-invariant.c did to the test case.
This is the "t.c.154r.loop2" RTL dump (obtained with -fdump-rtl-all-slim): ;; Function test (test) 3 NOTE_INSN_BASIC_BLOCK 6 r135:SI=unspec[const(unspec[const(unspec[0x0] 21+0x4)] 24)] 3 7 r135:SI=unspec[r135:SI,0x4,0x0] 4 8 use r135:SI 2 NOTE_INSN_FUNCTION_BEG L20: 5 NOTE_INSN_BASIC_BLOCK 9 r137:SI=unspec[`g'] 3 10 r136:SI=[r135:SI+r137:SI] REG_DEAD: r137:SI REG_EQUAL: `g' 11 r133:SI=[r136:SI+0x8] REG_EQUAL: [const(`g'+0x8)] ! Pay close attention here... 14 r138:SI=r136:SI+0x8 REG_DEAD: r136:SI REG_EQUAL: const(`g'+0x8) ! ...and here 15 r0:SI=r133:SI 16 r1:SI=r138:SI REG_DEAD: r138:SI REG_EQUAL: const(`g'+0x8) 17 r2:SI=r133:SI REG_DEAD: r133:SI 18 r0:SI=call [`func'] argc:0x0 REG_DEAD: r2:SI REG_DEAD: r1:SI 19 r134:SI=r0:SI REG_DEAD: r0:SI 21 pc={(r134:SI!=0x0)?L20:pc} REG_DEAD: r134:SI REG_BR_PROB: 0x238c 24 NOTE_INSN_BASIC_BLOCK The code has a load from the address "const(`g'+0x8)" and a load of the constant itself to a register: 11 r133:SI=[r136:SI+0x8] 14 r138:SI=r136:SI+0x8 loop-invariant.c correctly notices the constant in insn 14 can be moved and it moves the set to reg 138 from basic block 3 to basic block 2 (from the "t.c.156r.loop2_invariant" dump, all "deferring rescan insn*" lines removed): Set in insn 9 is invariant (0), cost 4, depends on Set in insn 10 is invariant (1), cost 4, depends on 0 Set in insn 14 is invariant (2), cost 4, depends on 1 Set in insn 16 is invariant (3), cost 0, depends on 2 Decided to move invariant 2 Decided to move invariant 1 Decided to move invariant 0 changing bb of uid 9 from 3 to 2 changing bb of uid 10 from 3 to 2 changing bb of uid 14 from 3 to 2 The resulting RTL dump is this: 3 NOTE_INSN_BASIC_BLOCK 6 r135:SI=unspec[const(unspec[const(unspec[0x0] 21+0x4)] 24)] 3 7 r135:SI=unspec[r135:SI,0x4,0x0] 4 8 use r135:SI 2 NOTE_INSN_FUNCTION_BEG 9 r140:SI=unspec[`g'] 3 10 r141:SI=[r135:SI+r140:SI] REG_DEAD: r137:SI REG_EQUAL: `g' 14 r142:SI=r141:SI+0x8 REG_DEAD: r136:SI REG_EQUAL: const(`g'+0x8) L20: 5 NOTE_INSN_BASIC_BLOCK 46 r137:SI=r140:SI 47 r136:SI=r141:SI 11 r133:SI=[r141:SI+0x8] ! Aha! Why not r133=[r142] here? REG_EQUAL: [const(`g'+0x8)] 48 r138:SI=r142:SI 15 r0:SI=r133:SI 16 r1:SI=r142:SI REG_DEAD: r138:SI REG_EQUAL: const(`g'+0x8) 17 r2:SI=r133:SI REG_DEAD: r133:SI 18 r0:SI=call [`func'] argc:0x0 REG_DEAD: r2:SI REG_DEAD: r1:SI 19 r134:SI=r0:SI REG_DEAD: r0:SI 21 pc={(r134:SI!=0x0)?L45:pc} REG_DEAD: r134:SI REG_BR_PROB: 0x238c L45: 44 NOTE_INSN_BASIC_BLOCK 24 NOTE_INSN_BASIC_BLOCK After loop-invariant.c, reg 142 is set to "const(`g'+0x8)" in basic block 2, before the loop: 14 r142:SI=r141:SI+0x8 But inside the loop, r142 is only used in insn 48 to set reg 138 (it was set in insn 14 before loop-invariant.c). The fact that r142="const(`g'+0x8)" is not used in insn 11: 11 r133:SI=[r141:SI+0x8] 48 r138:SI=r142:SI Somehow, loop-invariant has failed to notice or exploit the equivalence. -- steven at gcc dot gnu dot org changed: What |Removed |Added ---------------------------------------------------------------------------- Last reconfirmed|2009-06-22 16:28:19 |2010-01-02 00:42:32 date| | http://gcc.gnu.org/bugzilla/show_bug.cgi?id=39837