forked from chenzomi12/AISystem
-
Notifications
You must be signed in to change notification settings - Fork 0
/
05.srt
1322 lines (992 loc) · 22.4 KB
/
05.srt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1
00:00:00,000 --> 00:00:04,680
[字幕生成:BLACK 字幕校对:志宇]
2
00:00:06,680 --> 00:00:06,680
嗨,我是ZOMI
3
00:00:06,680 --> 00:00:08,800
今天还是延续上一节课的内容
4
00:00:08,800 --> 00:00:10,520
LLVM的架构和原理
5
00:00:10,520 --> 00:00:13,920
其实我没有想到看编译系的人还会比真的看
6
00:00:13,920 --> 00:00:17,120
AI核心技术相关的分享视频没有几个人看
7
00:00:17,120 --> 00:00:20,960
但是我讲关于编译系的内容反倒有很多人去看
8
00:00:25,560 --> 00:00:26,720
在上一节的内容里面
9
00:00:26,720 --> 00:00:29,520
其实已经讲了LLVM的一个项目的具体的发展
10
00:00:29,520 --> 00:00:32,640
还有LLVM的具体的设计和它的一个基本的架构
11
00:00:32,640 --> 00:00:33,800
那在这一节课里面
12
00:00:33,800 --> 00:00:35,800
会讲讲LLVM的一个中间表达
13
00:00:35,800 --> 00:00:38,240
还有LLVM的前端的详细过程
14
00:00:38,240 --> 00:00:39,920
LLVM的中间的优化流程
15
00:00:39,920 --> 00:00:41,440
还有LLVM的后端
16
00:00:41,440 --> 00:00:44,720
最后还会去介绍一下基于LLVM的项目
17
00:00:44,720 --> 00:00:47,160
但是如果这个视频过长的话
18
00:00:47,160 --> 00:00:48,680
我会把它剪成两段
19
00:00:48,680 --> 00:00:50,640
就是希望保持每一段有十几分钟
20
00:00:50,640 --> 00:00:51,480
然后看着不累
21
00:00:56,680 --> 00:00:59,080
下面来到LLVM的一个整体的架构图
22
00:00:59,080 --> 00:01:02,000
LLVM主要是跟传统的编译系的电影一样
23
00:01:02,000 --> 00:01:03,320
分开前端
24
00:01:03,320 --> 00:01:04,240
中间优化层
25
00:01:04,240 --> 00:01:05,200
还有后端
26
00:01:05,200 --> 00:01:07,320
而中间的每一个箭头
27
00:01:07,320 --> 00:01:09,520
代表的是一个IR的转换
28
00:01:09,520 --> 00:01:11,160
可以看到在LLVM的架构里面
29
00:01:11,160 --> 00:01:13,120
不管是前端优化层
30
00:01:13,120 --> 00:01:15,200
还有后端都会有大量的IR
31
00:01:15,200 --> 00:01:17,560
使得LLVM的模块化程度非常高
32
00:01:17,560 --> 00:01:20,200
可以大量的去附用一些相同的代码
33
00:01:20,200 --> 00:01:23,560
非常方便集成到不同的ID和其他编译器当中
34
00:01:25,720 --> 00:01:27,320
下面来看看第一个内容
35
00:01:27,320 --> 00:01:29,600
就是LLVM的IR中间表达
36
00:01:29,600 --> 00:01:32,920
左边的这个图就是GCC的一个表示方式
37
00:01:32,920 --> 00:01:35,360
它把前端跟后端其实已经怼到一起了
38
00:01:35,360 --> 00:01:39,280
没有明确的去把编译系的前端优化系和后端分开
39
00:01:39,280 --> 00:01:40,520
而LLVM的IR
40
00:01:40,520 --> 00:01:42,800
遵从了刚才讲的编译系的基本概念
41
00:01:42,800 --> 00:01:44,200
把前端分开出来
42
00:01:44,200 --> 00:01:45,440
然后中间通过IR
43
00:01:45,440 --> 00:01:47,200
把不同的优化系的part串起来
44
00:01:47,200 --> 00:01:48,920
最后就是后端的优化
45
00:01:50,560 --> 00:01:54,640
这并不意味着LLVM
只使用一个单一的 IR 进行表达
46
00:01:54,640 --> 00:01:56,880
LLVM的IR还是非常丰富的
47
00:01:56,920 --> 00:02:00,160
首先前端编译的时候传给中间优化层的时候
48
00:02:00,160 --> 00:02:02,600
它传的是一个AST的IR
49
00:02:02,600 --> 00:02:04,040
那AST也作为一种IR
50
00:02:04,040 --> 00:02:05,760
因为IR是个中间表达
51
00:02:05,760 --> 00:02:08,000
它没有一个固定的形态
52
00:02:08,000 --> 00:02:11,120
接着中间会有非常多的IR进行传递
53
00:02:11,120 --> 00:02:13,560
可能这些IR之间会有所差异
54
00:02:13,560 --> 00:02:15,160
也可能会是相同的
55
00:02:15,160 --> 00:02:16,280
那优化完之后
56
00:02:16,280 --> 00:02:19,080
它会传一个DAG图给后端
57
00:02:19,080 --> 00:02:21,440
为什么会用DAG图传给后端呢
58
00:02:21,440 --> 00:02:26,200
因为DAG图能够非常有效的去表示硬件的指定的顺序
59
00:02:26,240 --> 00:02:27,480
而在后端的优化的时候
60
00:02:27,480 --> 00:02:30,880
它可能又转回普通的IR进行一个优化
61
00:02:30,880 --> 00:02:32,600
最后再生成机器码
62
00:02:32,600 --> 00:02:34,560
这里面想表达的一个概念就是
63
00:02:34,560 --> 00:02:35,920
在编译不同的阶段
64
00:02:35,920 --> 00:02:37,840
会采用不同的数据结构
65
00:02:37,840 --> 00:02:39,520
不同的中间表达
66
00:02:39,520 --> 00:02:41,560
而中间表达说实话
67
00:02:41,560 --> 00:02:46,640
它就是一个人类或者所定义的特殊的数据结构
68
00:02:49,240 --> 00:02:50,040
Text的函数
69
00:02:50,040 --> 00:02:51,880
Text的函数里面其实比较简单
70
00:02:51,880 --> 00:02:54,560
int c 等于 a 乘以 b 加上 100
71
00:02:54,560 --> 00:02:58,560
然后使用 clang-c-emit-LLVM-text-c
72
00:02:58,560 --> 00:03:00,440
这一个 cpp 文件
73
00:03:00,440 --> 00:03:03,120
然后可以看到输出的 LLVM 的 IR
74
00:03:05,000 --> 00:03:07,680
LLVM IR 里面的分号代表的是一个注释
75
00:03:07,680 --> 00:03:09,760
所以看到分号里面基本上可以不用管
76
00:03:09,760 --> 00:03:12,600
这个分号里面后面的都是一个代表具体的注释
77
00:03:13,160 --> 00:03:14,080
全区的变量
78
00:03:14,080 --> 00:03:15,160
用 at 开头
79
00:03:15,160 --> 00:03:16,160
而局部的变量
80
00:03:16,160 --> 00:03:17,720
以百分号作为开头
81
00:03:17,720 --> 00:03:19,280
所以看到百分号3
82
00:03:19,280 --> 00:03:19,960
百分号4
83
00:03:19,960 --> 00:03:20,600
百分号5
84
00:03:20,600 --> 00:03:22,000
都是局部的变量
85
00:03:22,040 --> 00:03:24,000
IR 里面的 alloc start load
86
00:03:24,000 --> 00:03:24,880
mod add
87
00:03:24,880 --> 00:03:25,880
align i t
88
00:03:25,880 --> 00:03:28,040
这些都是明确的一个具体的指令
89
00:03:28,680 --> 00:03:31,360
这里面可以看到出现大量的 i32
90
00:03:31,360 --> 00:03:34,320
i32 主要是表示32位四个字节
91
00:03:34,760 --> 00:03:36,040
下面1234567
92
00:03:36,040 --> 00:03:37,320
就是 IR 的基本语法
93
00:03:37,320 --> 00:03:39,120
刚才以一个简单的例子
94
00:03:39,120 --> 00:03:40,360
给大家讲了一下
95
00:03:40,360 --> 00:03:41,360
具体的这些语法
96
00:03:41,360 --> 00:03:43,320
在 IR 当中是怎么样去表示的
97
00:03:43,960 --> 00:03:45,120
LLVM IR 里面
98
00:03:45,120 --> 00:03:47,280
主要是有两个基本的原则指导的
99
00:03:47,280 --> 00:03:49,080
整个 LLVM 核心的库
100
00:03:49,080 --> 00:03:51,840
叫做 LLVM Code 来去开发的
101
00:03:51,960 --> 00:03:52,920
这两个基本原则
102
00:03:53,080 --> 00:03:55,200
第一个就是 SSA 表示
103
00:03:55,200 --> 00:03:57,160
SSA 是静态单赋值
104
00:03:57,160 --> 00:03:58,960
会在后面去介绍的
105
00:03:58,960 --> 00:04:00,720
SSA 使得代码
106
00:04:00,840 --> 00:04:02,680
组织为三地址指令序列
107
00:04:02,680 --> 00:04:04,680
还有无线的一个寄存器
108
00:04:04,680 --> 00:04:06,160
还有无线寄存器的概念
109
00:04:06,160 --> 00:04:07,960
使得整个编译器的优化
110
00:04:07,960 --> 00:04:09,920
可以更快速的去执行
111
00:04:09,920 --> 00:04:11,480
第二个就是整个程序的
112
00:04:11,480 --> 00:04:12,880
IR 存储到磁盘里面
113
00:04:12,880 --> 00:04:14,920
想要加载的时候就加载
114
00:04:14,920 --> 00:04:16,360
想要链接的时候就链接
115
00:04:16,360 --> 00:04:17,680
所以使得编译优化
116
00:04:17,680 --> 00:04:18,560
还有 JIT 优化
117
00:04:18,560 --> 00:04:19,800
更容易的去实现
118
00:04:19,800 --> 00:04:20,760
执行的更快
119
00:04:22,240 --> 00:04:24,040
下面了解刚才讲到的
120
00:04:24,040 --> 00:04:25,120
第一条原则
121
00:04:25,400 --> 00:04:26,760
LMVM 的 IR 采用
122
00:04:26,760 --> 00:04:28,040
静态单赋值的形式
123
00:04:28,040 --> 00:04:30,920
也就是 Static Single Assignment SSA
124
00:04:30,920 --> 00:04:32,520
里面具有两个重要的原则
125
00:04:32,520 --> 00:04:33,880
刚才简单的提了
126
00:04:33,880 --> 00:04:35,720
第一个就是把代码组织为
127
00:04:35,720 --> 00:04:37,600
三地址的一个指令序列
128
00:04:37,600 --> 00:04:39,200
第二个就是指令寄存器的
129
00:04:39,200 --> 00:04:40,560
数量是无限的
130
00:04:41,720 --> 00:04:43,160
首先从下往上看
131
00:04:43,160 --> 00:04:44,440
为什么寄存器的数量
132
00:04:44,440 --> 00:04:46,320
要无限制在 IR 这一层
133
00:04:46,320 --> 00:04:48,160
因为 IR 它只是一个中间表达
134
00:04:48,160 --> 00:04:50,880
不希望跟后端的硬件相绑定
135
00:04:50,920 --> 00:04:52,960
硬件的寄存器的造价还是很贵的
136
00:04:52,960 --> 00:04:54,160
所以每一款芯片
137
00:04:54,160 --> 00:04:55,680
寄存器的数量是有限的
138
00:04:55,680 --> 00:04:57,360
但是在 IR 中间表达这一层
139
00:04:57,480 --> 00:04:58,880
是一个存软件
140
00:04:58,880 --> 00:05:00,640
存数据结构的表示
141
00:05:00,640 --> 00:05:02,680
所以为了避免跟硬件相关
142
00:05:02,680 --> 00:05:04,320
这里面假设寄存器的数量
143
00:05:04,320 --> 00:05:05,520
是无限制的
144
00:05:09,560 --> 00:05:11,560
下面来看看什么叫做
145
00:05:11,560 --> 00:05:15,040
Static Single Assignment 静态单赋值
146
00:05:15,480 --> 00:05:17,080
其实了解这个基本概念
147
00:05:17,080 --> 00:05:18,360
还是比较简单的
148
00:05:18,360 --> 00:05:19,680
就是程序中每个变量
149
00:05:19,680 --> 00:05:22,080
都有且只有一个赋值语句
150
00:05:22,640 --> 00:05:24,600
下面以 1x2 加 3
151
00:05:24,600 --> 00:05:27,520
作为 LLVM IR 的一个例子来看看
152
00:05:27,720 --> 00:05:29,680
现在定一个局部变量
153
00:05:29,680 --> 00:05:30,960
1x2
154
00:05:31,160 --> 00:05:33,600
接着再定一个局部变量
155
00:05:33,600 --> 00:05:35,840
把刚才 1x2 的结果加上 3
156
00:05:35,840 --> 00:05:38,480
然后再返回局部变量 0
157
00:05:38,480 --> 00:05:40,040
但是这里面有一个问题
158
00:05:40,040 --> 00:05:41,800
采用的是一个静态单赋值
159
00:05:41,800 --> 00:05:42,800
也就是每个变量
160
00:05:42,800 --> 00:05:44,400
都只能有一个赋值语句
161
00:05:44,400 --> 00:05:46,440
所以百分号 0 就不能复用
162
00:05:46,440 --> 00:05:47,880
只能用百分号 1
163
00:05:47,880 --> 00:05:49,320
来去表示 1x2
164
00:05:49,320 --> 00:05:51,320
再加上 3 的最后的结果
165
00:05:51,320 --> 00:05:52,800
然后返回百分号 1
166
00:05:53,320 --> 00:05:55,200
ZOMI老师我就有一个问题了
167
00:05:55,200 --> 00:05:57,120
为什么需要静态单赋值
168
00:05:57,120 --> 00:05:58,360
或者 SSA 呢
169
00:05:58,360 --> 00:05:59,720
它有什么好处吗
170
00:06:00,560 --> 00:06:03,320
其实这么设计是有两个好处的
171
00:06:03,320 --> 00:06:05,280
第一个可以反向的追溯到
172
00:06:05,280 --> 00:06:06,800
定义的唯一一个指令
173
00:06:06,800 --> 00:06:09,080
百分号 0 对应的是这条指令
174
00:06:09,080 --> 00:06:11,240
百分号 1 对应的是这一条指令
175
00:06:11,400 --> 00:06:12,960
如果定义的都是百分号 0
176
00:06:12,960 --> 00:06:15,480
怎么知道对应的是哪一条指令呢
177
00:06:15,680 --> 00:06:17,840
这种方式就非常方便于编译器
178
00:06:17,840 --> 00:06:19,840
做正向和反向的编译
179
00:06:20,280 --> 00:06:21,320
第二个好处就是
180
00:06:21,320 --> 00:06:23,360
极大地简化整个的优化过程
181
00:06:23,360 --> 00:06:24,440
因为 SSA 呢
182
00:06:24,440 --> 00:06:25,800
它会建立一个平凡的
183
00:06:25,800 --> 00:06:27,120
user defined 的一个链
184
00:06:27,120 --> 00:06:29,200
就是使用和定义的一个链条
185
00:06:29,520 --> 00:06:31,200
有了 user defined 这个链条
186
00:06:31,200 --> 00:06:32,400
可以很方便地去追溯
187
00:06:32,400 --> 00:06:33,440
每个值
188
00:06:33,440 --> 00:06:35,440
它对应的指令是怎么去使用的
189
00:06:36,040 --> 00:06:36,920
下面来看看
190
00:06:36,920 --> 00:06:39,840
LLVM IR 的一个基本的语法规则
191
00:06:40,240 --> 00:06:42,600
LLVM IR 是一类似于一个
192
00:06:42,600 --> 00:06:43,480
精简指令集
193
00:06:43,480 --> 00:06:44,480
也就是 VISCA 的一个
194
00:06:44,480 --> 00:06:45,840
底层虚拟的指令集
195
00:06:45,920 --> 00:06:47,520
但是它也只是一个类似
196
00:06:47,520 --> 00:06:49,400
而并不是真正的一个指令集
197
00:06:49,960 --> 00:06:52,320
LLVM IR 既然类似于真正的指令集
198
00:06:52,440 --> 00:06:53,600
它跟真正的指令集
199
00:06:53,720 --> 00:06:55,480
肯定会有一些相似的地方
200
00:06:55,720 --> 00:06:58,120
相似的地方就是同样去支持一些
201
00:06:58,120 --> 00:07:00,000
简单的指令的新型的序列
202
00:07:00,000 --> 00:07:02,080
例如添加相减比较分支
203
00:07:02,400 --> 00:07:04,000
刚才就是 add mod
204
00:07:04,000 --> 00:07:05,200
这些就是类似于
205
00:07:05,200 --> 00:07:06,680
精简的指令集的方式
206
00:07:07,000 --> 00:07:09,400
第二个就是指令都是三地址形式的
207
00:07:09,400 --> 00:07:10,320
刚才在讲
208
00:07:10,720 --> 00:07:12,560
LLVM IR 的一个基本原则的时候
209
00:07:12,560 --> 00:07:13,920
也介绍过三地址指令
210
00:07:13,920 --> 00:07:15,720
将会在后面去介绍的
211
00:07:15,840 --> 00:07:17,720
它们可以接受一定数量的输入
212
00:07:18,240 --> 00:07:19,840
然后在不同的继承器里面
213
00:07:19,840 --> 00:07:21,720
存储不同的计算结果
214
00:07:22,640 --> 00:07:25,520
第三个就是跟大部分精简指令集不同
215
00:07:25,520 --> 00:07:26,880
因为 LLVM IR 作为一个
216
00:07:26,880 --> 00:07:28,560
数据结构和软件的定义
217
00:07:29,360 --> 00:07:31,960
使用了墙类型剥离了机器的差异
218
00:07:31,960 --> 00:07:33,080
也就是我不用去管
219
00:07:33,080 --> 00:07:34,640
硬件到底有多少个指令
220
00:07:34,640 --> 00:07:36,600
不同的硬件其实有不同的指令
221
00:07:36,600 --> 00:07:38,320
也有不同数量的继承器
222
00:07:39,760 --> 00:07:40,800
最后一个就是
223
00:07:40,800 --> 00:07:43,800
LLVM IR 不使用固定的命名的继承器
224
00:07:43,800 --> 00:07:44,840
因为每个继承器
225
00:07:44,840 --> 00:07:46,280
或者每个类型的继承器
226
00:07:46,280 --> 00:07:47,240
都有自己的地址
227
00:07:47,240 --> 00:07:48,480
都有自己的名字
228
00:07:48,480 --> 00:07:51,040
LLVM IR 统一以百分号
229
00:07:51,040 --> 00:07:53,240
所有都叫做临时继承器
230
00:07:56,760 --> 00:07:59,920
刚才已经第三次提到三地址指令了
231
00:07:59,920 --> 00:08:01,120
那三地址指令
232
00:08:01,120 --> 00:08:02,280
在英文里面叫做
233
00:08:02,280 --> 00:08:03,760
Three Address Codes
234
00:08:03,760 --> 00:08:05,120
就是三地址指令
235
00:08:05,120 --> 00:08:06,800
直译过来的完全是
236
00:08:07,560 --> 00:08:08,800
每个三地址指令
237
00:08:08,800 --> 00:08:10,480
都可以被分解为一个四元组
238
00:08:10,480 --> 00:08:11,800
叫做 Four Tuples
239
00:08:12,600 --> 00:08:13,600
这个 Four Tuples
240
00:08:13,600 --> 00:08:14,880
这个四代表的就是
241
00:08:14,880 --> 00:08:17,000
运算服操作数一操作数二
242
00:08:17,000 --> 00:08:17,960
还有结果
243
00:08:17,960 --> 00:08:20,720
也就是我的操作数一跟操作数二
244
00:08:20,720 --> 00:08:22,320
执行了操作运算服之后
245
00:08:22,480 --> 00:08:24,000
我得到一个结果
246
00:08:24,880 --> 00:08:27,040
以 J 等于 S 加 Y 这个复制指令
247
00:08:27,160 --> 00:08:27,760
去表示
248
00:08:27,920 --> 00:08:29,200
四元组的表示就是
249
00:08:29,200 --> 00:08:31,320
X 加 Y 等于 Z
250
00:08:33,000 --> 00:08:35,280
了解完 LLVM IR 的设计原则