DescriptionHi I have attached a patch to do user directed function multiversioning. This is still in prototyping and I want to send this upstream for feedback. I wanted to first get some feedback from the team. Thanks, -Sri. User directed Function Multiversioning (MV) via Function Overloading ==================================================================== This patch adds support for user directed function MV via function overloading. Here is an example program with function versions: int foo (); /* Default version */ int foo () __attribute__ ((targetv("arch=corei7")));/*Specialized for corei7 */ int foo () __attribute__ ((targetv("arch=core2")));/*Specialized for core2 */ int main () { int (*p)() = &foo; return foo () + (*p)(); } int foo () { return 0; } int __attribute__ ((targetv("arch=corei7"))) foo () { return 0; } int __attribute__ ((targetv("arch=core2"))) foo () { return 0; } The above example has foo defined 3 times, but all 3 definitions of foo are different versions of the same function. The call to foo in main, directly and via a pointer, are calls to the multi-versioned function foo which is dispatched to the right foo at run-time. Function versions must have the same signature but must differ in the specifier string provided to a new attribute called "targetv", which is nothing but the target attribute with an extra specification to indicate a version. Any number of versions can be created using the targetv attribute but it is mandatory to have one function without the attribute, which is treated as the default version. The dispatching is done using the IFUNC mechanism to keep the dispatch overhead low. The compiler creates a dispatcher function which checks the CPU type and calls the right version of foo. The dispatching code checks for the platform type and calls the first version that matches. The default function is called if no specialized version is appropriate for execution. The pointer to foo is made to be the address of the dispatcher function, so that it is unique and calls made via the pointer also work correctly. The assembler names of the various versions of foo is made different, by tagging the specifier strings, to keep them unique. A specific version can be called directly by creating an alias to its assembler name. For instance, to call the corei7 version directly, make an alias : int foo_corei7 () __attribute__((alias ("_Z3foov.arch_corei7"))); and then call foo_corei7. Note that using IFUNC blocks inlining of versioned functions. I had implemented an optimization earlier to do hot path cloning to allow versioned functions to be inlined. Please see : http://gcc.gnu.org/ml/gcc-patches/2011-04/msg02285.html In the next iteration, I plan to merge these two. With that, hot code paths with versioned functions will be cloned so that versioned functions can be inlined. Patch Set 1 # Total comments: 11
MessagesTotal messages: 4 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||