[RFC PATCH 3/3] Misaligned MEM_REF reads

Richard Guenther rguenther@suse.de
Tue Feb 28 10:49:00 GMT 2012


On Tue, 28 Feb 2012, Martin Jambor wrote:

> Hi,
> 
> this patch fixes misaligned reads through MEM_REFs such as the one in
> the testcase which currently fails on both sparc64 and ia64 (again,
> the array and the loop are there to cross ia64 cache line and fail
> there too).  The patch has to be applied last in the series so that
> the current LHS expansion does not attempt to use the new code.
> 
> The mechanism is again very similar, except that we call
> extract_bit_field instead now.  We do not need to care about the
> mem_ref_refers_to_non_mem_p case because that is already handled at
> this stage.  On the other hand, messing with complex types actually
> breaks currently working testcases such as the one from the previous
> patch (I have not really fully investigated what goes on so far but it
> genuinely seems to work) so again I punt for complex modes.
> 
> There are two more movmisalign_optab generations in this function.
> There is the TARGET_MEM_REF case which I intend to piggy-back on in
> the same way like MEM_REF is handled in this patch once it leaves the
> RFC stage.  Finally, movmisalign_optab is also generated in
> VIEW_CONVERT_EXPR case but as far as I understand the code, misaligned
> loads are already handled there (only perhaps we should use
> SLOW_UNALIGNED_ACCESS instead of STRICT_ALIGNMENT there?).
> 
> Thanks,
> 
> Martin
> 
> 
> 2012-02-28  Martin Jambor  <mjambor@suse.cz>
> 
> 	* expr.c (expand_expr_real_1): handle misaligned scalar reads from
> 	memory through MEM_REFs by calling extract_bit_field.
> 
> 	* testsuite/gcc.dg/misaligned-expand-1.c: New test.
> 
> 
> Index: src/gcc/expr.c
> ===================================================================
> --- src.orig/gcc/expr.c
> +++ src/gcc/expr.c
> @@ -9453,21 +9453,29 @@ expand_expr_real_1 (tree exp, rtx target
>  	if (TREE_THIS_VOLATILE (exp))
>  	  MEM_VOLATILE_P (temp) = 1;
>  	if (mode != BLKmode
> -	    && align < GET_MODE_ALIGNMENT (mode)
> -	    /* If the target does not have special handling for unaligned
> -	       loads of mode then it can use regular moves for them.  */
> -	    && ((icode = optab_handler (movmisalign_optab, mode))
> -		!= CODE_FOR_nothing))
> +	    && !COMPLEX_MODE_P (mode)

I think the COMPLEX_MODE_P checks are wrong, you need to debug what
exactly goes wrong if we enter with such mode here.

Otherwise this patch looks ok as well.

Thanks,
Richard.

> +	    && align < GET_MODE_ALIGNMENT (mode))
>  	  {
> -	    struct expand_operand ops[2];
> +	    if ((icode = optab_handler (movmisalign_optab, mode))
> +		!= CODE_FOR_nothing)
> +	      {
> +		struct expand_operand ops[2];
>  
> -	    /* We've already validated the memory, and we're creating a
> -	       new pseudo destination.  The predicates really can't fail,
> -	       nor can the generator.  */
> -	    create_output_operand (&ops[0], NULL_RTX, mode);
> -	    create_fixed_operand (&ops[1], temp);
> -	    expand_insn (icode, 2, ops);
> -	    return ops[0].value;
> +		/* We've already validated the memory, and we're creating a
> +		   new pseudo destination.  The predicates really can't fail,
> +		   nor can the generator.  */
> +		create_output_operand (&ops[0], NULL_RTX, mode);
> +		create_fixed_operand (&ops[1], temp);
> +		expand_insn (icode, 2, ops);
> +		return ops[0].value;
> +	      }
> +	    else if (!COMPLEX_MODE_P (mode)
> +		     && SLOW_UNALIGNED_ACCESS (mode, align))
> +	      temp = extract_bit_field (temp, GET_MODE_BITSIZE (mode),
> +					0, TYPE_UNSIGNED (TREE_TYPE (exp)), true,
> +					(modifier == EXPAND_STACK_PARM
> +					 ? NULL_RTX : target),
> +					mode, mode);
>  	  }
>  	return temp;
>        }
> Index: src/gcc/testsuite/gcc.dg/misaligned-expand-1.c
> ===================================================================
> --- /dev/null
> +++ src/gcc/testsuite/gcc.dg/misaligned-expand-1.c
> @@ -0,0 +1,41 @@
> +/* Test that expand can generate correct loads of misaligned data even on
> +   strict alignment platforms.  */
> +
> +/* { dg-do run } */
> +/* { dg-options "-O0" } */
> +
> +extern void abort ();
> +
> +typedef unsigned int myint __attribute__((aligned(1)));
> +
> +unsigned int
> +foo (myint *p)
> +{
> +  return *p;
> +}
> +
> +#define cst 0xdeadbeef
> +#define NUM 8
> +
> +struct blah
> +{
> +  char c;
> +  myint i[NUM];
> +};
> +
> +struct blah g;
> +
> +int
> +main (int argc, char **argv)
> +{
> +  int i, k;
> +  for (k = 0; k < NUM; k++)
> +    {
> +      g.i[k] = cst;
> +      i = foo (&g.i[k]);
> +
> +      if (i != cst)
> +	abort ();
> +    }
> +  return 0;
> +}
> 
> 

-- 
Richard Guenther <rguenther@suse.de>
SUSE / SUSE Labs
SUSE LINUX Products GmbH - Nuernberg - AG Nuernberg - HRB 16746
GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer


More information about the Gcc-patches mailing list