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 <ja...@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