block_stmt_iterator loop_cond_bsi;
block_stmt_iterator incr_bsi;
bool insert_after;
- tree begin_label = tree_block_label (loop->latch);
- tree exit_label = tree_block_label (single_exit (loop)->dest);
tree init = build_int_cst (TREE_TYPE (niters), 0);
tree step = build_int_cst (TREE_TYPE (niters), 1);
- tree then_label;
- tree else_label;
LOC loop_loc;
orig_cond = get_loop_exit_condition (loop);
&incr_bsi, insert_after, &indx_before_incr, &indx_after_incr);
if (exit_edge->flags & EDGE_TRUE_VALUE) /* 'then' edge exits the loop. */
- {
- cond = build2 (GE_EXPR, boolean_type_node, indx_after_incr, niters);
- then_label = build1 (GOTO_EXPR, void_type_node, exit_label);
- else_label = build1 (GOTO_EXPR, void_type_node, begin_label);
- }
+ cond = build2 (GE_EXPR, boolean_type_node, indx_after_incr, niters);
else /* 'then' edge loops back. */
- {
- cond = build2 (LT_EXPR, boolean_type_node, indx_after_incr, niters);
- then_label = build1 (GOTO_EXPR, void_type_node, begin_label);
- else_label = build1 (GOTO_EXPR, void_type_node, exit_label);
- }
+ cond = build2 (LT_EXPR, boolean_type_node, indx_after_incr, niters);
cond_stmt = build3 (COND_EXPR, TREE_TYPE (orig_cond), cond,
- then_label, else_label);
+ NULL_TREE, NULL_TREE);
bsi_insert_before (&loop_cond_bsi, cond_stmt, BSI_SAME_STMT);
/* Remove old loop exit test: */
}
/* Generate new loop structure. */
- new_loop = duplicate_loop (loop, loop->outer);
+ new_loop = duplicate_loop (loop, loop_outer (loop));
if (!new_loop)
{
free (bbs);
{
block_stmt_iterator bsi;
edge new_e, enter_e;
- tree cond_stmt, then_label, else_label;
+ tree cond_stmt;
enter_e = EDGE_SUCC (guard_bb, 0);
enter_e->flags &= ~EDGE_FALLTHRU;
enter_e->flags |= EDGE_FALSE_VALUE;
bsi = bsi_last (guard_bb);
- then_label = build1 (GOTO_EXPR, void_type_node,
- tree_block_label (exit_bb));
- else_label = build1 (GOTO_EXPR, void_type_node,
- tree_block_label (enter_e->dest));
cond_stmt = build3 (COND_EXPR, void_type_node, cond,
- then_label, else_label);
+ NULL_TREE, NULL_TREE);
bsi_insert_after (&bsi, cond_stmt, BSI_NEW_STMT);
/* Add new edge to connect guard block to the merge/loop-exit block. */
new_e = make_edge (guard_bb, exit_bb, EDGE_TRUE_VALUE);
if (loop->inner
/* All loops have an outer scope; the only case loop->outer is NULL is for
the function itself. */
- || !loop->outer
+ || !loop_outer (loop)
|| loop->num_nodes != 2
|| !empty_block_p (loop->latch)
|| !single_exit (loop)
else
STMT_VINFO_DEF_TYPE (res) = vect_loop_def;
STMT_VINFO_SAME_ALIGN_REFS (res) = VEC_alloc (dr_p, heap, 5);
+ STMT_VINFO_INSIDE_OF_LOOP_COST (res) = 0;
+ STMT_VINFO_OUTSIDE_OF_LOOP_COST (res) = 0;
DR_GROUP_FIRST_DR (res) = NULL_TREE;
DR_GROUP_NEXT_DR (res) = NULL_TREE;
DR_GROUP_SIZE (res) = 0;
LOOP_VINFO_BBS (res) = bbs;
LOOP_VINFO_EXIT_COND (res) = NULL;
LOOP_VINFO_NITERS (res) = NULL;
+ LOOP_VINFO_COST_MODEL_MIN_ITERS (res) = 0;
LOOP_VINFO_VECTORIZABLE_P (res) = 0;
LOOP_PEELING_FOR_ALIGNMENT (res) = 0;
LOOP_VINFO_VECT_FACTOR (res) = 0;
VEC_free (tree, heap, LOOP_VINFO_MAY_MISALIGN_STMTS (loop_vinfo));
free (loop_vinfo);
+ loop->aux = NULL;
}
*dt = vect_constant_def;
return true;
}
+ if (is_gimple_min_invariant (operand))
+ {
+ *def = operand;
+ *dt = vect_invariant_def;
+ return true;
+ }
if (TREE_CODE (operand) != SSA_NAME)
{
if (IS_EMPTY_STMT (*def_stmt))
{
tree arg = TREE_OPERAND (*def_stmt, 0);
- if (TREE_CODE (arg) == INTEGER_CST || TREE_CODE (arg) == REAL_CST)
+ if (is_gimple_min_invariant (arg))
{
*def = operand;
*dt = vect_invariant_def;
widening operation that is supported by the target platform in
vector form (i.e., when operating on arguments of type VECTYPE).
- The two kinds of widening operations we currently support are
- NOP and WIDEN_MULT. This function checks if these operations
- are supported by the target platform either directly (via vector
- tree-codes), or via target builtins.
+ Widening operations we currently support are NOP (CONVERT), FLOAT
+ and WIDEN_MULT. This function checks if these operations are supported
+ by the target platform either directly (via vector tree-codes), or via
+ target builtins.
Output:
- CODE1 and CODE2 are codes of vector operations to be used when
tree wide_vectype = get_vectype_for_scalar_type (type);
enum tree_code c1, c2;
- /* The result of a vectorized widening operation usually requires two vectors
+ /* The result of a vectorized widening operation usually requires two vectors
(because the widened results do not fit int one vector). The generated
vector results would normally be expected to be generated in the same
order as in the original scalar computation. i.e. if 8 results are
break;
case NOP_EXPR:
+ case CONVERT_EXPR:
if (BYTES_BIG_ENDIAN)
{
c1 = VEC_UNPACK_HI_EXPR;
}
break;
+ case FLOAT_EXPR:
+ if (BYTES_BIG_ENDIAN)
+ {
+ c1 = VEC_UNPACK_FLOAT_HI_EXPR;
+ c2 = VEC_UNPACK_FLOAT_LO_EXPR;
+ }
+ else
+ {
+ c2 = VEC_UNPACK_FLOAT_HI_EXPR;
+ c1 = VEC_UNPACK_FLOAT_LO_EXPR;
+ }
+ break;
+
+ case FIX_TRUNC_EXPR:
+ /* ??? Not yet implemented due to missing VEC_UNPACK_FIX_TRUNC_HI_EXPR/
+ VEC_UNPACK_FIX_TRUNC_LO_EXPR tree codes and optabs used for
+ computing the operation. */
+ return false;
+
default:
gcc_unreachable ();
}
- *code1 = c1;
- *code2 = c2;
- optab1 = optab_for_tree_code (c1, vectype);
- optab2 = optab_for_tree_code (c2, vectype);
+ if (code == FIX_TRUNC_EXPR)
+ {
+ /* The signedness is determined from output operand. */
+ optab1 = optab_for_tree_code (c1, type);
+ optab2 = optab_for_tree_code (c2, type);
+ }
+ else
+ {
+ optab1 = optab_for_tree_code (c1, vectype);
+ optab2 = optab_for_tree_code (c2, vectype);
+ }
if (!optab1 || !optab2)
return false;
|| insn_data[icode2].operand[0].mode != TYPE_MODE (wide_vectype))
return false;
+ *code1 = c1;
+ *code2 = c2;
+ return true;
+}
+
+
+/* Function supportable_narrowing_operation
+
+ Check whether an operation represented by the code CODE is a
+ narrowing operation that is supported by the target platform in
+ vector form (i.e., when operating on arguments of type VECTYPE).
+
+ Narrowing operations we currently support are NOP (CONVERT) and
+ FIX_TRUNC. This function checks if these operations are supported by
+ the target platform directly via vector tree-codes.
+
+ Output:
+ - CODE1 is the code of a vector operation to be used when
+ vectorizing the operation, if available. */
+
+bool
+supportable_narrowing_operation (enum tree_code code,
+ tree stmt, tree vectype,
+ enum tree_code *code1)
+{
+ enum machine_mode vec_mode;
+ enum insn_code icode1;
+ optab optab1;
+ tree expr = GIMPLE_STMT_OPERAND (stmt, 1);
+ tree type = TREE_TYPE (expr);
+ tree narrow_vectype = get_vectype_for_scalar_type (type);
+ enum tree_code c1;
+
+ switch (code)
+ {
+ case NOP_EXPR:
+ case CONVERT_EXPR:
+ c1 = VEC_PACK_TRUNC_EXPR;
+ break;
+
+ case FIX_TRUNC_EXPR:
+ c1 = VEC_PACK_FIX_TRUNC_EXPR;
+ break;
+
+ case FLOAT_EXPR:
+ /* ??? Not yet implemented due to missing VEC_PACK_FLOAT_EXPR
+ tree code and optabs used for computing the operation. */
+ return false;
+
+ default:
+ gcc_unreachable ();
+ }
+
+ if (code == FIX_TRUNC_EXPR)
+ /* The signedness is determined from output operand. */
+ optab1 = optab_for_tree_code (c1, type);
+ else
+ optab1 = optab_for_tree_code (c1, vectype);
+
+ if (!optab1)
+ return false;
+
+ vec_mode = TYPE_MODE (vectype);
+ if ((icode1 = optab1->handlers[(int) vec_mode].insn_code) == CODE_FOR_nothing
+ || insn_data[icode1].operand[0].mode != TYPE_MODE (narrow_vectype))
+ return false;
+
+ *code1 = c1;
return true;
}