aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2018-01-01 00:51:14 +0100
committerJakub Jelinek <jakub@gcc.gnu.org>2018-01-01 00:51:14 +0100
commitc1329fc84c8f7ee892070cb4aa514c4dbab70625 (patch)
tree99327b117c62805bc20eb2ed91a3f21228c802e6 /gcc
parentd235d09b7c86a2955bebdcb1991cd21758bcc21b (diff)
downloadgcc-c1329fc84c8f7ee892070cb4aa514c4dbab70625.zip
gcc-c1329fc84c8f7ee892070cb4aa514c4dbab70625.tar.gz
gcc-c1329fc84c8f7ee892070cb4aa514c4dbab70625.tar.bz2
re PR tree-optimization/83609 (ICE in read_complex_part at gcc/expr.c:3202)
PR middle-end/83609 * expr.c (expand_assignment): Fix up a typo in simplify_gen_subreg last argument when extracting from CONCAT. If either from_real or from_imag is NULL, use expansion through memory. If result is not a CONCAT and simplify_gen_subreg fails, try to simplify_gen_subreg the parts directly to inner mode, if even that fails, use expansion through memory. * gcc.dg/pr83609.c: New test. * g++.dg/opt/pr83609.C: New test. From-SVN: r256052
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/expr.c33
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/g++.dg/opt/pr83609.C28
-rw-r--r--gcc/testsuite/gcc.dg/pr83609.c29
5 files changed, 97 insertions, 5 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 548bb17..98073e8 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,13 @@
2018-01-01 Jakub Jelinek <jakub@redhat.com>
+ PR middle-end/83609
+ * expr.c (expand_assignment): Fix up a typo in simplify_gen_subreg
+ last argument when extracting from CONCAT. If either from_real or
+ from_imag is NULL, use expansion through memory. If result is not
+ a CONCAT and simplify_gen_subreg fails, try to simplify_gen_subreg
+ the parts directly to inner mode, if even that fails, use expansion
+ through memory.
+
PR middle-end/83623
* expmed.c (expand_shift_1): For 2-byte rotates by BITS_PER_UNIT,
check for bswap in mode rather than HImode and use that in expand_unop
diff --git a/gcc/expr.c b/gcc/expr.c
index 4e7349e..0a73576 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -5158,7 +5158,9 @@ expand_assignment (tree to, tree from, bool nontemporal)
from_mode, 0);
rtx from_imag
= simplify_gen_subreg (to_mode, XEXP (result, 1),
- from_mode, 1);
+ from_mode, 0);
+ if (!from_real || !from_imag)
+ goto concat_store_slow;
emit_move_insn (XEXP (to_rtx, 0), from_real);
emit_move_insn (XEXP (to_rtx, 1), from_imag);
}
@@ -5167,14 +5169,35 @@ expand_assignment (tree to, tree from, bool nontemporal)
rtx from_rtx
= simplify_gen_subreg (GET_MODE (to_rtx), result,
TYPE_MODE (TREE_TYPE (from)), 0);
- emit_move_insn (XEXP (to_rtx, 0),
- read_complex_part (from_rtx, false));
- emit_move_insn (XEXP (to_rtx, 1),
- read_complex_part (from_rtx, true));
+ if (from_rtx)
+ {
+ emit_move_insn (XEXP (to_rtx, 0),
+ read_complex_part (from_rtx, false));
+ emit_move_insn (XEXP (to_rtx, 1),
+ read_complex_part (from_rtx, true));
+ }
+ else
+ {
+ machine_mode to_mode
+ = GET_MODE_INNER (GET_MODE (to_rtx));
+ rtx from_real
+ = simplify_gen_subreg (to_mode, result,
+ TYPE_MODE (TREE_TYPE (from)),
+ 0);
+ rtx from_imag
+ = simplify_gen_subreg (to_mode, result,
+ TYPE_MODE (TREE_TYPE (from)),
+ GET_MODE_SIZE (to_mode));
+ if (!from_real || !from_imag)
+ goto concat_store_slow;
+ emit_move_insn (XEXP (to_rtx, 0), from_real);
+ emit_move_insn (XEXP (to_rtx, 1), from_imag);
+ }
}
}
else
{
+ concat_store_slow:;
rtx temp = assign_stack_temp (GET_MODE (to_rtx),
GET_MODE_SIZE (GET_MODE (to_rtx)));
write_complex_part (temp, XEXP (to_rtx, 0), false);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index f89ae2e..59c9543 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,9 @@
2018-01-01 Jakub Jelinek <jakub@redhat.com>
+ PR middle-end/83609
+ * gcc.dg/pr83609.c: New test.
+ * g++.dg/opt/pr83609.C: New test.
+
PR middle-end/83623
* gcc.dg/pr83623.c: New test.
diff --git a/gcc/testsuite/g++.dg/opt/pr83609.C b/gcc/testsuite/g++.dg/opt/pr83609.C
new file mode 100644
index 0000000..a43d291
--- /dev/null
+++ b/gcc/testsuite/g++.dg/opt/pr83609.C
@@ -0,0 +1,28 @@
+// PR middle-end/83609
+// { dg-do compile }
+// { dg-options "-O2 -fno-tree-forwprop" }
+
+template <typename> class B;
+template <> struct B<float>
+{
+ float foo () { return __real__ b; }
+ _Complex float b;
+};
+
+void bar (int);
+
+template <class T>
+void
+baz ()
+{
+ B<T> h;
+ T *a = (T *) &h;
+ a[0] = a[1] = 6;
+ h.foo () ? void () : bar (7);
+}
+
+int
+main ()
+{
+ baz<float> ();
+}
diff --git a/gcc/testsuite/gcc.dg/pr83609.c b/gcc/testsuite/gcc.dg/pr83609.c
new file mode 100644
index 0000000..eac11fc
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr83609.c
@@ -0,0 +1,29 @@
+/* PR middle-end/83609 */
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-tree-forwprop -fno-tree-ccp -fno-tree-fre -fno-tree-pre -fno-code-hoisting" } */
+
+#if __SIZEOF_LONG_LONG__ == 2 * __SIZEOF_FLOAT__
+_Complex float
+foo (void)
+{
+ _Complex float c;
+ *((unsigned long long *)&c) = 0x123456789abcdef0ULL;
+ return c;
+}
+
+int
+main ()
+{
+ union { _Complex float c; unsigned long long l; } u;
+ u.c = foo ();
+ if (u.l != 0x123456789abcdef0ULL)
+ __builtin_abort ();
+ return 0;
+}
+#else
+int
+main ()
+{
+ return 0;
+}
+#endif