On Fri, Mar 15, 2013 at 3:37 PM, Xinliang David Li <davi...@google.com> wrote: > On Fri, Mar 15, 2013 at 2:55 PM, Sriraman Tallam <tmsri...@google.com> wrote: >> Hi, >> >> This patch is meant for google/gcc-4_7 but I want this to be >> considered for trunk when it opens again. This patch makes it easy to >> test for code coverage of multiversioned functions. Here is a >> motivating example: >> >> __attribute__((target ("default"))) int foo () { ... return 0; } >> __attribute__((target ("sse"))) int foo () { ... return 1; } >> __attribute__((target ("popcnt"))) int foo () { ... return 2; } >> >> int main () >> { >> return foo(); >> } >> >> Lets say your test CPU supports popcnt. A run of this program will >> invoke the popcnt version of foo (). Then, how do we test the sse >> version of foo()? To do that for the above example, we need to run >> this code on a CPU that has sse support but no popcnt support. >> Otherwise, we need to comment out the popcnt version and run this >> example. This can get painful when there are many versions. The same >> argument applies to testing the default version of foo. >> >> So, I am introducing the ability to mock a CPU. If the CPU you are >> testing on supports sse, you should be able to test the sse version. >> >> First, I have introduced a new flag called -fmv-debug. This patch >> invokes the function version dispatcher every time a call to a foo () >> is made. Without that flag, the version dispatch happens once at >> startup time via the IFUNC mechanism. >> >> Also, with -fmv-debug, the version dispatcher uses the two new >> builtins "__builtin_mock_cpu_is" and "__builtin_mock_cpu_supports" to >> check the cpu type and cpu isa. > > With this option, compiler probably can also define some macros so > that if user can use to write overriding hooks. > >> >> Then, I plan to add the following hooks to libgcc (in a different patch) : >> >> int set_mock_cpu_is (const char *cpu); >> int set_mock_cpu_supports (const char *isa); >> int init_mock_cpu (); // Clear the values of the mock cpu. >> >> With this support, here is how you can test for code coverage of the >> "sse" version and "default version of foo in the above example: >> >> int main () >> { >> // Test SSE version. >> if (__builtin_cpu_supports ("sse")) >> { >> init_mock_cpu(); >> set_mock_cpu_supports ("sse"); >> assert (foo () == 1); >> } >> // Test default version. >> init_mock_cpu(); >> assert (foo () == 0); >> } >> >> Invoking a multiversioned binary several times with appropriate mock >> cpu values for the various ISAs and CPUs will give the complete code >> coverage desired. Ofcourse, the underlying platform should be able to >> support the various features. >> > > It is the other way around -- it simplifies unit test writing and > running -- one unit test just need to be run on the same hardware > (with the most hw features) *ONCE* and all the versions can be > covered.
Yes, the test needs to run just once, potentially, if the test platform can support all of the features. > > > >> Note that the above test will work only with -fmv-debug as the >> dispatcher must be invoked on every multiversioned call to be able to >> dynamically change the version. >> >> Multiple ISA features can be set in the mock cpu by calling >> "set_mock_cpu_supports" several times with different ISA names. >> Calling "init_mock_cpu" will clear all the values. "set_mock_cpu_is" >> will set the CPU type. >> > > > Just through about another idea. Is it possible for compiler to create > some alias for each version so that they can be accessed explicitly, > just like the use of :: ? > > if (__buitin_cpu_supports ("sse")) > CHECK_RESULT (foo_sse (...)); > > CHECK_RESULT (foo_default(...)); This will work for this example. But, in general, this means changing the call site of every multiversioned call and that can become infeasible. Thanks Sri > > ... > > David > > >> This patch only includes the gcc changes. I will separately prepare a >> patch for the libgcc changes. Right now, since the libgcc changes are >> not available the two new mock cpu builtins check the real CPU like >> "__builtin_cpu_is" and "__builtin_cpu_supports". >> >> Patch attached. Please look at mv14_debug_code_coverage.C for an >> exhaustive example of testing for code coverage in the presence of >> multiple versions. >> >> Comments please. >> >> Thanks >> Sri