On October 6, 2018 10:17:48 PM GMT+02:00, Denis Khalikov 
<d.khali...@partner.samsung.com> wrote:
>Hello everyone,
>this is a patch which implements EfficiencySanitizer aka ESan
>into GCC. The EfficiencySanitizer tool is available in the llvm.
>So, the main idea was to port the runtime library into GCC and
>implement GCC compiler pass on GIMPLE IR with the same semantics
>as llvm does on llvm IR.
>The main difference that this patch also enables ESan under 32 bit
>ARM CPU with some changes to runtime library.
>Link to the RFC on the llvm-dev:
>https://lists.llvm.org/pipermail/llvm-dev/2016-April/098355.html
>
>I know this patch is not acceptable into GCC trunk, so, I send
>this patch in the weekend to don't bother anyone, but may be
>someone will be interested. Also, I'll be very appreciated for
>any feedback.
>GCC should be build with --enable-checking=release.
>
>This patch includes:
>
>1. GCC pass for the CacheFragmentation tool on the GIMPLE IR.
>Special compiler pass instruments every memory access into the struct
>field with gimple internal call ESAN_RECORD_ACCESS and expands
>it in sanopt pass.
>Creates fields counter array, each cell of that array
>counts memory accesses to the special field. Creates array of
>the structs, where the every instance of the struct represents meta
>info of the real struct.
>
>a. Source example:
>
>struct node {
>   int a;
>   int b;
>   int c;
>};
>
>int main () {
>   struct node c;
>   for (int i = 0; i < 100; ++i) {
>     c.a = i + 1;
>     c.b = i + 1;
>     c.c = i + 1;
>   }
>   return 0;
>}
>
>b. Instrumented GIMPLE:
>   <bb 4> :
>   _1 = i_4 + 1;
>   .ESAN_RECORD_ACCESS (0B, 0);
>   c.a = _1;
>   _2 = i_4 + 1;
>   .ESAN_RECORD_ACCESS (0B, 1);
>   c.b = _2;
>   _3 = i_4 + 1;
>   .ESAN_RECORD_ACCESS (0B, 2);
>   c.c = _3;
>   i_11 = i_4 + 1;
>
>c. Assembler:
>
># The fields counter array.
># Every cell 8 bytes long and represents the amount
># of the field accesses.
>
>     .weak    struct.node$1$1$1
>     .bss
>     .align 8
>     .type    struct.node$1$1$1, @object
>     .size    struct.node$1$1$1, 24
>struct.node$1$1$1:
>     .zero    24
>
># Increment the specific cell by the field index.
># Actually __esan_increment, could be inlined.
>    movl    $struct.node$1$1$1, %eax
>    movq    %rax, %rdi
>    call    __esan_increment
>    movl    %ebx, -32(%rbp)
>    movl    -20(%rbp), %eax
>    leal    1(%rax), %ebx
>    movl    $struct.node$1$1$1+8, %eax
>    movq    %rax, %rdi
>    call    __esan_increment
>    movl    %ebx, -28(%rbp)
>    movl    -20(%rbp), %eax
>    leal    1(%rax), %ebx
>    movl    $struct.node$1$1$1+16, %eax
>    movq    %rax, %rdi
>    call    __esan_increment
>
># The array of the structs with
># meta info like size of the special struct,
># number of the fields and pointer to the
># fields counter array.
>
>.Lesan_info0:
>     .quad    .LC0
>     .long    12
>     .long    3
>     .quad    0
>     .quad    0
>     .quad    0
>     .quad    struct.node$1$1$1
>     .quad    0
>
>__esan_init is inserted to the static constructor.
>__esan_exit is inserted to the static destructor.
>
>d. Output:
>
>==28719==  struct node
>==28719==   size = 12, count = 300, ratio = 2
>==28719==   # 0: count = 100
>==28719==   # 1: count = 100
>==28719==   # 2: count = 100
>==28719==EfficiencySanitizer: total struct field access count = 300
>
>2. GCC pass for the WorkingSet tool.
>Special compiler pass instruments every memory access in the program.
>Memory accesses are simply prepended with a function call like
>__esan_aligned_load(addr), __esan_aligned_store(addr).
>Also, __esan_init is inserted to the static constructor and
>__esan_exit is inserted to the static destructor.
>
>a. Assembler:
>
>   movq    -32(%rbp), %rax
>   movq    %rax, %rdi
>   call    __esan_aligned_store1
>
>The runtime library simply manages shadow memory and computes statistic
>of the program efficiency. The tool maps one cache line (64 bytes) of
>the program to the one byte of the shadow memory.
>The runtime library measures the data working set size of an
>application 
>at each snapshot during execution.
>
>b. Output:
>
>==28742== EfficiencySanitizer: the total working set size: 32 MB
>(524291 
>cache lines)
>
>HOW TO USE:
>
>WorkingSet tool.
>To measure the working set size, you should build your binary or
>shared library with compile time flag
>-fsanitize=efficiency-working-set and set runtime options 
>ESAN_OPTIONS=process_range_access=1:record_snapshots=1
>
>CacheFragmentation tool.
>To enable CacheFragmentation tool you should compile your binary or
>shared library with compile time flag -fsanitize=efficiency-cache-frag
>and set runtime options ESAN_OPTIONS=build_mode=0:verbosity=1

I wonder how this is more efficient or precise than tools like valgrind with a 
suitable CPU model? (with valgrind possibly using a JIT) 

Richard. 

Reply via email to