/* Return the mask input to a masked load or store. VEC_MASK is the vectorized
form of the scalar mask condition and LOOP_MASK, if nonnull, is the mask
that needs to be applied to all loads and stores in a vectorized loop.
- Return VEC_MASK if LOOP_MASK is null, otherwise return VEC_MASK & LOOP_MASK.
+ Return VEC_MASK if LOOP_MASK is null or if VEC_MASK is already masked,
+ otherwise return VEC_MASK & LOOP_MASK.
MASK_TYPE is the type of both masks. If new statements are needed,
insert them before GSI. */
static tree
-prepare_load_store_mask (tree mask_type, tree loop_mask, tree vec_mask,
- gimple_stmt_iterator *gsi)
+prepare_vec_mask (loop_vec_info loop_vinfo, tree mask_type, tree loop_mask,
+ tree vec_mask, gimple_stmt_iterator *gsi)
{
gcc_assert (useless_type_conversion_p (mask_type, TREE_TYPE (vec_mask)));
if (!loop_mask)
return vec_mask;
gcc_assert (TREE_TYPE (loop_mask) == mask_type);
+
+ if (loop_vinfo->vec_cond_masked_set.contains ({ vec_mask, loop_mask }))
+ return vec_mask;
+
tree and_res = make_temp_ssa_name (mask_type, NULL, "vec_mask_and");
gimple *and_stmt = gimple_build_assign (and_res, BIT_AND_EXPR,
vec_mask, loop_mask);
+
gsi_insert_before (gsi, and_stmt, GSI_SAME_STMT);
return and_res;
}
gcc_assert (ncopies == 1);
tree mask = vect_get_loop_mask (gsi, masks, vec_num,
vectype_out, i);
- vargs[mask_opno] = prepare_load_store_mask
- (TREE_TYPE (mask), mask, vargs[mask_opno], gsi);
+ vargs[mask_opno] = prepare_vec_mask
+ (loop_vinfo, TREE_TYPE (mask), mask,
+ vargs[mask_opno], gsi);
}
gcall *call;
tree mask = vect_get_loop_mask (gsi, masks, ncopies,
vectype_out, j);
vargs[mask_opno]
- = prepare_load_store_mask (TREE_TYPE (mask), mask,
- vargs[mask_opno], gsi);
+ = prepare_vec_mask (loop_vinfo, TREE_TYPE (mask), mask,
+ vargs[mask_opno], gsi);
}
gimple *new_stmt;
}
else
{
+ tree mask = NULL_TREE;
+ /* When combining two masks check if either of them is elsewhere
+ combined with a loop mask, if that's the case we can mark that the
+ new combined mask doesn't need to be combined with a loop mask. */
+ if (masked_loop_p && code == BIT_AND_EXPR)
+ {
+ if (loop_vinfo->scalar_cond_masked_set.contains ({ op0,
+ ncopies}))
+ {
+ mask = vect_get_loop_mask (gsi, masks, vec_num * ncopies,
+ vectype, i);
+
+ vop0 = prepare_vec_mask (loop_vinfo, TREE_TYPE (mask), mask,
+ vop0, gsi);
+ }
+
+ if (loop_vinfo->scalar_cond_masked_set.contains ({ op1,
+ ncopies }))
+ {
+ mask = vect_get_loop_mask (gsi, masks, vec_num * ncopies,
+ vectype, i);
+
+ vop1 = prepare_vec_mask (loop_vinfo, TREE_TYPE (mask), mask,
+ vop1, gsi);
+ }
+ }
+
new_stmt = gimple_build_assign (vec_dest, code, vop0, vop1, vop2);
new_temp = make_ssa_name (vec_dest, new_stmt);
gimple_assign_set_lhs (new_stmt, new_temp);
vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
+
+ /* Enter the combined value into the vector cond hash so we don't
+ AND it with a loop mask again. */
+ if (mask)
+ loop_vinfo->vec_cond_masked_set.add ({ new_temp, mask });
+
if (vec_cvt_dest)
{
new_temp = build1 (VIEW_CONVERT_EXPR, vectype_out, new_temp);
final_mask = vect_get_loop_mask (gsi, loop_masks, ncopies,
vectype, j);
if (vec_mask)
- final_mask = prepare_load_store_mask (mask_vectype, final_mask,
- vec_mask, gsi);
+ final_mask = prepare_vec_mask (loop_vinfo, mask_vectype,
+ final_mask, vec_mask, gsi);
gcall *call;
if (final_mask)
vec_num * ncopies,
vectype, vec_num * j + i);
if (vec_mask)
- final_mask = prepare_load_store_mask (mask_vectype, final_mask,
- vec_mask, gsi);
+ final_mask = prepare_vec_mask (loop_vinfo, mask_vectype,
+ final_mask, vec_mask, gsi);
if (memory_access_type == VMAT_GATHER_SCATTER)
{
final_mask = vect_get_loop_mask (gsi, loop_masks, ncopies,
vectype, j);
if (vec_mask)
- final_mask = prepare_load_store_mask (mask_vectype, final_mask,
- vec_mask, gsi);
+ final_mask = prepare_vec_mask (loop_vinfo, mask_vectype,
+ final_mask, vec_mask, gsi);
gcall *call;
if (final_mask)
vec_num * ncopies,
vectype, vec_num * j + i);
if (vec_mask)
- final_mask = prepare_load_store_mask (mask_vectype, final_mask,
- vec_mask, gsi);
+ final_mask = prepare_vec_mask (loop_vinfo, mask_vectype,
+ final_mask, vec_mask, gsi);
if (i > 0)
dataref_ptr = bump_vector_ptr (vinfo, dataref_ptr, ptr_incr,