VIEW_CONVERT_EXPR slots for strict-align targets (PR 83884)
authorRichard Sandiford <richard.sandiford@linaro.org>
Wed, 17 Jan 2018 09:28:28 +0000 (09:28 +0000)
committerRichard Sandiford <rsandifo@gcc.gnu.org>
Wed, 17 Jan 2018 09:28:28 +0000 (09:28 +0000)
This PR is about a case in which we VIEW_CONVERT a variable-sized
unaligned record:

 <record_type 0x7ffff6d92888 check_displace_generation__T245b sizes-gimplified type_7 BLK
    size <var_decl 0x7ffff6846510 D.3499 ...>
    unit-size <var_decl 0x7ffff68465a0 D.3500 ...>
    align:8 ...>

to an aligned 32-bit integer.  The strict-alignment handling of
this case creates an aligned temporary slot, moves the operand
into the slot in the operand's original mode, then accesses the
slot in the more-aligned result mode.

Previously the size of the temporary slot was calculated using:

                  HOST_WIDE_INT temp_size
                    = MAX (int_size_in_bytes (inner_type),
                           (HOST_WIDE_INT) GET_MODE_SIZE (mode));

int_size_in_bytes would return -1 for the variable-length type,
so we'd use the size of the result mode for the slot.  r256152 replaced
int_size_in_bytes with tree_to_poly_uint64, which triggered an ICE.

If op0 has BLKmode we do a block copy of GET_MODE_SIZE (mode) bytes
and then convert the slot to "mode":

                  poly_uint64 mode_size = GET_MODE_SIZE (mode);
                  ...
                  if (GET_MODE (op0) == BLKmode)
                    {
                      rtx size_rtx = gen_int_mode (mode_size, Pmode);
                      emit_block_move (new_with_op0_mode, op0, size_rtx,
                                       (modifier == EXPAND_STACK_PARM
                                        ? BLOCK_OP_CALL_PARM
                                        : BLOCK_OP_NORMAL));
                    }
                  else
                    ...

                  op0 = new_rtx;
                }
            }

          op0 = adjust_address (op0, mode, 0);

so I think in that case just the size of "mode" is enough, even if op0
is a fixed-size type.  For non-BLKmode op0 we first move in op0's mode
and then convert the slot to "mode":

                    emit_move_insn (new_with_op0_mode, op0);

                  op0 = new_rtx;
                }
            }

          op0 = adjust_address (op0, mode, 0);

so I think we want the maximum of the two mode sizes in that case.

2018-01-17  Richard Sandiford  <richard.sandiford@linaro.org>

gcc/
PR middle-end/83884
* expr.c (expand_expr_real_1): Use the size of GET_MODE (op0)
rather than the size of inner_type to determine the stack slot size
when handling VIEW_CONVERT_EXPRs on strict-alignment targets.

From-SVN: r256779

gcc/ChangeLog
gcc/expr.c

index 4f83eb6..4c51987 100644 (file)
@@ -1,3 +1,10 @@
+2018-01-17  Richard Sandiford  <richard.sandiford@linaro.org>
+
+       PR middle-end/83884
+       * expr.c (expand_expr_real_1): Use the size of GET_MODE (op0)
+       rather than the size of inner_type to determine the stack slot size
+       when handling VIEW_CONVERT_EXPRs on strict-alignment targets.
+
 2018-01-16  Sebastian Peryt  <sebastian.peryt@intel.com>
 
        PR target/83546
index 42f889f..36a6c72 100644 (file)
@@ -11145,11 +11145,11 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
                }
              else if (STRICT_ALIGNMENT)
                {
-                 tree inner_type = TREE_TYPE (treeop0);
                  poly_uint64 mode_size = GET_MODE_SIZE (mode);
-                 poly_uint64 op0_size
-                   = tree_to_poly_uint64 (TYPE_SIZE_UNIT (inner_type));
-                 poly_int64 temp_size = upper_bound (op0_size, mode_size);
+                 poly_uint64 temp_size = mode_size;
+                 if (GET_MODE (op0) != BLKmode)
+                   temp_size = upper_bound (temp_size,
+                                            GET_MODE_SIZE (GET_MODE (op0)));
                  rtx new_rtx
                    = assign_stack_temp_for_type (mode, temp_size, type);
                  rtx new_with_op0_mode