https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115863

--- Comment #12 from Richard Biener <rguenth at gcc dot gnu.org> ---
(In reply to Li Pan from comment #8)
> (In reply to Richard Biener from comment #7)
> > (In reply to Uroš Bizjak from comment #6)
> > > Please note that w/o .SAT_TRUNC the compiler is able to optimize hot loop 
> > > in
> > > compress2 to:
> > > 
> > >   <bb 5> [local count: 536870912]:
> > >   _18 = MIN_EXPR <left_8, 4294967295>;
> > >   iftmp.0_11 = (unsigned int) _18;
> > >   stream.avail_out = iftmp.0_11;
> > >   left_37 = left_8 - _18;
> > > 
> > > while .SAT_TRUNC somehow interferes with this optimization to produce:
> > > 
> > >   <bb 5> [local count: 536870912]:
> > >   _45 = MIN_EXPR <left_8, 4294967295>;
> > >   iftmp.0_11 = .SAT_TRUNC (left_8);
> > >   stream.avail_out = iftmp.0_11;
> > >   left_37 = left_8 - _45;
> > 
> > it looks like whatever recognizes .SAT_TRUNC doesn't pay attention that
> > there are other uses of the MIN_EXPR and thus the MIN_EXPR stays live.
> > 
> > IIRC :s on (match (...) is ignored (and that's good IMO) at the moment so
> > the user of the match predicate has to check.
> 
> Thanks Richard.
> Yes, the .SAT_TRUNC doesn't pay any attention the other possible use of
> MIN_EXPR.
> 
> As your suggestion, we may need one additional check here (like
> gimple_unsigned_sat_trunc() && no_other_MIN_EXPR_use_after_sat_trunc_p ())
> before we build the SAT_TRUNC call.
> Sorry I didn't get the point here why we need to do this, could you please
> help to explain a bit more about it? Like wrong code or something else in
> above
> sample code.

I'd amend the captured ops, like

(match (unsigned_integer_sat_trunc @0 @2)
 (convert (min@2 @0 INTEGER_CST@1))

(match (unsigned_integer_sat_trunc @0 @2)
 (bit_ior:c (negate (convert (gt@2 @0 INTEGER_CST@1)))

and in the transform do

  if (gimple_unsigned_integer_sat_trunc (lhs, ops, NULL)
    && has_single_use (ops[1])
    && direct_internal_fn_supported_p (IFN_SAT_TRUNC,

that would be the most simple way to avoid this.  Note it avoids the
alternate use for both the MIN_EXPR and the compare (for the 2nd pattern
it might be required to have more ops to check that, the convert and also the
negate).  I think you can't do

(match (unsigned_integer_sat_trunc @0 @2 @3 @4)
 (convert (min@2@3@4 @0 INTEGER_CST@1))

at the moment, but the machinery actually supports it for the case of
(convert?@1 (op@2 ...  where @1 and @2 refer to the same object when
the compare is not there.  So it might be a matter of amending parsing
here - of course it's a bit ugly.

Having a helper that can tell there's no external uses of a SSA chain
denoted by two end-points, namely the match root (the first op
you give to gimple_unsigned_integer_sat_trunc) and the "tail", the
matched ops[0] would be a nice thing to have.  Note that ops[0] is
the "wrong" root, so I think we want to match the real relevant
root which would be the compare in one case and the min in the other.
>From that the requirement would be

  tree op = ops[0];
  while (single_imm_use (op, &use_p, &use_stmt))
    {
      auto def = single_ssa_def_operand (use_stmt, SSA_OP_USE);
      op = DEF_FROM_PTR (def);
      if (op == lhs)
        return true;
    }
  return false;

and maybe call such helper gimple_isolated_expr_p (tree def, tree leaf);
where in principle this could support multiple leafs (just repeat the
above for each leaf).

The match.pd machinery could support this itself of course, you can
either add single_use () conditionals yourself, implement :s on the
individual operands or have a way to mark the whole expression in this
way.

So the easiest way is to do.  My above remarks are for some more general
utility.

(match (unsigned_integer_sat_trunc @0)
 (convert (min@2 @0 INTEGER_CST@1))
 (if (INTEGRAL_TYPE_P (type) && TYPE_UNSIGNED (type)
      && TYPE_UNSIGNED (TREE_TYPE (@0))
      && single_use (@2))

Reply via email to