https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63185
--- Comment #9 from Richard Biener <rguenth at gcc dot gnu.org> --- So the following incomplete patch solves the value-numbering issue in FRE2. diff --git a/gcc/tree-dfa.c b/gcc/tree-dfa.c index a121b880bb0..745d60cbda5 100644 --- a/gcc/tree-dfa.c +++ b/gcc/tree-dfa.c @@ -529,6 +529,31 @@ get_ref_base_and_extent (tree exp, poly_int64_pod *poffset, /* Remember that we have seen an array ref with a variable index. */ seen_variable_array_ref = true; + + wide_int min, max; + if (TREE_CODE (index) == SSA_NAME + && integer_zerop (array_ref_low_bound (exp)) + && (unit_size = array_ref_element_size (exp), + TREE_CODE (unit_size) == INTEGER_CST) + && get_range_info (index, &min, &max) == VR_RANGE + && wi::gts_p (max, 0)) + { + poly_offset_int rmaxsize; + rmaxsize = offset_int::from (max, UNSIGNED) * wi::to_offset (unit_size); + if (known_size_p (maxsize)) + { + if (known_lt (rmaxsize, maxsize)) + { + maxsize = rmaxsize; + seen_variable_array_ref = false; + } + } + else + { + maxsize = rmaxsize; + seen_variable_array_ref = false; + } + } } } break; diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c index 1463c1d4116..dad4e4fecdf 100644 --- a/gcc/tree-ssa-sccvn.c +++ b/gcc/tree-ssa-sccvn.c @@ -1960,19 +1960,46 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *vr_, && gimple_call_builtin_p (def_stmt, BUILT_IN_MEMSET) && integer_zerop (gimple_call_arg (def_stmt, 1)) && 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, 0)) + return (void *)-1; + } + else + { + if (TREE_CODE (base) != MEM_REF + || TREE_OPERAND (base, 0) != ref2 + || !integer_zerop (TREE_OPERAND (base, 1))) + return (void *)-1; + offset2 = 0; + } 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); return vn_reference_lookup_or_insert_for_pieces