1.Obtain the autoifunc proof-of-conccept code
tar xvf /public/spo600-autoifunc-preprocessor-pos.tgz
[hchoi72@israel autoifunc-preprocessor-poc]$ ll
total 56
-rw-r--r--. 1 hchoi72 hchoi72 212 Nov 8 09:59 adjust_channels.h
-rw-r--r--. 1 hchoi72 hchoi72 1310 Nov 8 09:59 function.c
-rw-r--r--. 1 hchoi72 hchoi72 197 Nov 8 09:59 function.h
-rw-r--r--. 1 hchoi72 hchoi72 18092 Nov 8 09:59 LICENSE
-rw-r--r--. 1 hchoi72 hchoi72 2448 Nov 8 09:59 main.c
-rw-r--r--. 1 hchoi72 hchoi72 941 Nov 8 10:42 Makefile
-rw-------. 1 hchoi72 hchoi72 0 Nov 8 09:59 nohup.out
-rw-r--r--. 1 hchoi72 hchoi72 571 Nov 8 10:17 README.md
drwxr-xr-x. 2 hchoi72 hchoi72 4096 Nov 8 10:11 scripts
drwxr-xr-x. 2 hchoi72 hchoi72 4096 Nov 8 09:59 tar
drwxr-xr-x. 4 hchoi72 hchoi72 4096 Nov 8 09:59 tests
2.Build the code
$ make
After building the code, function_ifunc.c
is generated.
[hchoi72@israel autoifunc-preprocessor-poc]$ ll
total 788
...
-rw-r--r--. 1 hchoi72 hchoi72 3224 Nov 8 13:22 function_ifunc.c
...
Compilation
gcc function.c -o function
gcc function_ifunc.c -o function_ifunc
./function
./function_ifunc
Resolver function
adjust_channels__resolver
- determines which version of
adjust_channels
function will be used based on the architecture - checks if SVE is supported. If it does, it returns a pointer to
adjust_channels__sve
. If it doesn't, it returns a pointer toadjust_channels__asimd
Two different copies of adjust_channels function
1.SVE Implementation - adjust_channels__sve
- uses Scalable Vector Extension instructions
2.ASIMD Implementation - adjust_channels__asimd
- uses advanced SIMD instructions
Pragma statements
#pragma GCC target "arch=armv8-a+sve"
#pragma GCC target "arch=armv8-a"
- specifies which architecture to be used for the compilation
- first pragma will use armv8-a+sve and second pragma will use armv8-a
Indirect function prototype
void adjust_channels(unsigned char *image,int x_size,int y_size,float red_factor,float green_factor,float blue_factor) **__attribute__(( ifunc("adjust_channels__resolver"))**);
- attributes specifies function implementation is going to be resolved at runtime depending on the result of
adjust_channels__resolver
3.Add the compiler option -fdump-tree-gimple
gcc function.c -o function -fdump-tree-gimple
gcc function_ifunc.c -o function_ifunc -fdump-tree-gimple
-> generate output files with the extension .gimple
in the same directory. Output files contain the gimple representation of the code.
[hchoi72@israel autoifunc-preprocessor-poc]$ ll
total 120
...
-rw-r--r--. 1 hchoi72 hchoi72 2026 Nov 8 14:09 function.c.006t.gimple
...
-rw-r--r--. 1 hchoi72 hchoi72 5337 Nov 8 14:09 function_ifunc.c.006t.gimple
...
4.GIMPLE
what is GIMPLE?
- stands for GCC Intermediate Representation
- simplified version of code, which makes the code easier to analyze and manipulate for optimization
Examine function_ifunc.c.006t.gimple
Are there any differences between the SVE and ASIMD versions of the function?
-
adjust_channels__sve
vsadjust_channels__asimd
- Main difference: How it performs the calculations
- Overall structure and logic are very similar
Has autovectorization been applied to the code at this poing in the compilation process?
- autovectorization: compiler optimization technique by automatically transforming code into SIMD code using vectorized instruction
- since autovectorization happens at later stage of compilation process, it is not very clear whether autovectorization has been applied
How do you know then?
- check whether compiler flags are following:
-02
,-03
or-ftree-vectorize
., etc - check if
-fopt-info
flag was specified in an optimization report - check out the assembly code to see whether any SIMD instructions are used
How are the #pragma lines in the source file reflected in the gimple?
#pragma GCC target "arch=armv8-a+sve"
- reflected as
__attribute__((target ("arch=armv8-a+sve")))
in the gimple - it's applied to function like
void adjust_channels__sve()
ormain()
as these functions are intneded for the ARMv8-A architecture with SVE
#pragma GCC target "arch=armv8-a"
- reflected as
__attribute__((target ("arch=armv8-a+sve", "arch=armv8-a")))
in the gimple
5.Steps to transform the gimple representation of function.c into the gimple represenation of function_ifunc.c
Main difference between function.c.006t.gimple
vs
function_ifunc.c.006t.gimple
- use SVE instruction in
function.c.006t.gimple
- use indirect function and both SVE and ASIMD instruction in
function_ifunc.c.006t.gimple
Steps
- include headers
#include <sys/auxv.h>
- add indirect function declaration in
function.c
before
void adjust_channels(unsigned char *image, int x_size, int y_size,float red_factor, float green_factor, float blue_factor);
after
void adjust_channels(unsigned char *image,int x_size,int y_size,float red_factor,float green_factor,float blue_factor) __attribute__(( ifunc("adjust_channels__resolver")));
- add Ifunc resolver function, which decides which version of
adjust_channels
to be used
static void (*adjust_channels__resolver(void)) {
long hwcaps = getauxval(AT_HWCAP);
long hwcaps2 = getauxval(AT_HWCAP2);
if (hwcaps & HWCAP_SVE) {
return adjust_channels__sve;
} else {
return adjust_channels__asimd;
}
};
Top comments (0)