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.



> 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(...));

...

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

Reply via email to