diff options
author | Richard Guenther <rguenther@suse.de> | 2011-10-18 08:46:00 +0000 |
---|---|---|
committer | Richard Biener <rguenth@gcc.gnu.org> | 2011-10-18 08:46:00 +0000 |
commit | cab35794426a18f99a26d47b2c94546569cfacc1 (patch) | |
tree | 1a8080e2ebcb325ca311d4643aef5acb4e9cbca5 /gcc/expr.c | |
parent | d17687f6f0ec28df90cb851a15cf0945d7b7ba57 (diff) | |
download | gcc-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.c | 39 |
1 files changed, 30 insertions, 9 deletions
@@ -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)) |