This is the mail archive of the gcc@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]
Other format: [Raw text]

Load hoisting bug


	We have not had enough fun with loop optimizations lately, so I
found one...

	The divconst-3.c regression on AIX which appeared at the beginning
of November is due to GCC miscompiling itself.  The miscompilation is
caused by a loop optimization which was not safe.

Prior to loop optimization:

(note 47 177 53 NOTE_INSN_LOOP_BEG)

(insn 68 66 69 (set (reg:SI 4 r4)
        (subreg:SI (reg/v:DI 119) 4)) 289 {*movsi_internal1} (nil)
    (nil))

(insn 69 68 71 (parallel[ 
            (set (reg:DI 3 r3)
                (mult:DI (sign_extend:DI (reg:SI 3 r3))
                    (sign_extend:DI (reg:SI 4 r4))))
            (clobber (scratch:SI))
            (clobber (reg:SI 0 r0))
        ] ) 76 {mull_call} (nil)
    (nil))

After loop optimization:

Insn 68: regno 4 (life 1), savings 1  moved to 178

(insn 178 177 179 (set (reg:SI 4 r4)
        (subreg:SI (reg/v:DI 119) 4)) -1 (nil)
    (nil))

(note 47 205 202 NOTE_INSN_LOOP_BEG)

(insn 69 66 71 (parallel[ 
            (set (reg:DI 3 r3)
                (mult:DI (sign_extend:DI (reg:SI 3 r3))
                    (sign_extend:DI (reg:SI 4 r4))))
            (clobber (scratch:SI))
            (clobber (reg:SI 0 r0))
        ] ) -1 (nil)
    (nil))


scan_loop() decides that it can move the SET of r4 out of the loop,
placing it on the move_movables list.

	The register only is used within the loop (prior to register
allocation).  loop_invariant_p() returns true which seems incorrect to me.
The value is invariant, but the register is not invariant.

(set (reg:DI 3) ...) uses the register pair r3 and r4 on a 32-bit target!
The instruction clobbers r3, so it needs to be restored on each iteration
(as gcc-3.0 correctly performed), but the mainline now is hoisting the
load out of the loop although the register is modified in the loop.  The
loop information array has r4 listed as set_in_loop=1.

	Is GCC getting confused by the use of a hard register?  Is GCC
getting confused because of DImode?  The pattern could explicitly clobber
r4, but GCC should know that DImode requires a pair of GPRs.

	I still am trying to figure out the origin of the problem.  Any
guidance would be appreciated.

Thanks, David


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