re PR middle-end/91001 (internal compiler error: in extract_insn, at recog.c:2310)
authorJakub Jelinek <jakub@redhat.com>
Thu, 5 Sep 2019 13:30:23 +0000 (15:30 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Thu, 5 Sep 2019 13:30:23 +0000 (15:30 +0200)
PR middle-end/91001
PR middle-end/91105
PR middle-end/91106
* calls.c (load_register_parameters): For TYPE_TRANSPARENT_AGGR
types, use type of their first field instead of type of
args[i].tree_value.

* gcc.c-torture/compile/pr91001.c: New test.

From-SVN: r275408

gcc/ChangeLog
gcc/calls.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/compile/pr91001.c [new file with mode: 0644]

index 1de9622..e76ed4a 100644 (file)
@@ -1,3 +1,12 @@
+2019-09-05  Jakub Jelinek  <jakub@redhat.com>
+
+       PR middle-end/91001
+       PR middle-end/91105
+       PR middle-end/91106
+       * calls.c (load_register_parameters): For TYPE_TRANSPARENT_AGGR
+       types, use type of their first field instead of type of
+       args[i].tree_value.
+
 2019-09-05  Richard Biener  <rguenther@suse.de>
 
        PR rtl-optimization/91656
index 6eefeec..e5086f4 100644 (file)
@@ -2771,6 +2771,11 @@ load_register_parameters (struct arg_data *args, int num_actuals,
          poly_int64 size = 0;
          HOST_WIDE_INT const_size = 0;
          rtx_insn *before_arg = get_last_insn ();
+         tree type = TREE_TYPE (args[i].tree_value);
+         if ((TREE_CODE (type) == UNION_TYPE
+              || TREE_CODE (type) == RECORD_TYPE)
+             && TYPE_TRANSPARENT_AGGR (type))
+           type = TREE_TYPE (first_field (type));
          /* Set non-negative if we must move a word at a time, even if
             just one word (e.g, partial == 4 && mode == DFmode).  Set
             to -1 if we just use a normal move insn.  This value can be
@@ -2783,11 +2788,11 @@ load_register_parameters (struct arg_data *args, int num_actuals,
              gcc_assert (partial % UNITS_PER_WORD == 0);
              nregs = partial / UNITS_PER_WORD;
            }
-         else if (TYPE_MODE (TREE_TYPE (args[i].tree_value)) == BLKmode)
+         else if (TYPE_MODE (type) == BLKmode)
            {
              /* Variable-sized parameters should be described by a
                 PARALLEL instead.  */
-             const_size = int_size_in_bytes (TREE_TYPE (args[i].tree_value));
+             const_size = int_size_in_bytes (type);
              gcc_assert (const_size >= 0);
              nregs = (const_size + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD;
              size = const_size;
@@ -2914,8 +2919,7 @@ load_register_parameters (struct arg_data *args, int num_actuals,
          if (GET_CODE (reg) == PARALLEL)
            use_group_regs (call_fusage, reg);
          else if (nregs == -1)
-           use_reg_mode (call_fusage, reg,
-                         TYPE_MODE (TREE_TYPE (args[i].tree_value)));
+           use_reg_mode (call_fusage, reg, TYPE_MODE (type));
          else if (nregs > 0)
            use_regs (call_fusage, REGNO (reg), nregs);
        }
index 1d48a80..3a905cb 100644 (file)
@@ -1,3 +1,10 @@
+2019-09-05  Jakub Jelinek  <jakub@redhat.com>
+
+       PR middle-end/91001
+       PR middle-end/91105
+       PR middle-end/91106
+       * gcc.c-torture/compile/pr91001.c: New test.
+
 2019-09-05  Richard Biener  <rguenther@suse.de>
 
        PR rtl-optimization/91656
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr91001.c b/gcc/testsuite/gcc.c-torture/compile/pr91001.c
new file mode 100644 (file)
index 0000000..4b6a017
--- /dev/null
@@ -0,0 +1,31 @@
+/* PR middle-end/91001 */
+/* PR middle-end/91105 */
+/* PR middle-end/91106 */
+
+struct __attribute__((packed)) S { short b; char c; };
+struct T { short b, c, d; };
+struct __attribute__((packed)) R { int b; char c; };
+union __attribute__((aligned(128), transparent_union)) U { struct S c; } u;
+union __attribute__((aligned(32), transparent_union)) V { struct T c; } v;
+union __attribute__((aligned(32), transparent_union)) W { struct R c; } w;
+void foo (union U);
+void bar (union V);
+void baz (union W);
+
+void
+qux (void)
+{
+  foo (u);
+}
+
+void
+quux (void)
+{
+  bar (v);
+}
+
+void
+corge (void)
+{
+  baz (w);
+}