Possible fix for target/8812 (register allocation bug)

Michael Rendell michaelgcc@mytelescope.com
Fri Jan 17 22:16:00 GMT 2003


Hello,

  Have a (probably incorrect) fix for gcc-20030113 for the problem reported
in target/8812 and am looking for some feedback.

  The basic problem is the code generated for the line:
    long offset2MatchDest = offset2Dest - matchOffset;
is:
    movw r26,r12
    movw r24,r10
    ldd r22,Y+5
    ldd r23,Y+6
    ldd r24,Y+7
    ldd r25,Y+8
    sub r24,r22
    sbc r25,r23
    sbc r26,r24
    sbc r27,r25
the allocated registers r24..27 and r22..25 overlap so the result
is incorrect.

The rtl before optimization is
    (note 39 38 40 4 ("mx.c") 252)
    (insn 40 39 41 4 0x40180478 (set (reg/v:SI 55)
            (minus:SI (reg/v:SI 47)
                (reg/v:SI 53))) 31 {subsi3} (insn_list 38 (nil))
        (nil))

and after optimization:
    note 39 38 118 4 ("mx.c") 252)
    (insn 118 39 119 4 (nil) (set (reg/v:SI 24 r24 [55])
            (reg/v:SI 2 r2 [47])) -1 (nil)
        (nil))
    (insn 119 118 40 4 (nil) (set (reg:SI 22 r22)
            (mem:SI (plus:HI (reg/f:HI 28 r28)
                    (const_int 1 [0x1])) [15 matchOffset S4 A8])) -1 (nil)
        (nil))
    (insn 40 119 41 4 0x40180478 (set (reg/v:SI 24 r24 [55])
            (minus:SI (reg/v:SI 24 r24 [55])
                (reg:SI 22 r22))) 31 {subsi3} (insn_list 38 (nil))
        (nil))

pseudo-reg 55 is allocated to r24..27, then choose_reload_regs (of reload1.c)
is called to reload pseudo-reg 53.  It finds 53 was previously loaded
into r22..25 (in the "if (search_equiv)" code block) and checks to see
if it can re-use this with the following code:
	      if (equiv != 0
                  && ((TEST_HARD_REG_BIT (reload_reg_used_at_all, regno)
                       && ! free_for_value_p (regno, rld[r].mode,
                                              rld[r].opnum, 
rld[r].when_needed,
                                              rld[r].in, rld[r].out, r, 1))
                      || ! TEST_HARD_REG_BIT (reg_class_contents[(int) 
rld[r].cl
ass],
                                              regno)))
                equiv = 0;

The TEST_HARD_REG_BIT (reload_reg_used_at_all, regno) test returns false
because the register overlap is not taken into account: r22 is not in use,
but the value is really in r22..25, and r24..27 are in use.

The code seems to be incorrectly assuming that the value is stored in one
hard register, when it is actually in four.  The problem can be fixed by
changing the call to TEST_HARD_REG_BIT() to something that tests if
any of the hard registers are used.

The attached patch adds this code and appears to work.

Am not sure that this is the correct fix - is this situation supposed to be
handled elsewhere?  If the fix is correct, other uses of TEST_HARD_REG_BIT()
are likely to suffer from the same problem.

Michael
-------------- next part --------------
A non-text attachment was scrubbed...
Name: reload1.c.patch
Type: text/x-diff
Size: 1170 bytes
Desc: not available
URL: <http://gcc.gnu.org/pipermail/gcc-bugs/attachments/20030117/f61c09dc/attachment.bin>


More information about the Gcc-bugs mailing list