[PATCH] Fix PR59990

Richard Biener rguenther@suse.de
Thu Jan 30 18:25:00 GMT 2014


The following attempts to provide a fix for PR59990 - the fact
that we shouldn't use FP modes to implement memcpy in the middle-end.
It consolidates the ubsan case for BOOLEAN and ENUMERAL types which
are desirable to avoid anyway.

Bootstrapped and tested on x86_64-unknown-linux-gnu.

Does this look reasonable?

Thanks,
Richard.

2014-01-30  Richard Biener  <rguenther@suse.de>

	PR middle-end/59990
	* builtins.c (fold_builtin_memory_op): Make sure to not
	use a floating-point mode or a boolean or enumeral type for
	the copy operation.

	* gcc.dg/torture/pr59990.c: New testcase.

Index: gcc/builtins.c
===================================================================
*** gcc/builtins.c	(revision 207306)
--- gcc/builtins.c	(working copy)
*************** fold_builtin_memory_op (location_t loc,
*** 8851,8856 ****
--- 8851,8862 ----
        if (!POINTER_TYPE_P (TREE_TYPE (src))
  	  || !POINTER_TYPE_P (TREE_TYPE (dest)))
  	return NULL_TREE;
+       /* In the following try to find a type that is most natural to be
+ 	 used for the memcpy source and destination and that allows
+ 	 the most optimization when memcpy is turned into a plain assignment
+ 	 using that type.  In theory we could always use a char[len] type
+ 	 but that only gains us that the destination and source possibly
+ 	 no longer will have their address taken.  */
        /* As we fold (void *)(p + CST) to (void *)p + CST undo this here.  */
        if (TREE_CODE (src) == POINTER_PLUS_EXPR)
  	{
*************** fold_builtin_memory_op (location_t loc,
*** 8886,8891 ****
--- 8892,8932 ----
  	  || TREE_ADDRESSABLE (desttype))
  	return NULL_TREE;
  
+       /* Make sure we are not copying using a floating-point mode or
+          a type whose size possibly does not match its precision.  */
+       if (FLOAT_MODE_P (TYPE_MODE (desttype))
+ 	  || TREE_CODE (desttype) == BOOLEAN_TYPE
+ 	  || TREE_CODE (desttype) == ENUMERAL_TYPE)
+ 	{
+ 	  /* A more suitable int_mode_for_mode would return a vector
+ 	     integer mode for a vector float mode or a integer complex
+ 	     mode for a float complex mode if there isn't a regular
+ 	     integer mode covering the mode of desttype.  */
+ 	  enum machine_mode mode = int_mode_for_mode (TYPE_MODE (desttype));
+ 	  if (mode == BLKmode)
+ 	    desttype = NULL_TREE;
+ 	  else
+ 	    desttype = build_nonstandard_integer_type (GET_MODE_BITSIZE (mode),
+ 						       1);
+ 	}
+       if (FLOAT_MODE_P (TYPE_MODE (srctype))
+ 	  || TREE_CODE (srctype) == BOOLEAN_TYPE
+ 	  || TREE_CODE (srctype) == ENUMERAL_TYPE)
+ 	{
+ 	  enum machine_mode mode = int_mode_for_mode (TYPE_MODE (srctype));
+ 	  if (mode == BLKmode)
+ 	    srctype = NULL_TREE;
+ 	  else
+ 	    srctype = build_nonstandard_integer_type (GET_MODE_BITSIZE (mode),
+ 						      1);
+ 	}
+       if (!srctype)
+ 	srctype = desttype;
+       if (!desttype)
+ 	desttype = srctype;
+       if (!srctype)
+ 	return NULL_TREE;
+ 
        src_align = get_pointer_alignment (src);
        dest_align = get_pointer_alignment (dest);
        if (dest_align < TYPE_ALIGN (desttype)
*************** fold_builtin_memory_op (location_t loc,
*** 8899,8927 ****
        off0 = build_int_cst (build_pointer_type_for_mode (char_type_node,
  							 ptr_mode, true), 0);
  
-       /* For -fsanitize={bool,enum} make sure the load isn't performed in
- 	 the bool or enum type.  */
-       if (((flag_sanitize & SANITIZE_BOOL)
- 	   && TREE_CODE (desttype) == BOOLEAN_TYPE)
- 	  || ((flag_sanitize & SANITIZE_ENUM)
- 	      && TREE_CODE (desttype) == ENUMERAL_TYPE))
- 	{
- 	  tree destitype
- 	    = lang_hooks.types.type_for_mode (TYPE_MODE (desttype),
- 					      TYPE_UNSIGNED (desttype));
- 	  desttype = build_aligned_type (destitype, TYPE_ALIGN (desttype));
- 	}
-       if (((flag_sanitize & SANITIZE_BOOL)
- 	   && TREE_CODE (srctype) == BOOLEAN_TYPE)
- 	  || ((flag_sanitize & SANITIZE_ENUM)
- 	      && TREE_CODE (srctype) == ENUMERAL_TYPE))
- 	{
- 	  tree srcitype
- 	    = lang_hooks.types.type_for_mode (TYPE_MODE (srctype),
- 					      TYPE_UNSIGNED (srctype));
- 	  srctype = build_aligned_type (srcitype, TYPE_ALIGN (srctype));
- 	}
- 
        destvar = dest;
        STRIP_NOPS (destvar);
        if (TREE_CODE (destvar) == ADDR_EXPR
--- 8940,8945 ----
Index: gcc/testsuite/gcc.dg/torture/pr59990.c
===================================================================
*** gcc/testsuite/gcc.dg/torture/pr59990.c	(revision 0)
--- gcc/testsuite/gcc.dg/torture/pr59990.c	(working copy)
***************
*** 0 ****
--- 1,18 ----
+ /* { dg-do run } */
+ 
+ extern void abort (void);
+ 
+ unsigned char value[4] = { 66, 9, 160, 255 };
+ 
+ int main (void)
+ {
+   volatile float f;
+   unsigned char a[4];
+ 
+   __builtin_memcpy ((void *)&f, value, 4);
+   __builtin_memcpy (a, (void *)&f, 4);
+   if (a[2] != 160)
+     abort ();
+ 
+   return 0;
+ }



More information about the Gcc-patches mailing list