+2016-10-29 Jakub Jelinek <jakub@redhat.com>
+
+ PR rtl-optimization/77919
+ * expr.c (expand_expr_real_1) <normal_inner_ref>: Only avoid forcing
+ into memory if both modes are complex and their inner modes have the
+ same precision. If the two modes are different complex modes, convert
+ each part separately and generate a new CONCAT.
+
2016-10-29 John David Anglin <danglin@gcc.gnu.org>
* config/pa/pa64-hpux.h (FINI_SECTION_ASM_OP): Define to null string.
{
if (bitpos == 0
&& bitsize == GET_MODE_BITSIZE (GET_MODE (op0))
- && COMPLEX_MODE_P (mode1))
+ && COMPLEX_MODE_P (mode1)
+ && COMPLEX_MODE_P (GET_MODE (op0))
+ && (GET_MODE_PRECISION (GET_MODE_INNER (mode1))
+ == GET_MODE_PRECISION (GET_MODE_INNER (GET_MODE (op0)))))
{
if (reversep)
op0 = flip_storage_order (GET_MODE (op0), op0);
+ if (mode1 != GET_MODE (op0))
+ {
+ rtx parts[2];
+ for (int i = 0; i < 2; i++)
+ {
+ rtx op = read_complex_part (op0, i != 0);
+ if (GET_CODE (op) == SUBREG)
+ op = force_reg (GET_MODE (op), op);
+ rtx temp = gen_lowpart_common (GET_MODE_INNER (mode1),
+ op);
+ if (temp)
+ op = temp;
+ else
+ {
+ if (!REG_P (op) && !MEM_P (op))
+ op = force_reg (GET_MODE (op), op);
+ op = gen_lowpart (GET_MODE_INNER (mode1), op);
+ }
+ parts[i] = op;
+ }
+ op0 = gen_rtx_CONCAT (mode1, parts[0], parts[1]);
+ }
return op0;
}
if (bitpos == 0
2016-10-29 Jakub Jelinek <jakub@redhat.com>
+ PR rtl-optimization/77919
+ * g++.dg/torture/pr77919-2.C: New test.
+
PR target/78148
* gcc.dg/pr78148.c: New test.
--- /dev/null
+// PR rtl-optimization/77919
+// { dg-do compile }
+
+typedef _Complex long long B;
+struct A { A (double) {} _Complex double i; };
+typedef struct { B b; } C;
+struct D { D (const B &x) : b (x) {} B b; };
+static inline B foo (const double *x) { C *a; a = (C *) x; return a->b; }
+static inline D baz (const A &x) { return foo ((double *) &x); }
+D b = baz (0);