On Wed, Aug 17, 2011 at 4:52 PM, Xinliang David Li <davi...@google.com> wrote:
> The gist of previous discussion is to use function overloading instead
> of exposing underlying implementation such as builtin_dispatch to the
> user. This new refined proposal has not changed in that, but is more
> elaborate on various use cases which has been carefully thought out.
> Please be specific on which part needs to improvement.

See below ...

> Thanks,
>
> David
>
> On Wed, Aug 17, 2011 at 12:29 AM, Richard Guenther
> <richard.guent...@gmail.com> wrote:
>> On Tue, Aug 16, 2011 at 10:37 PM, Sriraman Tallam <tmsri...@google.com> 
>> wrote:
>>> Hi,
>>>
>>>  I am working on supporting function multi-versioning in GCC and here
>>> is a write-up on its usability.
>>>
>>> Multiversioning Usability
>>> ====================
>>>
>>> For a simple motivating example,
>>>
>>> int
>>> find_popcount(unsigned int i)
>>> {
>>>  return __builtin_popcount(i);
>>> }
>>>
>>> Currently, compiling this with -mpopcnt will result in the “popcnt”
>>> instruction being used and otherwise call a built-in generic
>>> implementation. It is desirable to have two versions of this function
>>> so that it can be run both on targets that support the popcnt insn and
>>> those that do not.
>>>
>>>
>>> * Case I - User Guided Versioning where only one function body is
>>> provided by the user.
>>>
>>> This case addresses a use where the user wants multi-versioning but
>>> provides only one function body.  I want to add a new attribute called
>>> “mversion” which will be used like this:
>>>
>>> int __attribute__(mversion(“popcnt”))
>>> find_popcount(unsigned int i)
>>> {
>>>  return __builtin_popcount(i);
>>> }
>>>
>>> With the attribute, the compiler should understand that it should
>>> generate two versions for this function. The user makes a call to this
>>> function like a regular call but the code generated would call the
>>> appropriate function at run-time based on a check to determine if that
>>> instruction is supported or not.

The example seems to be particularly ill-suited.  Trying to 2nd guess you
here I think you want to direct the compiler to emit multiple versions
with different target capabilities enabled, probably for elaborate code that
_doesn't_ use any fancy builtins, right?  It seems this is a shortcut for

static inline __attribute__((always_iniline)) implementation () { ... }

symbol __attribute__((target("msse2"))) { implementation(); }
symbol __attribute__((target("msse3"))) { implementation(); }
...

and so should be fully handled by the frontend (if at all, it seems to
be purely syntactic sugar).

I'd like to see it omitted initially - we should get the core stuff right
and build "nice" stuff ontop of it later, if necessary.

>>> The attribute can be scaled to support many versions but allowing a
>>> comma separated list of values for the mversion attribute. For
>>> instance, “__attribute__(mversion(“sse3”, “sse4”, ...)) will provide a
>>> version for each. For N attributes, N clones plus one clone for the
>>> default case will have to be generated by the compiler. The arguments
>>> to the "mversion" attribute will be similar to the arguments supported
>>> by the "target" attribute.
>>>
>>> This attribute is useful if the same source is going to be used to
>>> generate the different versions. If this has to be done manually, the
>>> user has to duplicate the body of the function and specify a target
>>> attribute of “popcnt” on one clone. Then, the user has to use
>>> something like IFUNC support or manually write code to call the
>>> appropriate version. All of this will be done automatically by the
>>> compiler with this new attribute.
>>>
>>> * Case II - User Guided Versioning where the function bodies for each
>>> version differ and is provided by the user.
>>>
>>> This case pertains to multi-versioning when the source bodies of the
>>> two or more versions are different and are provided by the user. Here
>>> too, I want to use a new attribute, “version”. Now, the user can
>>> specify versioning intent like this:
>>>
>>> int __attribute__((version(“popcnt”))
>>> find_popcnt(unsigned int i)
>>> {
>>>   // inline assembly of the popcnt instruction, specialized version.
>>>  asm(“popcnt ….”);
>>> }
>>>
>>> int
>>> find_popcnt(unsigned int i)
>>> {
>>>  //generic code for doing this
>>>  ...
>>> }
>>>
>>> This uses function overloading to specify versions.  The compiler will
>>> understand that versioning is requested, since the functions have
>>> different attributes with "version", and will generate the code to
>>> execute the right function at run-time.  The compiler should check for
>>> the existence of one body without the attribute which will be the
>>> default version.

Yep, we agreed that this is a good idea.  But we also agreed to
use either the target attribute (for compiler-generated tests) or
a single predicate attribute that takes a function which is const
with no arguments and returns whether the variant is selected or not.

>>> * Case III - Versioning is done automatically by the compiler.
>>>
>>> I want to add a new compiler flag “-mversion” along the lines of “-m”.
>>> If the user specifies “-mversion=popcnt” then the compiler will
>>> automatically create two versions of any function that is impacted by
>>> the new instruction. The difference between “-m” and “-mversion” will

How do you plan to detect "impacted by the new instruction?".  Again
popcnt seems to be a poor example - most use probably lies in
autovectorization (but then it's closely tied to active capabilites of the
backend and not really ready for auto-versioning).

This will be a lot of work if it shouldn't be very inefficient.

Richard.

>>> be that while “-m” generates only the specialized version, “-mversion”
>>> will generate both the specialized and the generic versions.  There is
>>> no need to explicity mark any function for versioning, no source
>>> changes.
>>>
>>> The compiler will decide if it is beneficial to multi-version a
>>> function based on heuristics using hotness information, code size
>>> growth, etc.
>>>
>>>
>>> Runtime support
>>> ===============
>>>
>>> In order for the compiler to generate multi-versioned code, it needs
>>> to call functions that would test if a particular feature exists or
>>> not at run-time. For example, IsPopcntSupported() would be one such
>>> function. I have prepared a patch to do this which adds the runtime
>>> support in libgcc and supports new builtins to test the various
>>> features. I will send the patch separately to keep the dicussions
>>> focused.
>>>
>>>
>>> Thoughts?
>>
>> Please focus on one mechanism and re-use existing facilities as much as
>> possible.  Thus, see the old discussion where we settled on overloading
>> with either using the existing target attribute or a selector function.
>> I don't see any benefit repeating the discussions here.
>>
>> Richard.
>>
>>> Thanks,
>>> -Sri.
>>>
>>
>

Reply via email to