230 lines
7.2 KiB
Diff
230 lines
7.2 KiB
Diff
2007-12-17 Aldy Hernandez <aldyh@redhat.com>
|
|
|
|
PR tree-optimization/34448
|
|
PR tree-optimization/34465
|
|
* gimplify.c (gimplify_init_constructor): Add new parameter
|
|
notify_temp_creation. Use it.
|
|
(gimplify_modify_expr_rhs): Take volatiles into account when
|
|
optimizing constructors.
|
|
Do not optimize constructors if gimplify_init_constructor will dump to
|
|
memory.
|
|
* gcc.dg/tree-ssa/pr32901.c: Tests const volatiles.
|
|
* gcc.c-torture/compile/pr34448.c: New.
|
|
|
|
--- gcc/gimplify.c (revision 130934)
|
|
+++ gcc/gimplify.c (local)
|
|
@@ -3119,11 +3119,18 @@ gimplify_init_ctor_eval (tree object, VE
|
|
|
|
Note that we still need to clear any elements that don't have explicit
|
|
initializers, so if not all elements are initialized we keep the
|
|
- original MODIFY_EXPR, we just remove all of the constructor elements. */
|
|
+ original MODIFY_EXPR, we just remove all of the constructor elements.
|
|
+
|
|
+ If NOTIFY_TEMP_CREATION is true, do not gimplify, just return
|
|
+ GS_ERROR if we would have to create a temporary when gimplifying
|
|
+ this constructor. Otherwise, return GS_OK.
|
|
+
|
|
+ If NOTIFY_TEMP_CREATION is false, just do the gimplification. */
|
|
|
|
static enum gimplify_status
|
|
gimplify_init_constructor (tree *expr_p, tree *pre_p,
|
|
- tree *post_p, bool want_value)
|
|
+ tree *post_p, bool want_value,
|
|
+ bool notify_temp_creation)
|
|
{
|
|
tree object;
|
|
tree ctor = GENERIC_TREE_OPERAND (*expr_p, 1);
|
|
@@ -3134,10 +3141,13 @@ gimplify_init_constructor (tree *expr_p,
|
|
if (TREE_CODE (ctor) != CONSTRUCTOR)
|
|
return GS_UNHANDLED;
|
|
|
|
- ret = gimplify_expr (&GENERIC_TREE_OPERAND (*expr_p, 0), pre_p, post_p,
|
|
- is_gimple_lvalue, fb_lvalue);
|
|
- if (ret == GS_ERROR)
|
|
- return ret;
|
|
+ if (!notify_temp_creation)
|
|
+ {
|
|
+ ret = gimplify_expr (&GENERIC_TREE_OPERAND (*expr_p, 0), pre_p, post_p,
|
|
+ is_gimple_lvalue, fb_lvalue);
|
|
+ if (ret == GS_ERROR)
|
|
+ return ret;
|
|
+ }
|
|
object = GENERIC_TREE_OPERAND (*expr_p, 0);
|
|
|
|
elts = CONSTRUCTOR_ELTS (ctor);
|
|
@@ -3159,7 +3169,11 @@ gimplify_init_constructor (tree *expr_p,
|
|
individual elements. The exception is that a CONSTRUCTOR node
|
|
with no elements indicates zero-initialization of the whole. */
|
|
if (VEC_empty (constructor_elt, elts))
|
|
- break;
|
|
+ {
|
|
+ if (notify_temp_creation)
|
|
+ return GS_OK;
|
|
+ break;
|
|
+ }
|
|
|
|
/* Fetch information about the constructor to direct later processing.
|
|
We might want to make static versions of it in various cases, and
|
|
@@ -3175,6 +3189,8 @@ gimplify_init_constructor (tree *expr_p,
|
|
&& TREE_READONLY (object)
|
|
&& TREE_CODE (object) == VAR_DECL)
|
|
{
|
|
+ if (notify_temp_creation)
|
|
+ return GS_ERROR;
|
|
DECL_INITIAL (object) = ctor;
|
|
TREE_STATIC (object) = 1;
|
|
if (!DECL_NAME (object))
|
|
@@ -3251,7 +3267,12 @@ gimplify_init_constructor (tree *expr_p,
|
|
|
|
if (size > 0 && !can_move_by_pieces (size, align))
|
|
{
|
|
- tree new = create_tmp_var_raw (type, "C");
|
|
+ tree new;
|
|
+
|
|
+ if (notify_temp_creation)
|
|
+ return GS_ERROR;
|
|
+
|
|
+ new = create_tmp_var_raw (type, "C");
|
|
|
|
gimple_add_tmp_var (new);
|
|
TREE_STATIC (new) = 1;
|
|
@@ -3273,6 +3294,9 @@ gimplify_init_constructor (tree *expr_p,
|
|
}
|
|
}
|
|
|
|
+ if (notify_temp_creation)
|
|
+ return GS_OK;
|
|
+
|
|
/* If there are nonzero elements, pre-evaluate to capture elements
|
|
overlapping with the lhs into temporaries. We must do this before
|
|
clearing to fetch the values before they are zeroed-out. */
|
|
@@ -3312,6 +3336,9 @@ gimplify_init_constructor (tree *expr_p,
|
|
{
|
|
tree r, i;
|
|
|
|
+ if (notify_temp_creation)
|
|
+ return GS_OK;
|
|
+
|
|
/* Extract the real and imaginary parts out of the ctor. */
|
|
gcc_assert (VEC_length (constructor_elt, elts) == 2);
|
|
r = VEC_index (constructor_elt, elts, 0)->value;
|
|
@@ -3348,6 +3375,9 @@ gimplify_init_constructor (tree *expr_p,
|
|
unsigned HOST_WIDE_INT ix;
|
|
constructor_elt *ce;
|
|
|
|
+ if (notify_temp_creation)
|
|
+ return GS_OK;
|
|
+
|
|
/* Go ahead and simplify constant constructors to VECTOR_CST. */
|
|
if (TREE_CONSTANT (ctor))
|
|
{
|
|
@@ -3488,10 +3518,28 @@ gimplify_modify_expr_rhs (tree *expr_p,
|
|
constructor expression to the RHS of the MODIFY_EXPR. */
|
|
if (DECL_INITIAL (*from_p)
|
|
&& TYPE_READONLY (TREE_TYPE (*from_p))
|
|
+ && !TREE_THIS_VOLATILE (*from_p)
|
|
&& TREE_CODE (DECL_INITIAL (*from_p)) == CONSTRUCTOR)
|
|
{
|
|
- *from_p = DECL_INITIAL (*from_p);
|
|
- ret = GS_OK;
|
|
+ tree old_from = *from_p;
|
|
+
|
|
+ /* Move the constructor into the RHS. */
|
|
+ *from_p = DECL_INITIAL (*from_p);
|
|
+
|
|
+ /* Let's see if gimplify_init_constructor will need to put
|
|
+ it in memory. If so, revert the change. */
|
|
+ ret = gimplify_init_constructor (expr_p, NULL, NULL, false, true);
|
|
+ if (ret == GS_ERROR)
|
|
+ {
|
|
+ *from_p = old_from;
|
|
+ /* Fall through. */
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ *from_p = unshare_expr (*from_p);
|
|
+ ret = GS_OK;
|
|
+ break;
|
|
+ }
|
|
}
|
|
ret = GS_UNHANDLED;
|
|
break;
|
|
@@ -3551,7 +3599,8 @@ gimplify_modify_expr_rhs (tree *expr_p,
|
|
case CONSTRUCTOR:
|
|
/* If we're initializing from a CONSTRUCTOR, break this into
|
|
individual MODIFY_EXPRs. */
|
|
- return gimplify_init_constructor (expr_p, pre_p, post_p, want_value);
|
|
+ return gimplify_init_constructor (expr_p, pre_p, post_p, want_value,
|
|
+ false);
|
|
|
|
case COND_EXPR:
|
|
/* If we're assigning to a non-register type, push the assignment
|
|
--- gcc/testsuite/gcc.c-torture/compile/pr34448.c (revision 130934)
|
|
+++ gcc/testsuite/gcc.c-torture/compile/pr34448.c (local)
|
|
@@ -0,0 +1,34 @@
|
|
+/* { dg-do compile } */
|
|
+/* { dg-options "-O" } */
|
|
+
|
|
+typedef struct chunk_t chunk_t;
|
|
+struct chunk_t
|
|
+{
|
|
+ unsigned char *ptr;
|
|
+ long unsigned int len;
|
|
+};
|
|
+extern chunk_t asn1_wrap (chunk_t c, ...);
|
|
+typedef struct linked_list_t linked_list_t;
|
|
+chunk_t ietfAttr_list_encode (linked_list_t * list);
|
|
+extern linked_list_t *groups;
|
|
+static unsigned char ASN1_group_oid_str[] = {
|
|
+ 0x06
|
|
+};
|
|
+static const chunk_t ASN1_group_oid = {
|
|
+ ASN1_group_oid_str, sizeof (ASN1_group_oid_str)
|
|
+};
|
|
+static chunk_t
|
|
+build_attribute_type (const chunk_t type, chunk_t content)
|
|
+{
|
|
+ return type;
|
|
+}
|
|
+static chunk_t
|
|
+build_attributes (void)
|
|
+{
|
|
+ return asn1_wrap (build_attribute_type (ASN1_group_oid,
|
|
+ ietfAttr_list_encode (groups)));
|
|
+}
|
|
+void build_attr_cert (void)
|
|
+{
|
|
+ asn1_wrap (build_attributes ());
|
|
+}
|
|
--- gcc/testsuite/gcc.dg/tree-ssa/pr32901.c (revision 130934)
|
|
+++ gcc/testsuite/gcc.dg/tree-ssa/pr32901.c (local)
|
|
@@ -7,7 +7,7 @@ struct foo {
|
|
unsigned : 4;
|
|
};
|
|
|
|
-extern struct foo thefoo;
|
|
+extern struct foo thefoo, theotherfoo;
|
|
|
|
void setup_foo(void)
|
|
{
|
|
@@ -15,10 +15,16 @@ void setup_foo(void)
|
|
.a1 = 1,
|
|
.a2 = 5,
|
|
};
|
|
+ volatile const struct foo volinit = {
|
|
+ .a1 = 0,
|
|
+ .a2 = 6
|
|
+ };
|
|
thefoo = init;
|
|
+ theotherfoo = volinit;
|
|
}
|
|
|
|
-/* { dg-final { scan-tree-dump-times "thefoo.0 = \{\}" 1 "gimple"} } */
|
|
-/* { dg-final { scan-tree-dump-times "thefoo.0.a1 = 1" 1 "gimple"} } */
|
|
-/* { dg-final { scan-tree-dump-times "thefoo.0.a2 = 5" 1 "gimple"} } */
|
|
+/* { dg-final { scan-tree-dump-times "thefoo.* = {}" 1 "gimple"} } */
|
|
+/* { dg-final { scan-tree-dump-times "thefoo.* = 1" 1 "gimple"} } */
|
|
+/* { dg-final { scan-tree-dump-times "thefoo.* = 5" 1 "gimple"} } */
|
|
+/* { dg-final { scan-tree-dump-times "theotherfoo = volinit" 1 "gimple"} } */
|
|
/* { dg-final { cleanup-tree-dump "gimple" } } */
|