Interesting idea about lazy IFUNC relocation.

David

On Mon, Mar 18, 2013 at 2:02 AM, Richard Biener
<richard.guent...@gmail.com> wrote:
> On Fri, Mar 15, 2013 at 10: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.
>>
>> 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.
>>
>> 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.
>>
>> 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.
>
> Err.  As we are using IFUNCs isn't it simply possible to do this in
> the dynamic loader - for example by simlply pre-loading a library
> with the IFUNC relocators implemented differently?  Thus, shouldn't
> we simply provide such library as a convenience?
>
> Thanks,
> Richard.
>
>> Thanks
>> Sri

Reply via email to