On Sat, Jan 25, 2025 at 4:37 AM Alexandre Oliva <ol...@adacore.com> wrote: > > On Jan 24, 2025, Richard Biener <richard.guent...@gmail.com> wrote: > > > Hmm. I think when an original ref could trap that should be the > > insertion point (or the original ref should post-dominate the insertion > > point). > > I suppose we could do that, but... intuitively, it doesn't feel safe to > move a nontrapping load down to combine it with a trapping load either. > > > It's fine when an originally may-trap reference becomes not trapping > > (and it really cannot trap). Introducing new (may-)traps is never OK. > > I don't really see how a may-trap reference to a certain range of bits > could possibly become non-trapping by merely reissuing it, so I can't > respond intelligently to your assessment.
What I was saying that the conservative tree_could_trap_p could say 'yes' to a certain encoding of a ref but 'no' to another if in reality the ref can never trap. We of course cannot (apart from bugs in tree_could_trap_p) turn a for-sure trap into a not-trap by simply rewriting the ref. > > So, can we split the patch to the case with the testcase at hand and > > consider the assert and the extra tree_could_trap_p checks separately? > > The approved patch, with the testcase and the simplest fix, is already > in. I've rebased the additional defensive checks and interface changes > into the following, but I don't have any pressing need of getting them > in: I don't know how to trigger any of the issues tested for. > > > If decode_field_reference finds a load that accesses past the inner > object's size, bail out. > > If loads we're attempting to combine don't have the same trapping > status, bail out, to avoid replacing the wrong load and enabling loads > to be moved that shouldn't. > > Regstrapped on x86_64-linux-gnu. Should I put this in? > > > for gcc/ChangeLog > > PR tree-optimization/118514 > * gimple-fold.cc (decode_field_reference): Refuse to consider > merging out-of-bounds BIT_FIELD_REFs. > (fold_truth_andor_for_ifcombine): Check that combinable loads > have the same trapping status. > * tree-eh.cc (bit_field_ref_in_bounds_p): Rename to... > (access_in_bounds_of_type_p): ... this. Change interface, > export. > (tree_could_trap_p): Adjust. > * tree-eh.h (access_in_bounds_of_type_p): Declare. > --- > gcc/gimple-fold.cc | 16 ++++++++++------ > gcc/tree-eh.cc | 25 +++++++++++++------------ > gcc/tree-eh.h | 1 + > 3 files changed, 24 insertions(+), 18 deletions(-) > > diff --git a/gcc/gimple-fold.cc b/gcc/gimple-fold.cc > index 45485782cdf91..24aada4bc8fee 100644 > --- a/gcc/gimple-fold.cc > +++ b/gcc/gimple-fold.cc > @@ -7686,10 +7686,8 @@ decode_field_reference (tree *pexp, HOST_WIDE_INT > *pbitsize, > || bs <= shiftrt > || offset != 0 > || TREE_CODE (inner) == PLACEHOLDER_EXPR > - /* Reject out-of-bound accesses (PR79731). */ > - || (! AGGREGATE_TYPE_P (TREE_TYPE (inner)) > - && compare_tree_int (TYPE_SIZE (TREE_TYPE (inner)), > - bp + bs) < 0) > + /* Reject out-of-bound accesses (PR79731, PR118514). */ > + || !access_in_bounds_of_type_p (TREE_TYPE (inner), bs, bp) So I think we want this bit in (and it's dependences), but > || (INTEGRAL_TYPE_P (TREE_TYPE (inner)) > && !type_has_mode_precision_p (TREE_TYPE (inner)))) > return NULL_TREE; > @@ -8228,8 +8226,12 @@ fold_truth_andor_for_ifcombine (enum tree_code code, > tree truth_type, > std::swap (rl_loc, rr_loc); > } > > + /* Check that the loads that we're trying to combine have the same vuse and > + same trapping status. */ > if ((ll_load && rl_load) > - ? gimple_vuse (ll_load) != gimple_vuse (rl_load) > + ? (gimple_vuse (ll_load) != gimple_vuse (rl_load) > + || (tree_could_trap_p (gimple_assign_rhs1 (ll_load)) > + != tree_could_trap_p (gimple_assign_rhs1 (rl_load)))) > : (!ll_load != !rl_load)) this and > return 0; > > @@ -8282,7 +8284,9 @@ fold_truth_andor_for_ifcombine (enum tree_code code, > tree truth_type, > else if (lr_reversep != rr_reversep > || ! operand_equal_p (lr_inner, rr_inner, 0) > || ((lr_load && rr_load) > - ? gimple_vuse (lr_load) != gimple_vuse (rr_load) > + ? (gimple_vuse (lr_load) != gimple_vuse (rr_load) > + || (tree_could_trap_p (gimple_assign_rhs1 (lr_load)) > + != tree_could_trap_p (gimple_assign_rhs1 (rr_load)))) > : (!lr_load != !rr_load))) this not at this point (I see the assert is no longer in the patch). So, apart from these two hunks this is OK as well. Thanks, Richard. > return 0; > > diff --git a/gcc/tree-eh.cc b/gcc/tree-eh.cc > index 27a4b2b5b1665..68008cea588a7 100644 > --- a/gcc/tree-eh.cc > +++ b/gcc/tree-eh.cc > @@ -2646,24 +2646,22 @@ range_in_array_bounds_p (tree ref) > return true; > } > > -/* Return true iff EXPR, a BIT_FIELD_REF, accesses a bit range that is known > to > - be in bounds for the referred operand type. */ > +/* Return true iff a BIT_FIELD_REF <(TYPE)???, SIZE, OFFSET> would access a > bit > + range that is known to be in bounds for TYPE. */ > > -static bool > -bit_field_ref_in_bounds_p (tree expr) > +bool > +access_in_bounds_of_type_p (tree type, poly_uint64 size, poly_uint64 offset) > { > - tree size_tree; > - poly_uint64 size_max, min, wid, max; > + tree type_size_tree; > + poly_uint64 type_size_max, min = offset, wid = size, max; > > - size_tree = TYPE_SIZE (TREE_TYPE (TREE_OPERAND (expr, 0))); > - if (!size_tree || !poly_int_tree_p (size_tree, &size_max)) > + type_size_tree = TYPE_SIZE (type); > + if (!type_size_tree || !poly_int_tree_p (type_size_tree, &type_size_max)) > return false; > > - min = bit_field_offset (expr); > - wid = bit_field_size (expr); > max = min + wid; > if (maybe_lt (max, min) > - || maybe_lt (size_max, max)) > + || maybe_lt (type_size_max, max)) > return false; > > return true; > @@ -2712,7 +2710,10 @@ tree_could_trap_p (tree expr) > switch (code) > { > case BIT_FIELD_REF: > - if (DECL_P (TREE_OPERAND (expr, 0)) && !bit_field_ref_in_bounds_p > (expr)) > + if (DECL_P (TREE_OPERAND (expr, 0)) > + && !access_in_bounds_of_type_p (TREE_TYPE (TREE_OPERAND (expr, 0)), > + bit_field_size (expr), > + bit_field_offset (expr))) > return true; > /* Fall through. */ > > diff --git a/gcc/tree-eh.h b/gcc/tree-eh.h > index 69fe193f1b82f..1fe6de80c42e7 100644 > --- a/gcc/tree-eh.h > +++ b/gcc/tree-eh.h > @@ -36,6 +36,7 @@ extern void redirect_eh_dispatch_edge (geh_dispatch *, > edge, basic_block); > extern bool operation_could_trap_helper_p (enum tree_code, bool, bool, bool, > bool, tree, bool *); > extern bool operation_could_trap_p (enum tree_code, bool, bool, tree); > +extern bool access_in_bounds_of_type_p (tree, poly_uint64, poly_uint64); > extern bool tree_could_trap_p (tree); > extern tree rewrite_to_non_trapping_overflow (tree); > extern bool stmt_could_throw_p (function *, gimple *); > > > > -- > Alexandre Oliva, happy hacker https://FSFLA.org/blogs/lxo/ > Free Software Activist GNU Toolchain Engineer > More tolerance and less prejudice are key for inclusion and diversity > Excluding neuro-others for not behaving ""normal"" is *not* inclusive