This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: Alias analysis - does base_alias_check still work ?
- From: Daniel Berlin <dberlin at dberlin dot org>
- To: Toon Moene <toon at moene dot indiv dot nluug dot nl>
- Cc: gcc at gcc dot gnu dot org
- Date: Fri, 19 Jul 2002 10:51:59 -0400 (EDT)
- Subject: Re: Alias analysis - does base_alias_check still work ?
On Fri, 19 Jul 2002, Toon Moene wrote:
> I wrote:
>
> > f/com.c contains the following note, preceding the definition of
> >
> > #define LANG_HOOKS_GET_ALIAS_SET hook_get_alias_set_0
> >
> > /* We do not wish to use alias-set based aliasing at all. Used in the
> > extreme (every object with its own set, with equivalences recorded)
> > it
> > might be helpful, but there are problems when it comes to inlining.
> > We
> > get on ok with flag_argument_noalias, and alias-set aliasing does
> > currently limit how stack slots can be reused, which is a lose. */
> >
> > I do not know if all the facts mentioned here still actually hold, but I
> > do have strong doubts that base_alias_check in alias.c still does its
> > duty.
> >
> > Consider the following Fortran source:
> >
> > SUBROUTINE SIMPLE(A, B)
> > B = 3.0
> > A = 2.0
> > B = A*B
> > END
> >
> > one would assume that alias analysis at least once should check that the
> > assignment to A in line 3 doesn't change the value of B set in line 2,
> > which, with
> >
> > flag_argument_noalias > 1
> >
> > [arguments don't alias] in effect, would be the case.
> >
> > However, according to my experiments with setting breakpoints in
> > base_alias_check, it never passes that point.
>
> Sigh, that's just because it doesn't need to. The code generated looks
> like this:
>
> ...
> movl $0x40400000, (%edx) ! B=3.0
> movl $0x40000000, (%eax) ! A=2.0
> flds (%edx) ! put B on stack
> ...
>
> which, of course, gets neatly around the problem of whether the store into
> A would change B.
>
> Now for the real issue. To have register renaming be really effective,
> alias analysis has to work well.
>
> Take the following example:
>
> subroutine saxpy(n,sa,sx,sy)
> real sx(n),sy(n),sa
> integer i,n
> do i = 1,n
> sy(i) = sy(i) + sa*sx(i)
> enddo
> end
>
> If we compile this with -O2 -march=pentium4 -mfpmath=sse -funroll-loops
> -frename-registers, we get for the unrolled loop:
>
> .L6:
> movaps %xmm1, %xmm7
> movaps %xmm1, %xmm6
> movaps %xmm1, %xmm5
> mulss (%edx), %xmm7
> movaps %xmm1, %xmm4
> addss (%eax), %xmm7
> movss %xmm7, (%eax)
> mulss 4(%edx), %xmm6
> addss 4(%eax), %xmm6
> movss %xmm6, 4(%eax)
> mulss 8(%edx), %xmm5
> addss 8(%eax), %xmm5
> movss %xmm5, 8(%eax)
> mulss 12(%edx), %xmm4
> addl $16, %edx
> addss 12(%eax), %xmm4
> movss %xmm4, 12(%eax)
> addl $16, %eax
> subl $4, %ecx
> jns .L6
>
> Obviously, register renaming has done its work, but the (re-)scheduling of
> instructions leaves something to be desired. After much gdb'ing in
> sched-deps.c and alias.c I believe to have found the cause: the
> rescheduling of this loop after register renaming is run after register
> allocation (hey, no surprise :-). However, alias analysis is really
> careful about assumptions on the contents of these hard registers, so
> almost no instruction gets moved around.
>
> OK, but what if we allow instruction scheduling before register allocation
> (that would only be beneficial if the floating point (pseudo) registers
> have different "names" already, but fortunately, they do), using
> -fschedule-insns instead of -frename-registers:
>
> .L6:
> movaps %xmm4, %xmm0
> movaps %xmm4, %xmm1
> movaps %xmm4, %xmm2
> movaps %xmm4, %xmm3
> mulss (%edx), %xmm0
> mulss 4(%edx), %xmm1
> mulss 8(%edx), %xmm2
> mulss 12(%edx), %xmm3
> addss (%eax), %xmm0
> addss 4(%eax), %xmm1
> addss 8(%eax), %xmm2
> addss 12(%eax), %xmm3
> movss %xmm0, (%eax)
> movss %xmm1, 4(%eax)
> movss %xmm2, 8(%eax)
> movss %xmm3, 12(%eax)
> addl $16, %edx
> addl $16, %eax
> subl $4, %ecx
> jns .L6
>
> Bingo ! That's a lot better !
>
> Which begs the question: Is there a reason -fschedule-insns isn't on by
> default when using -O2 ?
Err, it is.
if (optimize >= 2)
{
flag_optimize_sibling_calls = 1;
flag_cse_follow_jumps = 1;
flag_cse_skip_blocks = 1;
flag_gcse = 1;
flag_expensive_optimizations = 1;
flag_strength_reduce = 1;
flag_rerun_cse_after_loop = 1;
flag_rerun_loop_opt = 1;
flag_caller_saves = 1;
flag_force_mem = 1;
flag_peephole2 = 1;
#ifdef INSN_SCHEDULING
flag_schedule_insns = 1;
flag_schedule_insns_after_reload = 1;
#endif
flag_regmove = 1;
flag_strict_aliasing = 1;
flag_delete_null_pointer_checks = 1;
flag_reorder_blocks = 1;
flag_reorder_functions = 1;
}
>
> Cheers,
>
>