mchalupa / dg

[LLVM Static Slicer] Various program analyses, construction of dependence graphs and program slicing of LLVM bitcode.
MIT License
475 stars 131 forks source link

Slicer with Pointer Analysis #321

Open mye-rutgers opened 4 years ago

mye-rutgers commented 4 years ago

Hello,

I applied the following code to the llvm-slicer tool with the slicing criterion 13:b. Then, I used the llvm-to-source script to view the sliced line numbers. Only the line 13 was kept after the slicing, although the line 6 also changed the value stored in the same memory. Would you mind providing any help with the reason why only the line 13 was kept? Thank you!

1   void fact(int x, int *y)
2   {
3      int r = x;
4      while (--x >= 2)
5          r *= x;
6      *y = *y + 5;
7    }
8
9   int main(void)
10  {
11     int a = 5;
12     int b[3] = {1, 2, 3};
13     *b = 2;
14     b[2] = 8;
15     fact(a, b);
16     return 0;
17  }
mchalupa commented 4 years ago

Hi, could you fill in the commands that you used (clang, llvm-slicer) and their output? Thanks

mchalupa commented 4 years ago

And what version of dg you have.

mchalupa commented 4 years ago

Oh, actually I see. The line 6 is called only after line 13, so it has no effect on the value of b on line 13.

mye-rutgers commented 4 years ago

@mchalupa Thank you so much for your reply. Here is the original file (i.e., fact1.c) I ran:

1   #include <stdio.h>
2  
3   void fact(int x, int *y)
4   {
5   int r = x;
6   while (--x >=2)
7       r *= x;
8   *y = *y + 5;
9   }
10 
11  int main(void)
12  {
13  int a = 5;
14  int b[3] = {1, 2, 3};
15  *b = 2;
16  b[2] = 8;
17  fact(a, b);
18  return 0;
19   }

Here are the commands and their outputs:

$ clang -c -g -emit-llvm fact1.c -o fact1.bc

$ ./llvm-slicer -c 15:b fact1.bc 
Matched line 15 with variable b to:
  store i32 2, i32* %3, align 4, !dbg !18
[llvm-slicer] CPU time of pointer analysis: 2.487000e-03 s
[llvm-slicer] CPU time of reaching definitions analysis: 1.950000e-03 s
[llvm-slicer] CPU time of control dependence analysis: 1.770000e-04 s
[llvm-slicer] Finding dependent nodes took 0 sec 0 ms
[llvm-slicer] Slicing dependence graph took 0 sec 0 ms
[llvm-slicer] Sliced away 41 from 44 nodes in DG
[llvm-slicer] saving sliced module to: fact1.sliced

$ ./llvm-to-source fact1.sliced 
15

My Clang version is 3.8.0-2ubuntu4, and the dg version is up to the commit 25c4268.

The further test I did was applying the different criterion 8:y. Although the program needed the line 14 for the variable definition and line 15 for the initial value of b (i.e., the same memory space of y in the function fact), the slicer sliced them away. The following shows the commands and outputs.

$ ./llvm-slicer -c 8:y fact1.bc 
Matched line 8 with variable y to:
  %13 = load i32*, i32** %2, align 8, !dbg !27
Matched line 8 with variable y to:
  %16 = load i32*, i32** %2, align 8, !dbg !30
[llvm-slicer] CPU time of pointer analysis: 4.514000e-03 s
[llvm-slicer] CPU time of reaching definitions analysis: 1.899000e-03 s
[llvm-slicer] CPU time of control dependence analysis: 1.330000e-04 s
[llvm-slicer] Finding dependent nodes took 0 sec 0 ms
[llvm-slicer] Slicing dependence graph took 0 sec 0 ms
[llvm-slicer] Sliced away 34 from 44 nodes in DG
[llvm-slicer] saving sliced module to: fact1.sliced

$ ./llvm-to-source fact1.sliced 
8
13
17
mchalupa commented 3 years ago

For the slicing criterion 15:b, I already answered (with lines referring to the previous code)

Oh, actually I see. The line 6 is called only after line 13, so it has no effect on the value of b on line 13

For the slicing criterion 8:y, the slicer computes the slice w.r.t the value of the variable `y. That is the reason why the initialization of 'b' is not included in the slice (since it does not affect the value of 'y') I suppose you want to slice w.r.t the value of '*y', that is, the value of 'b'. In that case, the array definition is kept in the code along with the initialization of the first element (however, the llvm-to-source does not show the initialization -- it is a rather stupid tool -- but you can check it with the -annotate=slice option):

tools/llvm-slicer -c 8:b -annotate slice,memacc fact1.bc && tools/llvm-to-source fact1.sliced fact1.c
Matched line 8 with variable b to:
  %17 = load i32, i32* %16, align 4, !dbg !29
Matched line 8 with variable b to:
  store i32 %18, i32* %19, align 4, !dbg !32
[llvm-slicer] CPU time of pointer analysis: 5.460000e-03 s
[llvm-slicer] CPU time of reaching definitions analysis: 3.202000e-03 s
[llvm-slicer] CPU time of control dependence analysis: 3.010000e-04 s
[llvm-slicer] Finding dependent nodes took 0 sec 0 ms
[llvm-slicer] Saving IR with annotations to fact1-debug.ll
ERROR: Unhandled intrinsic
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %4, i8* align 4 bitcast ([3 x i32]* @__const.main.b to i8*), i64 12, i1 false), !dbg !20
[llvm-slicer] Slicing dependence graph took 0 sec 0 ms
[llvm-slicer] Sliced away 29 from 44 nodes in DG
[llvm-slicer] saving sliced module to: fact1.sliced
4: {
8:     *y = *y + 5;
9: }
12: {
13:     int a = 5;
15:     *b = 2;
17:     fact(a, b);
19: }