re PR c/87691 (transparent_union attribute does not work with MODE_PARTIAL_INT)
authorJozef Lawrynowicz <jozefl@gcc.gnu.org>
Wed, 7 Nov 2018 22:06:26 +0000 (22:06 +0000)
committerJozef Lawrynowicz <jozefl@gcc.gnu.org>
Wed, 7 Nov 2018 22:06:26 +0000 (22:06 +0000)
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

gcc/ChangeLog
gcc/stor-layout.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/msp430/pr87691.c [new file with mode: 0644]

index 966f0cb..c1eef4c 100644 (file)
@@ -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>
 
index 42df257..4f32317 100644 (file)
@@ -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))
index 689d7a7..51f1b60 100644 (file)
@@ -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 (file)
index 0000000..c00425d
--- /dev/null
@@ -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;
+}