aboutsummaryrefslogtreecommitdiff
path: root/gcc/expr.c
diff options
context:
space:
mode:
authorRichard Guenther <rguenther@suse.de>2011-10-18 08:46:00 +0000
committerRichard Biener <rguenth@gcc.gnu.org>2011-10-18 08:46:00 +0000
commitcab35794426a18f99a26d47b2c94546569cfacc1 (patch)
tree1a8080e2ebcb325ca311d4643aef5acb4e9cbca5 /gcc/expr.c
parentd17687f6f0ec28df90cb851a15cf0945d7b7ba57 (diff)
downloadgcc-cab35794426a18f99a26d47b2c94546569cfacc1.zip
gcc-cab35794426a18f99a26d47b2c94546569cfacc1.tar.gz
gcc-cab35794426a18f99a26d47b2c94546569cfacc1.tar.bz2
re PR middle-end/50716 (Segmentation fault caused by misaligned vector access)
2011-10-18 Richard Guenther <rguenther@suse.de> PR middle-end/50716 * expr.c (get_object_or_type_alignment): New function. (expand_assignment): Use it. (expand_expr_real_1): Likewise. From-SVN: r180125
Diffstat (limited to 'gcc/expr.c')
-rw-r--r--gcc/expr.c39
1 files changed, 30 insertions, 9 deletions
diff --git a/gcc/expr.c b/gcc/expr.c
index b020978..c1117a8 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -4544,6 +4544,27 @@ get_bit_range (unsigned HOST_WIDE_INT *bitstart,
}
}
+/* Return the alignment of the object EXP, also considering its type
+ when we do not know of explicit misalignment.
+ ??? Note that, in the general case, the type of an expression is not kept
+ consistent with misalignment information by the front-end, for
+ example when taking the address of a member of a packed structure.
+ However, in most of the cases, expressions have the alignment of
+ their type, so we optimistically fall back to the alignment of the
+ type when we cannot compute a misalignment. */
+
+static unsigned int
+get_object_or_type_alignment (tree exp)
+{
+ unsigned HOST_WIDE_INT misalign;
+ unsigned int align = get_object_alignment_1 (exp, &misalign);
+ if (misalign != 0)
+ align = (misalign & -misalign);
+ else
+ align = MAX (TYPE_ALIGN (TREE_TYPE (exp)), align);
+ return align;
+}
+
/* Expand an assignment that stores the value of FROM into TO. If NONTEMPORAL
is true, try generating a nontemporal store. */
@@ -4553,7 +4574,7 @@ expand_assignment (tree to, tree from, bool nontemporal)
rtx to_rtx = 0;
rtx result;
enum machine_mode mode;
- int align;
+ unsigned int align;
enum insn_code icode;
/* Don't crash if the lhs of the assignment was erroneous. */
@@ -4571,8 +4592,8 @@ expand_assignment (tree to, tree from, bool nontemporal)
if ((TREE_CODE (to) == MEM_REF
|| TREE_CODE (to) == TARGET_MEM_REF)
&& mode != BLKmode
- && ((align = MAX (TYPE_ALIGN (TREE_TYPE (to)), get_object_alignment (to)))
- < (signed) GET_MODE_ALIGNMENT (mode))
+ && ((align = get_object_or_type_alignment (to))
+ < GET_MODE_ALIGNMENT (mode))
&& ((icode = optab_handler (movmisalign_optab, mode))
!= CODE_FOR_nothing))
{
@@ -9241,7 +9262,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (exp));
struct mem_address addr;
enum insn_code icode;
- int align;
+ unsigned int align;
get_address_description (exp, &addr);
op0 = addr_for_mem_ref (&addr, as, true);
@@ -9249,9 +9270,9 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
temp = gen_rtx_MEM (mode, op0);
set_mem_attributes (temp, exp, 0);
set_mem_addr_space (temp, as);
- align = MAX (TYPE_ALIGN (TREE_TYPE (exp)), get_object_alignment (exp));
+ align = get_object_or_type_alignment (exp);
if (mode != BLKmode
- && (unsigned) align < GET_MODE_ALIGNMENT (mode)
+ && align < GET_MODE_ALIGNMENT (mode)
/* If the target does not have special handling for unaligned
loads of mode then it can use regular moves for them. */
&& ((icode = optab_handler (movmisalign_optab, mode))
@@ -9278,7 +9299,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
tree base = TREE_OPERAND (exp, 0);
gimple def_stmt;
enum insn_code icode;
- int align;
+ unsigned align;
/* Handle expansion of non-aliased memory with non-BLKmode. That
might end up in a register. */
if (TREE_CODE (base) == ADDR_EXPR)
@@ -9329,7 +9350,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
gimple_assign_rhs1 (def_stmt), mask);
TREE_OPERAND (exp, 0) = base;
}
- align = MAX (TYPE_ALIGN (TREE_TYPE (exp)), get_object_alignment (exp));
+ align = get_object_or_type_alignment (exp);
op0 = expand_expr (base, NULL_RTX, VOIDmode, EXPAND_SUM);
op0 = memory_address_addr_space (address_mode, op0, as);
if (!integer_zerop (TREE_OPERAND (exp, 1)))
@@ -9345,7 +9366,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
if (TREE_THIS_VOLATILE (exp))
MEM_VOLATILE_P (temp) = 1;
if (mode != BLKmode
- && (unsigned) align < GET_MODE_ALIGNMENT (mode)
+ && align < GET_MODE_ALIGNMENT (mode)
/* If the target does not have special handling for unaligned
loads of mode then it can use regular moves for them. */
&& ((icode = optab_handler (movmisalign_optab, mode))