15. Basic Block
15
int foo (ini n)
{
int ret;
if (n > 10)
ret = n * 2;
else
ret = n + 2;
return ret;
}
16. Basic Block
16
int foo (ini n)
{
int ret;
if (n > 10)
ret = n * 2;
else
ret = n + 2;
return ret;
}
17. Basic Block
17
int foo (ini n)
{
int ret;
if (n > 10)
ret = n * 2;
else
ret = n + 2;
return ret;
}
int ret;
if (n > 10)
ret = n * 2; ret = n + 2;
return ret;
18. CFG
18
int foo (ini n)
{
int ret;
if (n > 10)
ret = n * 2;
else
ret = n + 2;
return ret;
}
int ret;
if (n > 10)
ret = n * 2; ret = n + 2;
return ret;
19. Basic Block
19
int sum (int n)
{
int ret = 0;
int i;
for (i = 0; i < n; ++i)
ret += i;
return ret;
}
20. Basic Block
20
int sum (int n)
{
int ret = 0;
int i;
for (i = 0; i < n; ++i)
ret += i;
return ret;
}
21. Basic Block
21
int sum (int n)
{
int ret = 0;
int i;
for (i = 0; i < n; ++i)
ret += i;
return ret;
}
int ret = 0;
int i;
i = 0;
i < n;
ret += i;
++i
return ret
22. CFG
22
int sum (int n)
{
int ret = 0;
int i;
for (i = 0; i < n; ++i)
ret += i;
return ret;
}
int ret = 0;
int i;
i = 0;
i < n;
ret += i;
++i
return ret
24. SSA
24
int foo ()
{
int ret;
ret = 10;
ret = 20;
return ret;
}
25. SSA
25
int foo ()
{
int ret;
ret = 10;
ret = 20;
return ret;
}
int foo ()
{
int ret;
ret1 = 10;
ret2 = 20;
return ret2;
}
每次賦值都會一個版本號
26. SSA
26
int foo ()
{
int ret;
ret = 10;
ret = 20;
return ret;
}
int foo ()
{
int ret;
ret1 = 10;
ret2 = 20;
return ret2;
}
每次賦值都會一個版本號
標完後可以馬上知道
是使用哪個運算式的結果
27. SSA
27
int foo (ini n)
{
int ret;
if (n > 10)
ret = n * 2;
else
ret = n + 2;
return ret;
}
28. SSA
28
int foo (ini n)
{
int ret;
if (n > 10)
ret = n * 2;
else
ret = n + 2;
return ret;
}
int foo (ini n)
{
int ret;
if (n > 10)
ret1 = n * 2;
else
ret2 = n + 2;
return ret?;
}
程式中有分歧點會合時
無法判定是從何而來
29. SSA
29
int foo (ini n)
{
int ret;
if (n > 10)
ret = n * 2;
else
ret = n + 2;
return ret;
}
int foo (ini n)
{
int ret;
if (n > 10)
ret1 = n * 2;
else
ret2 = n + 2;
ret3 = Φ (ret1, ret2)
return ret3;
}
此時需要使用Φ來
處理這種情況,
表示值的定義
需由程式流程決定
並給予新的版本號
62. Constant Propagation
62
int foo(int a)
{
int magic_num = 10;
return a + magic_num;
}
int foo(int a)
{
int magic_num = 10;
return a + 10;
}
63. Constant Propagation
63
opt foo.ll -mem2reg -view-cfg
int foo(int a)
{
int magic_num = 10;
return a + magic_num;
}
這種最佳化太基本了,
在mem2reg過程順便作掉
int foo(int a)
{
int magic_num = 10;
return a + 10;
}
64. Constant Propagation
64
int foo(int a)
{
int magic_num = 10;
return a + magic_num;
}
int foo(int a)
{
int magic_num = 10;
return a + 10;
}
千萬不要覺得寫成右邊那樣
會比較快就寫一堆
該死的 Magic Number!!!!
78. Inline + Propagation
78
int add(int a, int b)
{
return a + b;
}
int foo(int n){
int sum = 0;
int i, t;
for (i = 0; i < n ;++i) {
t = add(10, 20);
sum = add(sum, i);
sum = add(sum, t);
}
return sum;
}
79. Inline + Propagation
79
int add(int a, int b)
{
return a + b;
}
int foo(int n){
int sum = 0;
int i, t;
for (i = 0; i < n ;++i) {
t = add(10, 20);
sum = add(sum, i);
sum = add(sum, t);
}
return sum;
}
define i32 @add(i32 %a, i32 %b) {
%1 = add i32 %a, %b
ret i32 %1
}
define i32 @foo(i32 %n) {
br label %1
; <label>:1
%sum.0 = phi i32 [ 0, %0 ], [ %6, %7 ]
%i.0 = phi i32 [ 0, %0 ], [ %8, %7 ]
%2 = icmp slt i32 %i.0, %n
br i1 %2, label %3, label %9
; <label>:3
%4 = call i32 @add(i32 10, i32 20)
%5 = call i32 @add(i32 %sum.0, i32 %i.0)
%6 = call i32 @add(i32 %5, i32 %4)
br label %7
; <label>:7
%8 = add i32 %i.0, 1
br label %1
; <label>:9
ret i32 %sum.0
}
clang -emit-llvm -S inline.c
opt inline.ll -mem2reg -S
82. DCE
82
int foo()
{
a = 5;
if (a > 10)
b = 10;
else
b = 20;
return b;
}
83. DCE
83
int foo()
{
a = 5;
if (a > 10)
b = 10;
else
b = 20;
return b;
}
int foo()
{
a = 5;
if (5 > 10)
b = 10;
else
b = 20;
return b;
}
Constant Propagation
84. DCE
84
int foo()
{
a = 5;
if (a > 10)
b = 10;
else
b = 20;
return b;
}
int foo()
{
a = 5;
if (5 > 10)
b = 10;
else
b = 20;
return b;
}
int foo()
{
a = 5;
if (false)
b = 10;
else
b = 20;
return b;
}
Constant Propagation
Constant
Folding
85. DCE
85
int foo()
{
a = 5;
if (a > 10)
b = 10;
else
b = 20;
return b;
}
int foo()
{
a = 5;
if (5 > 10)
b = 10;
else
b = 20;
return b;
}
int foo()
{
a = 5;
if (false)
b = 10;
else
b = 20;
return b;
}
Constant Propagation
int foo()
{
b = 20;
return b;
}
Constant
Folding
DCE
86. DCE
86
int foo()
{
a = 5;
if (a > 10)
b = 10;
else
b = 20;
return b;
}
int foo()
{
a = 5;
if (5 > 10)
b = 10;
else
b = 20;
return b;
}
int foo()
{
a = 5;
if (false)
b = 10;
else
b = 20;
return b;
}
int foo()
{
b = 20;
return b;
}
int foo()
{
return 20;
}
Constant Propagation
Constant
Folding
Constant DCE
Propagation
87. 用LLVM觀察DCE (1/5)
87
int foo()
{
int a;
int b;
a = 5;
if (a > 10)
b = a + 10;
else
b = a + 20;
return b;
}
clang -S -emit-llvm dce.c
define i32 @foo() {
entry:
%a = alloca i32
%b = alloca i32
store i32 5, i32* %a
%0 = load i32* %a
%cmp = icmp sgt i32 %0, 10
br i1 %cmp, label %if.then, label %if.else
if.then:
%1 = load i32* %a
%add = add i32 %1, 10
store i32 %add, i32* %b
br label %if.end
if.else:
%2 = load i32* %a
%add1 = add i32 %2, 20
store i32 %add1, i32* %b
br label %if.end
if.end:
%3 = load i32* %b
ret i32 %3
}
100. Loop Unroll
100
• Loop Unroll:迴圈展開
– 跳躍指令在大多數架構下比一般運算指令貴
– 展開後Loop index可能從變數變成常數
sum = 0;
for (i = 0; i < 3; ++i)
sum = sum + i
sum = 0;
sum = sum + 0
sum = sum + 1
sum = sum + 2
101. 用LLVM觀察Loop Unroll (1/8)
101
int add(int a, int b)
{
return a + b;
}i
nt foo()
{
int sum = 0;
int i;
for (i = 0; i < 3; ++i)
sum = add(sum, i);
return sum;
}
clang -emit-llvm -S for.c
opt for.ll -mem2reg -S
define i32 @add(i32 %a, i32 %b) {
entry:
%add = add i32 %a, %b
ret i32 %add
}
define i32 @foo() {
entry:
br label %for.cond
for.cond:
%i.0 = phi i32 [ 0, %entry ],
[ %inc, %for.inc ]
%sum.0 = phi i32 [ 0, %entry ],
[ %call, %for.inc ]
%cmp = icmp slt i32 %i.0, 3
br i1 %cmp, label %for.body, label %for.end
for.body:
%call = call i32 @add(i32 %sum.0, i32 %i.0)
br label %for.inc
for.inc:
%inc = add i32 %i.0, 1
br label %for.cond
for.end:
ret i32 %sum.0
}