redscript-mc 1.2.30 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/commands/build-test.md +10 -0
- package/.claude/commands/deploy-demo.md +12 -0
- package/.claude/commands/stage-status.md +13 -0
- package/.claude/settings.json +12 -0
- package/.github/workflows/ci.yml +1 -0
- package/CLAUDE.md +231 -0
- package/demo.gif +0 -0
- package/dist/cli.js +2 -554
- package/dist/compile.js +2 -266
- package/dist/index.js +2 -159
- package/dist/lowering/index.js +5 -3
- package/dist/src/__tests__/cli.test.d.ts +1 -0
- package/dist/src/__tests__/cli.test.js +104 -0
- package/dist/src/__tests__/codegen.test.d.ts +1 -0
- package/dist/src/__tests__/codegen.test.js +152 -0
- package/dist/src/__tests__/compile-all.test.d.ts +10 -0
- package/dist/src/__tests__/compile-all.test.js +108 -0
- package/dist/src/__tests__/dce.test.d.ts +1 -0
- package/dist/src/__tests__/dce.test.js +102 -0
- package/dist/src/__tests__/diagnostics.test.d.ts +4 -0
- package/dist/src/__tests__/diagnostics.test.js +177 -0
- package/dist/src/__tests__/e2e.test.d.ts +6 -0
- package/dist/src/__tests__/e2e.test.js +1789 -0
- package/dist/src/__tests__/entity-types.test.d.ts +1 -0
- package/dist/src/__tests__/entity-types.test.js +203 -0
- package/dist/src/__tests__/formatter.test.d.ts +1 -0
- package/dist/src/__tests__/formatter.test.js +40 -0
- package/dist/src/__tests__/lexer.test.d.ts +1 -0
- package/dist/src/__tests__/lexer.test.js +343 -0
- package/dist/src/__tests__/lowering.test.d.ts +1 -0
- package/dist/src/__tests__/lowering.test.js +1015 -0
- package/dist/src/__tests__/macro.test.d.ts +8 -0
- package/dist/src/__tests__/macro.test.js +306 -0
- package/dist/src/__tests__/mc-integration.test.d.ts +12 -0
- package/dist/src/__tests__/mc-integration.test.js +817 -0
- package/dist/src/__tests__/mc-syntax.test.d.ts +1 -0
- package/dist/src/__tests__/mc-syntax.test.js +124 -0
- package/dist/src/__tests__/nbt.test.d.ts +1 -0
- package/dist/src/__tests__/nbt.test.js +82 -0
- package/dist/src/__tests__/optimizer-advanced.test.d.ts +1 -0
- package/dist/src/__tests__/optimizer-advanced.test.js +124 -0
- package/dist/src/__tests__/optimizer.test.d.ts +1 -0
- package/dist/src/__tests__/optimizer.test.js +149 -0
- package/dist/src/__tests__/parser.test.d.ts +1 -0
- package/dist/src/__tests__/parser.test.js +807 -0
- package/dist/src/__tests__/repl.test.d.ts +1 -0
- package/dist/src/__tests__/repl.test.js +27 -0
- package/dist/src/__tests__/runtime.test.d.ts +1 -0
- package/dist/src/__tests__/runtime.test.js +289 -0
- package/dist/src/__tests__/stdlib-advanced.test.d.ts +4 -0
- package/dist/src/__tests__/stdlib-advanced.test.js +374 -0
- package/dist/src/__tests__/stdlib-bigint.test.d.ts +7 -0
- package/dist/src/__tests__/stdlib-bigint.test.js +426 -0
- package/dist/src/__tests__/stdlib-math.test.d.ts +7 -0
- package/dist/src/__tests__/stdlib-math.test.js +351 -0
- package/dist/src/__tests__/stdlib-vec.test.d.ts +4 -0
- package/dist/src/__tests__/stdlib-vec.test.js +263 -0
- package/dist/src/__tests__/structure-optimizer.test.d.ts +1 -0
- package/dist/src/__tests__/structure-optimizer.test.js +33 -0
- package/dist/src/__tests__/typechecker.test.d.ts +1 -0
- package/dist/src/__tests__/typechecker.test.js +552 -0
- package/dist/src/__tests__/var-allocator.test.d.ts +1 -0
- package/dist/src/__tests__/var-allocator.test.js +69 -0
- package/dist/src/ast/types.d.ts +515 -0
- package/dist/src/ast/types.js +9 -0
- package/dist/src/builtins/metadata.d.ts +36 -0
- package/dist/src/builtins/metadata.js +1014 -0
- package/dist/src/cli.d.ts +11 -0
- package/dist/src/cli.js +443 -0
- package/dist/src/codegen/cmdblock/index.d.ts +26 -0
- package/dist/src/codegen/cmdblock/index.js +45 -0
- package/dist/src/codegen/mcfunction/index.d.ts +40 -0
- package/dist/src/codegen/mcfunction/index.js +606 -0
- package/dist/src/codegen/structure/index.d.ts +24 -0
- package/dist/src/codegen/structure/index.js +279 -0
- package/dist/src/codegen/var-allocator.d.ts +45 -0
- package/dist/src/codegen/var-allocator.js +104 -0
- package/dist/src/compile.d.ts +37 -0
- package/dist/src/compile.js +165 -0
- package/dist/src/diagnostics/index.d.ts +44 -0
- package/dist/src/diagnostics/index.js +140 -0
- package/dist/src/events/types.d.ts +35 -0
- package/dist/src/events/types.js +59 -0
- package/dist/src/formatter/index.d.ts +1 -0
- package/dist/src/formatter/index.js +26 -0
- package/dist/src/index.d.ts +22 -0
- package/dist/src/index.js +45 -0
- package/dist/src/ir/builder.d.ts +33 -0
- package/dist/src/ir/builder.js +99 -0
- package/dist/src/ir/types.d.ts +132 -0
- package/dist/src/ir/types.js +15 -0
- package/dist/src/lexer/index.d.ts +37 -0
- package/dist/src/lexer/index.js +569 -0
- package/dist/src/lowering/index.d.ts +188 -0
- package/dist/src/lowering/index.js +3405 -0
- package/dist/src/mc-test/client.d.ts +128 -0
- package/dist/src/mc-test/client.js +174 -0
- package/dist/src/mc-test/runner.d.ts +28 -0
- package/dist/src/mc-test/runner.js +151 -0
- package/dist/src/mc-test/setup.d.ts +11 -0
- package/dist/src/mc-test/setup.js +98 -0
- package/dist/src/mc-validator/index.d.ts +17 -0
- package/dist/src/mc-validator/index.js +322 -0
- package/dist/src/nbt/index.d.ts +86 -0
- package/dist/src/nbt/index.js +250 -0
- package/dist/src/optimizer/commands.d.ts +38 -0
- package/dist/src/optimizer/commands.js +451 -0
- package/dist/src/optimizer/dce.d.ts +34 -0
- package/dist/src/optimizer/dce.js +639 -0
- package/dist/src/optimizer/passes.d.ts +34 -0
- package/dist/src/optimizer/passes.js +243 -0
- package/dist/src/optimizer/structure.d.ts +9 -0
- package/dist/src/optimizer/structure.js +356 -0
- package/dist/src/parser/index.d.ts +93 -0
- package/dist/src/parser/index.js +1687 -0
- package/dist/src/repl.d.ts +16 -0
- package/dist/src/repl.js +165 -0
- package/dist/src/runtime/index.d.ts +107 -0
- package/dist/src/runtime/index.js +1409 -0
- package/dist/src/typechecker/index.d.ts +61 -0
- package/dist/src/typechecker/index.js +1034 -0
- package/dist/src/types/entity-hierarchy.d.ts +29 -0
- package/dist/src/types/entity-hierarchy.js +107 -0
- package/dist/src2/__tests__/e2e/basic.test.d.ts +8 -0
- package/dist/src2/__tests__/e2e/basic.test.js +140 -0
- package/dist/src2/__tests__/e2e/macros.test.d.ts +9 -0
- package/dist/src2/__tests__/e2e/macros.test.js +182 -0
- package/dist/src2/__tests__/e2e/migrate.test.d.ts +13 -0
- package/dist/src2/__tests__/e2e/migrate.test.js +2739 -0
- package/dist/src2/__tests__/hir/desugar.test.d.ts +1 -0
- package/dist/src2/__tests__/hir/desugar.test.js +234 -0
- package/dist/src2/__tests__/lir/lower.test.d.ts +1 -0
- package/dist/src2/__tests__/lir/lower.test.js +559 -0
- package/dist/src2/__tests__/lir/types.test.d.ts +1 -0
- package/dist/src2/__tests__/lir/types.test.js +185 -0
- package/dist/src2/__tests__/lir/verify.test.d.ts +1 -0
- package/dist/src2/__tests__/lir/verify.test.js +221 -0
- package/dist/src2/__tests__/mir/arithmetic.test.d.ts +1 -0
- package/dist/src2/__tests__/mir/arithmetic.test.js +130 -0
- package/dist/src2/__tests__/mir/control-flow.test.d.ts +1 -0
- package/dist/src2/__tests__/mir/control-flow.test.js +205 -0
- package/dist/src2/__tests__/mir/verify.test.d.ts +1 -0
- package/dist/src2/__tests__/mir/verify.test.js +223 -0
- package/dist/src2/__tests__/optimizer/block_merge.test.d.ts +1 -0
- package/dist/src2/__tests__/optimizer/block_merge.test.js +78 -0
- package/dist/src2/__tests__/optimizer/branch_simplify.test.d.ts +1 -0
- package/dist/src2/__tests__/optimizer/branch_simplify.test.js +58 -0
- package/dist/src2/__tests__/optimizer/constant_fold.test.d.ts +1 -0
- package/dist/src2/__tests__/optimizer/constant_fold.test.js +131 -0
- package/dist/src2/__tests__/optimizer/copy_prop.test.d.ts +1 -0
- package/dist/src2/__tests__/optimizer/copy_prop.test.js +91 -0
- package/dist/src2/__tests__/optimizer/dce.test.d.ts +1 -0
- package/dist/src2/__tests__/optimizer/dce.test.js +76 -0
- package/dist/src2/__tests__/optimizer/pipeline.test.d.ts +1 -0
- package/dist/src2/__tests__/optimizer/pipeline.test.js +102 -0
- package/dist/src2/emit/compile.d.ts +19 -0
- package/dist/src2/emit/compile.js +80 -0
- package/dist/src2/emit/index.d.ts +17 -0
- package/dist/src2/emit/index.js +172 -0
- package/dist/src2/hir/lower.d.ts +15 -0
- package/dist/src2/hir/lower.js +378 -0
- package/dist/src2/hir/types.d.ts +373 -0
- package/dist/src2/hir/types.js +16 -0
- package/dist/src2/lir/lower.d.ts +15 -0
- package/dist/src2/lir/lower.js +453 -0
- package/dist/src2/lir/types.d.ts +136 -0
- package/dist/src2/lir/types.js +11 -0
- package/dist/src2/lir/verify.d.ts +14 -0
- package/dist/src2/lir/verify.js +113 -0
- package/dist/src2/mir/lower.d.ts +9 -0
- package/dist/src2/mir/lower.js +1030 -0
- package/dist/src2/mir/macro.d.ts +22 -0
- package/dist/src2/mir/macro.js +168 -0
- package/dist/src2/mir/types.d.ts +183 -0
- package/dist/src2/mir/types.js +11 -0
- package/dist/src2/mir/verify.d.ts +16 -0
- package/dist/src2/mir/verify.js +216 -0
- package/dist/src2/optimizer/block_merge.d.ts +12 -0
- package/dist/src2/optimizer/block_merge.js +84 -0
- package/dist/src2/optimizer/branch_simplify.d.ts +9 -0
- package/dist/src2/optimizer/branch_simplify.js +28 -0
- package/dist/src2/optimizer/constant_fold.d.ts +10 -0
- package/dist/src2/optimizer/constant_fold.js +85 -0
- package/dist/src2/optimizer/copy_prop.d.ts +9 -0
- package/dist/src2/optimizer/copy_prop.js +113 -0
- package/dist/src2/optimizer/dce.d.ts +8 -0
- package/dist/src2/optimizer/dce.js +155 -0
- package/dist/src2/optimizer/pipeline.d.ts +10 -0
- package/dist/src2/optimizer/pipeline.js +42 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/docs/compiler-pipeline-redesign.md +2243 -0
- package/docs/optimization-ideas.md +1076 -0
- package/editors/vscode/package-lock.json +3 -3
- package/editors/vscode/package.json +1 -1
- package/jest.config.js +1 -1
- package/package.json +6 -5
- package/scripts/postbuild.js +15 -0
- package/src/__tests__/cli.test.ts +8 -220
- package/src/__tests__/dce.test.ts +11 -56
- package/src/__tests__/diagnostics.test.ts +59 -38
- package/src/__tests__/mc-integration.test.ts +1 -2
- package/src/ast/types.ts +6 -1
- package/src/cli.ts +29 -156
- package/src/compile.ts +6 -162
- package/src/index.ts +14 -178
- package/src/mc-test/runner.ts +4 -3
- package/src/parser/index.ts +1 -1
- package/src/repl.ts +1 -1
- package/src/runtime/index.ts +1 -1
- package/src2/__tests__/e2e/basic.test.ts +154 -0
- package/src2/__tests__/e2e/macros.test.ts +199 -0
- package/src2/__tests__/e2e/migrate.test.ts +3008 -0
- package/src2/__tests__/hir/desugar.test.ts +263 -0
- package/src2/__tests__/lir/lower.test.ts +619 -0
- package/src2/__tests__/lir/types.test.ts +207 -0
- package/src2/__tests__/lir/verify.test.ts +249 -0
- package/src2/__tests__/mir/arithmetic.test.ts +156 -0
- package/src2/__tests__/mir/control-flow.test.ts +242 -0
- package/src2/__tests__/mir/verify.test.ts +254 -0
- package/src2/__tests__/optimizer/block_merge.test.ts +84 -0
- package/src2/__tests__/optimizer/branch_simplify.test.ts +64 -0
- package/src2/__tests__/optimizer/constant_fold.test.ts +145 -0
- package/src2/__tests__/optimizer/copy_prop.test.ts +99 -0
- package/src2/__tests__/optimizer/dce.test.ts +83 -0
- package/src2/__tests__/optimizer/pipeline.test.ts +116 -0
- package/src2/emit/compile.ts +99 -0
- package/src2/emit/index.ts +222 -0
- package/src2/hir/lower.ts +428 -0
- package/src2/hir/types.ts +216 -0
- package/src2/lir/lower.ts +556 -0
- package/src2/lir/types.ts +109 -0
- package/src2/lir/verify.ts +129 -0
- package/src2/mir/lower.ts +1160 -0
- package/src2/mir/macro.ts +167 -0
- package/src2/mir/types.ts +106 -0
- package/src2/mir/verify.ts +218 -0
- package/src2/optimizer/block_merge.ts +93 -0
- package/src2/optimizer/branch_simplify.ts +27 -0
- package/src2/optimizer/constant_fold.ts +88 -0
- package/src2/optimizer/copy_prop.ts +106 -0
- package/src2/optimizer/dce.ts +133 -0
- package/src2/optimizer/pipeline.ts +44 -0
- package/tsconfig.json +2 -2
- package/src/__tests__/codegen.test.ts +0 -161
- package/src/__tests__/e2e.test.ts +0 -2039
- package/src/__tests__/entity-types.test.ts +0 -236
- package/src/__tests__/lowering.test.ts +0 -1185
- package/src/__tests__/macro.test.ts +0 -343
- package/src/__tests__/nbt.test.ts +0 -58
- package/src/__tests__/optimizer-advanced.test.ts +0 -144
- package/src/__tests__/optimizer.test.ts +0 -162
- package/src/__tests__/runtime.test.ts +0 -305
- package/src/__tests__/stdlib-advanced.test.ts +0 -379
- package/src/__tests__/stdlib-bigint.test.ts +0 -427
- package/src/__tests__/stdlib-math.test.ts +0 -374
- package/src/__tests__/stdlib-vec.test.ts +0 -259
- package/src/__tests__/structure-optimizer.test.ts +0 -38
- package/src/__tests__/var-allocator.test.ts +0 -75
- package/src/codegen/cmdblock/index.ts +0 -63
- package/src/codegen/mcfunction/index.ts +0 -662
- package/src/codegen/structure/index.ts +0 -346
- package/src/codegen/var-allocator.ts +0 -104
- package/src/ir/builder.ts +0 -116
- package/src/ir/types.ts +0 -134
- package/src/lowering/index.ts +0 -3876
- package/src/optimizer/commands.ts +0 -534
- package/src/optimizer/dce.ts +0 -679
- package/src/optimizer/passes.ts +0 -250
- package/src/optimizer/structure.ts +0 -450
|
@@ -0,0 +1,1076 @@
|
|
|
1
|
+
尽量按**你这种 C-like → IR → mcfunction** 的流水线来想,覆盖:
|
|
2
|
+
|
|
3
|
+
* 前端/中端优化
|
|
4
|
+
* 后端/发射优化
|
|
5
|
+
* 数据表示优化
|
|
6
|
+
* 控制流优化
|
|
7
|
+
* 工程层面的分析与 cost model
|
|
8
|
+
|
|
9
|
+
我不会只列教科书名字,也会写一点**在你这里具体意味着什么**。
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# 一、编译目标无关的优化
|
|
14
|
+
|
|
15
|
+
这些优化原则上不依赖 Minecraft,换成别的后端也成立。
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## A. 常量与表达式优化
|
|
20
|
+
|
|
21
|
+
### 1. 常量折叠(Constant Folding)
|
|
22
|
+
|
|
23
|
+
编译期直接算出来:
|
|
24
|
+
|
|
25
|
+
```c
|
|
26
|
+
x = 2 + 3 * 4
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
变成:
|
|
30
|
+
|
|
31
|
+
```c
|
|
32
|
+
x = 14
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
包括:
|
|
36
|
+
|
|
37
|
+
* 算术常量折叠
|
|
38
|
+
* 比较常量折叠
|
|
39
|
+
* 逻辑常量折叠
|
|
40
|
+
* 位运算常量折叠
|
|
41
|
+
* 类型转换常量折叠
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
### 2. 常量传播(Constant Propagation)
|
|
46
|
+
|
|
47
|
+
已知某变量是常量,就继续传播:
|
|
48
|
+
|
|
49
|
+
```c
|
|
50
|
+
a = 5
|
|
51
|
+
b = a + 2
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
变成:
|
|
55
|
+
|
|
56
|
+
```c
|
|
57
|
+
b = 7
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
### 3. 稀疏条件常量传播(SCCP)
|
|
63
|
+
|
|
64
|
+
同时做:
|
|
65
|
+
|
|
66
|
+
* 常量传播
|
|
67
|
+
* 死分支消除
|
|
68
|
+
|
|
69
|
+
例如:
|
|
70
|
+
|
|
71
|
+
```c
|
|
72
|
+
if (0) { ... } else { ... }
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
直接删掉前者。
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
### 4. 代数化简(Algebraic Simplification)
|
|
80
|
+
|
|
81
|
+
例如:
|
|
82
|
+
|
|
83
|
+
* `x + 0 -> x`
|
|
84
|
+
* `x - 0 -> x`
|
|
85
|
+
* `x * 1 -> x`
|
|
86
|
+
* `x * 0 -> 0`
|
|
87
|
+
* `x / 1 -> x`
|
|
88
|
+
* `!!x -> x!=0` 或规范形式
|
|
89
|
+
* `x == x -> true`(需注意 NaN/未定义语义之类,如果你语言有的话)
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
### 5. 强度削弱(Strength Reduction)
|
|
94
|
+
|
|
95
|
+
把贵操作变便宜操作,例如:
|
|
96
|
+
|
|
97
|
+
* `x * 2 -> x + x`
|
|
98
|
+
* `x << 1` 之类(如果 IR/语言支持位移)
|
|
99
|
+
|
|
100
|
+
不过这个要看后端成本模型,不一定总是更优。
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
### 6. 公共子表达式消除(CSE)
|
|
105
|
+
|
|
106
|
+
同一表达式重复算多次,提一次:
|
|
107
|
+
|
|
108
|
+
```c
|
|
109
|
+
t1 = a + b
|
|
110
|
+
t2 = a + b
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
变成复用 `t1`。
|
|
114
|
+
|
|
115
|
+
分:
|
|
116
|
+
|
|
117
|
+
* 局部 CSE
|
|
118
|
+
* 全局 CSE / GVN
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
### 7. 值编号(Value Numbering)
|
|
123
|
+
|
|
124
|
+
识别“虽然写法不同,但值等价”的表达式,用于支撑 CSE/GVN。
|
|
125
|
+
|
|
126
|
+
---
|
|
127
|
+
|
|
128
|
+
## B. 复制与赋值相关优化
|
|
129
|
+
|
|
130
|
+
### 8. 复制传播(Copy Propagation)
|
|
131
|
+
|
|
132
|
+
例如:
|
|
133
|
+
|
|
134
|
+
```c
|
|
135
|
+
a = b
|
|
136
|
+
c = a
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
变成:
|
|
140
|
+
|
|
141
|
+
```c
|
|
142
|
+
c = b
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
### 9. 冗余 move 消除
|
|
148
|
+
|
|
149
|
+
例如:
|
|
150
|
+
|
|
151
|
+
```c
|
|
152
|
+
a = b
|
|
153
|
+
b = a
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
或者 `x = x` 之类无意义 copy。
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
### 10. 目的地前推(Destination Forwarding)
|
|
161
|
+
|
|
162
|
+
例如:
|
|
163
|
+
|
|
164
|
+
```c
|
|
165
|
+
t = a + b
|
|
166
|
+
x = t
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
直接改成把结果写到 `x`。
|
|
170
|
+
|
|
171
|
+
这个虽然在你后端里特别有用,但原则上是目标无关的中端优化。
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
### 11. 临时变量消除
|
|
176
|
+
|
|
177
|
+
减少无意义 `tmp`:
|
|
178
|
+
|
|
179
|
+
* tmp 只用一次
|
|
180
|
+
* tmp 只是中转
|
|
181
|
+
* tmp 生命周期很短
|
|
182
|
+
|
|
183
|
+
---
|
|
184
|
+
|
|
185
|
+
## C. 死代码与可达性优化
|
|
186
|
+
|
|
187
|
+
### 12. 死代码消除(DCE)
|
|
188
|
+
|
|
189
|
+
删除结果没人用、且无副作用的指令。
|
|
190
|
+
|
|
191
|
+
---
|
|
192
|
+
|
|
193
|
+
### 13. 死存储消除(Dead Store Elimination)
|
|
194
|
+
|
|
195
|
+
某次写入后来在被读之前就被覆盖了,可以删。
|
|
196
|
+
|
|
197
|
+
---
|
|
198
|
+
|
|
199
|
+
### 14. 不可达代码消除(Unreachable Code Elimination)
|
|
200
|
+
|
|
201
|
+
删掉永远到不了的 block。
|
|
202
|
+
|
|
203
|
+
---
|
|
204
|
+
|
|
205
|
+
### 15. 死分支消除(Dead Branch Elimination)
|
|
206
|
+
|
|
207
|
+
条件恒定时,删掉一边分支。
|
|
208
|
+
|
|
209
|
+
---
|
|
210
|
+
|
|
211
|
+
### 16. 死函数消除
|
|
212
|
+
|
|
213
|
+
没被调用的函数不生成。
|
|
214
|
+
|
|
215
|
+
---
|
|
216
|
+
|
|
217
|
+
## D. 控制流图优化
|
|
218
|
+
|
|
219
|
+
### 17. 基本块合并(Block Merging)
|
|
220
|
+
|
|
221
|
+
一个块只跳到下一个,下一个也只有这一个前驱,那就并掉。
|
|
222
|
+
|
|
223
|
+
---
|
|
224
|
+
|
|
225
|
+
### 18. 跳转穿透 / 跳转线程化(Jump Threading)
|
|
226
|
+
|
|
227
|
+
例如:
|
|
228
|
+
|
|
229
|
+
```text
|
|
230
|
+
A -> B -> C
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
如果 B 只是跳转,可直接 A -> C。
|
|
234
|
+
|
|
235
|
+
---
|
|
236
|
+
|
|
237
|
+
### 19. 分支简化(Branch Simplification)
|
|
238
|
+
|
|
239
|
+
例如:
|
|
240
|
+
|
|
241
|
+
* 条件取反消掉多余 not
|
|
242
|
+
* `if cond goto L1 else goto L2` 规范化
|
|
243
|
+
* 两边都跳同一目标就变无条件跳转
|
|
244
|
+
|
|
245
|
+
---
|
|
246
|
+
|
|
247
|
+
### 20. 条件合并 / 条件规约
|
|
248
|
+
|
|
249
|
+
例如多个条件共享子条件,提出来。
|
|
250
|
+
|
|
251
|
+
---
|
|
252
|
+
|
|
253
|
+
### 21. 结构化控制流简化
|
|
254
|
+
|
|
255
|
+
例如把一些笨重的 CFG 重新变成更简单的:
|
|
256
|
+
|
|
257
|
+
* 单边 if
|
|
258
|
+
* 早返回
|
|
259
|
+
* guard 风格
|
|
260
|
+
|
|
261
|
+
---
|
|
262
|
+
|
|
263
|
+
### 22. 尾合并(Tail Merging)
|
|
264
|
+
|
|
265
|
+
多个 block 末尾有相同后缀,合并成共享尾部。
|
|
266
|
+
|
|
267
|
+
---
|
|
268
|
+
|
|
269
|
+
### 23. 尾调用优化(Tail Call Optimization)
|
|
270
|
+
|
|
271
|
+
如果你的语言/调用约定允许。
|
|
272
|
+
|
|
273
|
+
---
|
|
274
|
+
|
|
275
|
+
## E. 循环优化
|
|
276
|
+
|
|
277
|
+
这些比较经典,但你未必都需要。
|
|
278
|
+
|
|
279
|
+
### 24. 循环不变代码外提(LICM)
|
|
280
|
+
|
|
281
|
+
循环里每次都一样的东西拿到外面。
|
|
282
|
+
|
|
283
|
+
---
|
|
284
|
+
|
|
285
|
+
### 25. 循环强度削弱
|
|
286
|
+
|
|
287
|
+
例如归纳变量变换。
|
|
288
|
+
|
|
289
|
+
---
|
|
290
|
+
|
|
291
|
+
### 26. 归纳变量优化(Induction Variable Optimization)
|
|
292
|
+
|
|
293
|
+
识别 `i=i+1` 这种模式,减少冗余计算。
|
|
294
|
+
|
|
295
|
+
---
|
|
296
|
+
|
|
297
|
+
### 27. 循环展开(Loop Unrolling)
|
|
298
|
+
|
|
299
|
+
减少分支开销,但会增大代码体积。对 mc 这种目标常常不一定划算。
|
|
300
|
+
|
|
301
|
+
---
|
|
302
|
+
|
|
303
|
+
### 28. 循环旋转(Loop Rotation)
|
|
304
|
+
|
|
305
|
+
改变循环形状以便其他优化。
|
|
306
|
+
|
|
307
|
+
---
|
|
308
|
+
|
|
309
|
+
### 29. 循环删除
|
|
310
|
+
|
|
311
|
+
如果循环没有可观察副作用且结果没用。
|
|
312
|
+
|
|
313
|
+
---
|
|
314
|
+
|
|
315
|
+
## F. 过程间优化(IPO)
|
|
316
|
+
|
|
317
|
+
### 30. 函数内联(Inlining)
|
|
318
|
+
|
|
319
|
+
把小函数展开到调用点。
|
|
320
|
+
|
|
321
|
+
---
|
|
322
|
+
|
|
323
|
+
### 31. 参数常量化 / 专门化(Function Specialization)
|
|
324
|
+
|
|
325
|
+
若某调用点参数恒定,生成特化版本。
|
|
326
|
+
|
|
327
|
+
---
|
|
328
|
+
|
|
329
|
+
### 32. 过程间常量传播
|
|
330
|
+
|
|
331
|
+
跨函数传播常量。
|
|
332
|
+
|
|
333
|
+
---
|
|
334
|
+
|
|
335
|
+
### 33. 过程间死代码消除
|
|
336
|
+
|
|
337
|
+
内联/分析后删除不再需要的参数、返回值、函数。
|
|
338
|
+
|
|
339
|
+
---
|
|
340
|
+
|
|
341
|
+
### 34. 纯函数分析 / 副作用分析
|
|
342
|
+
|
|
343
|
+
标记:
|
|
344
|
+
|
|
345
|
+
* pure
|
|
346
|
+
* read-only
|
|
347
|
+
* write-only
|
|
348
|
+
* no-return
|
|
349
|
+
* deterministic
|
|
350
|
+
|
|
351
|
+
这会支撑很多优化。
|
|
352
|
+
|
|
353
|
+
---
|
|
354
|
+
|
|
355
|
+
## G. 数据流与表示层优化
|
|
356
|
+
|
|
357
|
+
### 35. SSA 化带来的优化
|
|
358
|
+
|
|
359
|
+
不是单个优化,但会极大简化:
|
|
360
|
+
|
|
361
|
+
* 常量传播
|
|
362
|
+
* DCE
|
|
363
|
+
* GVN
|
|
364
|
+
* copy coalescing
|
|
365
|
+
|
|
366
|
+
---
|
|
367
|
+
|
|
368
|
+
### 36. 活跃性分析(Liveness Analysis)
|
|
369
|
+
|
|
370
|
+
支撑:
|
|
371
|
+
|
|
372
|
+
* 临时复用
|
|
373
|
+
* 槽位复用
|
|
374
|
+
* 生命周期缩短
|
|
375
|
+
|
|
376
|
+
---
|
|
377
|
+
|
|
378
|
+
### 37. 区间分析 / 值域分析(Range Analysis)
|
|
379
|
+
|
|
380
|
+
知道变量可能范围后,可做:
|
|
381
|
+
|
|
382
|
+
* 条件简化
|
|
383
|
+
* 溢出检查消除
|
|
384
|
+
* 匹配范围更紧
|
|
385
|
+
|
|
386
|
+
---
|
|
387
|
+
|
|
388
|
+
### 38. 别名分析(Alias Analysis)
|
|
389
|
+
|
|
390
|
+
判断两个写入/读取会不会指向同一存储位置。
|
|
391
|
+
|
|
392
|
+
在抽象语言层是通用优化关键基础。
|
|
393
|
+
|
|
394
|
+
---
|
|
395
|
+
|
|
396
|
+
### 39. 逃逸分析(Escape Analysis)
|
|
397
|
+
|
|
398
|
+
某对象/变量是否逃出当前作用域,可决定是否需要更“重”的表示。
|
|
399
|
+
|
|
400
|
+
---
|
|
401
|
+
|
|
402
|
+
### 40. 冗余加载消除
|
|
403
|
+
|
|
404
|
+
已知值没变,不必再 load。
|
|
405
|
+
|
|
406
|
+
---
|
|
407
|
+
|
|
408
|
+
### 41. 冗余比较消除
|
|
409
|
+
|
|
410
|
+
同一条件已经比较过且中间未破坏,可复用结论。
|
|
411
|
+
|
|
412
|
+
---
|
|
413
|
+
|
|
414
|
+
## H. 代码尺寸与布局优化
|
|
415
|
+
|
|
416
|
+
### 42. 代码尺寸优化
|
|
417
|
+
|
|
418
|
+
在多个等价方案中选更短的 IR / 更少指令。
|
|
419
|
+
|
|
420
|
+
---
|
|
421
|
+
|
|
422
|
+
### 43. 热路径优化 / 冷路径下沉
|
|
423
|
+
|
|
424
|
+
如果你有 profiling 或启发式,可把常走路径做得更短。
|
|
425
|
+
|
|
426
|
+
---
|
|
427
|
+
|
|
428
|
+
### 44. 块布局优化(Block Layout)
|
|
429
|
+
|
|
430
|
+
让常见 fallthrough 更自然,减少跳转。
|
|
431
|
+
|
|
432
|
+
---
|
|
433
|
+
|
|
434
|
+
### 45. 函数布局优化
|
|
435
|
+
|
|
436
|
+
把经常一起调用的放近一些。
|
|
437
|
+
对文本后端意义没那么大,但仍可用于组织输出和减少间接结构。
|
|
438
|
+
|
|
439
|
+
---
|
|
440
|
+
|
|
441
|
+
## I. 前端层面的规范化
|
|
442
|
+
|
|
443
|
+
这些不一定叫“优化”,但很值钱。
|
|
444
|
+
|
|
445
|
+
### 46. 语法糖消除
|
|
446
|
+
|
|
447
|
+
* `for -> while`
|
|
448
|
+
* `a += b -> a = a + b`
|
|
449
|
+
* `?:` 展开
|
|
450
|
+
* 短路逻辑显式化
|
|
451
|
+
|
|
452
|
+
---
|
|
453
|
+
|
|
454
|
+
### 47. 表达式规范化
|
|
455
|
+
|
|
456
|
+
把复杂嵌套表达式拆成统一格式,便于后续优化。
|
|
457
|
+
|
|
458
|
+
---
|
|
459
|
+
|
|
460
|
+
### 48. 布尔规范化
|
|
461
|
+
|
|
462
|
+
统一布尔值/条件表示方式,避免后端到处特判。
|
|
463
|
+
|
|
464
|
+
---
|
|
465
|
+
|
|
466
|
+
### 49. ANF / 三地址化
|
|
467
|
+
|
|
468
|
+
将复杂表达式变成一串简单绑定,便于分析。
|
|
469
|
+
|
|
470
|
+
---
|
|
471
|
+
|
|
472
|
+
---
|
|
473
|
+
|
|
474
|
+
# 二、编译目标有关的优化
|
|
475
|
+
|
|
476
|
+
这里说的是**与 Minecraft 命令系统 / scoreboard / NBT / execute / function 调用模型有关**的优化。
|
|
477
|
+
这些往往才是你项目里**最有收益**的部分。
|
|
478
|
+
|
|
479
|
+
---
|
|
480
|
+
|
|
481
|
+
## A. scoreboard 相关优化
|
|
482
|
+
|
|
483
|
+
### 1. scoreboard 槽位复用
|
|
484
|
+
|
|
485
|
+
不同变量生命周期不重叠时,复用同一个 player/objective 槽。
|
|
486
|
+
|
|
487
|
+
这是你的“寄存器分配”对应物。
|
|
488
|
+
|
|
489
|
+
---
|
|
490
|
+
|
|
491
|
+
### 2. scoreboard 临时变量消除
|
|
492
|
+
|
|
493
|
+
例如:
|
|
494
|
+
|
|
495
|
+
```text
|
|
496
|
+
t = a
|
|
497
|
+
t += b
|
|
498
|
+
x = t
|
|
499
|
+
```
|
|
500
|
+
|
|
501
|
+
直接:
|
|
502
|
+
|
|
503
|
+
```text
|
|
504
|
+
x = a
|
|
505
|
+
x += b
|
|
506
|
+
```
|
|
507
|
+
|
|
508
|
+
---
|
|
509
|
+
|
|
510
|
+
### 3. scoreboard copy coalescing
|
|
511
|
+
|
|
512
|
+
尽量让逻辑变量映射到同一物理槽,减少 `operation =` 拷贝。
|
|
513
|
+
|
|
514
|
+
---
|
|
515
|
+
|
|
516
|
+
### 4. 立即数物化优化
|
|
517
|
+
|
|
518
|
+
有些常量是否值得:
|
|
519
|
+
|
|
520
|
+
* 直接写死
|
|
521
|
+
* 用预存常量槽
|
|
522
|
+
* 用某种 shared constant table
|
|
523
|
+
|
|
524
|
+
取决于命令成本。
|
|
525
|
+
|
|
526
|
+
---
|
|
527
|
+
|
|
528
|
+
### 5. scoreboard 读后写 / 写后写消除
|
|
529
|
+
|
|
530
|
+
例如某个槽刚被写,后面覆盖前没有读,前写可删。
|
|
531
|
+
|
|
532
|
+
虽然本质像 dead store,但这里是对 scoreboard 物理资源层做的。
|
|
533
|
+
|
|
534
|
+
---
|
|
535
|
+
|
|
536
|
+
### 6. scoreboard 运算形式选择
|
|
537
|
+
|
|
538
|
+
例如实现 `x += 1` 时到底用:
|
|
539
|
+
|
|
540
|
+
* `players add`
|
|
541
|
+
* 还是通过某个常量槽 `operation +=`
|
|
542
|
+
|
|
543
|
+
要看支持的操作和命令数。
|
|
544
|
+
|
|
545
|
+
---
|
|
546
|
+
|
|
547
|
+
### 7. scoreboard objective 组织优化
|
|
548
|
+
|
|
549
|
+
* 合并 objective
|
|
550
|
+
* 分离热/冷 objective
|
|
551
|
+
* 命名策略
|
|
552
|
+
* 初始化策略
|
|
553
|
+
|
|
554
|
+
有时影响指令复杂度和管理复杂度。
|
|
555
|
+
|
|
556
|
+
---
|
|
557
|
+
|
|
558
|
+
### 8. scoreboard 生命周期缩短
|
|
559
|
+
|
|
560
|
+
尽量早释放槽,给复用创造机会。
|
|
561
|
+
|
|
562
|
+
---
|
|
563
|
+
|
|
564
|
+
## B. execute 上下文优化
|
|
565
|
+
|
|
566
|
+
### 9. execute 链合并
|
|
567
|
+
|
|
568
|
+
多条拥有相同上下文的命令合并:
|
|
569
|
+
|
|
570
|
+
```mcfunction
|
|
571
|
+
execute as ... at ... run cmd1
|
|
572
|
+
execute as ... at ... run cmd2
|
|
573
|
+
```
|
|
574
|
+
|
|
575
|
+
可变成一次 `run function` 或更紧凑布局。
|
|
576
|
+
|
|
577
|
+
---
|
|
578
|
+
|
|
579
|
+
### 10. execute context hoisting
|
|
580
|
+
|
|
581
|
+
把公共前缀提到外面:
|
|
582
|
+
|
|
583
|
+
```mcfunction
|
|
584
|
+
execute as A at @s run ...
|
|
585
|
+
execute as A at @s run ...
|
|
586
|
+
```
|
|
587
|
+
|
|
588
|
+
提成:
|
|
589
|
+
|
|
590
|
+
```mcfunction
|
|
591
|
+
execute as A at @s run function ...
|
|
592
|
+
```
|
|
593
|
+
|
|
594
|
+
---
|
|
595
|
+
|
|
596
|
+
### 11. execute context sinking
|
|
597
|
+
|
|
598
|
+
反过来,有时不要过度 hoist。若共享体太短、额外 function call 更贵,则下沉更优。
|
|
599
|
+
|
|
600
|
+
所以这是个 cost-model 问题。
|
|
601
|
+
|
|
602
|
+
---
|
|
603
|
+
|
|
604
|
+
### 12. execute 前缀共享
|
|
605
|
+
|
|
606
|
+
例如:
|
|
607
|
+
|
|
608
|
+
* 两条命令共享 `as @e[tag=x] at @s`
|
|
609
|
+
* 一条额外多了 `if score ...`
|
|
610
|
+
|
|
611
|
+
则可以组织成前缀树风格,减少重复。
|
|
612
|
+
|
|
613
|
+
---
|
|
614
|
+
|
|
615
|
+
### 13. 嵌套 execute 扁平化
|
|
616
|
+
|
|
617
|
+
减少层层生成的 execute 包装。
|
|
618
|
+
|
|
619
|
+
---
|
|
620
|
+
|
|
621
|
+
### 14. execute 排序优化
|
|
622
|
+
|
|
623
|
+
对命令重新排序,使能共享更多上下文前缀。
|
|
624
|
+
前提是副作用和依赖允许。
|
|
625
|
+
|
|
626
|
+
---
|
|
627
|
+
|
|
628
|
+
### 15. 上下文等价分析
|
|
629
|
+
|
|
630
|
+
识别两个看似不同、其实等价的 context,支撑合并。
|
|
631
|
+
|
|
632
|
+
---
|
|
633
|
+
|
|
634
|
+
### 16. 无效上下文变换消除
|
|
635
|
+
|
|
636
|
+
例如:
|
|
637
|
+
|
|
638
|
+
* 重复 `as @s`
|
|
639
|
+
* 无意义 `at @s`
|
|
640
|
+
* 重复 positioned / rotated 等同设置
|
|
641
|
+
|
|
642
|
+
---
|
|
643
|
+
|
|
644
|
+
## C. 条件与分支 lowering 优化
|
|
645
|
+
|
|
646
|
+
### 17. `if/else` 到 execute guard 的选择优化
|
|
647
|
+
|
|
648
|
+
同样的高层分支,可以 lower 成:
|
|
649
|
+
|
|
650
|
+
* 两个分支函数
|
|
651
|
+
* 一个 guard 执行 then,else 单独处理
|
|
652
|
+
* 条件写值再统一 merge
|
|
653
|
+
|
|
654
|
+
要选命令数更少/热路径更短的形式。
|
|
655
|
+
|
|
656
|
+
---
|
|
657
|
+
|
|
658
|
+
### 18. 条件链合并
|
|
659
|
+
|
|
660
|
+
多个语句有同样条件:
|
|
661
|
+
|
|
662
|
+
```mcfunction
|
|
663
|
+
execute if score X matches 1 run cmd1
|
|
664
|
+
execute if score X matches 1 run cmd2
|
|
665
|
+
```
|
|
666
|
+
|
|
667
|
+
提成共享 guard block/function。
|
|
668
|
+
|
|
669
|
+
---
|
|
670
|
+
|
|
671
|
+
### 19. 条件取反与规范化
|
|
672
|
+
|
|
673
|
+
选择更短、更自然的:
|
|
674
|
+
|
|
675
|
+
* `if`
|
|
676
|
+
* `unless`
|
|
677
|
+
* matches 某区间
|
|
678
|
+
* 用比较结果槽
|
|
679
|
+
* 直接比较两 score
|
|
680
|
+
|
|
681
|
+
---
|
|
682
|
+
|
|
683
|
+
### 20. 分支消解成条件执行
|
|
684
|
+
|
|
685
|
+
某些小分支不值得真的拆 block / function,直接变成 guarded commands。
|
|
686
|
+
|
|
687
|
+
---
|
|
688
|
+
|
|
689
|
+
### 21. merge 点消除
|
|
690
|
+
|
|
691
|
+
高层 CFG 的 merge 若只为了拼值,可以改成直接在各分支写最终位置。
|
|
692
|
+
|
|
693
|
+
---
|
|
694
|
+
|
|
695
|
+
### 22. 范围匹配优化
|
|
696
|
+
|
|
697
|
+
`matches 0..0`、`matches 1..` 等范围表达选择更合适写法。
|
|
698
|
+
|
|
699
|
+
---
|
|
700
|
+
|
|
701
|
+
## D. function / mcfunction 组织优化
|
|
702
|
+
|
|
703
|
+
### 23. 小函数内联
|
|
704
|
+
|
|
705
|
+
如果一次 `function` 调用开销/文本冗余不划算,就直接内联。
|
|
706
|
+
|
|
707
|
+
---
|
|
708
|
+
|
|
709
|
+
### 24. 重复片段 outline
|
|
710
|
+
|
|
711
|
+
反过来,多个地方重复相同命令序列时,抽成函数复用。
|
|
712
|
+
|
|
713
|
+
这在 mc 里不是传统编译器常见优化,但非常实际。
|
|
714
|
+
|
|
715
|
+
---
|
|
716
|
+
|
|
717
|
+
### 25. function 边界调整
|
|
718
|
+
|
|
719
|
+
选择哪些 block 真正成为独立 mcfunction,哪些留在同文件/同逻辑块。
|
|
720
|
+
|
|
721
|
+
---
|
|
722
|
+
|
|
723
|
+
### 26. 热路径内联,冷路径抽取
|
|
724
|
+
|
|
725
|
+
常走路径减少 function call,冷路径抽出去减体积。
|
|
726
|
+
|
|
727
|
+
---
|
|
728
|
+
|
|
729
|
+
### 27. 调用图裁剪
|
|
730
|
+
|
|
731
|
+
没必要暴露/生成的辅助函数不输出。
|
|
732
|
+
|
|
733
|
+
---
|
|
734
|
+
|
|
735
|
+
### 28. trampoline / jump-only function 消除
|
|
736
|
+
|
|
737
|
+
有些函数只是立即调用另一个函数或只有一条跳转,直接消掉。
|
|
738
|
+
|
|
739
|
+
---
|
|
740
|
+
|
|
741
|
+
## E. NBT / storage / 数据载体选择优化
|
|
742
|
+
|
|
743
|
+
### 29. 变量放 scoreboard 还是 NBT
|
|
744
|
+
|
|
745
|
+
这是很大的后端优化点。根据变量用途选择:
|
|
746
|
+
|
|
747
|
+
* 高频算术 -> scoreboard
|
|
748
|
+
* 结构化数据 -> storage/NBT
|
|
749
|
+
* 持久化/跨 tick -> storage/NBT
|
|
750
|
+
* 临时值 -> scoreboard
|
|
751
|
+
|
|
752
|
+
---
|
|
753
|
+
|
|
754
|
+
### 30. NBT 读写缓存
|
|
755
|
+
|
|
756
|
+
如果某个 NBT 值反复参与计算,可先读到 scoreboard 临时,再批量用。
|
|
757
|
+
|
|
758
|
+
---
|
|
759
|
+
|
|
760
|
+
### 31. 冗余 NBT load/store 消除
|
|
761
|
+
|
|
762
|
+
连续多次读同一路径、中间无改动,可复用;
|
|
763
|
+
写后又被覆盖,前写可删。
|
|
764
|
+
|
|
765
|
+
---
|
|
766
|
+
|
|
767
|
+
### 32. 批量 NBT 访问优化
|
|
768
|
+
|
|
769
|
+
若多次访问同一个 compound/list 附近路径,考虑重组表示或合并操作。
|
|
770
|
+
|
|
771
|
+
---
|
|
772
|
+
|
|
773
|
+
### 33. NBT 路径规范化
|
|
774
|
+
|
|
775
|
+
减少路径层级、统一访问形式,便于匹配与优化。
|
|
776
|
+
|
|
777
|
+
---
|
|
778
|
+
|
|
779
|
+
### 34. 数据布局优化
|
|
780
|
+
|
|
781
|
+
例如某个数组/结构到底怎么放:
|
|
782
|
+
|
|
783
|
+
* list
|
|
784
|
+
* int array
|
|
785
|
+
* object/compound
|
|
786
|
+
* 多个平行字段
|
|
787
|
+
|
|
788
|
+
不同布局会极大影响命令复杂度。
|
|
789
|
+
|
|
790
|
+
---
|
|
791
|
+
|
|
792
|
+
### 35. 热数据 / 冷数据分离
|
|
793
|
+
|
|
794
|
+
高频访问的变量不要都塞进深层 NBT。
|
|
795
|
+
|
|
796
|
+
---
|
|
797
|
+
|
|
798
|
+
## F. selector / entity 查询优化
|
|
799
|
+
|
|
800
|
+
### 36. selector 查询去重
|
|
801
|
+
|
|
802
|
+
同一 tick / 同一 block 里相同 selector 不要重复逻辑构造或重复包装。
|
|
803
|
+
|
|
804
|
+
---
|
|
805
|
+
|
|
806
|
+
### 37. selector 结果缓存
|
|
807
|
+
|
|
808
|
+
若语义允许,把结果绑定到上下文或标记,减少反复筛选。
|
|
809
|
+
|
|
810
|
+
---
|
|
811
|
+
|
|
812
|
+
### 38. selector 收窄
|
|
813
|
+
|
|
814
|
+
让 selector 更具体,减少扫描成本和误匹配风险。
|
|
815
|
+
|
|
816
|
+
---
|
|
817
|
+
|
|
818
|
+
### 39. 查询顺序优化
|
|
819
|
+
|
|
820
|
+
先用便宜条件筛,再做贵条件。
|
|
821
|
+
|
|
822
|
+
虽然 Minecraft 具体实现细节不是完全公开优化接口,但结构上还是成立。
|
|
823
|
+
|
|
824
|
+
---
|
|
825
|
+
|
|
826
|
+
### 40. `@s` 上下文化
|
|
827
|
+
|
|
828
|
+
如果已经在 `as` 某实体上下文中,就尽量用 `@s` 而不是重新 selector。
|
|
829
|
+
|
|
830
|
+
---
|
|
831
|
+
|
|
832
|
+
## G. 命令级 peephole 优化
|
|
833
|
+
|
|
834
|
+
### 41. 相邻命令合并
|
|
835
|
+
|
|
836
|
+
例如两条连续操作可改写为更短序列。
|
|
837
|
+
|
|
838
|
+
---
|
|
839
|
+
|
|
840
|
+
### 42. 无效命令消除
|
|
841
|
+
|
|
842
|
+
例如产生了 no-op:
|
|
843
|
+
|
|
844
|
+
* 加 0
|
|
845
|
+
* 复制给自己
|
|
846
|
+
* 条件恒真/恒假 guarding 的残留
|
|
847
|
+
|
|
848
|
+
---
|
|
849
|
+
|
|
850
|
+
### 43. 命令顺序微调
|
|
851
|
+
|
|
852
|
+
为了减少临时槽、共享 context 或避免多余 copy,对相邻命令重排。
|
|
853
|
+
|
|
854
|
+
---
|
|
855
|
+
|
|
856
|
+
### 44. 原语选择优化
|
|
857
|
+
|
|
858
|
+
某个语义用多种命令都能实现时,选更便宜的那个。
|
|
859
|
+
|
|
860
|
+
---
|
|
861
|
+
|
|
862
|
+
### 45. 文本层重复前缀压缩
|
|
863
|
+
|
|
864
|
+
虽然不是运行时优化,但能减少产物冗余和维护成本。
|
|
865
|
+
|
|
866
|
+
---
|
|
867
|
+
|
|
868
|
+
## H. Tick / 调度模型相关优化
|
|
869
|
+
|
|
870
|
+
### 46. 热路径每 tick 命令数优化
|
|
871
|
+
|
|
872
|
+
对每 tick 运行的函数特别 aggressive 地压命令数。
|
|
873
|
+
|
|
874
|
+
---
|
|
875
|
+
|
|
876
|
+
### 47. 冷路径延迟求值
|
|
877
|
+
|
|
878
|
+
不常用逻辑不要提前算。
|
|
879
|
+
|
|
880
|
+
---
|
|
881
|
+
|
|
882
|
+
### 48. 多 tick 拆分
|
|
883
|
+
|
|
884
|
+
如果某逻辑可以分摊到多个 tick,减少单 tick 峰值成本。
|
|
885
|
+
|
|
886
|
+
这已经有点接近调度优化,不只是传统编译优化了。
|
|
887
|
+
|
|
888
|
+
---
|
|
889
|
+
|
|
890
|
+
### 49. 增量更新
|
|
891
|
+
|
|
892
|
+
某状态没变就不重复计算/写回。
|
|
893
|
+
|
|
894
|
+
---
|
|
895
|
+
|
|
896
|
+
### 50. 事件驱动替代轮询
|
|
897
|
+
|
|
898
|
+
能在状态变化时触发,就不要每 tick 扫。
|
|
899
|
+
|
|
900
|
+
这个很目标相关,而且往往收益巨大。
|
|
901
|
+
|
|
902
|
+
---
|
|
903
|
+
|
|
904
|
+
## I. 目标特有的控制流表示优化
|
|
905
|
+
|
|
906
|
+
### 51. CFG 到 function graph 的划分优化
|
|
907
|
+
|
|
908
|
+
Minecraft 没有原生 jump,只有 function 调用和条件执行。
|
|
909
|
+
所以你怎么把 CFG 切成 function graph,本身就是大优化点。
|
|
910
|
+
|
|
911
|
+
---
|
|
912
|
+
|
|
913
|
+
### 52. “真假分支”布局选择
|
|
914
|
+
|
|
915
|
+
对于:
|
|
916
|
+
|
|
917
|
+
```c
|
|
918
|
+
if (cond) A else B
|
|
919
|
+
```
|
|
920
|
+
|
|
921
|
+
到底:
|
|
922
|
+
|
|
923
|
+
* then inline, else function
|
|
924
|
+
* else inline, then function
|
|
925
|
+
* 两边都 function
|
|
926
|
+
* guard 一个块另一个 fallthrough
|
|
927
|
+
|
|
928
|
+
要看热度与大小。
|
|
929
|
+
|
|
930
|
+
---
|
|
931
|
+
|
|
932
|
+
### 53. 早退出(early exit)风格生成
|
|
933
|
+
|
|
934
|
+
把复杂嵌套分支改为多个 guard-return 风格,有时更适合 mcfunction。
|
|
935
|
+
|
|
936
|
+
---
|
|
937
|
+
|
|
938
|
+
### 54. 状态机化优化
|
|
939
|
+
|
|
940
|
+
复杂控制流可编译成显式状态机,但状态机本身也可再优化:
|
|
941
|
+
|
|
942
|
+
* 合并状态
|
|
943
|
+
* 删除空状态
|
|
944
|
+
* 热状态收紧
|
|
945
|
+
|
|
946
|
+
---
|
|
947
|
+
|
|
948
|
+
## J. 资源命名与产物组织优化
|
|
949
|
+
|
|
950
|
+
### 55. 文件拆分策略优化
|
|
951
|
+
|
|
952
|
+
文件过大不好管,过碎调用多。需要平衡。
|
|
953
|
+
|
|
954
|
+
---
|
|
955
|
+
|
|
956
|
+
### 56. 名称池化 / 常量池化
|
|
957
|
+
|
|
958
|
+
统一临时名、目标名、常量槽等,减少管理成本。
|
|
959
|
+
|
|
960
|
+
---
|
|
961
|
+
|
|
962
|
+
### 57. 初始化代码最小化
|
|
963
|
+
|
|
964
|
+
objectives、storage、常量表初始化尽量只做一次、只做必要内容。
|
|
965
|
+
|
|
966
|
+
---
|
|
967
|
+
|
|
968
|
+
---
|
|
969
|
+
|
|
970
|
+
# 三、很值得单独列出来的“分析”
|
|
971
|
+
|
|
972
|
+
这些不是直接优化,但没它们很多优化做不好。
|
|
973
|
+
|
|
974
|
+
---
|
|
975
|
+
|
|
976
|
+
## 编译目标无关分析
|
|
977
|
+
|
|
978
|
+
* use-def / def-use
|
|
979
|
+
* 活跃性分析
|
|
980
|
+
* 到达定义
|
|
981
|
+
* 常量分析
|
|
982
|
+
* 值域分析
|
|
983
|
+
* 别名分析
|
|
984
|
+
* 副作用分析
|
|
985
|
+
* 纯函数分析
|
|
986
|
+
* CFG 分析
|
|
987
|
+
* dominator / post-dominator
|
|
988
|
+
* loop analysis
|
|
989
|
+
* call graph analysis
|
|
990
|
+
|
|
991
|
+
---
|
|
992
|
+
|
|
993
|
+
## 编译目标有关分析
|
|
994
|
+
|
|
995
|
+
* execute context 等价/包含分析
|
|
996
|
+
* scoreboard 槽生命周期分析
|
|
997
|
+
* storage path alias 分析
|
|
998
|
+
* selector 成本/重复分析
|
|
999
|
+
* tick 热度分析
|
|
1000
|
+
* function call 成本分析
|
|
1001
|
+
* 条件 lowering 成本分析
|
|
1002
|
+
* 数据载体选择分析(scoreboard vs NBT)
|
|
1003
|
+
* 命令数与热路径 cost model
|
|
1004
|
+
|
|
1005
|
+
---
|
|
1006
|
+
|
|
1007
|
+
# 四、如果按“最值得先做”的优先级排
|
|
1008
|
+
|
|
1009
|
+
如果你现在真在做这个编译器,我会建议你优先做这些。
|
|
1010
|
+
|
|
1011
|
+
---
|
|
1012
|
+
|
|
1013
|
+
## 先做:目标无关
|
|
1014
|
+
|
|
1015
|
+
1. 常量折叠
|
|
1016
|
+
2. 常量传播
|
|
1017
|
+
3. copy propagation
|
|
1018
|
+
4. DCE
|
|
1019
|
+
5. block merge
|
|
1020
|
+
6. branch simplification
|
|
1021
|
+
7. 小函数内联
|
|
1022
|
+
8. 活跃性分析
|
|
1023
|
+
9. destination forwarding
|
|
1024
|
+
10. 临时变量消除
|
|
1025
|
+
|
|
1026
|
+
---
|
|
1027
|
+
|
|
1028
|
+
## 先做:目标有关
|
|
1029
|
+
|
|
1030
|
+
1. scoreboard 临时消除
|
|
1031
|
+
2. scoreboard 槽位复用
|
|
1032
|
+
3. execute 链合并
|
|
1033
|
+
4. 条件 guard 合并
|
|
1034
|
+
5. function 边界优化
|
|
1035
|
+
6. scoreboard / NBT 载体选择
|
|
1036
|
+
7. 冗余 NBT load/store 消除
|
|
1037
|
+
8. selector/context 复用
|
|
1038
|
+
9. 热路径命令数优化
|
|
1039
|
+
10. peephole
|
|
1040
|
+
|
|
1041
|
+
---
|
|
1042
|
+
|
|
1043
|
+
# 五、哪些“看起来很经典”,但你未必该急着做
|
|
1044
|
+
|
|
1045
|
+
这些不是没用,而是对你当前项目可能性价比不高:
|
|
1046
|
+
|
|
1047
|
+
* 完整 GVN/PRE
|
|
1048
|
+
* 很重的循环优化体系
|
|
1049
|
+
* 完整 SSA-based global optimizer
|
|
1050
|
+
* 特别复杂的 interprocedural alias analysis
|
|
1051
|
+
* 自动 profile-guided optimization
|
|
1052
|
+
* 超复杂 instruction scheduling
|
|
1053
|
+
|
|
1054
|
+
因为你的目标不是 CPU,很多收益不如目标特化优化直接。
|
|
1055
|
+
|
|
1056
|
+
---
|
|
1057
|
+
|
|
1058
|
+
# 六、一个更实用的归纳
|
|
1059
|
+
|
|
1060
|
+
你其实可以把所有优化再抽成两句话:
|
|
1061
|
+
|
|
1062
|
+
## 目标无关优化,本质上是在做:
|
|
1063
|
+
|
|
1064
|
+
* 少算
|
|
1065
|
+
* 不重复算
|
|
1066
|
+
* 不存没用的值
|
|
1067
|
+
* 不走没必要的控制流
|
|
1068
|
+
* 更晚丢信息
|
|
1069
|
+
|
|
1070
|
+
## 目标有关优化,本质上是在做:
|
|
1071
|
+
|
|
1072
|
+
* 少发命令
|
|
1073
|
+
* 少切 execute 上下文
|
|
1074
|
+
* 少分 function
|
|
1075
|
+
* 少碰昂贵载体(NBT / selector / 深层 context)
|
|
1076
|
+
* 把值放到最适合 Minecraft 的地方
|