summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoredlinger <edlinger@138bc75d-0d04-0410-961f-82ee72b054a4>2015-01-27 17:07:24 +0000
committeredlinger <edlinger@138bc75d-0d04-0410-961f-82ee72b054a4>2015-01-27 17:07:24 +0000
commitace0e93c74f0e98798ca33b8acbfe348e57cdc62 (patch)
treef8629d31cade44b547901ff38bccebb0bb25f53f
parentd14801f5a2323f6e724bd36d04373b4aa0864351 (diff)
downloadgcc-ace0e93c74f0e98798ca33b8acbfe348e57cdc62.tar.gz
Backport from mainline
fix for PR middle-end/57748 git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/gcc-4_8-branch@220179 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog20
-rw-r--r--gcc/cfgexpand.c2
-rw-r--r--gcc/expr.c213
-rw-r--r--gcc/expr.h11
-rw-r--r--gcc/testsuite/ChangeLog16
5 files changed, 136 insertions, 126 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index a1283d165a5..30a658d20ff 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,23 @@
+2015-01-27 Mikael Pettersson <mikpelinux@gmail.com>
+
+ Backport from mainline
+
+ 2013-09-20 Bernd Edlinger <bernd.edlinger@hotmail.de>
+
+ PR middle-end/57748
+ * expr.c (expand_assignment): Remove misalignp code path.
+
+ 2014-01-08 Bernd Edlinger <bernd.edlinger@hotmail.de>
+
+ PR middle-end/57748
+ * expr.h (expand_expr_real, expand_expr_real_1): Add new parameter
+ inner_reference_p.
+ (expand_expr, expand_normal): Adjust.
+ * expr.c (expand_expr_real, expand_expr_real_1): Add new parameter
+ inner_reference_p. Use inner_reference_p to expand inner references.
+ (store_expr): Adjust.
+ * cfgexpand.c (expand_call_stmt): Adjust.
+
2015-01-26 Uros Bizjak <ubizjak@gmail.com>
Backport from mainline
diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
index 1321c214d92..3edfeeea3d0 100644
--- a/gcc/cfgexpand.c
+++ b/gcc/cfgexpand.c
@@ -2111,7 +2111,7 @@ expand_call_stmt (gimple stmt)
if (lhs)
expand_assignment (lhs, exp, false);
else
- expand_expr_real_1 (exp, const0_rtx, VOIDmode, EXPAND_NORMAL, NULL);
+ expand_expr (exp, const0_rtx, VOIDmode, EXPAND_NORMAL);
mark_transaction_restart_calls (stmt);
}
diff --git a/gcc/expr.c b/gcc/expr.c
index 8a82b7af03f..8ec37336989 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -4708,8 +4708,6 @@ expand_assignment (tree to, tree from, bool nontemporal)
int unsignedp;
int volatilep = 0;
tree tem;
- bool misalignp;
- rtx mem = NULL_RTX;
push_temp_slots ();
tem = get_inner_reference (to, &bitsize, &bitpos, &offset, &mode1,
@@ -4728,40 +4726,7 @@ expand_assignment (tree to, tree from, bool nontemporal)
&& DECL_BIT_FIELD_TYPE (TREE_OPERAND (to, 1)))
get_bit_range (&bitregion_start, &bitregion_end, to, &bitpos, &offset);
- /* If we are going to use store_bit_field and extract_bit_field,
- make sure to_rtx will be safe for multiple use. */
- mode = TYPE_MODE (TREE_TYPE (tem));
- if (TREE_CODE (tem) == MEM_REF
- && mode != BLKmode
- && ((align = get_object_alignment (tem))
- < GET_MODE_ALIGNMENT (mode))
- && ((icode = optab_handler (movmisalign_optab, mode))
- != CODE_FOR_nothing))
- {
- struct expand_operand ops[2];
-
- misalignp = true;
- to_rtx = gen_reg_rtx (mode);
- mem = expand_expr (tem, NULL_RTX, VOIDmode, EXPAND_WRITE);
-
- /* If the misaligned store doesn't overwrite all bits, perform
- rmw cycle on MEM. */
- if (bitsize != GET_MODE_BITSIZE (mode))
- {
- create_input_operand (&ops[0], to_rtx, mode);
- create_fixed_operand (&ops[1], mem);
- /* The movmisalign<mode> pattern cannot fail, else the assignment
- would silently be omitted. */
- expand_insn (icode, 2, ops);
-
- mem = copy_rtx (mem);
- }
- }
- else
- {
- misalignp = false;
- to_rtx = expand_expr (tem, NULL_RTX, VOIDmode, EXPAND_WRITE);
- }
+ to_rtx = expand_expr (tem, NULL_RTX, VOIDmode, EXPAND_WRITE);
/* If the bitfield is volatile, we want to access it in the
field's mode, not the computed mode.
@@ -4900,17 +4865,6 @@ expand_assignment (tree to, tree from, bool nontemporal)
get_alias_set (to), nontemporal);
}
- if (misalignp)
- {
- struct expand_operand ops[2];
-
- create_fixed_operand (&ops[0], mem);
- create_input_operand (&ops[1], to_rtx, mode);
- /* The movmisalign<mode> pattern cannot fail, else the assignment
- would silently be omitted. */
- expand_insn (icode, 2, ops);
- }
-
if (result)
preserve_temp_slots (result);
pop_temp_slots ();
@@ -5262,7 +5216,7 @@ store_expr (tree exp, rtx target, int call_param_p, bool nontemporal)
temp = expand_expr_real (exp, tmp_target, GET_MODE (target),
(call_param_p
? EXPAND_STACK_PARM : EXPAND_NORMAL),
- &alt_rtl);
+ &alt_rtl, false);
}
/* If TEMP is a VOIDmode constant and the mode of the type of EXP is not
@@ -7881,11 +7835,21 @@ expand_constructor (tree exp, rtx target, enum expand_modifier modifier,
address, and ALT_RTL is non-NULL, then *ALT_RTL is set to the
DECL_RTL of the VAR_DECL. *ALT_RTL is also set if EXP is a
COMPOUND_EXPR whose second argument is such a VAR_DECL, and so on
- recursively. */
+ recursively.
+
+ If INNER_REFERENCE_P is true, we are expanding an inner reference.
+ In this case, we don't adjust a returned MEM rtx that wouldn't be
+ sufficiently aligned for its mode; instead, it's up to the caller
+ to deal with it afterwards. This is used to make sure that unaligned
+ base objects for which out-of-bounds accesses are supported, for
+ example record types with trailing arrays, aren't realigned behind
+ the back of the caller.
+ The normal operating mode is to pass FALSE for this parameter. */
rtx
expand_expr_real (tree exp, rtx target, enum machine_mode tmode,
- enum expand_modifier modifier, rtx *alt_rtl)
+ enum expand_modifier modifier, rtx *alt_rtl,
+ bool inner_reference_p)
{
rtx ret;
@@ -7897,7 +7861,8 @@ expand_expr_real (tree exp, rtx target, enum machine_mode tmode,
return ret ? ret : const0_rtx;
}
- ret = expand_expr_real_1 (exp, target, tmode, modifier, alt_rtl);
+ ret = expand_expr_real_1 (exp, target, tmode, modifier, alt_rtl,
+ inner_reference_p);
return ret;
}
@@ -9190,7 +9155,8 @@ expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode,
rtx
expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
- enum expand_modifier modifier, rtx *alt_rtl)
+ enum expand_modifier modifier, rtx *alt_rtl,
+ bool inner_reference_p)
{
rtx op0, op1, temp, decl_rtl;
tree type;
@@ -9336,7 +9302,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
set_curr_insn_location (gimple_location (g));
r = expand_expr_real (gimple_assign_rhs_to_tree (g), target,
- tmode, modifier, NULL);
+ tmode, modifier, NULL, inner_reference_p);
set_curr_insn_location (saved_loc);
if (REG_P (r) && !REG_EXPR (r))
set_reg_attrs_for_decl_rtl (SSA_NAME_VAR (exp), r);
@@ -9557,7 +9523,8 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
case SAVE_EXPR:
{
tree val = treeop0;
- rtx ret = expand_expr_real_1 (val, target, tmode, modifier, alt_rtl);
+ rtx ret = expand_expr_real_1 (val, target, tmode, modifier, alt_rtl,
+ inner_reference_p);
if (!SAVE_EXPR_RESOLVED_P (exp))
{
@@ -9706,6 +9673,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
MEM_VOLATILE_P (temp) = 1;
if (modifier != EXPAND_WRITE
&& modifier != EXPAND_MEMORY
+ && !inner_reference_p
&& mode != BLKmode
&& align < GET_MODE_ALIGNMENT (mode))
{
@@ -9940,18 +9908,19 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
computation, since it will need a temporary and TARGET is known
to have to do. This occurs in unchecked conversion in Ada. */
orig_op0 = op0
- = expand_expr (tem,
- (TREE_CODE (TREE_TYPE (tem)) == UNION_TYPE
- && COMPLETE_TYPE_P (TREE_TYPE (tem))
- && (TREE_CODE (TYPE_SIZE (TREE_TYPE (tem)))
- != INTEGER_CST)
- && modifier != EXPAND_STACK_PARM
- ? target : NULL_RTX),
- VOIDmode,
- (modifier == EXPAND_INITIALIZER
- || modifier == EXPAND_CONST_ADDRESS
- || modifier == EXPAND_STACK_PARM)
- ? modifier : EXPAND_NORMAL);
+ = expand_expr_real (tem,
+ (TREE_CODE (TREE_TYPE (tem)) == UNION_TYPE
+ && COMPLETE_TYPE_P (TREE_TYPE (tem))
+ && (TREE_CODE (TYPE_SIZE (TREE_TYPE (tem)))
+ != INTEGER_CST)
+ && modifier != EXPAND_STACK_PARM
+ ? target : NULL_RTX),
+ VOIDmode,
+ (modifier == EXPAND_INITIALIZER
+ || modifier == EXPAND_CONST_ADDRESS
+ || modifier == EXPAND_STACK_PARM)
+ ? modifier : EXPAND_NORMAL,
+ NULL, true);
/* If the bitfield is volatile, we want to access it in the
@@ -10302,17 +10271,18 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
{
/* See the normal_inner_ref case for the rationale. */
orig_op0
- = expand_expr (tem,
- (TREE_CODE (TREE_TYPE (tem)) == UNION_TYPE
- && (TREE_CODE (TYPE_SIZE (TREE_TYPE (tem)))
- != INTEGER_CST)
- && modifier != EXPAND_STACK_PARM
- ? target : NULL_RTX),
- VOIDmode,
- (modifier == EXPAND_INITIALIZER
- || modifier == EXPAND_CONST_ADDRESS
- || modifier == EXPAND_STACK_PARM)
- ? modifier : EXPAND_NORMAL);
+ = expand_expr_real (tem,
+ (TREE_CODE (TREE_TYPE (tem)) == UNION_TYPE
+ && (TREE_CODE (TYPE_SIZE (TREE_TYPE (tem)))
+ != INTEGER_CST)
+ && modifier != EXPAND_STACK_PARM
+ ? target : NULL_RTX),
+ VOIDmode,
+ (modifier == EXPAND_INITIALIZER
+ || modifier == EXPAND_CONST_ADDRESS
+ || modifier == EXPAND_STACK_PARM)
+ ? modifier : EXPAND_NORMAL,
+ NULL, true);
if (MEM_P (orig_op0))
{
@@ -10339,8 +10309,8 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
}
if (!op0)
- op0 = expand_expr (treeop0,
- NULL_RTX, VOIDmode, modifier);
+ op0 = expand_expr_real (treeop0, NULL_RTX, VOIDmode, modifier,
+ NULL, inner_reference_p);
/* If the input and output modes are both the same, we are done. */
if (mode == GET_MODE (op0))
@@ -10407,50 +10377,53 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
op0 = copy_rtx (op0);
set_mem_align (op0, MAX (MEM_ALIGN (op0), TYPE_ALIGN (type)));
}
- else if (mode != BLKmode
- && MEM_ALIGN (op0) < GET_MODE_ALIGNMENT (mode)
- /* If the target does have special handling for unaligned
- loads of mode then use them. */
- && ((icode = optab_handler (movmisalign_optab, mode))
- != CODE_FOR_nothing))
- {
- rtx reg, insn;
-
- op0 = adjust_address (op0, mode, 0);
- /* We've already validated the memory, and we're creating a
- new pseudo destination. The predicates really can't
- fail. */
- reg = gen_reg_rtx (mode);
-
- /* Nor can the insn generator. */
- insn = GEN_FCN (icode) (reg, op0);
- emit_insn (insn);
- return reg;
- }
- else if (STRICT_ALIGNMENT
+ else if (modifier != EXPAND_WRITE
+ && modifier != EXPAND_MEMORY
+ && !inner_reference_p
&& mode != BLKmode
&& MEM_ALIGN (op0) < GET_MODE_ALIGNMENT (mode))
{
- tree inner_type = TREE_TYPE (treeop0);
- HOST_WIDE_INT temp_size
- = MAX (int_size_in_bytes (inner_type),
- (HOST_WIDE_INT) GET_MODE_SIZE (mode));
- rtx new_rtx
- = assign_stack_temp_for_type (mode, temp_size, type);
- rtx new_with_op0_mode
- = adjust_address (new_rtx, GET_MODE (op0), 0);
-
- gcc_assert (!TREE_ADDRESSABLE (exp));
-
- if (GET_MODE (op0) == BLKmode)
- emit_block_move (new_with_op0_mode, op0,
- GEN_INT (GET_MODE_SIZE (mode)),
- (modifier == EXPAND_STACK_PARM
- ? BLOCK_OP_CALL_PARM : BLOCK_OP_NORMAL));
- else
- emit_move_insn (new_with_op0_mode, op0);
+ /* If the target does have special handling for unaligned
+ loads of mode then use them. */
+ if ((icode = optab_handler (movmisalign_optab, mode))
+ != CODE_FOR_nothing)
+ {
+ rtx reg, insn;
+
+ op0 = adjust_address (op0, mode, 0);
+ /* We've already validated the memory, and we're creating a
+ new pseudo destination. The predicates really can't
+ fail. */
+ reg = gen_reg_rtx (mode);
+
+ /* Nor can the insn generator. */
+ insn = GEN_FCN (icode) (reg, op0);
+ emit_insn (insn);
+ return reg;
+ }
+ else if (STRICT_ALIGNMENT)
+ {
+ tree inner_type = TREE_TYPE (treeop0);
+ HOST_WIDE_INT temp_size
+ = MAX (int_size_in_bytes (inner_type),
+ (HOST_WIDE_INT) GET_MODE_SIZE (mode));
+ rtx new_rtx
+ = assign_stack_temp_for_type (mode, temp_size, type);
+ rtx new_with_op0_mode
+ = adjust_address (new_rtx, GET_MODE (op0), 0);
+
+ gcc_assert (!TREE_ADDRESSABLE (exp));
+
+ if (GET_MODE (op0) == BLKmode)
+ emit_block_move (new_with_op0_mode, op0,
+ GEN_INT (GET_MODE_SIZE (mode)),
+ (modifier == EXPAND_STACK_PARM
+ ? BLOCK_OP_CALL_PARM : BLOCK_OP_NORMAL));
+ else
+ emit_move_insn (new_with_op0_mode, op0);
- op0 = new_rtx;
+ op0 = new_rtx;
+ }
}
op0 = adjust_address (op0, mode, 0);
@@ -10550,7 +10523,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
/* WITH_SIZE_EXPR expands to its first argument. The caller should
have pulled out the size to use in whatever context it needed. */
return expand_expr_real (treeop0, original_target, tmode,
- modifier, alt_rtl);
+ modifier, alt_rtl, inner_reference_p);
default:
return expand_expr_real_2 (&ops, target, tmode, modifier);
diff --git a/gcc/expr.h b/gcc/expr.h
index 98c9daeda9c..4adebe43044 100644
--- a/gcc/expr.h
+++ b/gcc/expr.h
@@ -41,7 +41,8 @@ along with GCC; see the file COPYING3. If not see
is a constant that is not a legitimate address.
EXPAND_WRITE means we are only going to write to the resulting rtx.
EXPAND_MEMORY means we are interested in a memory result, even if
- the memory is constant and we could have propagated a constant value. */
+ the memory is constant and we could have propagated a constant value,
+ or the memory is unaligned on a STRICT_ALIGNMENT target. */
enum expand_modifier {EXPAND_NORMAL = 0, EXPAND_STACK_PARM, EXPAND_SUM,
EXPAND_CONST_ADDRESS, EXPAND_INITIALIZER, EXPAND_WRITE,
EXPAND_MEMORY};
@@ -428,9 +429,9 @@ extern rtx force_operand (rtx, rtx);
/* Work horses for expand_expr. */
extern rtx expand_expr_real (tree, rtx, enum machine_mode,
- enum expand_modifier, rtx *);
+ enum expand_modifier, rtx *, bool);
extern rtx expand_expr_real_1 (tree, rtx, enum machine_mode,
- enum expand_modifier, rtx *);
+ enum expand_modifier, rtx *, bool);
extern rtx expand_expr_real_2 (sepops, rtx, enum machine_mode,
enum expand_modifier);
@@ -441,13 +442,13 @@ static inline rtx
expand_expr (tree exp, rtx target, enum machine_mode mode,
enum expand_modifier modifier)
{
- return expand_expr_real (exp, target, mode, modifier, NULL);
+ return expand_expr_real (exp, target, mode, modifier, NULL, false);
}
static inline rtx
expand_normal (tree exp)
{
- return expand_expr_real (exp, NULL_RTX, VOIDmode, EXPAND_NORMAL, NULL);
+ return expand_expr_real (exp, NULL_RTX, VOIDmode, EXPAND_NORMAL, NULL, false);
}
/* At the start of a function, record that we have no previously-pushed
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index f55d90c46d1..d034bb2b7a5 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,19 @@
+2015-01-27 Mikael Pettersson <mikpelinux@gmail.com>
+
+ Backport from mainline
+
+ 2013-09-20 Bernd Edlinger <bernd.edlinger@hotmail.de>
+
+ PR middle-end/57748
+ * gcc.dg/torture/pr57748-1.c: New test.
+ * gcc.dg/torture/pr57748-2.c: New test.
+
+ 2014-01-08 Bernd Edlinger <bernd.edlinger@hotmail.de>
+
+ PR middle-end/57748
+ * gcc.dg/torture/pr57748-3.c: New test.
+ * gcc.dg/torture/pr57748-4.c: New test.
+
2015-01-24 Thomas Koenig <tkoenig@gcc.gnu.org>
PR fortran/56867