This patch makes the CONCAT handing in expand_assignment cope with
polynomial mode sizes.  The mode of the CONCAT must be complex,
so we can base the tests on the sizes of the real and imaginary
components.


2017-10-23  Richard Sandiford  <richard.sandif...@linaro.org>
            Alan Hayward  <alan.hayw...@arm.com>
            David Sherwood  <david.sherw...@arm.com>

gcc/
        * expr.c (expand_assignment): Cope with polynomial mode sizes
        when assigning to a CONCAT.

Index: gcc/expr.c
===================================================================
--- gcc/expr.c  2017-10-23 17:25:54.178292230 +0100
+++ gcc/expr.c  2017-10-23 17:25:56.086223649 +0100
@@ -5109,32 +5109,36 @@ expand_assignment (tree to, tree from, b
       /* Handle expand_expr of a complex value returning a CONCAT.  */
       else if (GET_CODE (to_rtx) == CONCAT)
        {
-         unsigned short mode_bitsize = GET_MODE_BITSIZE (GET_MODE (to_rtx));
+         machine_mode to_mode = GET_MODE (to_rtx);
+         gcc_checking_assert (COMPLEX_MODE_P (to_mode));
+         poly_int64 mode_bitsize = GET_MODE_BITSIZE (to_mode);
+         unsigned short inner_bitsize = GET_MODE_UNIT_BITSIZE (to_mode);
          if (COMPLEX_MODE_P (TYPE_MODE (TREE_TYPE (from)))
              && known_zero (bitpos)
              && must_eq (bitsize, mode_bitsize))
            result = store_expr (from, to_rtx, false, nontemporal, reversep);
-         else if (must_eq (bitsize, mode_bitsize / 2)
+         else if (must_eq (bitsize, inner_bitsize)
                   && (known_zero (bitpos)
-                      || must_eq (bitpos, mode_bitsize / 2)))
+                      || must_eq (bitpos, inner_bitsize)))
            result = store_expr (from, XEXP (to_rtx, maybe_nonzero (bitpos)),
                                 false, nontemporal, reversep);
-         else if (must_le (bitpos + bitsize, mode_bitsize / 2))
+         else if (must_le (bitpos + bitsize, inner_bitsize))
            result = store_field (XEXP (to_rtx, 0), bitsize, bitpos,
                                  bitregion_start, bitregion_end,
                                  mode1, from, get_alias_set (to),
                                  nontemporal, reversep);
-         else if (must_ge (bitpos, mode_bitsize / 2))
+         else if (must_ge (bitpos, inner_bitsize))
            result = store_field (XEXP (to_rtx, 1), bitsize,
-                                 bitpos - mode_bitsize / 2,
+                                 bitpos - inner_bitsize,
                                  bitregion_start, bitregion_end,
                                  mode1, from, get_alias_set (to),
                                  nontemporal, reversep);
-         else if (known_zero (bitpos) && must_eq (bitsize, mode_bitsize))
+         else if (known_zero (bitpos)
+                  && must_eq (bitsize, mode_bitsize))
            {
              rtx from_rtx;
              result = expand_normal (from);
-             from_rtx = simplify_gen_subreg (GET_MODE (to_rtx), result,
+             from_rtx = simplify_gen_subreg (to_mode, result,
                                              TYPE_MODE (TREE_TYPE (from)), 0);
              emit_move_insn (XEXP (to_rtx, 0),
                              read_complex_part (from_rtx, false));

Reply via email to