Skip to content

Commit 6ae4205

Browse files
committed
Update control flow with function details
1 parent 7f07c6c commit 6ae4205

File tree

5 files changed

+122
-115
lines changed

5 files changed

+122
-115
lines changed
Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
11
; calling_convention_test.ll
2-
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
3-
target triple = "x86_64-apple-macosx10.15.0"
4-
52
%ReturnType = type { i32, i32 }
63
define %ReturnType @foo(i32 %a1, i32 %a2, i32 %a3, i32 %a4, i32 %a5, i32 %a6, i32 %a7, i32 %a8) {
74
ret %ReturnType { i32 1, i32 2 }
@@ -10,4 +7,4 @@ define %ReturnType @foo(i32 %a1, i32 %a2, i32 %a3, i32 %a4, i32 %a5, i32 %a6, i3
107
define i32 @main() {
118
%1 = call %ReturnType @foo(i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8)
129
ret i32 0
13-
}
10+
}
Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
11
; tail_call_test.ll
2-
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
3-
target triple = "x86_64-apple-macosx10.15.0"
4-
52
define fastcc i32 @foo(i32 %a) {
63
%res = icmp eq i32 %a, 1
74
br i1 %res, label %btrue, label %bfalse
@@ -11,4 +8,4 @@ bfalse:
118
%sub = sub i32 %a, 1
129
%tail_call = tail call fastcc i32 @foo(i32 %sub)
1310
ret i32 %tail_call
14-
}
11+
}

src/05-控制流/01-控制语句.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# 控制语句
22

3+
在控制流中,最基础的就是控制语句,也就是与汇编中的跳转相关的。
4+
35
## 汇编层面的控制语句
46

57
在大多数语言中,常见的控制语句主要有四种:
@@ -408,7 +410,7 @@ foo:
408410
retq
409411
```
410412

411-
算上注释,C语言代码9行,汇编语言代码11行,LLVM IR代码14行。这LLVM IR同时比低层次和高层次的代码都长,这显然是不可以接受的。究其原因,就是这里把`y`看成了可变变量。那么,有没有什么办法让`y`不可变但仍然能实现这个功能呢?
413+
算上注释,C语言代码9行,汇编语言代码11行,LLVM IR代码14行。这LLVM IR同时比低层次和高层次的代码都长,而且这种模式在真实的代码中出现的次数会非常多,这显然是不可以接受的。究其原因,就是这里把`y`看成了可变变量。那么,有没有什么办法让`y`不可变但仍然能实现这个功能呢?
412414

413415
首先,我们来看看同样区分可变变量与不可变变量的Rust是怎么做的:
414416

@@ -433,6 +435,8 @@ define void @foo(i32 %x) {
433435

434436
`select`指令接受三个参数。第一个参数是用来判断的布尔值,也就是`i1`类型的`icmp`判断的结果,如果其为`true`,则返回第二个参数,否则返回第三个参数。极其合理。
435437

438+
`select`不仅可以简化LLVM代码,也可以优化生成的二进制程序。在大部分情况下,在AMD64架构中,LLVM会将`select`指令编译为[`CMOV`cc](https://www.felixcloutier.com/x86/cmovcc)指令,也就是条件赋值,从而优化了生成的二进制代码。
439+
436440
### `phi`
437441

438442
`select`只能支持两个选择,`true`选择一个分支,`false`选择另一个分支,我们是不是可以有支持多种选择的类似`switch`的版本呢?同时,我们也可以换个角度思考,`select`是根据`i1`的值来进行判断,我们其实可以根据控制流进行判断。这就是在SSA技术中大名鼎鼎的`phi`指令。

0 commit comments

Comments
 (0)