{
stmt_vec_info def = loop_vinfo->lookup_def (reduc_def);
stmt_vec_info vdef = vect_stmt_to_vectorize (def);
- if (STMT_VINFO_REDUC_IDX (vdef) == -1)
+ int reduc_idx = STMT_VINFO_REDUC_IDX (vdef);
+
+ if (reduc_idx == -1)
{
if (dump_enabled_p ())
dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
return false;
}
}
- else if (!stmt_info)
- /* First non-conversion stmt. */
- stmt_info = vdef;
- reduc_def = op.ops[STMT_VINFO_REDUC_IDX (vdef)];
+ else
+ {
+ /* First non-conversion stmt. */
+ if (!stmt_info)
+ stmt_info = vdef;
+
+ if (lane_reducing_op_p (op.code))
+ {
+ enum vect_def_type dt;
+ tree vectype_op;
+
+ /* The last operand of lane-reducing operation is for
+ reduction. */
+ gcc_assert (reduc_idx > 0 && reduc_idx == (int) op.num_ops - 1);
+
+ if (!vect_is_simple_use (op.ops[0], loop_vinfo, &dt, &vectype_op))
+ return false;
+
+ tree type_op = TREE_TYPE (op.ops[0]);
+
+ if (!vectype_op)
+ {
+ vectype_op = get_vectype_for_scalar_type (loop_vinfo,
+ type_op);
+ if (!vectype_op)
+ return false;
+ }
+
+ /* For lane-reducing operation vectorizable analysis needs the
+ reduction PHI information */
+ STMT_VINFO_REDUC_DEF (def) = phi_info;
+
+ /* Each lane-reducing operation has its own input vectype, while
+ reduction PHI will record the input vectype with the least
+ lanes. */
+ STMT_VINFO_REDUC_VECTYPE_IN (vdef) = vectype_op;
+
+ /* To accommodate lane-reducing operations of mixed input
+ vectypes, choose input vectype with the least lanes for the
+ reduction PHI statement, which would result in the most
+ ncopies for vectorized reduction results. */
+ if (!vectype_in
+ || (GET_MODE_SIZE (SCALAR_TYPE_MODE (TREE_TYPE (vectype_in)))
+ < GET_MODE_SIZE (SCALAR_TYPE_MODE (type_op))))
+ vectype_in = vectype_op;
+ }
+ else
+ vectype_in = STMT_VINFO_VECTYPE (phi_info);
+ }
+
+ reduc_def = op.ops[reduc_idx];
reduc_chain_length++;
if (!stmt_info && slp_node)
slp_for_stmt_info = SLP_TREE_CHILDREN (slp_for_stmt_info)[0];
tree vectype_out = STMT_VINFO_VECTYPE (stmt_info);
STMT_VINFO_REDUC_VECTYPE (reduc_info) = vectype_out;
+ STMT_VINFO_REDUC_VECTYPE_IN (reduc_info) = vectype_in;
+
gimple_match_op op;
if (!gimple_extract_op (stmt_info->stmt, &op))
gcc_unreachable ();
= get_vectype_for_scalar_type (loop_vinfo,
TREE_TYPE (op.ops[i]), slp_op[i]);
- /* To properly compute ncopies we are interested in the widest
- non-reduction input type in case we're looking at a widening
- accumulation that we later handle in vect_transform_reduction. */
- if (lane_reducing
- && vectype_op[i]
- && (!vectype_in
- || (GET_MODE_SIZE (SCALAR_TYPE_MODE (TREE_TYPE (vectype_in)))
- < GET_MODE_SIZE (SCALAR_TYPE_MODE (TREE_TYPE (vectype_op[i]))))))
- vectype_in = vectype_op[i];
-
/* Record how the non-reduction-def value of COND_EXPR is defined.
??? For a chain of multiple CONDs we'd have to match them up all. */
if (op.code == COND_EXPR && reduc_chain_length == 1)
}
}
}
- if (!vectype_in)
- vectype_in = STMT_VINFO_VECTYPE (phi_info);
- STMT_VINFO_REDUC_VECTYPE_IN (reduc_info) = vectype_in;
-
- /* Each lane-reducing operation has its own input vectype, while reduction
- PHI records the input vectype with least lanes. */
- if (lane_reducing)
- STMT_VINFO_REDUC_VECTYPE_IN (stmt_info) = vectype_in;
enum vect_reduction_type reduction_type = STMT_VINFO_REDUC_TYPE (phi_info);
STMT_VINFO_REDUC_TYPE (reduc_info) = reduction_type;