aboutsummaryrefslogtreecommitdiff
path: root/gcc/expr.c
diff options
context:
space:
mode:
authorAlexandre Oliva <oliva@adacore.com>2021-05-03 22:48:47 -0300
committerAlexandre Oliva <oliva@gnu.org>2021-05-03 22:48:47 -0300
commitda9e6e63d1ae22e530ec7baf59f6ed028bf05776 (patch)
tree41e492d87df336bef4a7c9bb310627ba3fcb62aa /gcc/expr.c
parente690396da796cc4e1a0592336b37fec4e97262da (diff)
downloadgcc-da9e6e63d1ae22e530ec7baf59f6ed028bf05776.zip
gcc-da9e6e63d1ae22e530ec7baf59f6ed028bf05776.tar.gz
gcc-da9e6e63d1ae22e530ec7baf59f6ed028bf05776.tar.bz2
introduce try store by multiple pieces
The ldist pass turns even very short loops into memset calls. E.g., the TFmode emulation calls end with a loop of up to 3 iterations, to zero out trailing words, and the loop distribution pass turns them into calls of the memset builtin. Though short constant-length clearing memsets are usually dealt with efficiently, for non-constant-length ones, the options are setmemM, or a function calls. RISC-V doesn't have any setmemM pattern, so the loops above end up "optimized" into memset calls, incurring not only the overhead of an explicit call, but also discarding the information the compiler has about the alignment of the destination, and that the length is a multiple of the word alignment. This patch handles variable lengths with multiple conditional power-of-2-constant-sized stores-by-pieces, so as to reduce the overhead of length compares. It also changes the last copy-prop pass into ccp, so that pointer alignment and length's nonzero bits are detected and made available for the expander, even for ldist-introduced SSA_NAMEs. for gcc/ChangeLog * builtins.c (try_store_by_multiple_pieces): New. (expand_builtin_memset_args): Use it. If target_char_cast fails, proceed as for non-constant val. Pass len's ctz to... * expr.c (clear_storage_hints): ... this. Try store by multiple pieces after setmem. (clear_storage): Adjust. * expr.h (clear_storage_hints): Likewise. (try_store_by_multiple_pieces): Declare. * passes.def: Replace the last copy_prop with ccp.
Diffstat (limited to 'gcc/expr.c')
-rw-r--r--gcc/expr.c9
1 files changed, 7 insertions, 2 deletions
diff --git a/gcc/expr.c b/gcc/expr.c
index b4c110f..1b65f6b 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -3150,7 +3150,8 @@ clear_storage_hints (rtx object, rtx size, enum block_op_methods method,
unsigned int expected_align, HOST_WIDE_INT expected_size,
unsigned HOST_WIDE_INT min_size,
unsigned HOST_WIDE_INT max_size,
- unsigned HOST_WIDE_INT probable_max_size)
+ unsigned HOST_WIDE_INT probable_max_size,
+ unsigned ctz_size)
{
machine_mode mode = GET_MODE (object);
unsigned int align;
@@ -3197,6 +3198,10 @@ clear_storage_hints (rtx object, rtx size, enum block_op_methods method,
expected_align, expected_size,
min_size, max_size, probable_max_size))
;
+ else if (try_store_by_multiple_pieces (object, size, ctz_size,
+ min_size, max_size,
+ NULL_RTX, 0, align))
+ ;
else if (ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (object)))
return set_storage_via_libcall (object, size, const0_rtx,
method == BLOCK_OP_TAILCALL);
@@ -3214,7 +3219,7 @@ clear_storage (rtx object, rtx size, enum block_op_methods method)
min = max = UINTVAL (size);
else
max = GET_MODE_MASK (GET_MODE (size));
- return clear_storage_hints (object, size, method, 0, -1, min, max, max);
+ return clear_storage_hints (object, size, method, 0, -1, min, max, max, 0);
}