Am Dienstag, dem 16.12.2025 um 13:03 +0100 schrieb Martin Jambor:
> Hi,
> 
> On Tue, Dec 16 2025, Richard Biener wrote:
> > On Mon, Dec 15, 2025 at 9:42 PM Martin Uecker <[email protected]> wrote:
> > > 
> > > Am Montag, dem 15.12.2025 um 14:00 +0100 schrieb Richard Biener:
> > > > On Sun, Dec 14, 2025 at 3:33 PM Martin Uecker via Gcc <[email protected]> 
> > > > wrote:
> > > > > 
> > > > > Am Sonntag, dem 14.12.2025 um 15:10 +0100 schrieb Andreas Schwab:
> > > > > > On Dez 14 2025, Martin Uecker via Gcc wrote:
> > > > > > 
> > > > > > > One could use templates in C++ or macros, but then this is
> > > > > > > rather heavy weight and also rigid as one has to structure the
> > > > > > > code around it.   I am rather looking for some lightweight
> > > > > > > solution such as annotation I could put on the argument or 
> > > > > > > variable
> > > > > > > that says: If this is value is known to be a compile-time
> > > > > > > constant, please create a specialized code path when optimizing.
> > > > > > > (maybe with some limit on recursion), maybe only for specified
> > > > > > > parameter ranges.
> > > > > > > 
> > > > > > > Or are there other better ways to do this already?
> > > > > > 
> > > > > > Is __builtin_constant_p what you are looking for?
> > > > > 
> > > > > Not really.  I know I can use it in some inline wrapper to
> > > > > add my own compile-time specialization, but I want the compiler
> > > > > to create the specialized code for me without having to duplicate
> > > > > it the source.  It can specialize code already just fine if it
> > > > > likes to do so, but there seems to be no good  way to
> > > > > enforce this.
> > > > 
> > > > It only specializes at calls with constant arguments.  And it will not
> > > > replace calls to with non-constant arguments with if (val == constant)
> > > > specialization(); else regular();
> > > > either.  IIRC at some point we've talked about collecting
> > > > "interesting" constants and directing
> > > > all calls to a dispatcher.  There might be a PR about this.
> > > > 
> > > > So, do you actually want to have the unspecialized function replaced by
> > > > a dispatcher that has a few values specialized?
> > > 
> > > I am not 100% sure myself what I want/need, but something like a
> > > dispatcher based on some manually specified constants is indeed
> > > what I had in mind, e.g.
> > > 
> > > int foo(int n)
> > >         [[gnu::specialize(0)]]
> > > {
> > >         ...
> > > }
> > > 
> > > or maybe even inside functions
> > > 
> > > int foo(int n)
> > > {
> > >   ...
> > >   [[gnu::specialize(n == 3)]];
> > >   ...
> > > }
> > 
> > OK, so apart from this particular transform not being available
> > (but all building blocks are) this sounds like a user-hint for
> > interesting (common?) constants to specialize for.  I could
> > imagine FDO could collect histograms of function arguments
> > (in the callee) as well, we could see during fnsummary computation
> > which of the common constants would be worth specializing for
> > (like we value-profile divisions already).  The above function
> > attribute would then provide alternate input for the machinery.
> > 
> 
> So far our speculative edges always create comparison of the target
> address (whether it equals the function we think it is), we do not emit
> comparisons of values of parameters (yet).  All the other building
> blocks are indeed there, I think.
> 
> ...which is still something that needs to be clarified, we do want to
> have these run-time checks right?  Because earlier in the thread the
> proposal looked as if we wanted to clone whenever we know the constant
> is there but only if we know at compile time it is there.  (That would
> be really easy to implement because we would really have everything in
> place).

This is not fully clear to me either. 

If you can clone based on constants, you could write the
dispatcher yourself

if (x == 3) foo(3);
if (x == 4) foo(4); 

but it is much better to have this automatically generated.


It may still be useful to also have the clone-based-on-constants
feature to ensure propagation of the specialized code into other
function.  For example,

int bar(int x [[gnu::specialize]]) // specialize for constants
{
 ....
}

int foo(int x)
        [[gnu::specialize(x == 3)]];    // create dispatcher
{
  bar(x);       // since x is constant, also clone bar
}


So maybe dispatcher generation and cloning based on constants
should be seen as two complementary features.

I am also not sure how the interface should look like exactly.


> 
> Also, if we want the run-time checks, how do you want indirect calls to
> behave?
> 
> > We also have value-ranges as IPA inputs, so even
> > [[gnu::specialize(n < 5)]] might make sense?
> 
> We could do that too.  At least currently for the parameters themselves,
> we do not track value ranges for parts of aggregate parameters.
> 
> > 
> > I do like the ability to use assume-like expressions, but it might be
> > a bit awkward to translate this into useful info.  Can such attribute
> > placement be restricted to be before any in-function mention of the
> > arguments to avoid like
> > 
> > int foo(int n)
> > {
> >   n++;
> >   [[gnu::specialize(n == 3)]];
> > }
> > 
> > ?
> > 
> > Can you open a PR for this?
> 
> Please CC mee too, thanks.

I will file a bug.

Martin

Reply via email to