On 10/21/21 3:46 PM, Richard Biener wrote:
On Thu, Oct 21, 2021 at 3:30 PM Aldy Hernandez <al...@redhat.com> wrote:



On 10/21/21 3:14 PM, Richard Biener wrote:
On Thu, Oct 21, 2021 at 2:56 PM Aldy Hernandez <al...@redhat.com> wrote:

On Thu, Oct 21, 2021 at 12:20 PM Richard Biener
<richard.guent...@gmail.com> wrote:

On Wed, Oct 20, 2021 at 10:58 PM Jeff Law <jeffreya...@gmail.com> wrote:



On 10/18/2021 2:17 AM, Aldy Hernandez wrote:


On 10/18/21 12:52 AM, Jeff Law wrote:


On 10/8/2021 9:12 AM, Aldy Hernandez via Gcc-patches wrote:
The following patch converts the strlen pass from evrp to ranger,
leaving DOM as the last remaining user.
So is there any reason why we can't convert DOM as well?   DOM's use
of EVRP is pretty limited.  You've mentioned FP bits before, but my
recollection is those are not part of the EVRP analysis DOM uses.
Hell, give me a little guidance and I'll do the work...

Not only will I take you up on that offer, but I can provide 90% of
the work.  Here be dragons, though (well, for me, maybe not for you ;-)).

DOM is actually an evrp pass at -O1 in disguise.  The reason it really
is a covert evrp pass is because:

a) It calls extract_range_from_stmt on each statement.

b) It folds conditionals with simplify_using_ranges.

c) But most importantly, it exports discovered ranges when it's done
(evrp_range_analyzer(true)).

If you look at the evrp pass, you'll notice that that's basically what
it does, albeit with the substitute and fold engine, which also calls
gimple fold plus other goodies.

But I could argue that we've made DOM into an evrp pass without
noticing.  The last item (c) is particularly invasive because these
exported ranges show up in other passes unexpectedly.  For instance, I
saw an RTL pass at -O1 miss an optimization because it was dependent
on some global range being set.  IMO, DOM should not export global
ranges it discovered during its walk (do one thing and do it well),
but I leave it to you experts to pontificate.
All true.  But I don't think we've got many, if any, hard dependencies
on those behaviors.


The attached patch is rather trivial.  It's mostly deleting state.  It
seems DOM spends a lot of time massaging the IL so that it can fold
conditionals or thread paths.  None of this is needed, because the
ranger can do all of this.  Well, except floats, but...
Massaging the IL should only take two forms IIRC.

First, if we have a simplification we can do.  That could be const/copy
propagation, replacing an expression with an SSA_NAME or constant and
the like.  It doesn't massage the IL just to massage the IL.

Second, we do temporarily copy propagate the current known values of an
SSA name into use points and then see if that allows us to determine if
a statement is already in the hash tables.  But we undo that so that
nobody should see that temporary change in state.

Are you sure we still do that?  I can't find it at least.

I couldn't either, but perhaps what Jeff is referring to is the ad-hoc
copy propagation that happens in the DOM's use of the threader:

        /* Make a copy of the uses & vuses into USES_COPY, then cprop into
           the operands.  */
        FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_ALL_USES)
          {
            tree tmp = NULL;
            tree use = USE_FROM_PTR (use_p);

            copy[i++] = use;
            if (TREE_CODE (use) == SSA_NAME)
          tmp = SSA_NAME_VALUE (use);
            if (tmp)
          SET_USE (use_p, tmp);
          }

        cached_lhs = simplifier->simplify (stmt, stmt, bb, this);

        /* Restore the statement's original uses/defs.  */
        i = 0;
        FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_ALL_USES)
          SET_USE (use_p, copy[i++]);

Ah, likely.  These days we'd likely use a gimple_match_op but then
this seems heavily abstracted, no idea where simplifier->simplify
might lead to ;)
I'm also not sure why the threader would do the valueization here and
not the simplify() function (and lookup_avail_expr misses an 'exploded' operand
lookup as well).  Lot's of legacy code ;)

Yes, there's a lot of legacy code I've left mostly alone.

There are two copies of simplify() now, the DOM version
(dom_jt_simplifier::simplify) and the VRP version
(hybrid_jt_simplifier::simplify).  Each do slightly different things, as
has always been the case.  It's just that the separation is now explicit.

No idea what's up with the valueization either.  The VRP version doesn't
need any of this valuezation or on the side structures.  You just ask
the range of a stmt on a path and it gives you an answer.

Yeah, but it doesn't "simplify", it uses ranger to do constant folding
... (ick).
For random expressions I'd have used gimple_simplify (in fact it somehow
tries to do value-numbering or sth like that to derive new equivalences).

The ranger is read-only. It is not folding anything. The simplify() callback is only returning the singleton the conditional resolves to (1 or 0 iirc). It is up to the caller (the forward threader in this case) to do any changes. This is how it always has been with either evrp, or VRP, or the const/copies/avails clients.



But I think the above is not going to be an issue unless ranger runs in
circles around backedges, arriving at this very same stmt again?  A way
out might be to copy the stmt to the stack, adjust operands and use that
for the simplify entry.

If you look at the patch I sent Jeff, you'll see that I've removed most
of what's in that function.  There's no need to propagate anything.  The
ranger can simplify the final conditional without having to set up anything.

So maybe we can remove all that code (jt_state::register_equivs_stmt).

That's the plan! But for that to happen we need to remove the evrp use in DOM and its threader. I've done most of the work in the patch, but it still needs some TLC. I'm unlikely to have time to finish it in this release, as I'm trying to remove the VRP threader altogether.

Aldy

Reply via email to