On Fri, Jun 5, 2026 at 12:53 PM Georg-Johann Lay via Gcc <[email protected]> wrote: > > Am 05.06.26 um 11:41 schrieb Andrew Pinski: > > On Fri, Jun 5, 2026 at 2:25 AM Georg-Johann Lay via Gcc <[email protected]> > > wrote: > >> > >> In match.pd there are two kinds of patterns: Canonicalizations > >> and optimizations. > >> > >> While canonicalizations simplify the compile task by reducing > >> combinatorial complexity, optimization patterns try to improve > >> code performance. > >> > >> The trouble with the optimization patterns is that they operate blindly, > >> not considering costs or target capabilities in any way. > >> > >> Particularly bad example are patterns of the form > >> > >> /* (zero_one == 0) ? y : z <op> y -> ((typeof(y))zero_one * z) <op> y */ > >> /* (zero_one != 0) ? z <op> y : y -> ((typeof(y))zero_one * z) <op> y */ > > > > The simple answer here is expand should see if `((typeof(y))zero_one * > > z)` is cheaper than `(zero_one) ? z : 0`. I have some ideas on > > implementing that but I have not got around to it yet. > > That's already a bad proxy because `(zero_one == 0) ? y : z <op> y` > my be cheaper (an actually is on avr) than `(zero_one) ? z : 0`. > > Moreover, the multiplication in the mentioned form may no survive > until expand, e.g. may have been transformed to something different > when the code is more complex than a minimal example.
In this case gating the transform on TYPE_PRECISION (type) <= GET_MODE_PRECISION (word_mode) would work? To the extent still leaving AVR with a 8 bit multiply instead of a test-and-branch. In general I agree with Andrew that match.pd, for this kind of "optimizations", needs to apply costing. I'll note that this pattern attempts at if-converting code which can expose the code to additional optimization which you might lose when not applying if-conversion, so it's not always black-or-white and costing just a single transform can miss a bigger picture (that's a general problem, of course). > Johann > > >> that map single-bit tests to multiplications, even on machines where > >> multiplication is very expensive, and even when a target doesn't support > >> multiplications. > >> > >> All a back end can do is try to write patterns for the insn combiner and > >> such, that try to undo code that makes GCC look stupid and ridiculous. > >> > >> In cases where MUL is expanded to a libcall, rolling back is not even > >> possible. > >> > >> So the question is: Is possible and wanted to give targets > >> a say in whether match.pd patterns should be rejected? > >> > >> The next question is how this could be implemented? > >> > >> Here is a proposal: > >> > >> Support a file like <target>.pd in the back end, that, if present, > >> takes precedence over the middle end's match.pd. That way, a backend > >> could reject / FAIL patterns like the ones above. That's an interesting idea. To be practical w/o changs the target.pd would need to be included first and would need to "succeed" in transforming. So I'm not sure this is very maintainable - also considering that match.pd might change slightly and the target.pd no longer matching. I actually do consider a target.pd useful, but limited to pre-RTL-expansiion and to add additional patterns, not disable others. > >> > >> The advantages are: > >> > >> * There's already support to generate .cc from .pd. > >> > >> * No cluttering up of match.pd of any kind. > >> > >> * No need for complicated C code that evaluates trees or RTXes like > >> in rtx costs. > >> > >> As a final note: Using the existence of a standard insn as a proxy would > >> be a bad choice. Existence of say, mulsi3, doesn't mean at all that > >> such a pattern is cheap in any way. > >> > >> > >> Thanks, > >> Johann > >> >
