aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJozef Lawrynowicz <jozefl@gcc.gnu.org>2018-11-07 22:06:26 +0000
committerJozef Lawrynowicz <jozefl@gcc.gnu.org>2018-11-07 22:06:26 +0000
commitc2ca29d5a35f8dd62f76df48e16bbac7320660c8 (patch)
tree1ca8080d96fb6d191045c84771064ac19c0dd628
parente217792beda1ca48daea497c00694a3924f992c5 (diff)
downloadgcc-c2ca29d5a35f8dd62f76df48e16bbac7320660c8.zip
gcc-c2ca29d5a35f8dd62f76df48e16bbac7320660c8.tar.gz
gcc-c2ca29d5a35f8dd62f76df48e16bbac7320660c8.tar.bz2
re PR c/87691 (transparent_union attribute does not work with MODE_PARTIAL_INT)
2018-11-07 Jozef Lawrynowicz <jozef.l@mittosystems.com> PR c/87691 gcc/ChangeLog: * stor-layout.c (compute_record_mode): Set TYPE_MODE of UNION_TYPE to the mode of the widest field iff the widest field has mode class MODE_INT, or MODE_PARTIAL_INT and the union would be passed by reference. gcc/testsuite/ChangeLog: * gcc.target/msp430/pr87691.c: New test. From-SVN: r265894
-rw-r--r--gcc/ChangeLog18
-rw-r--r--gcc/stor-layout.c21
-rw-r--r--gcc/testsuite/ChangeLog9
-rw-r--r--gcc/testsuite/gcc.target/msp430/pr87691.c41
4 files changed, 78 insertions, 11 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 966f0cb..c1eef4c 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,9 +1,17 @@
-2018-11-17 Nikolai Merinov <n.merinov@inango-systems.com>
+2018-11-07 Jozef Lawrynowicz <jozef.l@mittosystems.com>
- * common.opt: Add -Wattribute-warning.
- * doc/invoke.texi: Add documentation for -Wno-attribute-warning.
- * expr.c (expand_expr_real_1): Add new attribute to warning_at
- call to allow user configure behavior of "warning" attribute.
+ PR c/87691
+ * stor-layout.c (compute_record_mode): Set TYPE_MODE of UNION_TYPE
+ to the mode of the widest field iff the widest field has mode class
+ MODE_INT, or MODE_PARTIAL_INT and the union would be passed by
+ reference.
+
+2018-11-07 Nikolai Merinov <n.merinov@inango-systems.com>
+
+ * common.opt: Add -Wattribute-warning.
+ * doc/invoke.texi: Add documentation for -Wno-attribute-warning.
+ * expr.c (expand_expr_real_1): Add new attribute to warning_at
+ call to allow user configure behavior of "warning" attribute.
2018-11-07 Segher Boessenkool <segher@kernel.crashing.org>
diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c
index 42df257..4f32317 100644
--- a/gcc/stor-layout.c
+++ b/gcc/stor-layout.c
@@ -1834,7 +1834,13 @@ compute_record_mode (tree type)
/* If this field is the whole struct, remember its mode so
that, say, we can put a double in a class into a DF
register instead of forcing it to live in the stack. */
- if (simple_cst_equal (TYPE_SIZE (type), DECL_SIZE (field)))
+ if (simple_cst_equal (TYPE_SIZE (type), DECL_SIZE (field))
+ /* Partial int types (e.g. __int20) may have TYPE_SIZE equal to
+ wider types (e.g. int32), despite precision being less. Ensure
+ that the TYPE_MODE of the struct does not get set to the partial
+ int mode if there is a wider type also in the struct. */
+ && known_gt (GET_MODE_PRECISION (DECL_MODE (field)),
+ GET_MODE_PRECISION (mode)))
mode = DECL_MODE (field);
/* With some targets, it is sub-optimal to access an aligned
@@ -1844,10 +1850,17 @@ compute_record_mode (tree type)
}
/* If we only have one real field; use its mode if that mode's size
- matches the type's size. This only applies to RECORD_TYPE. This
- does not apply to unions. */
+ matches the type's size. This generally only applies to RECORD_TYPE.
+ For UNION_TYPE, if the widest field is MODE_INT then use that mode.
+ If the widest field is MODE_PARTIAL_INT, and the union will be passed
+ by reference, then use that mode. */
poly_uint64 type_size;
- if (TREE_CODE (type) == RECORD_TYPE
+ if ((TREE_CODE (type) == RECORD_TYPE
+ || (TREE_CODE (type) == UNION_TYPE
+ && (GET_MODE_CLASS (mode) == MODE_INT
+ || (GET_MODE_CLASS (mode) == MODE_PARTIAL_INT
+ && targetm.calls.pass_by_reference (pack_cumulative_args (0),
+ mode, type, 0)))))
&& mode != VOIDmode
&& poly_int_tree_p (TYPE_SIZE (type), &type_size)
&& known_eq (GET_MODE_BITSIZE (mode), type_size))
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 689d7a7..51f1b60 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,6 +1,11 @@
-2018-11-17 Nikolai Merinov <n.merinov@inango-systems.com>
+2018-11-07 Jozef Lawrynowicz <jozef.l@mittosystems.com>
- * gcc.dg/Wno-attribute-warning.c: New test.
+ PR c/87691
+ * gcc.target/msp430/pr87691.c: New test.
+
+2018-11-07 Nikolai Merinov <n.merinov@inango-systems.com>
+
+ * gcc.dg/Wno-attribute-warning.c: New test.
2018-11-07 Nathan Sidwell <nathan@acm.org>
diff --git a/gcc/testsuite/gcc.target/msp430/pr87691.c b/gcc/testsuite/gcc.target/msp430/pr87691.c
new file mode 100644
index 0000000..c00425d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/msp430/pr87691.c
@@ -0,0 +1,41 @@
+/* PR 87691 - Test that a union containing __int20 and a float is not treated as
+ 20-bits in size. */
+
+/* { dg-do compile } */
+/* { dg-skip-if "no __int20 for mcpu=msp430" { *-*-* } { "-mcpu=msp430" } { "" } } */
+/* { dg-final { scan-assembler-not "MOVX.A" } } */
+
+/* To move a 20-bit value from memory (using indexed or indirect register
+ mode), onto the stack (also addressed using indexed or indirect register
+ mode), MOVX.A must be used. MOVA does not support these addressing modes.
+ Therefore, to check that the union is not manipulated as a 20-bit type,
+ test that no MOVX.A instructions are present in the assembly.
+
+ MOVA is used to fill/spill u.i, but if the union is treated as 20 bits in
+ size, MOVX.A would be used. No other __int20 operations are present
+ in the source, so there will be no valid uses of MOVX.A in the resulting
+ assembly. */
+
+union U1
+{
+ float f;
+ __int20 i;
+};
+
+union U2
+{
+ __int20 i;
+ float f;
+};
+
+float foo1 (union U1 u)
+{
+ u.i += 42;
+ return u.f;
+}
+
+float foo2 (union U2 u)
+{
+ u.i += 42;
+ return u.f;
+}