* Latent bug in update_equiv_regs?
@ 2009-08-20 0:01 Jeff Law
2009-08-20 0:24 ` Ian Lance Taylor
0 siblings, 1 reply; 8+ messages in thread
From: Jeff Law @ 2009-08-20 0:01 UTC (permalink / raw)
To: GCC
Somehow I can't help but think I'm missing something here...
Given:
(set (reg X) (mem Y))
(...)
(set (mem Y) (reg Z))
(...)
(use (reg X))
update_equiv_regs can set an equivalence between (reg X) and (mem Y)
which is clearly wrong as (mem Y) is set to (reg Z).
99.99% of the time this doesn't cause us any problems. However, imagine
if (reg X) is not assigned a hard register. Reload then gleefully
replaces uses of (reg X) with its equivalent memory location. Given the
RTL above that's clearly bad.
It looks like this code is supposed to wipe the problematic equivalence:
/* We only handle the case of a pseudo register being set
once, or always to the same value. */
/* ??? The mn10200 port breaks if we add equivalences for
values that need an ADDRESS_REGS register and set them
equivalent
to a MEM of a pseudo. The actual problem is in the
over-conservative
handling of INPADDR_ADDRESS / INPUT_ADDRESS / INPUT triples in
calculate_needs, but we traditionally work around this problem
here by rejecting equivalences when the destination is in
a register
that's likely spilled. This is fragile, of course, since the
preferred class of a pseudo depends on all instructions
that set
or use it. */
if (!REG_P (dest)
|| (regno = REGNO (dest)) < FIRST_PSEUDO_REGISTER
|| reg_equiv[regno].init_insns == const0_rtx
|| (CLASS_LIKELY_SPILLED_P (reg_preferred_class (regno))
&& MEM_P (src) && ! reg_equiv[regno].is_arg_equivalence))
{
/* This might be setting a SUBREG of a pseudo, a pseudo
that is
also set somewhere else to a constant. */
note_stores (set, no_equiv, NULL);
continue;
}
However, if we look at no_equiv we see the following:
/* Mark REG as having no known equivalence.
Some instructions might have been processed before and furnished
with REG_EQUIV notes for this register; these notes will have to be
removed.
STORE is the piece of RTL that does the non-constant / conflicting
assignment - a SET, CLOBBER or REG_INC note. It is currently not used,
but needs to be there because this function is called from
note_stores. */
static void
no_equiv (rtx reg, const_rtx store ATTRIBUTE_UNUSED, void *data
ATTRIBUTE_UNUSED)
{
int regno;
rtx list;
if (!REG_P (reg))
return;
[ ... ]
Thus no_equiv doesn't do anything when passed a MEM.
I haven't tried triggering this problem with the mainline sources...
What am I missing?
jeff
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: Latent bug in update_equiv_regs?
2009-08-20 0:01 Latent bug in update_equiv_regs? Jeff Law
@ 2009-08-20 0:24 ` Ian Lance Taylor
2009-08-20 1:20 ` Jeff Law
0 siblings, 1 reply; 8+ messages in thread
From: Ian Lance Taylor @ 2009-08-20 0:24 UTC (permalink / raw)
To: Jeff Law; +Cc: GCC
Jeff Law <law@redhat.com> writes:
> Somehow I can't help but think I'm missing something here...
>
> Given:
>
> (set (reg X) (mem Y))
>
> (...)
>
> (set (mem Y) (reg Z))
>
> (...)
>
> (use (reg X))
>
>
>
> update_equiv_regs can set an equivalence between (reg X) and (mem Y)
> which is clearly wrong as (mem Y) is set to (reg Z).
My understanding is that that scenario is supposed to not happen because
update_equiv_regs is only supposed to equate a register and a memory
location in the specific cases where that is OK. It's not no_equiv that
is supposed to fix this, the equivalence should only be created when it
will always be OK.
So I think you need to explain more about why the equivalence was
created.
Ian
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: Latent bug in update_equiv_regs?
2009-08-20 0:24 ` Ian Lance Taylor
@ 2009-08-20 1:20 ` Jeff Law
2009-08-20 4:48 ` Ian Lance Taylor
2009-08-20 9:48 ` Richard Guenther
0 siblings, 2 replies; 8+ messages in thread
From: Jeff Law @ 2009-08-20 1:20 UTC (permalink / raw)
To: Ian Lance Taylor; +Cc: GCC
On 08/19/09 17:46, Ian Lance Taylor wrote:
>
> My understanding is that that scenario is supposed to not happen because
> update_equiv_regs is only supposed to equate a register and a memory
> location in the specific cases where that is OK. It's not no_equiv that
> is supposed to fix this, the equivalence should only be created when it
> will always be OK.
>
> So I think you need to explain more about why the equivalence was
> created.
>
> Ian
>
You're right. This should have been rejected by validate_equiv_mem, but
isn't because the two memory references are in different alias sets.
You can see this in the mainline sources configured for
i686-pc-linux-gnu by compiling
libgomp/testsuite/libgomp.fortran/reduction1.f90 with -O3 -fopenmp
In the .expand dump we have:
(insn 242 241 243 47 j.f90:138 (set (reg:SF 74 [ D.3137 ])
(mem/s:SF (plus:SI (reg/f:SI 247 [ .omp_data_i ])
(const_int 32 [0x20])) [2 .omp_data_i_55(D)->c+0 S4
A64])) -1 (nil))
[ ... ]
(insn 247 246 248 47 j.f90:138 (set (mem/s:SF (plus:SI (reg/f:SI 247 [
.omp_data_i ])
(const_int 32 [0x20])) [13 S4 A64])
(reg:SF 351)) -1 (nil))
As you can see we've got different alias sets on the two MEMs. This
could be an expansion bug, f95 bug, or a bug in one of the SSA
optimizers. Ugh.
Thanks,
jeff
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: Latent bug in update_equiv_regs?
2009-08-20 1:20 ` Jeff Law
@ 2009-08-20 4:48 ` Ian Lance Taylor
2009-08-20 14:03 ` Jeff Law
2009-08-20 9:48 ` Richard Guenther
1 sibling, 1 reply; 8+ messages in thread
From: Ian Lance Taylor @ 2009-08-20 4:48 UTC (permalink / raw)
To: Jeff Law; +Cc: GCC
Jeff Law <law@redhat.com> writes:
> You're right. This should have been rejected by validate_equiv_mem,
> but isn't because the two memory references are in different alias
> sets.
>
> You can see this in the mainline sources configured for
> i686-pc-linux-gnu by compiling
> libgomp/testsuite/libgomp.fortran/reduction1.f90 with -O3 -fopenmp
>
> In the .expand dump we have:
>
> (insn 242 241 243 47 j.f90:138 (set (reg:SF 74 [ D.3137 ])
> (mem/s:SF (plus:SI (reg/f:SI 247 [ .omp_data_i ])
> (const_int 32 [0x20])) [2 .omp_data_i_55(D)->c+0 S4
> A64])) -1 (nil))
> [ ... ]
>
> (insn 247 246 248 47 j.f90:138 (set (mem/s:SF (plus:SI (reg/f:SI 247 [
> .omp_data_i ])
> (const_int 32 [0x20])) [13 S4 A64])
> (reg:SF 351)) -1 (nil))
>
> As you can see we've got different alias sets on the two MEMs. This
> could be an expansion bug, f95 bug, or a bug in one of the SSA
> optimizers. Ugh.
My first guess would be our current ooglie booglie: invalid stack slot
sharing in cfgexpand.c.
Ian
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: Latent bug in update_equiv_regs?
2009-08-20 1:20 ` Jeff Law
2009-08-20 4:48 ` Ian Lance Taylor
@ 2009-08-20 9:48 ` Richard Guenther
2009-08-20 14:27 ` Jeff Law
1 sibling, 1 reply; 8+ messages in thread
From: Richard Guenther @ 2009-08-20 9:48 UTC (permalink / raw)
To: Jeff Law; +Cc: Ian Lance Taylor, GCC
On Thu, Aug 20, 2009 at 2:33 AM, Jeff Law<law@redhat.com> wrote:
> On 08/19/09 17:46, Ian Lance Taylor wrote:
>>
>> My understanding is that that scenario is supposed to not happen because
>> update_equiv_regs is only supposed to equate a register and a memory
>> location in the specific cases where that is OK. It's not no_equiv that
>> is supposed to fix this, the equivalence should only be created when it
>> will always be OK.
>>
>> So I think you need to explain more about why the equivalence was
>> created.
>>
>> Ian
>>
>
> You're right. This should have been rejected by validate_equiv_mem, but
> isn't because the two memory references are in different alias sets.
>
> You can see this in the mainline sources configured for i686-pc-linux-gnu by
> compiling libgomp/testsuite/libgomp.fortran/reduction1.f90 with -O3 -fopenmp
>
> In the .expand dump we have:
>
> (insn 242 241 243 47 j.f90:138 (set (reg:SF 74 [ D.3137 ])
> (mem/s:SF (plus:SI (reg/f:SI 247 [ .omp_data_i ])
> (const_int 32 [0x20])) [2 .omp_data_i_55(D)->c+0 S4 A64])) -1
> (nil))
> [ ... ]
>
> (insn 247 246 248 47 j.f90:138 (set (mem/s:SF (plus:SI (reg/f:SI 247 [
> .omp_data_i ])
> (const_int 32 [0x20])) [13 S4 A64])
> (reg:SF 351)) -1 (nil))
>
> As you can see we've got different alias sets on the two MEMs. This could
> be an expansion bug, f95 bug, or a bug in one of the SSA optimizers. Ugh.
It looks indeed bogus. Do you have a testcase at hand?
Richard.
> Thanks,
> jeff
>
>
>
>
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: Latent bug in update_equiv_regs?
2009-08-20 4:48 ` Ian Lance Taylor
@ 2009-08-20 14:03 ` Jeff Law
0 siblings, 0 replies; 8+ messages in thread
From: Jeff Law @ 2009-08-20 14:03 UTC (permalink / raw)
To: Ian Lance Taylor; +Cc: GCC
On 08/19/09 18:48, Ian Lance Taylor wrote:
> Jeff Law<law@redhat.com> writes:
>
>
>> You're right. This should have been rejected by validate_equiv_mem,
>> but isn't because the two memory references are in different alias
>> sets.
>>
>> You can see this in the mainline sources configured for
>> i686-pc-linux-gnu by compiling
>> libgomp/testsuite/libgomp.fortran/reduction1.f90 with -O3 -fopenmp
>>
>> In the .expand dump we have:
>>
>> (insn 242 241 243 47 j.f90:138 (set (reg:SF 74 [ D.3137 ])
>> (mem/s:SF (plus:SI (reg/f:SI 247 [ .omp_data_i ])
>> (const_int 32 [0x20])) [2 .omp_data_i_55(D)->c+0 S4
>> A64])) -1 (nil))
>> [ ... ]
>>
>> (insn 247 246 248 47 j.f90:138 (set (mem/s:SF (plus:SI (reg/f:SI 247 [
>> .omp_data_i ])
>> (const_int 32 [0x20])) [13 S4 A64])
>> (reg:SF 351)) -1 (nil))
>>
>> As you can see we've got different alias sets on the two MEMs. This
>> could be an expansion bug, f95 bug, or a bug in one of the SSA
>> optimizers. Ugh.
>>
> My first guess would be our current ooglie booglie: invalid stack slot
> sharing in cfgexpand.c.
>
I don't think that's the case. I hacked up partition_stack_vars to not
share anything and still get the same failure.
Jeff
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: Latent bug in update_equiv_regs?
2009-08-20 9:48 ` Richard Guenther
@ 2009-08-20 14:27 ` Jeff Law
2009-08-20 15:11 ` Richard Guenther
0 siblings, 1 reply; 8+ messages in thread
From: Jeff Law @ 2009-08-20 14:27 UTC (permalink / raw)
To: Richard Guenther; +Cc: Ian Lance Taylor, GCC
[-- Attachment #1: Type: text/plain, Size: 930 bytes --]
On 08/20/09 02:45, Richard Guenther wrote:
>
> It looks indeed bogus. Do you have a testcase at hand?
>
Compile the attached testcase with -O3 -mopenmp on i686-pc-linux-gnu.
Find MAIN__.omp_fn.2 in the .expand dump.
Within that function, you're looking for this sequence of insns:
;; D.3137_29 = REALPART_EXPR <.omp_data_i_55(D)->c>;
(insn 242 241 0 j.f90:138 (set (reg:SF 74 [ D.3137 ])
(mem/s:SF (plus:SI (reg/f:SI 247 [ .omp_data_i ])
(const_int 32 [0x20])) [2 .omp_data_i_55(D)->c+0 S4
A64])) -1 (nil))
[ ... ]
(insn 247 246 0 j.f90:138 (set (mem/s:SF (plus:SI (reg/f:SI 247 [
.omp_data_i ])
(const_int 32 [0x20])) [13 S4 A64])
(reg:SF 351)) -1 (nil))
This doesn't cause a libgomp testsuite failure in the mainline because
(reg:SF 74) gets a hard reg and thus reload doesn't utilize the bogus
REG_EQUIV note that eventually gets added to insn 242.
Jeff
[-- Attachment #2: reduction1.f90 --]
[-- Type: text/plain, Size: 4309 bytes --]
! { dg-do run }
!$ use omp_lib
integer :: i, ia (6), n, cnt
real :: r, ra (4)
double precision :: d, da (5)
complex :: c, ca (3)
logical :: v
i = 1
ia = 2
r = 3
ra = 4
d = 5.5
da = 6.5
c = cmplx (7.5, 1.5)
ca = cmplx (8.5, -3.0)
v = .false.
cnt = -1
!$omp parallel num_threads (3) private (n) reduction (.or.:v) &
!$omp & reduction (+:i, ia, r, ra, d, da, c, ca)
!$ if (i .ne. 0 .or. any (ia .ne. 0)) v = .true.
!$ if (r .ne. 0 .or. any (ra .ne. 0)) v = .true.
!$ if (d .ne. 0 .or. any (da .ne. 0)) v = .true.
!$ if (c .ne. cmplx (0) .or. any (ca .ne. cmplx (0))) v = .true.
n = omp_get_thread_num ()
if (n .eq. 0) then
cnt = omp_get_num_threads ()
i = 4
ia(3:5) = -2
r = 5
ra(1:2) = 6.5
d = -2.5
da(2:4) = 8.5
c = cmplx (2.5, -3.5)
ca(1) = cmplx (4.5, 5)
else if (n .eq. 1) then
i = 2
ia(4:6) = 5
r = 1
ra(2:4) = -1.5
d = 8.5
da(1:3) = 2.5
c = cmplx (0.5, -3)
ca(2:3) = cmplx (-1, 6)
else
i = 1
ia = 1
r = -1
ra = -1
d = 1
da = -1
c = 1
ca = cmplx (-1, 0)
end if
!$omp end parallel
if (v) call abort
if (cnt .eq. 3) then
if (i .ne. 8 .or. any (ia .ne. (/3, 3, 1, 6, 6, 8/))) call abort
if (r .ne. 8 .or. any (ra .ne. (/9.5, 8.0, 1.5, 1.5/))) call abort
if (d .ne. 12.5 .or. any (da .ne. (/8.0, 16.5, 16.5, 14.0, 5.5/))) call abort
if (c .ne. cmplx (11.5, -5)) call abort
if (ca(1) .ne. cmplx (12, 2)) call abort
if (ca(2) .ne. cmplx (6.5, 3) .or. ca(2) .ne. ca(3)) call abort
end if
i = 1
ia = 2
r = 3
ra = 4
d = 5.5
da = 6.5
c = cmplx (7.5, 1.5)
ca = cmplx (8.5, -3.0)
v = .false.
cnt = -1
!$omp parallel num_threads (3) private (n) reduction (.or.:v) &
!$omp & reduction (-:i, ia, r, ra, d, da, c, ca)
!$ if (i .ne. 0 .or. any (ia .ne. 0)) v = .true.
!$ if (r .ne. 0 .or. any (ra .ne. 0)) v = .true.
!$ if (d .ne. 0 .or. any (da .ne. 0)) v = .true.
!$ if (c .ne. cmplx (0) .or. any (ca .ne. cmplx (0))) v = .true.
n = omp_get_thread_num ()
if (n .eq. 0) then
cnt = omp_get_num_threads ()
i = 4
ia(3:5) = -2
r = 5
ra(1:2) = 6.5
d = -2.5
da(2:4) = 8.5
c = cmplx (2.5, -3.5)
ca(1) = cmplx (4.5, 5)
else if (n .eq. 1) then
i = 2
ia(4:6) = 5
r = 1
ra(2:4) = -1.5
d = 8.5
da(1:3) = 2.5
c = cmplx (0.5, -3)
ca(2:3) = cmplx (-1, 6)
else
i = 1
ia = 1
r = -1
ra = -1
d = 1
da = -1
c = 1
ca = cmplx (-1, 0)
end if
!$omp end parallel
if (v) call abort
if (cnt .eq. 3) then
if (i .ne. 8 .or. any (ia .ne. (/3, 3, 1, 6, 6, 8/))) call abort
if (r .ne. 8 .or. any (ra .ne. (/9.5, 8.0, 1.5, 1.5/))) call abort
if (d .ne. 12.5 .or. any (da .ne. (/8.0, 16.5, 16.5, 14.0, 5.5/))) call abort
if (c .ne. cmplx (11.5, -5)) call abort
if (ca(1) .ne. cmplx (12, 2)) call abort
if (ca(2) .ne. cmplx (6.5, 3) .or. ca(2) .ne. ca(3)) call abort
end if
i = 1
ia = 2
r = 4
ra = 8
d = 16
da = 32
c = 2
ca = cmplx (0, 2)
v = .false.
cnt = -1
!$omp parallel num_threads (3) private (n) reduction (.or.:v) &
!$omp & reduction (*:i, ia, r, ra, d, da, c, ca)
!$ if (i .ne. 1 .or. any (ia .ne. 1)) v = .true.
!$ if (r .ne. 1 .or. any (ra .ne. 1)) v = .true.
!$ if (d .ne. 1 .or. any (da .ne. 1)) v = .true.
!$ if (c .ne. cmplx (1) .or. any (ca .ne. cmplx (1))) v = .true.
n = omp_get_thread_num ()
if (n .eq. 0) then
cnt = omp_get_num_threads ()
i = 3
ia(3:5) = 2
r = 0.5
ra(1:2) = 2
d = -1
da(2:4) = -2
c = 2.5
ca(1) = cmplx (-5, 0)
else if (n .eq. 1) then
i = 2
ia(4:6) = -2
r = 8
ra(2:4) = -0.5
da(1:3) = -1
c = -3
ca(2:3) = cmplx (0, -1)
else
ia = 2
r = 0.5
ra = 0.25
d = 2.5
da = -1
c = cmplx (0, -1)
ca = cmplx (-1, 0)
end if
!$omp end parallel
if (v) call abort
if (cnt .eq. 3) then
if (i .ne. 6 .or. any (ia .ne. (/4, 4, 8, -16, -16, -8/))) call abort
if (r .ne. 8 .or. any (ra .ne. (/4., -2., -1., -1./))) call abort
if (d .ne. -40 .or. any (da .ne. (/32., -64., -64., 64., -32./))) call abort
if (c .ne. cmplx (0, 15)) call abort
if (ca(1) .ne. cmplx (0, 10)) call abort
if (ca(2) .ne. cmplx (-2, 0) .or. ca(2) .ne. ca(3)) call abort
end if
end
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: Latent bug in update_equiv_regs?
2009-08-20 14:27 ` Jeff Law
@ 2009-08-20 15:11 ` Richard Guenther
0 siblings, 0 replies; 8+ messages in thread
From: Richard Guenther @ 2009-08-20 15:11 UTC (permalink / raw)
To: Jeff Law; +Cc: Ian Lance Taylor, GCC
On Thu, Aug 20, 2009 at 3:37 PM, Jeff Law<law@redhat.com> wrote:
> On 08/20/09 02:45, Richard Guenther wrote:
>>
>> It looks indeed bogus. Do you have a testcase at hand?
>>
>
> Compile the attached testcase with -O3 -mopenmp on i686-pc-linux-gnu. Find
> MAIN__.omp_fn.2 in the .expand dump.
>
> Within that function, you're looking for this sequence of insns:
>
>
>
> ;; D.3137_29 = REALPART_EXPR <.omp_data_i_55(D)->c>;
>
> (insn 242 241 0 j.f90:138 (set (reg:SF 74 [ D.3137 ])
> (mem/s:SF (plus:SI (reg/f:SI 247 [ .omp_data_i ])
> (const_int 32 [0x20])) [2 .omp_data_i_55(D)->c+0 S4 A64])) -1
> (nil))
>
> [ ... ]
>
> (insn 247 246 0 j.f90:138 (set (mem/s:SF (plus:SI (reg/f:SI 247 [
> .omp_data_i ])
> (const_int 32 [0x20])) [13 S4 A64])
> (reg:SF 351)) -1 (nil))
>
>
> This doesn't cause a libgomp testsuite failure in the mainline because
> (reg:SF 74) gets a hard reg and thus reload doesn't utilize the bogus
> REG_EQUIV note that eventually gets added to insn 242.
I suppose we are using the complex type alias-set at one place and
the component at another. My suggestion would be to handle
complex types like we do array and vector tyoes in get_alias_set,
thus assign the component alias set to the complex types.
Richard.
> Jeff
>
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2009-08-20 14:03 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-08-20 0:01 Latent bug in update_equiv_regs? Jeff Law
2009-08-20 0:24 ` Ian Lance Taylor
2009-08-20 1:20 ` Jeff Law
2009-08-20 4:48 ` Ian Lance Taylor
2009-08-20 14:03 ` Jeff Law
2009-08-20 9:48 ` Richard Guenther
2009-08-20 14:27 ` Jeff Law
2009-08-20 15:11 ` Richard Guenther
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).