@@ -2531,12 +2531,15 @@ mask_exists (int size, const vec<int> &vec)
/* Helper function for predicate_statements. STMT is a memory read or
write and it needs to be predicated by MASK. Return a statement
- that does so. */
+ that does so. SSA_NAMES is the set of SSA names defined earlier in
+ STMT's block. */
-static gimple *
-predicate_load_or_store (gimple_stmt_iterator *gsi, gassign *stmt, tree mask)
+static gimple_seq
+predicate_load_or_store (gimple_stmt_iterator *gsi, gassign *stmt, tree mask,
+ hash_set<tree_ssa_name_hash> *ssa_names)
{
- gcall *new_stmt;
+ gimple_seq stmts = NULL;
+ gcall *call_stmt;
tree lhs = gimple_assign_lhs (stmt);
tree rhs = gimple_assign_rhs1 (stmt);
@@ -2552,21 +2555,88 @@ predicate_load_or_store (gimple_stmt_iterator *gsi, gassign *stmt, tree mask)
ref);
if (TREE_CODE (lhs) == SSA_NAME)
{
- new_stmt
- = gimple_build_call_internal (IFN_MASK_LOAD, 3, addr,
- ptr, mask);
- gimple_call_set_lhs (new_stmt, lhs);
- gimple_set_vuse (new_stmt, gimple_vuse (stmt));
+ /* Get the preferred vector mode and its corresponding mask for the
+ masked load. We need this to query the target's supported else
+ operands. */
+ machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
+ scalar_mode smode = as_a <scalar_mode> (mode);
+
+ machine_mode vmode = targetm.vectorize.preferred_simd_mode (smode);
+ machine_mode mask_mode
+ = targetm.vectorize.get_mask_mode (vmode).require ();
+
+ auto_vec<int> elsvals;
+ internal_fn ifn;
+ bool have_masked_load
+ = target_supports_mask_load_store_p (vmode, mask_mode, true, &ifn,
+ &elsvals);
+
+ /* We might need to explicitly zero inactive elements if there are
+ padding bits in the type that might leak otherwise.
+ Refer to PR115336. */
+ bool need_zero
+ = TYPE_PRECISION (TREE_TYPE (lhs)) < GET_MODE_PRECISION (smode);
+
+ int elsval;
+ bool implicit_zero = false;
+ if (have_masked_load)
+ {
+ gcc_assert (elsvals.length ());
+
+ /* But not if the target already provide implicit zeroing of inactive
+ elements. */
+ implicit_zero = elsvals.contains (MASK_LOAD_ELSE_ZERO);
+
+ /* For now, just use the first else value if zero is unsupported. */
+ elsval = implicit_zero ? MASK_LOAD_ELSE_ZERO : *elsvals.begin ();
+ }
+ else
+ {
+ /* We cannot vectorize this either way so just use a zero even
+ if it is unsupported. */
+ elsval = MASK_LOAD_ELSE_ZERO;
+ }
+
+ tree els = vect_get_mask_load_else (elsval, TREE_TYPE (lhs));
+
+ call_stmt
+ = gimple_build_call_internal (IFN_MASK_LOAD, 4, addr,
+ ptr, mask, els);
+
+ /* Build the load call and, if the else value is nonzero,
+ a COND_EXPR that enforces it. */
+ tree loadlhs;
+ if (!need_zero || implicit_zero)
+ gimple_call_set_lhs (call_stmt, gimple_get_lhs (stmt));
+ else
+ {
+ loadlhs = make_temp_ssa_name (TREE_TYPE (lhs), NULL, "_ifc_");
+ ssa_names->add (loadlhs);
+ gimple_call_set_lhs (call_stmt, loadlhs);
+ }
+ gimple_set_vuse (call_stmt, gimple_vuse (stmt));
+ gimple_seq_add_stmt (&stmts, call_stmt);
+
+ if (need_zero && !implicit_zero)
+ {
+ tree cond_rhs
+ = fold_build_cond_expr (TREE_TYPE (loadlhs), mask, loadlhs,
+ build_zero_cst (TREE_TYPE (loadlhs)));
+ gassign *cond_stmt
+ = gimple_build_assign (gimple_get_lhs (stmt), cond_rhs);
+ gimple_seq_add_stmt (&stmts, cond_stmt);
+ }
}
else
{
- new_stmt
+ call_stmt
= gimple_build_call_internal (IFN_MASK_STORE, 4, addr, ptr,
mask, rhs);
- gimple_move_vops (new_stmt, stmt);
+ gimple_move_vops (call_stmt, stmt);
+ gimple_seq_add_stmt (&stmts, call_stmt);
}
- gimple_call_set_nothrow (new_stmt, true);
- return new_stmt;
+ gimple_call_set_nothrow (call_stmt, true);
+ return stmts;
}
/* STMT uses OP_LHS. Check whether it is equivalent to:
@@ -2836,7 +2906,6 @@ predicate_statements (loop_p loop)
{
tree lhs = gimple_assign_lhs (stmt);
tree mask;
- gimple *new_stmt;
gimple_seq stmts = NULL;
machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
/* We checked before setting GF_PLF_2 that an equivalent
@@ -2870,11 +2939,18 @@ predicate_statements (loop_p loop)
vect_masks.safe_push (mask);
}
if (gimple_assign_single_p (stmt))
- new_stmt = predicate_load_or_store (&gsi, stmt, mask);
- else
- new_stmt = predicate_rhs_code (stmt, mask, cond, &ssa_names);
+ {
+ gimple_seq call_seq
+ = predicate_load_or_store (&gsi, stmt, mask, &ssa_names);
- gsi_replace (&gsi, new_stmt, true);
+ gsi_replace_with_seq (&gsi, call_seq, true);
+ }
+ else
+ {
+ gimple *new_stmt;
+ new_stmt = predicate_rhs_code (stmt, mask, cond, &ssa_names);
+ gsi_replace (&gsi, new_stmt, true);
+ }
}
else if (((lhs = gimple_assign_lhs (stmt)), true)
&& (INTEGRAL_TYPE_P (TREE_TYPE (lhs))