Commit 868363d4 by Richard Sandiford Committed by Richard Sandiford

Fold MASK_LOAD/STORE with an all-true mask

This patch folds IFN_MASK_LOAD and IFN_MASK_STOREs to normal accesses
if the mask is all-true.  This can happen for fully-masked loops that
didn't actually need to be (which could be handled by the vectoriser
instead), or for unrolled fully-masked loops whose first iteration is
guaranteed to operate on a full vector.  It's also useful when the
accesses are generated directly by intrinsics (to follow for SVE).

2019-08-05  Richard Sandiford  <richard.sandiford@arm.com>

gcc/
	* gimple-fold.c (gimple_fold_mask_load_store_mem_ref)
	(gimple_fold_mask_load, gimple_fold_mask_store): New functions.
	(gimple_fold_call): Use them to fold IFN_MASK_LOAD and
	IFN_MASK_STORE.

gcc/testsuite/
	* gcc.target/aarch64/sve/mask_load_1.c: New test.

From-SVN: r274118
parent 779724a5
2019-08-05 Richard Sandiford <richard.sandiford@arm.com> 2019-08-05 Richard Sandiford <richard.sandiford@arm.com>
* gimple-fold.c (gimple_fold_mask_load_store_mem_ref)
(gimple_fold_mask_load, gimple_fold_mask_store): New functions.
(gimple_fold_call): Use them to fold IFN_MASK_LOAD and
IFN_MASK_STORE.
2019-08-05 Richard Sandiford <richard.sandiford@arm.com>
* gimple.h (gimple_move_vops): Declare. * gimple.h (gimple_move_vops): Declare.
* gimple.c (gimple_move_vops): New function * gimple.c (gimple_move_vops): New function
* gimple-fold.c (replace_call_with_call_and_fold) * gimple-fold.c (replace_call_with_call_and_fold)
......
...@@ -4180,6 +4180,63 @@ arith_overflowed_p (enum tree_code code, const_tree type, ...@@ -4180,6 +4180,63 @@ arith_overflowed_p (enum tree_code code, const_tree type,
return wi::min_precision (wres, sign) > TYPE_PRECISION (type); 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. /* 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 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. simplifies to a constant value. Return true if any changes were made.
...@@ -4409,6 +4466,12 @@ gimple_fold_call (gimple_stmt_iterator *gsi, bool inplace) ...@@ -4409,6 +4466,12 @@ gimple_fold_call (gimple_stmt_iterator *gsi, bool inplace)
subcode = MULT_EXPR; subcode = MULT_EXPR;
cplx_result = true; cplx_result = true;
break; 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: default:
break; break;
} }
......
2019-08-05 Richard Sandiford <richard.sandiford@arm.com>
* gcc.target/aarch64/sve/mask_load_1.c: New test.
2019-08-05 Jozef Lawrynowicz <jozef.l@mittosystems.com> 2019-08-05 Jozef Lawrynowicz <jozef.l@mittosystems.com>
* gcc.target/msp430/pr80993.c: Add cleanup-saved-temps to final * gcc.target/msp430/pr80993.c: Add cleanup-saved-temps to final
......
/* { dg-do compile } */
/* { dg-options "-O2 -ftree-vectorize -msve-vector-bits=256 -fdump-tree-optimized" } */
void
f (int *x)
{
for (int i = 0; i < 8; ++i)
x[i] += 1;
}
/* { dg-final { scan-tree-dump { = MEM <vector\(8\) int>} "optimized" } } */
/* { dg-final { scan-tree-dump { MEM <vector\(8\) int> \[[^]]*\] = } "optimized" } } */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment