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