This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

giv combination causes incorrect code



Compile the attached testcase for a mips-sgi-irix6.5 target with -O2.

In the .cse dump we have:

(note 18 60 24 "" NOTE_INSN_LOOP_BEG)

[ ... ]

(insn 28 26 30 (set (reg/v:SI 81)
        (plus:SI (reg/v:SI 81)
            (const_int -4 [0xfffffffc]))) 3 {addsi3_internal} (nil)
    (nil))

(insn 30 28 33 (set (mem:SI (reg/v:SI 81) 2)
        (reg/v:SI 82)) 236 {movsi_internal2} (nil)
    (nil))

(insn 33 30 35 (set (reg/v:SI 81)
        (plus:SI (reg/v:SI 81)
            (const_int -4 [0xfffffffc]))) 3 {addsi3_internal} (nil)
    (nil))

(insn 35 33 38 (set (mem:SI (reg/v:SI 81) 2)
        (reg/v:SI 82)) 236 {movsi_internal2} (nil)
    (nil))

(insn 38 35 40 (set (reg/v:SI 81)
        (plus:SI (reg/v:SI 81)
            (const_int -4 [0xfffffffc]))) 3 {addsi3_internal} (nil)
    (nil))

(insn 40 38 43 (set (mem:SI (reg/v:SI 81) 2)
        (reg/v:SI 82)) 236 {movsi_internal2} (nil)
    (nil))

(insn 43 40 45 (set (reg/v:SI 81)
        (plus:SI (reg/v:SI 81)
            (const_int -4 [0xfffffffc]))) 3 {addsi3_internal} (nil)
    (nil))

(insn 45 43 47 (set (mem:SI (reg/v:SI 81) 2)
        (reg/v:SI 82)) 236 {movsi_internal2} (nil)
    (nil))

(note 47 45 63 "" NOTE_INSN_LOOP_CONT)

(note 63 47 21 "" NOTE_INSN_LOOP_VTOP)

[ ... ]

So, from the .cse dump you can see that we're setting 4 consecutive memory
locations to the value that is in reg 82.


We end up turning the first 3 increments of 81 into givs which is find
and leaves us with something like this:

(note 18 60 24 "" NOTE_INSN_LOOP_BEG)
[ ... ]

(insn 28 26 30 (set (reg:SI 85)
        (plus:SI (reg/v:SI 81)
            (const_int -4 [0xfffffffc]))) 3 {addsi3_internal} (nil)
    (nil))

(insn 30 28 33 (set (mem:SI (reg:SI 85) 2)
        (reg/v:SI 82)) 236 {movsi_internal2} (nil)
    (nil))

(insn 33 30 35 (set (reg:SI 86)
        (plus:SI (reg/v:SI 81)
            (const_int -8 [0xfffffff8]))) 3 {addsi3_internal} (nil)
    (nil))

(insn 35 33 38 (set (mem:SI (reg:SI 86) 2)
        (reg/v:SI 82)) 236 {movsi_internal2} (nil)
    (nil))

(insn 38 35 40 (set (reg:SI 87)
        (plus:SI (reg/v:SI 81)
            (const_int -12 [0xfffffff4]))) 3 {addsi3_internal} (nil)
    (nil))


(insn 40 38 43 (set (mem:SI (reg:SI 87) 2)
        (reg/v:SI 82)) 236 {movsi_internal2} (nil)
    (nil))

(insn 43 40 45 (set (reg/v:SI 81)
        (plus:SI (reg/v:SI 81)
            (const_int -16 [0xfffffff0]))) 3 {addsi3_internal} (nil)
    (nil))

(insn 45 43 47 (set (mem:SI (reg/v:SI 81) 2)
        (reg/v:SI 82)) -1 (nil)
    (nil))

(note 47 45 63 "" NOTE_INSN_LOOP_CONT)


The RTL still looks sane at this point.  We still set 4 consecutive memory
locations to the value held in (reg:SI 82).


Then giv combination or some related code in loop goes nuts and tries to
derive the memory address in insn 45 using the giv in insn 33 without taking
into consideration that (reg:SI 81) changed between those two insns.  We
eventuall end up with something like this:

(insn 78 60 18 (set (reg:SI 91)
        (plus:SI (reg/v:SI 81)
            (const_int -8 [0xfffffff8]))) -1 (nil)
    (nil))

(note 18 78 24 "" NOTE_INSN_LOOP_BEG)

(insn 69 26 30 (set (reg:SI 89)
        (plus:SI (reg/v:SI 81)
            (const_int -4 [0xfffffffc]))) -1 (nil)
    (nil))

(insn 30 69 33 (set (mem:SI (plus:SI (reg:SI 91)
                (const_int 4 [0x4])) 2)
        (reg/v:SI 82)) -1 (nil)
    (nil))

(insn 33 30 81 (set (reg:SI 88)
        (plus:SI (reg:SI 89)
            (const_int -4 [0xfffffffc]))) -1 (nil)
    (nil))

(insn 81 33 35 (set (reg:SI 88)
        (reg:SI 91)) -1 (nil)
    (nil))

(insn 35 81 38 (set (mem:SI (reg:SI 91) 2)
        (reg/v:SI 82)) -1 (nil)
    (nil))

(insn 38 35 40 (set (reg:SI 87)
        (plus:SI (reg/v:SI 81)
            (const_int -12 [0xfffffff4]))) -1 (nil)
    (nil))

(insn 40 38 75 (set (mem:SI (plus:SI (reg:SI 91)
                (const_int -4 [0xfffffffc])) 2)
        (reg/v:SI 82)) -1 (nil)
    (nil))

(insn 75 40 43 (set (reg:SI 91)
        (plus:SI (reg:SI 91)
            (const_int -16 [0xfffffff0]))) -1 (nil)
    (nil))

(insn 43 75 45 (set (reg/v:SI 81)
        (plus:SI (reg/v:SI 81)
            (const_int -16 [0xfffffff0]))) -1 (nil)
    (nil))

(insn 45 43 47 (set (mem:SI (plus:SI (reg:SI 91)
                (const_int 24 [0x18])) 2)
        (reg/v:SI 82)) -1 (nil)
    (nil))

(note 47 45 63 "" NOTE_INSN_LOOP_CONT)


Note carefully the address in insn 45.  It's totally bogus.  The right value
would be (plus:SI (reg:SI 91) (const_int 8))

giv at 45 combined with giv at 33
[ ... ]
giv at 45 recombined with giv at 33 as (plus:SI (reg:SI 88)
    (const_int 24 [0x18]))
giv at 45 reduced to (plus:SI (reg:SI 91)
    (const_int 24 [0x18]))



Here's the testcase.



void foo (int *BM_tab, int j)
{
  int *BM_tab_base;

  BM_tab_base = BM_tab;
  BM_tab += 0400;
  while (BM_tab_base != BM_tab)
    {
      *--BM_tab = j;
      *--BM_tab = j;
      *--BM_tab = j;
      *--BM_tab = j;
    }
}




Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]