aboutsummaryrefslogtreecommitdiff
path: root/gcc/gimple-fold.c
diff options
context:
space:
mode:
authorEric Botcazou <ebotcazou@gcc.gnu.org>2020-07-03 18:10:25 +0200
committerEric Botcazou <ebotcazou@gcc.gnu.org>2020-07-03 18:31:04 +0200
commite362a897655e3b92949b65a2b53e00fb3ab8ded0 (patch)
tree4a6123efd03f9969c0a3124c6add9061e421a983 /gcc/gimple-fold.c
parentb9a15a8325ba89b926e3c437b7961829a6b2fa2b (diff)
downloadgcc-e362a897655e3b92949b65a2b53e00fb3ab8ded0.zip
gcc-e362a897655e3b92949b65a2b53e00fb3ab8ded0.tar.gz
gcc-e362a897655e3b92949b65a2b53e00fb3ab8ded0.tar.bz2
Extend store merging to STRING_CST
The GIMPLE store merging pass doesn't merge STRING_CSTs in the general case, although they are accepted by native_encode_expr; the reason is that the pass only works with integral modes, i.e. with chunks whose size is a power of two. There are two possible ways of extending it to handle STRING_CSTs: 1) lift the condition of integral modes and treat STRING_CSTs as other _CST nodes but with arbitrary size; 2) implement a specific and separate handling for STRING_CSTs. The attached patch implements 2) for the following reasons: on the one hand, even in Ada where character strings are first-class citizens, cases where merging STRING_CSTs with other *_CST nodes would be possible are quite rare in practice; on the other hand, string concatenations happen more naturally and frequently thanks to the "&" operator, giving rise to merging opportunities. gcc/ChangeLog: * gimple-fold.c (gimple_fold_builtin_memory_op): Fold calls that were initially created for the assignment of a variable-sized object and whose source is now a string constant. * gimple-ssa-store-merging.c (struct merged_store_group): Document STRING_CST for rhs_code field. Add string_concatenation boolean field. (merged_store_group::merged_store_group): Initialize it as well as bit_insertion here. (merged_store_group::do_merge): Set it upon seeing a STRING_CST. Also set bit_insertion here upon seeing a BIT_INSERT_EXPR. (merged_store_group::apply_stores): Clear it for small regions. Do not create a power-of-2-sized buffer if it is still true. And do not set bit_insertion here again. (encode_tree_to_bitpos): Deal with BLKmode for the expression. (merged_store_group::can_be_merged_into): Deal with STRING_CST. (imm_store_chain_info::coalesce_immediate_stores): Set bit_insertion to true after changing MEM_REF stores into BIT_INSERT_EXPR stores. (count_multiple_uses): Return 0 for STRING_CST. (split_group): Do not split the group for a string concatenation. (imm_store_chain_info::output_merged_store): Constify and rename some local variables. Build an array type as destination type for a string concatenation, as well as a zero mask, and call build_string to build the source. (lhs_valid_for_store_merging_p): Return true for VIEW_CONVERT_EXPR. (pass_store_merging::process_store): Accept STRING_CST on the RHS. * gimple.h (gimple_call_alloca_for_var_p): New accessor function. * gimplify.c (gimplify_modify_expr_to_memcpy): Set alloca_for_var. * tree.h (CALL_ALLOCA_FOR_VAR_P): Document it for BUILT_IN_MEMCPY. gcc/testsuite/ChangeLog: * gnat.dg/opt87.adb: New test. * gnat.dg/opt87_pkg.ads: New helper. * gnat.dg/opt87_pkg.adb: Likewise.
Diffstat (limited to 'gcc/gimple-fold.c')
-rw-r--r--gcc/gimple-fold.c50
1 files changed, 35 insertions, 15 deletions
diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c
index 4e3de95..72c5e43 100644
--- a/gcc/gimple-fold.c
+++ b/gcc/gimple-fold.c
@@ -700,7 +700,6 @@ gimple_fold_builtin_memory_op (gimple_stmt_iterator *gsi,
gimple *stmt = gsi_stmt (*gsi);
tree lhs = gimple_call_lhs (stmt);
tree len = gimple_call_arg (stmt, 2);
- tree destvar, srcvar;
location_t loc = gimple_location (stmt);
/* If the LEN parameter is a constant zero or in range where
@@ -741,7 +740,7 @@ gimple_fold_builtin_memory_op (gimple_stmt_iterator *gsi,
}
else
{
- tree srctype, desttype;
+ tree srctype, desttype, destvar, srcvar, srcoff;
unsigned int src_align, dest_align;
tree off0;
const char *tmp_str;
@@ -991,7 +990,9 @@ gimple_fold_builtin_memory_op (gimple_stmt_iterator *gsi,
/* Choose between src and destination type for the access based
on alignment, whether the access constitutes a register access
and whether it may actually expose a declaration for SSA rewrite
- or SRA decomposition. */
+ or SRA decomposition. Also try to expose a string constant, we
+ might be able to concatenate several of them later into a single
+ string store. */
destvar = NULL_TREE;
srcvar = NULL_TREE;
if (TREE_CODE (dest) == ADDR_EXPR
@@ -1008,7 +1009,16 @@ gimple_fold_builtin_memory_op (gimple_stmt_iterator *gsi,
&& (is_gimple_reg_type (srctype)
|| dest_align >= TYPE_ALIGN (srctype)))
srcvar = fold_build2 (MEM_REF, srctype, src, off0);
- if (srcvar == NULL_TREE && destvar == NULL_TREE)
+ /* FIXME: Don't transform copies from strings with known original length.
+ As soon as strlenopt tests that rely on it for passing are adjusted,
+ this hack can be removed. */
+ else if (gimple_call_alloca_for_var_p (stmt)
+ && (srcvar = string_constant (src, &srcoff, NULL, NULL))
+ && integer_zerop (srcoff)
+ && tree_int_cst_equal (TYPE_SIZE_UNIT (TREE_TYPE (srcvar)), len)
+ && dest_align >= TYPE_ALIGN (TREE_TYPE (srcvar)))
+ srctype = TREE_TYPE (srcvar);
+ else
return false;
/* Now that we chose an access type express the other side in
@@ -1071,19 +1081,29 @@ gimple_fold_builtin_memory_op (gimple_stmt_iterator *gsi,
goto set_vop_and_replace;
}
- /* We get an aggregate copy. Use an unsigned char[] type to
- perform the copying to preserve padding and to avoid any issues
- with TREE_ADDRESSABLE types or float modes behavior on copying. */
- desttype = build_array_type_nelts (unsigned_char_type_node,
- tree_to_uhwi (len));
- srctype = desttype;
- if (src_align > TYPE_ALIGN (srctype))
- srctype = build_aligned_type (srctype, src_align);
+ /* We get an aggregate copy. If the source is a STRING_CST, then
+ directly use its type to perform the copy. */
+ if (TREE_CODE (srcvar) == STRING_CST)
+ desttype = srctype;
+
+ /* Or else, use an unsigned char[] type to perform the copy in order
+ to preserve padding and to avoid any issues with TREE_ADDRESSABLE
+ types or float modes behavior on copying. */
+ else
+ {
+ desttype = build_array_type_nelts (unsigned_char_type_node,
+ tree_to_uhwi (len));
+ srctype = desttype;
+ if (src_align > TYPE_ALIGN (srctype))
+ srctype = build_aligned_type (srctype, src_align);
+ srcvar = fold_build2 (MEM_REF, srctype, src, off0);
+ }
+
if (dest_align > TYPE_ALIGN (desttype))
desttype = build_aligned_type (desttype, dest_align);
- new_stmt
- = gimple_build_assign (fold_build2 (MEM_REF, desttype, dest, off0),
- fold_build2 (MEM_REF, srctype, src, off0));
+ destvar = fold_build2 (MEM_REF, desttype, dest, off0);
+ new_stmt = gimple_build_assign (destvar, srcvar);
+
set_vop_and_replace:
gimple_move_vops (new_stmt, stmt);
if (!lhs)