/* Convert tree expression to rtl instructions, for GNU compiler.
Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
- Free Software Foundation, Inc.
+ 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011,
+ 2012 Free Software Foundation, Inc.
This file is part of GCC.
int reverse;
};
-static unsigned HOST_WIDE_INT move_by_pieces_ninsns (unsigned HOST_WIDE_INT,
- unsigned int,
- unsigned int);
static void move_by_pieces_1 (rtx (*) (rtx, ...), enum machine_mode,
struct move_by_pieces_d *);
static bool block_move_libcall_safe_for_call_parm (void);
/* Return number of insns required to move L bytes by pieces.
ALIGN (in bits) is maximum alignment we can assume. */
-static unsigned HOST_WIDE_INT
+unsigned HOST_WIDE_INT
move_by_pieces_ninsns (unsigned HOST_WIDE_INT l, unsigned int align,
unsigned int max_size)
{
(1) One or more auto-inc style memory references (aka pushes),
(2) One or more addition/subtraction with the SP as destination,
(3) A single move insn with the SP as destination,
- (4) A call_pop insn.
+ (4) A call_pop insn,
+ (5) Noreturn call insns if !ACCUMULATE_OUTGOING_ARGS.
- Insns in the sequence that do not modify the SP are ignored.
+ Insns in the sequence that do not modify the SP are ignored,
+ except for noreturn calls.
The return value is the amount of adjustment that can be trivially
verified, via immediate operand or auto-inc. If the adjustment
this_delta = find_args_size_adjust (insn);
if (this_delta == 0)
- continue;
+ {
+ if (!CALL_P (insn)
+ || ACCUMULATE_OUTGOING_ARGS
+ || find_reg_note (insn, REG_NORETURN, NULL_RTX) == NULL_RTX)
+ continue;
+ }
gcc_assert (!saw_unknown);
if (this_delta == HOST_WIDE_INT_MIN)
|| bitpos % GET_MODE_ALIGNMENT (mode))
&& SLOW_UNALIGNED_ACCESS (mode, MEM_ALIGN (target)))
|| (bitpos % BITS_PER_UNIT != 0)))
+ || (bitsize >= 0 && mode != BLKmode
+ && GET_MODE_BITSIZE (mode) > bitsize)
/* If the RHS and field are a constant size and the size of the
RHS isn't the same size as the bitfield, we must use bitfield
operations. */
return temp;
}
- case VEC_EXTRACT_EVEN_EXPR:
- case VEC_EXTRACT_ODD_EXPR:
- case VEC_INTERLEAVE_HIGH_EXPR:
- case VEC_INTERLEAVE_LOW_EXPR:
- goto binop;
-
case VEC_LSHIFT_EXPR:
case VEC_RSHIFT_EXPR:
{
case VEC_PERM_EXPR:
expand_operands (treeop0, treeop1, target, &op0, &op1, EXPAND_NORMAL);
op2 = expand_normal (treeop2);
+
+ /* Careful here: if the target doesn't support integral vector modes,
+ a constant selection vector could wind up smooshed into a normal
+ integral constant. */
+ if (CONSTANT_P (op2) && GET_CODE (op2) != CONST_VECTOR)
+ {
+ tree sel_type = TREE_TYPE (treeop2);
+ enum machine_mode vmode
+ = mode_for_vector (TYPE_MODE (TREE_TYPE (sel_type)),
+ TYPE_VECTOR_SUBPARTS (sel_type));
+ gcc_assert (GET_MODE_CLASS (vmode) == MODE_VECTOR_INT);
+ op2 = simplify_subreg (vmode, op2, TYPE_MODE (sel_type), 0);
+ gcc_assert (op2 && GET_CODE (op2) == CONST_VECTOR);
+ }
+ else
+ gcc_assert (GET_MODE_CLASS (GET_MODE (op2)) == MODE_VECTOR_INT);
+
temp = expand_vec_perm (mode, op0, op1, op2, target);
gcc_assert (temp);
return temp;