/* Lower vector operations to scalar operations.
- Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
This file is part of GCC.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA. */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA. */
#include "config.h"
#include "system.h"
{
if (bitpos)
return gimplify_build3 (bsi, BIT_FIELD_REF, type, t, bitsize, bitpos);
-
- /* Build a conversion; VIEW_CONVERT_EXPR is very expensive unless T will
- anyway be stored in memory, so prefer NOP_EXPR. */
- else if (TYPE_MODE (type) == BLKmode)
- return gimplify_build1 (bsi, VIEW_CONVERT_EXPR, type, t);
else
- return gimplify_build1 (bsi, NOP_EXPR, type, t);
+ return gimplify_build1 (bsi, VIEW_CONVERT_EXPR, type, t);
}
static tree
tree type, tree inner_type,
tree a, tree b, enum tree_code code)
{
- tree head, *chain = &head;
+ VEC(constructor_elt,gc) *v;
tree part_width = TYPE_SIZE (inner_type);
tree index = bitsize_int (0);
int nunits = TYPE_VECTOR_SUBPARTS (type);
/ tree_low_cst (TYPE_SIZE (TREE_TYPE (type)), 1);
int i;
+ v = VEC_alloc(constructor_elt, gc, (nunits + delta - 1) / delta);
for (i = 0; i < nunits;
i += delta, index = int_const_binop (PLUS_EXPR, index, part_width, 0))
{
tree result = f (bsi, inner_type, a, b, index, part_width, code);
- *chain = tree_cons (NULL_TREE, result, NULL_TREE);
- chain = &TREE_CHAIN (*chain);
+ constructor_elt *ce = VEC_quick_push (constructor_elt, v, NULL);
+ ce->index = NULL_TREE;
+ ce->value = result;
}
- return build1 (CONSTRUCTOR, type, head);
+ return build_constructor (type, v);
}
/* Expand a vector operation to scalars with the freedom to use
{
case PLUS_EXPR:
case MINUS_EXPR:
- if (!TYPE_TRAP_SIGNED (type))
+ if (!TYPE_OVERFLOW_TRAPS (type))
return expand_vector_addition (bsi, do_binop, do_plus_minus, type,
TREE_OPERAND (rhs, 0),
TREE_OPERAND (rhs, 1), code);
break;
case NEGATE_EXPR:
- if (!TYPE_TRAP_SIGNED (type))
+ if (!TYPE_OVERFLOW_TRAPS (type))
return expand_vector_addition (bsi, do_unop, do_negate, type,
TREE_OPERAND (rhs, 0),
NULL_TREE, code);
enum machine_mode best_mode = VOIDmode, mode;
int best_nunits = 0;
- if (GET_MODE_CLASS (inner_mode) == MODE_FLOAT)
+ if (SCALAR_FLOAT_MODE_P (inner_mode))
mode = MIN_MODE_VECTOR_FLOAT;
else
mode = MIN_MODE_VECTOR_INT;
{
case RETURN_EXPR:
stmt = TREE_OPERAND (stmt, 0);
- if (!stmt || TREE_CODE (stmt) != MODIFY_EXPR)
+ if (!stmt || TREE_CODE (stmt) != GIMPLE_MODIFY_STMT)
return;
/* FALLTHRU */
- case MODIFY_EXPR:
- p_lhs = &TREE_OPERAND (stmt, 0);
- p_rhs = &TREE_OPERAND (stmt, 1);
+ case GIMPLE_MODIFY_STMT:
+ p_lhs = &GIMPLE_STMT_OPERAND (stmt, 0);
+ p_rhs = &GIMPLE_STMT_OPERAND (stmt, 1);
lhs = *p_lhs;
rhs = *p_rhs;
break;
&& TREE_CODE_CLASS (code) != tcc_binary)
return;
- if (code == NOP_EXPR || code == VIEW_CONVERT_EXPR)
+ if (code == NOP_EXPR
+ || code == FLOAT_EXPR
+ || code == FIX_TRUNC_EXPR
+ || code == VIEW_CONVERT_EXPR)
return;
gcc_assert (code != CONVERT_EXPR);
op = optab_for_tree_code (code, type);
+ /* For widening/narrowing vector operations, the relevant type is of the
+ arguments, not the widened result. */
+ if (code == WIDEN_SUM_EXPR
+ || code == VEC_WIDEN_MULT_HI_EXPR
+ || code == VEC_WIDEN_MULT_LO_EXPR
+ || code == VEC_UNPACK_HI_EXPR
+ || code == VEC_UNPACK_LO_EXPR
+ || code == VEC_PACK_MOD_EXPR
+ || code == VEC_PACK_SAT_EXPR)
+ type = TREE_TYPE (TREE_OPERAND (rhs, 0));
+
/* Optabs will try converting a negation into a subtraction, so
look for it as well. TODO: negation of floating-point vectors
might be turned into an exclusive OR toggling the sign bit. */
compute_type = TREE_TYPE (type);
}
+ gcc_assert (code != VEC_LSHIFT_EXPR && code != VEC_RSHIFT_EXPR);
rhs = expand_vector_operation (bsi, type, compute_type, rhs, code);
if (lang_hooks.types_compatible_p (TREE_TYPE (lhs), TREE_TYPE (rhs)))
*p_rhs = rhs;
else
- {
- /* Build a conversion; VIEW_CONVERT_EXPR is very expensive unless T will
- be stored in memory anyway, so prefer NOP_EXPR. We should also try
- performing the VIEW_CONVERT_EXPR on the left side of the
- assignment. */
- if (TYPE_MODE (TREE_TYPE (rhs)) == BLKmode)
- *p_rhs = gimplify_build1 (bsi, VIEW_CONVERT_EXPR, TREE_TYPE (lhs), rhs);
- else
- *p_rhs = gimplify_build1 (bsi, NOP_EXPR, TREE_TYPE (lhs), rhs);
- }
+ *p_rhs = gimplify_build1 (bsi, VIEW_CONVERT_EXPR, TREE_TYPE (lhs), rhs);
mark_stmt_modified (bsi_stmt (*bsi));
}
return flag_tree_vectorize != 0;
}
-static void
+static unsigned int
expand_vector_operations (void)
{
block_stmt_iterator bsi;
update_stmt_if_modified (bsi_stmt (bsi));
}
}
+ return 0;
}
struct tree_opt_pass pass_lower_vector =