[PATCH] c++: __builtin_clear_padding builtin C++ tail padding fix [PR88101]

Jakub Jelinek jakub@redhat.com
Wed Nov 18 08:48:30 GMT 2020


On Mon, Nov 16, 2020 at 10:13:52PM +0100, Jakub Jelinek via Gcc-patches wrote:
> On Sun, Nov 15, 2020 at 11:57:55PM -1200, Jakub Jelinek via Gcc-patches wrote:
> > Tested on x86_64-linux, i686-linux and powerpc64-linux, ok for trunk?
> 
> Here is an incremental patch that resolves the remaining FIXMEs, in
> particular implements VLAs (except for variable length structures)
> and for larger fixed sized arrays or members with larger array types
> uses runtime loops for the clearing (unless inside of a union).
> Furthermore, I've added diagnostics about last argument being const whatever *
> (similarly to e.g. __builtin_*_overflow) and also about _Atomic whatever *.

And another incrementaly patch, I've noticed ICEs on the following testcase.
For C++ we need to take DECL_SIZE_UNIT (field) as the size of the fields rather than
their TYPE_SIZE_UNIT (TREE_TYPE (field)), because in C++ tail padding is
often reused for other fields.

Bootstrapped/regtested (on top of the earlier 2 patches) on x86_64-linux and
i686-linux, ok for trunk?

2020-11-18  Jakub Jelinek  <jakub@redhat.com>

	PR libstdc++/88101
	* gimple-fold.c (clear_padding_type): Add sz argument,
	don't set it to int_size_in_bytes.  Adjust recursive calls.
	In RECORD_TYPEs, use DECL_SIZE_UNIT for fldsz.
	(clear_padding_union): Use DECL_SIZE_UNIT for fldsz and
	pass it to clear_padding_type.
	(clear_padding_emit_loop): Adjust clear_padding_type caller.
	(gimple_fold_builtin_clear_padding): Likewise.

	* g++.dg/torture/builtin-clear-padding-1.C: New test.

--- gcc/gimple-fold.c.jj	2020-11-16 18:47:42.997770758 +0100
+++ gcc/gimple-fold.c	2020-11-17 10:37:50.014877514 +0100
@@ -4211,7 +4211,7 @@ clear_padding_add_padding (clear_padding
     }
 }
 
-static void clear_padding_type (clear_padding_struct *, tree);
+static void clear_padding_type (clear_padding_struct *, tree, HOST_WIDE_INT);
 
 /* Clear padding bits of union type TYPE.  */
 
@@ -4253,12 +4253,12 @@ clear_padding_union (clear_padding_struc
   for (tree field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
     if (TREE_CODE (field) == FIELD_DECL)
       {
-	HOST_WIDE_INT fldsz = int_size_in_bytes (TREE_TYPE (field));
+	HOST_WIDE_INT fldsz = tree_to_shwi (DECL_SIZE_UNIT (field));
 	gcc_assert (union_buf->size == 0);
 	union_buf->off = start_off;
 	union_buf->size = start_size;
 	memset (union_buf->buf, ~0, start_size);
-	clear_padding_type (union_buf, TREE_TYPE (field));
+	clear_padding_type (union_buf, TREE_TYPE (field), fldsz);
 	clear_padding_add_padding (union_buf, sz - fldsz);
 	clear_padding_flush (union_buf, true);
       }
@@ -4339,7 +4339,7 @@ clear_padding_emit_loop (clear_padding_s
   g = gimple_build_label (l1);
   gimple_set_location (g, buf->loc);
   gsi_insert_before (buf->gsi, g, GSI_SAME_STMT);
-  clear_padding_type (buf, type);
+  clear_padding_type (buf, type, buf->sz);
   clear_padding_flush (buf, true);
   g = gimple_build_assign (buf->base, POINTER_PLUS_EXPR, buf->base,
 			   size_int (buf->sz));
@@ -4360,9 +4360,8 @@ clear_padding_emit_loop (clear_padding_s
    gimple_fold_builtin_clear_padding.  */
 
 static void
-clear_padding_type (clear_padding_struct *buf, tree type)
+clear_padding_type (clear_padding_struct *buf, tree type, HOST_WIDE_INT sz)
 {
-  HOST_WIDE_INT sz = int_size_in_bytes (type);
   switch (TREE_CODE (type))
     {
     case RECORD_TYPE:
@@ -4441,11 +4440,11 @@ clear_padding_type (clear_padding_struct
 	    else
 	      {
 		HOST_WIDE_INT pos = int_byte_position (field);
-		HOST_WIDE_INT fldsz = int_size_in_bytes (TREE_TYPE (field));
+		HOST_WIDE_INT fldsz = tree_to_shwi (DECL_SIZE_UNIT (field));
 		gcc_assert (pos >= 0 && fldsz >= 0 && pos >= cur_pos);
 		clear_padding_add_padding (buf, pos - cur_pos);
 		cur_pos = pos;
-		clear_padding_type (buf, TREE_TYPE (field));
+		clear_padding_type (buf, TREE_TYPE (field), fldsz);
 		cur_pos += fldsz;
 	      }
 	  }
@@ -4453,9 +4452,9 @@ clear_padding_type (clear_padding_struct
       clear_padding_add_padding (buf, sz - cur_pos);
       break;
     case ARRAY_TYPE:
-      HOST_WIDE_INT nelts;
-      nelts = int_size_in_bytes (TREE_TYPE (type));
-      nelts = sz / nelts;
+      HOST_WIDE_INT nelts, fldsz;
+      fldsz = int_size_in_bytes (TREE_TYPE (type));
+      nelts = sz / fldsz;
       if (nelts > 1
 	  && sz > 8 * UNITS_PER_WORD
 	  && buf->union_ptr == NULL
@@ -4479,7 +4478,7 @@ clear_padding_type (clear_padding_struct
 				   size_int (sz));
 	  gimple_set_location (g, buf->loc);
 	  gsi_insert_before (buf->gsi, g, GSI_SAME_STMT);
-	  buf->sz = sz / nelts;
+	  buf->sz = fldsz;
 	  buf->align = TYPE_ALIGN (elttype);
 	  buf->off = 0;
 	  buf->size = 0;
@@ -4493,7 +4492,7 @@ clear_padding_type (clear_padding_struct
 	  break;
 	}
       for (HOST_WIDE_INT i = 0; i < nelts; i++)
-	clear_padding_type (buf, TREE_TYPE (type));
+	clear_padding_type (buf, TREE_TYPE (type), fldsz);
       break;
     case UNION_TYPE:
       clear_padding_union (buf, type, sz);
@@ -4519,13 +4518,15 @@ clear_padding_type (clear_padding_struct
       buf->size += sz;
       break;
     case COMPLEX_TYPE:
-      clear_padding_type (buf, TREE_TYPE (type));
-      clear_padding_type (buf, TREE_TYPE (type));
+      fldsz = int_size_in_bytes (TREE_TYPE (type));
+      clear_padding_type (buf, TREE_TYPE (type), fldsz);
+      clear_padding_type (buf, TREE_TYPE (type), fldsz);
       break;
     case VECTOR_TYPE:
       nelts = TYPE_VECTOR_SUBPARTS (type).to_constant ();
+      fldsz = int_size_in_bytes (TREE_TYPE (type));
       for (HOST_WIDE_INT i = 0; i < nelts; i++)
-	clear_padding_type (buf, TREE_TYPE (type));
+	clear_padding_type (buf, TREE_TYPE (type), fldsz);
       break;
     default:
       gcc_assert ((size_t) sz <= clear_padding_unit);
@@ -4609,7 +4610,7 @@ gimple_fold_builtin_clear_padding (gimpl
 	  gimple_set_location (g, loc);
 	  gsi_insert_before (gsi, g, GSI_SAME_STMT);
 	}
-      clear_padding_type (&buf, type);
+      clear_padding_type (&buf, type, buf.sz);
       clear_padding_flush (&buf, true);
     }
 
--- gcc/testsuite/g++.dg/torture/builtin-clear-padding-1.C.jj	2020-11-17 10:35:24.792522768 +0100
+++ gcc/testsuite/g++.dg/torture/builtin-clear-padding-1.C	2020-11-17 10:35:10.689682539 +0100
@@ -0,0 +1,31 @@
+/* PR libstdc++/88101 */
+
+struct S {} s1, s2;
+struct T : public S { char a; short b; char c; } t1, t2;
+struct U : public T { char d; long long e; char f; } u1, u2;
+
+__attribute__((noipa)) void
+foo (T *t, U *u)
+{
+  int i;
+  t->a = -1; t->b = -1; t->c = -1;
+  u->a = -1; u->b = -1; u->c = -1; u->d = -1; u->e = -1; u->f = -1;
+}
+
+int
+main ()
+{
+  __builtin_memset (&s2, -1, sizeof (s2));
+  __builtin_memset (&t2, -1, sizeof (t2));
+  __builtin_memset (&u2, -1, sizeof (u2));
+  foo (&t1, &u1);
+  foo (&t2, &u2);
+  __builtin_clear_padding (&s2);
+  __builtin_clear_padding (&t2);
+  __builtin_clear_padding (&u2);
+  if (__builtin_memcmp (&s1, &s2, sizeof (s1))
+      || __builtin_memcmp (&t1, &t2, sizeof (t1))
+      || __builtin_memcmp (&u1, &u2, sizeof (u1)))
+    __builtin_abort ();
+  return 0;
+}


	Jakub



More information about the Gcc-patches mailing list