* 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 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 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 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).