}
}
+/* 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. */
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. */
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))
{
case VEC_EXTRACT_EVEN_EXPR:
case VEC_EXTRACT_ODD_EXPR:
- {
- expand_operands (treeop0, treeop1,
- NULL_RTX, &op0, &op1, EXPAND_NORMAL);
- this_optab = optab_for_tree_code (code, type, optab_default);
- temp = expand_binop (mode, this_optab, op0, op1, target, unsignedp,
- OPTAB_WIDEN);
- gcc_assert (temp);
- return temp;
- }
-
case VEC_INTERLEAVE_HIGH_EXPR:
case VEC_INTERLEAVE_LOW_EXPR:
- {
- expand_operands (treeop0, treeop1,
- NULL_RTX, &op0, &op1, EXPAND_NORMAL);
- this_optab = optab_for_tree_code (code, type, optab_default);
- temp = expand_binop (mode, this_optab, op0, op1, target, unsignedp,
- OPTAB_WIDEN);
- gcc_assert (temp);
- return temp;
- }
+ goto binop;
case VEC_LSHIFT_EXPR:
case VEC_RSHIFT_EXPR:
return target;
}
+ case VEC_WIDEN_LSHIFT_HI_EXPR:
+ case VEC_WIDEN_LSHIFT_LO_EXPR:
+ {
+ tree oprnd0 = treeop0;
+ tree oprnd1 = treeop1;
+
+ expand_operands (oprnd0, oprnd1, NULL_RTX, &op0, &op1, EXPAND_NORMAL);
+ target = expand_widen_pattern_expr (ops, op0, op1, NULL_RTX,
+ target, unsignedp);
+ gcc_assert (target);
+ return target;
+ }
+
case VEC_PACK_TRUNC_EXPR:
case VEC_PACK_SAT_EXPR:
case VEC_PACK_FIX_TRUNC_EXPR:
goto binop;
case VEC_PERM_EXPR:
- target = expand_vec_perm_expr (type, treeop0, treeop1, treeop2, target);
- gcc_assert (target);
- return target;
+ expand_operands (treeop0, treeop1, target, &op0, &op1, EXPAND_NORMAL);
+ op2 = expand_normal (treeop2);
+ temp = expand_vec_perm (mode, op0, op1, op2, target);
+ gcc_assert (temp);
+ return temp;
case DOT_PROD_EXPR:
{
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);
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))
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)
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)))
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))