return wi::min_precision (wres, sign) > TYPE_PRECISION (type);
}
+/* If IFN_MASK_LOAD/STORE call CALL is unconditional, return a MEM_REF
+ for the memory it references, otherwise return null. VECTYPE is the
+ type of the memory vector. */
+
+static tree
+gimple_fold_mask_load_store_mem_ref (gcall *call, tree vectype)
+{
+ tree ptr = gimple_call_arg (call, 0);
+ tree alias_align = gimple_call_arg (call, 1);
+ tree mask = gimple_call_arg (call, 2);
+ if (!tree_fits_uhwi_p (alias_align) || !integer_all_onesp (mask))
+ return NULL_TREE;
+
+ unsigned HOST_WIDE_INT align = tree_to_uhwi (alias_align) * BITS_PER_UNIT;
+ if (TYPE_ALIGN (vectype) != align)
+ vectype = build_aligned_type (vectype, align);
+ tree offset = build_zero_cst (TREE_TYPE (alias_align));
+ return fold_build2 (MEM_REF, vectype, ptr, offset);
+}
+
+/* Try to fold IFN_MASK_LOAD call CALL. Return true on success. */
+
+static bool
+gimple_fold_mask_load (gimple_stmt_iterator *gsi, gcall *call)
+{
+ tree lhs = gimple_call_lhs (call);
+ if (!lhs)
+ return false;
+
+ if (tree rhs = gimple_fold_mask_load_store_mem_ref (call, TREE_TYPE (lhs)))
+ {
+ gassign *new_stmt = gimple_build_assign (lhs, rhs);
+ gimple_set_location (new_stmt, gimple_location (call));
+ gimple_move_vops (new_stmt, call);
+ gsi_replace (gsi, new_stmt, false);
+ return true;
+ }
+ return false;
+}
+
+/* Try to fold IFN_MASK_STORE call CALL. Return true on success. */
+
+static bool
+gimple_fold_mask_store (gimple_stmt_iterator *gsi, gcall *call)
+{
+ tree rhs = gimple_call_arg (call, 3);
+ if (tree lhs = gimple_fold_mask_load_store_mem_ref (call, TREE_TYPE (rhs)))
+ {
+ gassign *new_stmt = gimple_build_assign (lhs, rhs);
+ gimple_set_location (new_stmt, gimple_location (call));
+ gimple_move_vops (new_stmt, call);
+ gsi_replace (gsi, new_stmt, false);
+ return true;
+ }
+ return false;
+}
+
/* Attempt to fold a call statement referenced by the statement iterator GSI.
The statement may be replaced by another statement, e.g., if the call
simplifies to a constant value. Return true if any changes were made.
subcode = MULT_EXPR;
cplx_result = true;
break;
+ case IFN_MASK_LOAD:
+ changed |= gimple_fold_mask_load (gsi, stmt);
+ break;
+ case IFN_MASK_STORE:
+ changed |= gimple_fold_mask_store (gsi, stmt);
+ break;
default:
break;
}