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));