aboutsummaryrefslogtreecommitdiff
path: root/gcc/expr.cc
diff options
context:
space:
mode:
authorAlexandre Oliva <oliva@adacore.com>2024-08-31 06:03:12 -0300
committerAlexandre Oliva <oliva@gnu.org>2024-08-31 06:03:12 -0300
commit673a448aa24efedd5ac140ebf7bfe652d7a6a846 (patch)
tree9a95bf9cca082583142ef5acf360865412df78ef /gcc/expr.cc
parent08693e29ec186fd7941d0b73d4d466388971fe2f (diff)
downloadgcc-673a448aa24efedd5ac140ebf7bfe652d7a6a846.zip
gcc-673a448aa24efedd5ac140ebf7bfe652d7a6a846.tar.gz
gcc-673a448aa24efedd5ac140ebf7bfe652d7a6a846.tar.bz2
Optimize initialization of small padded objects
When small objects containing padding bits (or bytes) are fully initialized, we will often store them in registers, and setting bitfields and other small fields will attempt to preserve the uninitialized padding bits, which tends to be expensive. Zero-initializing registers, OTOH, tends to be cheap. So, if we're optimizing, zero-initialize such small padded objects even if that's not needed for correctness. We can't zero-initialize all such padding objects, though: if there's no padding whatsoever, and all fields are initialized with nonzero, the zero initialization would be flagged as dead. That's why we introduce machinery to detect whether objects have padding bits. I considered distinguishing between bitfields, units and larger padding elements, but I didn't pursue that distinction. Since the object's zero-initialization subsumes fields' zero-initialization, the empty string test in builtin-snprintf-6.c's test_assign_aggregate would regress without the addition of native_encode_constructor. for gcc/ChangeLog * expr.cc (categorize_ctor_elements_1): Change p_complete to int, to distinguish complete initialization in presence or absence of uninitialized padding bits. (categorize_ctor_elements): Likewise. Adjust all callers... * expr.h (categorize_ctor_elements): ... and declaration. (type_has_padding_at_level_p): New. * gimple-fold.cc (type_has_padding_at_level_p): New. * fold-const.cc (native_encode_constructor): New. (native_encode_expr): Call it. * gimplify.cc (gimplify_init_constructor): Clear small non-addressable non-volatile objects with padding or other uninitialized fields as an optimization. for gcc/testsuite/ChangeLog * gcc.dg/init-pad-1.c: New.
Diffstat (limited to 'gcc/expr.cc')
-rw-r--r--gcc/expr.cc20
1 files changed, 13 insertions, 7 deletions
diff --git a/gcc/expr.cc b/gcc/expr.cc
index 8d17a5a..320be8b 100644
--- a/gcc/expr.cc
+++ b/gcc/expr.cc
@@ -7096,7 +7096,7 @@ count_type_elements (const_tree type, bool for_ctor_p)
static bool
categorize_ctor_elements_1 (const_tree ctor, HOST_WIDE_INT *p_nz_elts,
HOST_WIDE_INT *p_unique_nz_elts,
- HOST_WIDE_INT *p_init_elts, bool *p_complete)
+ HOST_WIDE_INT *p_init_elts, int *p_complete)
{
unsigned HOST_WIDE_INT idx;
HOST_WIDE_INT nz_elts, unique_nz_elts, init_elts, num_fields;
@@ -7218,7 +7218,10 @@ categorize_ctor_elements_1 (const_tree ctor, HOST_WIDE_INT *p_nz_elts,
if (*p_complete && !complete_ctor_at_level_p (TREE_TYPE (ctor),
num_fields, elt_type))
- *p_complete = false;
+ *p_complete = 0;
+ else if (*p_complete > 0
+ && type_has_padding_at_level_p (TREE_TYPE (ctor)))
+ *p_complete = -1;
*p_nz_elts += nz_elts;
*p_unique_nz_elts += unique_nz_elts;
@@ -7239,7 +7242,10 @@ categorize_ctor_elements_1 (const_tree ctor, HOST_WIDE_INT *p_nz_elts,
and place it in *P_ELT_COUNT.
* whether the constructor is complete -- in the sense that every
meaningful byte is explicitly given a value --
- and place it in *P_COMPLETE.
+ and place it in *P_COMPLETE:
+ - 0 if any field is missing
+ - 1 if all fields are initialized, and there's no padding
+ - -1 if all fields are initialized, but there's padding
Return whether or not CTOR is a valid static constant initializer, the same
as "initializer_constant_valid_p (CTOR, TREE_TYPE (CTOR)) != 0". */
@@ -7247,12 +7253,12 @@ categorize_ctor_elements_1 (const_tree ctor, HOST_WIDE_INT *p_nz_elts,
bool
categorize_ctor_elements (const_tree ctor, HOST_WIDE_INT *p_nz_elts,
HOST_WIDE_INT *p_unique_nz_elts,
- HOST_WIDE_INT *p_init_elts, bool *p_complete)
+ HOST_WIDE_INT *p_init_elts, int *p_complete)
{
*p_nz_elts = 0;
*p_unique_nz_elts = 0;
*p_init_elts = 0;
- *p_complete = true;
+ *p_complete = 1;
return categorize_ctor_elements_1 (ctor, p_nz_elts, p_unique_nz_elts,
p_init_elts, p_complete);
@@ -7313,7 +7319,7 @@ mostly_zeros_p (const_tree exp)
if (TREE_CODE (exp) == CONSTRUCTOR)
{
HOST_WIDE_INT nz_elts, unz_elts, init_elts;
- bool complete_p;
+ int complete_p;
categorize_ctor_elements (exp, &nz_elts, &unz_elts, &init_elts,
&complete_p);
@@ -7331,7 +7337,7 @@ all_zeros_p (const_tree exp)
if (TREE_CODE (exp) == CONSTRUCTOR)
{
HOST_WIDE_INT nz_elts, unz_elts, init_elts;
- bool complete_p;
+ int complete_p;
categorize_ctor_elements (exp, &nz_elts, &unz_elts, &init_elts,
&complete_p);