diff options
author | Richard Guenther <rguenther@suse.de> | 2012-06-05 09:24:43 +0000 |
---|---|---|
committer | Richard Biener <rguenth@gcc.gnu.org> | 2012-06-05 09:24:43 +0000 |
commit | b6dd52618f43de2492a727317bd6af3acfa78a23 (patch) | |
tree | 80310ade27a32fd660f2a3eea597d5c759baeec8 /gcc/tree-loop-distribution.c | |
parent | 44072af5b08af901bf25a728a6beecde0664e92c (diff) | |
download | gcc-b6dd52618f43de2492a727317bd6af3acfa78a23.zip gcc-b6dd52618f43de2492a727317bd6af3acfa78a23.tar.gz gcc-b6dd52618f43de2492a727317bd6af3acfa78a23.tar.bz2 |
re PR tree-optimization/53081 (memcpy/memset loop recognition)
2012-06-05 Richard Guenther <rguenther@suse.de>
PR tree-optimization/53081
* tree-loop-distribution.c (generate_memset_builtin): Handle all
kinds of byte-sized stores.
(classify_partition): Likewise.
(tree_loop_distribution): Adjust seed statements used for
!flag_tree_loop_distribution.
* gcc.dg/tree-ssa/ldist-19.c: New testcase.
* gcc.c-torture/execute/builtins/builtins.exp: Always pass
-fno-tree-loop-distribute-patterns.
From-SVN: r188232
Diffstat (limited to 'gcc/tree-loop-distribution.c')
-rw-r--r-- | gcc/tree-loop-distribution.c | 66 |
1 files changed, 60 insertions, 6 deletions
diff --git a/gcc/tree-loop-distribution.c b/gcc/tree-loop-distribution.c index db4fefc..5903918 100644 --- a/gcc/tree-loop-distribution.c +++ b/gcc/tree-loop-distribution.c @@ -332,6 +332,7 @@ generate_memset_builtin (struct loop *loop, struct graph *rdg, gimple_seq stmt_list = NULL, stmts; struct data_reference *dr = XCNEW (struct data_reference); location_t loc; + tree val; stmt = partition->main_stmt; loc = gimple_location (stmt); @@ -364,13 +365,44 @@ generate_memset_builtin (struct loop *loop, struct graph *rdg, mem = force_gimple_operand (addr_base, &stmts, true, NULL); gimple_seq_add_seq (&stmt_list, stmts); + /* This exactly matches the pattern recognition in classify_partition. */ + val = gimple_assign_rhs1 (stmt); + if (integer_zerop (val) + || real_zerop (val) + || TREE_CODE (val) == CONSTRUCTOR) + val = integer_zero_node; + else if (integer_all_onesp (val)) + val = build_int_cst (integer_type_node, -1); + else + { + if (TREE_CODE (val) == INTEGER_CST) + val = fold_convert (integer_type_node, val); + else if (!useless_type_conversion_p (integer_type_node, TREE_TYPE (val))) + { + gimple cstmt; + tree tem = create_tmp_reg (integer_type_node, NULL); + tem = make_ssa_name (tem, NULL); + cstmt = gimple_build_assign_with_ops (NOP_EXPR, tem, val, NULL_TREE); + gimple_seq_add_stmt (&stmt_list, cstmt); + val = tem; + } + } + fn = build_fold_addr_expr (builtin_decl_implicit (BUILT_IN_MEMSET)); - fn_call = gimple_build_call (fn, 3, mem, integer_zero_node, nb_bytes); + fn_call = gimple_build_call (fn, 3, mem, val, nb_bytes); gimple_seq_add_stmt (&stmt_list, fn_call); gsi_insert_seq_after (&gsi, stmt_list, GSI_CONTINUE_LINKING); if (dump_file && (dump_flags & TDF_DETAILS)) - fprintf (dump_file, "generated memset zero\n"); + { + fprintf (dump_file, "generated memset"); + if (integer_zerop (val)) + fprintf (dump_file, " zero\n"); + else if (integer_all_onesp (val)) + fprintf (dump_file, " minus one\n"); + else + fprintf (dump_file, "\n"); + } } /* Remove and destroy the loop LOOP. */ @@ -865,7 +897,19 @@ classify_partition (loop_p loop, struct graph *rdg, partition_t partition) return; partition->main_stmt = stmt; rhs = gimple_assign_rhs1 (stmt); - if (!(integer_zerop (rhs) || real_zerop (rhs))) + if (!(integer_zerop (rhs) + || integer_all_onesp (rhs) + || real_zerop (rhs) + || (TREE_CODE (rhs) == CONSTRUCTOR + && !TREE_CLOBBER_P (rhs)) + || (INTEGRAL_TYPE_P (TREE_TYPE (rhs)) + && (TYPE_MODE (TREE_TYPE (gimple_assign_lhs (stmt))) + == TYPE_MODE (unsigned_char_type_node))))) + return; + if (TREE_CODE (rhs) == SSA_NAME + && !SSA_NAME_IS_DEFAULT_DEF (rhs) + && flow_bb_inside_loop_p + (loop, gimple_bb (SSA_NAME_DEF_STMT (rhs)))) return; if (VEC_length (data_reference_p, RDG_DATAREFS (rdg, i)) != 1) return; @@ -1346,9 +1390,19 @@ tree_loop_distribution (void) /* If we are only performing pattern detection restrict what we try to distribute to stores from constants. */ - if (!flag_tree_loop_distribution - && !is_gimple_min_invariant (gimple_assign_rhs1 (stmt))) - continue; + if (!flag_tree_loop_distribution) + { + tree rhs = gimple_assign_rhs1 (stmt); + if (!is_gimple_min_invariant (rhs) + && TREE_CODE (rhs) != CONSTRUCTOR + && TREE_CODE (rhs) != SSA_NAME) + continue; + if (TREE_CODE (rhs) == SSA_NAME + && !SSA_NAME_IS_DEFAULT_DEF (rhs) + && flow_bb_inside_loop_p + (loop, gimple_bb (SSA_NAME_DEF_STMT (rhs)))) + continue; + } VEC_safe_push (gimple, heap, work_list, stmt); } |