@@ -573,6 +573,35 @@ layout_aggregate_type (AggregateDeclaration *decl, tree type,
}
}
+/* Given a record type TYPE compute the finalized record mode if all fields have
+ had their types resolved and sizes determined. */
+
+void
+finish_aggregate_mode (tree type)
+{
+ for (tree field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
+ {
+ /* Fields of type `typeof(*null)' have no size, so let them force the
+ record type mode to be computed as BLKmode. */
+ if (TYPE_MAIN_VARIANT (TREE_TYPE (field)) == noreturn_type_node)
+ break;
+
+ if (DECL_SIZE (field) == NULL_TREE)
+ return;
+ }
+
+ compute_record_mode (type);
+
+ /* Propagate computed mode to all variants of this aggregate type. */
+ for (tree t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
+ {
+ if (t == type)
+ continue;
+
+ SET_TYPE_MODE (t, TYPE_MODE (type));
+ }
+}
+
/* If the aggregate type TYPE completes the type of any previous field
declarations, lay them out now. */
@@ -596,6 +625,9 @@ finish_incomplete_fields (tree type)
}
relayout_decl (field);
+
+ /* Relayout of field may change the mode of its RECORD_TYPE. */
+ finish_aggregate_mode (DECL_FIELD_CONTEXT (field));
}
/* No more forward references to process. */
@@ -615,9 +647,6 @@ finish_aggregate_type (unsigned structsize, unsigned alignsize, tree type)
SET_TYPE_ALIGN (type, alignsize * BITS_PER_UNIT);
TYPE_PACKED (type) = (alignsize == 1);
- /* Set the back-end type mode. */
- compute_record_mode (type);
-
/* Layout all fields now the type is complete. */
for (tree field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
{
@@ -662,6 +691,9 @@ finish_aggregate_type (unsigned structsize, unsigned alignsize, tree type)
}
}
+ /* Set the back-end type mode after all fields have had their size set. */
+ finish_aggregate_mode (type);
+
/* Fix up all forward-referenced variants of this aggregate type. */
for (tree t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
{
@@ -673,7 +705,6 @@ finish_aggregate_type (unsigned structsize, unsigned alignsize, tree type)
TYPE_SIZE (t) = TYPE_SIZE (type);
TYPE_SIZE_UNIT (t) = TYPE_SIZE_UNIT (type);
TYPE_PACKED (type) = TYPE_PACKED (type);
- SET_TYPE_MODE (t, TYPE_MODE (type));
SET_TYPE_ALIGN (t, TYPE_ALIGN (type));
TYPE_USER_ALIGN (t) = TYPE_USER_ALIGN (type);
}
new file mode 100644
@@ -0,0 +1,25 @@
+// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110406
+// { dg-do compile { target i?86-*-* x86_64-*-* } }
+// { dg-options "-fdump-tree-optimized" }
+struct cpuid_abcd_t
+{
+ uint eax;
+ uint ebx;
+ uint ecx;
+ uint edx;
+};
+
+cpuid_abcd_t cpuid_insn(const uint in_eax)
+{
+ cpuid_abcd_t ret = void;
+ asm { "cpuid"
+ : "=a" (ret.eax),
+ "=b" (ret.ebx),
+ "=c" (ret.ecx),
+ "=d" (ret.edx)
+ : "a" (in_eax)
+ :;
+ }
+ return ret;
+}
+// { dg-final { scan-tree-dump-not "MEM <vector\\(4\\) uint>" "optimized" } }