On 06/07/2013 12:25 PM, Jakub Jelinek wrote:
> This PR is about DATA_ALIGNMENT macro increasing alignment of some decls
> for optimization purposes beyond ABI mandated levels.  It is fine to emit
> the vars aligned as much as we want for optimization purposes, but if we
> can't be sure that references to that decl bind to the definition we
> increased the alignment on (e.g. common variables, or -fpic code without
> hidden visibility, weak vars etc.), we can't assume that alignment.

When the linker merges common blocks, it chooses both maximum size and maximum
alignment.  Thus for any common block for which we can prove the block must
reside in the module (any executable, or hidden common in shared object), we
can go ahead and use the increased alignment.

It's only in shared objects with non-hidden common blocks that we have a
problem, since in that case we may resolve the common block via copy reloc to a
memory block in another module.

So while decl_binds_to_current_def_p is a good starting point, I think we can
do a little better with common blocks.  Which ought to take care of those
vectorization regressions you mention.

> @@ -966,8 +966,12 @@ align_variable (tree decl, bool dont_out
>        align = MAX_OFILE_ALIGNMENT;
>      }
>  
> -  /* On some machines, it is good to increase alignment sometimes.  */
> -  if (! DECL_USER_ALIGN (decl))
> +  /* On some machines, it is good to increase alignment sometimes.
> +     But as DECL_ALIGN is used both for actually emitting the variable
> +     and for code accessing the variable as guaranteed alignment, we
> +     can only increase the alignment if it is a performance optimization
> +     if the references to it must bind to the current definition.  */
> +  if (! DECL_USER_ALIGN (decl) && decl_binds_to_current_def_p (decl))
>      {
>  #ifdef DATA_ALIGNMENT
>        unsigned int data_align = DATA_ALIGNMENT (TREE_TYPE (decl), align);
> @@ -988,12 +992,69 @@ align_variable (tree decl, bool dont_out
>       }
>  #endif
>      }
> +#ifdef DATA_ABI_ALIGNMENT
> +  else if (! DECL_USER_ALIGN (decl))
> +    {
> +      unsigned int data_align = DATA_ABI_ALIGNMENT (TREE_TYPE (decl), align);
> +      /* For backwards compatibility, don't assume the ABI alignment for
> +      TLS variables.  */
> +      if (! DECL_THREAD_LOCAL_P (decl) || data_align <= BITS_PER_WORD)
> +     align = data_align;
> +    }
> +#endif

This structure would seem to do the wrong thing if DATA_ABI_ALIGNMENT is
defined, but DATA_ALIGNMENT isn't.  And while I realize you documented it, I
don't like the restriction that D_A /must/ return something larger than D_A_A.
 All that means is that in complex cases D_A will have to call D_A_A itself.

I would think that it would be better to rearrange as

  if (!D_U_A)
    {
  #ifdef D_A_A
      align = ...
  #endif
  #ifdef D_A
      if (d_b_t_c_d_p)
        align = ...
  #endif
    }

Why the special case for TLS?  If we really want that special case surely that
test should go into D_A_A itself, and not here in generic code.

> Bootstrapped/regtested on x86_64-linux and i686-linux.  No idea about other
> targets, I've kept them all using DATA_ALIGNMENT, which is considered
> optimization increase only now, if there is some ABI mandated alignment
> increase on other targets, that should be done in DATA_ABI_ALIGNMENT as
> well as DATA_ALIGNMENT.

I've had a brief look over the instances of D_A within the tree atm.  Most of
them carry the cut-n-paste comment "for the same reasons".  These I believe
never intended an ABI change, and were really only interested in optimization.

But these I think require a good hard look to see if they really intended an
ABI alignment:

c6x     comment explicitly mentions abi
cris    compiler options for alignment -- systemwide or local?
mmix    comment mentions GETA instruction
s390    comment mentions LARL instruction
rs6000  SPE and E500 portion of the alignment non-optional?

Relevant port maintainers CCed.


r~

Reply via email to