From 3f90a68f0fda2f571ba2a3463096b82dbea51217 Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Thu, 17 May 2018 12:06:44 +0000 Subject: [PATCH] tree-ssa-sccvn.c (vn_reference_lookup_3): Improve memset handling. 2018-05-17 Richard Biener * tree-ssa-sccvn.c (vn_reference_lookup_3): Improve memset handling. * gcc.dg/tree-ssa/ssa-fre-63.c: New testcase. From-SVN: r260318 --- gcc/ChangeLog | 4 ++ gcc/testsuite/ChangeLog | 4 ++ gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-63.c | 11 ++++ gcc/tree-ssa-sccvn.c | 72 +++++++++++++++++++--- 4 files changed, 81 insertions(+), 10 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-63.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b80d6be1357..8a800a775ce 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,7 @@ +2018-05-17 Richard Biener + + * tree-ssa-sccvn.c (vn_reference_lookup_3): Improve memset handling. + 2018-05-17 Bin Cheng Richard Biener diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 69a899840dd..2139976c9f0 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2018-05-17 Richard Biener + + * gcc.dg/tree-ssa/ssa-fre-63.c: New testcase. + 2018-05-17 Bin Cheng PR tree-optimization/85793 diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-63.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-63.c new file mode 100644 index 00000000000..39e8c08cef9 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-63.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-fre1-stats" } */ + +int foo(char *x) +{ + __builtin_memset (&x[1], 'c', 42); + return x[0] + x[1] + x[42] + x[43]; +} + +/* We should eliminate x[1] and x[42] and their conversions to int. */ +/* { dg-final { scan-tree-dump "Eliminated: 4" "fre1" } } */ diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c index 1463c1d4116..39de866a8ce 100644 --- a/gcc/tree-ssa-sccvn.c +++ b/gcc/tree-ssa-sccvn.c @@ -1958,23 +1958,75 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *vr_, 1) Memset. */ if (is_gimple_reg_type (vr->type) && gimple_call_builtin_p (def_stmt, BUILT_IN_MEMSET) - && integer_zerop (gimple_call_arg (def_stmt, 1)) + && (integer_zerop (gimple_call_arg (def_stmt, 1)) + || (INTEGRAL_TYPE_P (vr->type) && known_eq (ref->size, 8))) && poly_int_tree_p (gimple_call_arg (def_stmt, 2)) - && TREE_CODE (gimple_call_arg (def_stmt, 0)) == ADDR_EXPR) + && (TREE_CODE (gimple_call_arg (def_stmt, 0)) == ADDR_EXPR + || TREE_CODE (gimple_call_arg (def_stmt, 0)) == SSA_NAME)) { - tree ref2 = TREE_OPERAND (gimple_call_arg (def_stmt, 0), 0); tree base2; poly_int64 offset2, size2, maxsize2; bool reverse; - base2 = get_ref_base_and_extent (ref2, &offset2, &size2, &maxsize2, - &reverse); + tree ref2 = gimple_call_arg (def_stmt, 0); + if (TREE_CODE (ref2) == SSA_NAME) + { + ref2 = SSA_VAL (ref2); + if (TREE_CODE (ref2) == SSA_NAME + && (TREE_CODE (base) != MEM_REF + || TREE_OPERAND (base, 0) != ref2)) + { + gimple *def_stmt = SSA_NAME_DEF_STMT (ref2); + if (gimple_assign_single_p (def_stmt) + && gimple_assign_rhs_code (def_stmt) == ADDR_EXPR) + ref2 = gimple_assign_rhs1 (def_stmt); + } + } + if (TREE_CODE (ref2) == ADDR_EXPR) + { + ref2 = TREE_OPERAND (ref2, 0); + base2 = get_ref_base_and_extent (ref2, &offset2, &size2, &maxsize2, + &reverse); + if (!known_size_p (maxsize2) + || !operand_equal_p (base, base2, OEP_ADDRESS_OF)) + return (void *)-1; + } + else if (TREE_CODE (ref2) == SSA_NAME) + { + poly_int64 soff; + if (TREE_CODE (base) != MEM_REF + || !(mem_ref_offset (base) << LOG2_BITS_PER_UNIT).to_shwi (&soff)) + return (void *)-1; + offset += soff; + offset2 = 0; + if (TREE_OPERAND (base, 0) != ref2) + { + gimple *def = SSA_NAME_DEF_STMT (ref2); + if (is_gimple_assign (def) + && gimple_assign_rhs_code (def) == POINTER_PLUS_EXPR + && gimple_assign_rhs1 (def) == TREE_OPERAND (base, 0) + && poly_int_tree_p (gimple_assign_rhs2 (def)) + && (wi::to_poly_offset (gimple_assign_rhs2 (def)) + << LOG2_BITS_PER_UNIT).to_shwi (&offset2)) + { + ref2 = gimple_assign_rhs1 (def); + if (TREE_CODE (ref2) == SSA_NAME) + ref2 = SSA_VAL (ref2); + } + else + return (void *)-1; + } + } + else + return (void *)-1; tree len = gimple_call_arg (def_stmt, 2); - if (known_size_p (maxsize2) - && operand_equal_p (base, base2, 0) - && known_subrange_p (offset, maxsize, offset2, - wi::to_poly_offset (len) << LOG2_BITS_PER_UNIT)) + if (known_subrange_p (offset, maxsize, offset2, + wi::to_poly_offset (len) << LOG2_BITS_PER_UNIT)) { - tree val = build_zero_cst (vr->type); + tree val; + if (integer_zerop (gimple_call_arg (def_stmt, 1))) + val = build_zero_cst (vr->type); + else + val = fold_convert (vr->type, gimple_call_arg (def_stmt, 1)); return vn_reference_lookup_or_insert_for_pieces (vuse, vr->set, vr->type, vr->operands, val); } -- 2.30.2