[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