-
Notifications
You must be signed in to change notification settings - Fork 87
/
Copy pathword_allocScript.sml
1641 lines (1556 loc) · 62.9 KB
/
word_allocScript.sml
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
(*
This is the compiler's regsiter allocator. It supports different modes:
0) simple allocator, no spill heuristics;
1) simple allocator + spill heuristics;
2) IRC allocator, no spill heuristics (default);
3) IRC allocator + spill heuristics;
4) linear scan register allocator.
*)
open preamble wordLangTheory;
open linear_scanTheory;
open reg_allocTheory;
val _ = new_theory "word_alloc";
val _ = set_grammar_ancestry [
"asm" (* for arity-2 Const *),
"reg_alloc",
"misc",
"wordLang"
]
val _ = patternMatchesLib.ENABLE_PMATCH_CASES();
Overload Move0[inferior] = ``Move 0n``;
Overload Move1[inferior] = ``Move 1n``;
(*SSA form*)
Definition apply_nummap_key_def:
apply_nummap_key f names =
fromAList (MAP (λx,y.f x,y) (toAList names))
End
Definition option_lookup_def:
option_lookup t v = dtcase lookup v t of NONE => 0n | SOME x => x
End
Definition even_list_def:
(even_list = GENLIST (\x.2*x))
End
(*Consistently sets up the next alloc variable rename for v*)
Definition next_var_rename_def:
next_var_rename v ssa (na:num) = (na,insert v na ssa,na+4)
End
Definition list_next_var_rename_def:
(list_next_var_rename [] ssa (na:num) = ([],ssa,na)) ∧
(list_next_var_rename (x::xs) ssa na =
(*Write this way to make it ascending, can also use acc passing*)
let (y,ssa',na') = next_var_rename x ssa na in
let (ys,ssa'',na'') = list_next_var_rename xs ssa' na' in
(y::ys,ssa'',na''))
End
Definition fake_move_def:
fake_move v : α wordLang$prog = Inst (Const v 0w)
End
(*Do the merging moves only*)
Definition merge_moves_def:
(merge_moves [] ssa_L ssa_R (na:num) = ([],[],na,ssa_L,ssa_R)) ∧
(merge_moves (x::xs) ssa_L ssa_R na =
let (seqL,seqR,na',ssa_L',ssa_R') =
merge_moves xs ssa_L ssa_R na in
let optLx = lookup x ssa_L' in
let optLy = lookup x ssa_R' in
dtcase (optLx,optLy) of
(SOME Lx,SOME Ly) =>
if Lx = Ly then
(seqL,seqR,na',ssa_L',ssa_R')
else
let Lmove = (na',Lx) in
let Rmove = (na',Ly) in
(Lmove::seqL, Rmove::seqR,na'+4, insert x na' ssa_L'
, insert x na' ssa_R')
| _ => (seqL,seqR,na',ssa_L',ssa_R'))
End
(* tracking priority of moves
0 = unprioritized
1 = base "high" priority
2 = higher priority than base
T, INL <- left side
F, INR <- right side
*)
Definition priority_def:
(priority NONE b = 1n) ∧
(priority (SOME (INL())) b =
if b then 2 else 1) ∧
(priority (SOME (INR())) b =
if b then 1 else 2)
End
(*Separately do the fake moves*)
Definition fake_moves_def:
(fake_moves prio [] ssa_L ssa_R (na:num) = (Skip:'a wordLang$prog,Skip:'a wordLang$prog,na,ssa_L,ssa_R)) ∧
(fake_moves prio (x::xs) ssa_L ssa_R na =
let (seqL,seqR,na',ssa_L',ssa_R') =
fake_moves prio xs ssa_L ssa_R na in
let optLx = lookup x ssa_L' in
let optLy = lookup x ssa_R' in
dtcase (optLx,optLy) of
(NONE,SOME Ly) =>
let Lmove = Seq seqL (fake_move na') in
let Rmove = Seq seqR (Move (priority prio F) [(na',Ly)]) in
(Lmove, Rmove,na'+4, insert x na' ssa_L', insert x na' ssa_R')
| (SOME Lx,NONE) =>
let Lmove = Seq seqL (Move (priority prio T) [(na',Lx)]) in
let Rmove = Seq seqR (fake_move na') in
(Lmove, Rmove,na'+4, insert x na' ssa_L', insert x na' ssa_R')
| _ => (seqL,seqR,na',ssa_L',ssa_R'))
End
Definition fix_inconsistencies_def:
fix_inconsistencies prio ssa_L ssa_R na =
let var_union = MAP FST (toAList (union ssa_L ssa_R)) in
let (Lmov,Rmov,na',ssa_L',ssa_R') =
merge_moves var_union ssa_L ssa_R na in
let (Lseq,Rseq,na'',ssa_L'',ssa_R'') =
fake_moves prio var_union ssa_L' ssa_R' na' in
(Seq (Move (priority prio T) Lmov) Lseq,Seq (Move (priority prio F) Rmov) Rseq,na'',ssa_L'')
End
(*ssa_cc_trans_inst does not need to interact with stack*)
(* Note: this needs to return a prog to support specific registers for AddCarry and other special insts
*)
Definition ssa_cc_trans_inst_def:
(ssa_cc_trans_inst Skip ssa na = (Skip,ssa,na)) ∧
(ssa_cc_trans_inst (Const reg w) ssa na =
let (reg',ssa',na') = next_var_rename reg ssa na in
(Inst (Const reg' w),ssa',na')) ∧
(ssa_cc_trans_inst (Arith (Binop bop r1 r2 ri)) ssa na =
dtcase ri of
Reg r3 =>
let r3' = option_lookup ssa r3 in
let r2' = option_lookup ssa r2 in
let (r1',ssa',na') = next_var_rename r1 ssa na in
(Inst (Arith (Binop bop r1' r2' (Reg r3'))),ssa',na')
| _ =>
let r2' = option_lookup ssa r2 in
let (r1',ssa',na') = next_var_rename r1 ssa na in
(Inst (Arith (Binop bop r1' r2' ri)),ssa',na')) ∧
(ssa_cc_trans_inst (Arith (Shift shift r1 r2 n)) ssa na =
let r2' = option_lookup ssa r2 in
let (r1',ssa',na') = next_var_rename r1 ssa na in
(Inst (Arith (Shift shift r1' r2' n)),ssa',na')) ∧
(ssa_cc_trans_inst (Arith (Div r1 r2 r3)) ssa na =
let r2' = option_lookup ssa r2 in
let r3' = option_lookup ssa r3 in
let (r1',ssa',na') = next_var_rename r1 ssa na in
(Inst (Arith (Div r1' r2' r3')),ssa',na')) ∧
(ssa_cc_trans_inst (Arith (AddCarry r1 r2 r3 r4)) ssa na =
let r2' = option_lookup ssa r2 in
let r3' = option_lookup ssa r3 in
let r4' = option_lookup ssa r4 in
let (r1',ssa',na') = next_var_rename r1 ssa na in
let mov_in = Move1 [(0,r4')] in
let (r4'',ssa'',na'') = next_var_rename r4 ssa' na' in
let mov_out = Move1 [(r4'',0)] in
(Seq mov_in (Seq (Inst (Arith (AddCarry r1' r2' r3' 0))) mov_out), ssa'',na'')) ∧
(* Note: for AddOverflow and SubOverflow, setting r4 to 0 is not necessary
However, this helps with word_to_stack which currently only spills
one register on writes
*)
(ssa_cc_trans_inst (Arith (AddOverflow r1 r2 r3 r4)) ssa na =
let r2' = option_lookup ssa r2 in
let r3' = option_lookup ssa r3 in
(* TODO: This might need to be made a strong preference *)
let (r1',ssa',na') = next_var_rename r1 ssa na in
let (r4'',ssa'',na'') = next_var_rename r4 ssa' na' in
let mov_out = Move1 [(r4'',0)] in
(Seq (Inst (Arith (AddOverflow r1' r2' r3' 0))) mov_out, ssa'',na'')) ∧
(ssa_cc_trans_inst (Arith (SubOverflow r1 r2 r3 r4)) ssa na =
let r2' = option_lookup ssa r2 in
let r3' = option_lookup ssa r3 in
let (r1',ssa',na') = next_var_rename r1 ssa na in
let (r4'',ssa'',na'') = next_var_rename r4 ssa' na' in
let mov_out = Move1 [(r4'',0)] in
(Seq (Inst (Arith (SubOverflow r1' r2' r3' 0))) mov_out, ssa'',na'')) ∧
(ssa_cc_trans_inst (Arith (LongMul r1 r2 r3 r4)) ssa na =
let r3' = option_lookup ssa r3 in
let r4' = option_lookup ssa r4 in
let mov_in = Move1 [(0,r3');(4,r4')] in
let (r1',ssa',na') = next_var_rename r1 ssa na in
let (r2',ssa'',na'') = next_var_rename r2 ssa' na' in
let mov_out = Move1 [(r2',0);(r1',6)] in
(Seq mov_in (Seq (Inst (Arith (LongMul 6 0 0 4))) mov_out),ssa'',na'')) ∧
(ssa_cc_trans_inst (Arith (LongDiv r1 r2 r3 r4 r5)) ssa na =
let r3' = option_lookup ssa r3 in
let r4' = option_lookup ssa r4 in
let r5' = option_lookup ssa r5 in
let mov_in = Move1 [(6,r3');(0,r4')] in
let (r2',ssa',na') = next_var_rename r2 ssa na in
let (r1',ssa'',na'') = next_var_rename r1 ssa' na' in
let mov_out = Move1 [(r2',6);(r1',0)] in
(Seq mov_in (Seq (Inst (Arith (LongDiv 0 6 6 0 r5'))) mov_out),ssa'',na'')) ∧
(ssa_cc_trans_inst (Mem Load r (Addr a w)) ssa na =
let a' = option_lookup ssa a in
let (r',ssa',na') = next_var_rename r ssa na in
(Inst (Mem Load r' (Addr a' w)),ssa',na')) ∧
(ssa_cc_trans_inst (Mem Store r (Addr a w)) ssa na =
let a' = option_lookup ssa a in
let r' = option_lookup ssa r in
(Inst (Mem Store r' (Addr a' w)),ssa,na)) ∧
(ssa_cc_trans_inst (Mem Load8 r (Addr a w)) ssa na =
let a' = option_lookup ssa a in
let (r',ssa',na') = next_var_rename r ssa na in
(Inst (Mem Load8 r' (Addr a' w)),ssa',na')) ∧
(ssa_cc_trans_inst (Mem Store8 r (Addr a w)) ssa na =
let a' = option_lookup ssa a in
let r' = option_lookup ssa r in
(Inst (Mem Store8 r' (Addr a' w)),ssa,na)) ∧
(ssa_cc_trans_inst (FP (FPLess r f1 f2)) ssa na =
let (r',ssa',na') = next_var_rename r ssa na in
(Inst (FP (FPLess r' f1 f2)),ssa',na')) ∧
(ssa_cc_trans_inst (FP (FPLessEqual r f1 f2)) ssa na =
let (r',ssa',na') = next_var_rename r ssa na in
(Inst (FP (FPLessEqual r' f1 f2)),ssa',na')) ∧
(ssa_cc_trans_inst (FP (FPEqual r f1 f2)) ssa na =
let (r',ssa',na') = next_var_rename r ssa na in
(Inst (FP (FPEqual r' f1 f2)),ssa',na')) ∧
(ssa_cc_trans_inst (FP (FPMovToReg r1 r2 d):'a inst) ssa na =
if dimindex(:'a) = 64 then
let (r1',ssa',na') = next_var_rename r1 ssa na in
(Inst (FP (FPMovToReg r1' r2 d)),ssa',na')
else
let (r1',ssa',na') = next_var_rename r1 ssa na in
let (r2',ssa'',na'') = next_var_rename r2 ssa' na' in
(Inst (FP (FPMovToReg r1' r2' d)),ssa'',na'')) ∧
(ssa_cc_trans_inst (FP (FPMovFromReg d r1 r2)) ssa na =
if dimindex(:'a) = 64 then
let r1' = option_lookup ssa r1 in
(Inst (FP (FPMovFromReg d r1' 0)),ssa,na)
else
let r1' = option_lookup ssa r1 in
let r2' = option_lookup ssa r2 in
if r1' = r2'
then
(* force distinct with an extra Move *)
let (r2'',ssa',na') = next_var_rename r2 ssa na in
let mov_in = Move0 [(r2'',r2')] in
(Seq mov_in (Inst (FP (FPMovFromReg d r1' r2''))),
ssa',na')
else
(Inst (FP (FPMovFromReg d r1' r2')),ssa,na)) ∧
(*Catchall -- for future instructions to be added, and all other FP *)
(ssa_cc_trans_inst x ssa na = (Inst x,ssa,na))
End
(*Expressions only ever need to lookup a variable's current ssa map
so it doesn't need the other parts *)
Definition ssa_cc_trans_exp_def:
(ssa_cc_trans_exp t (Var num) =
Var (option_lookup t num)) ∧
(ssa_cc_trans_exp t (Load exp) = Load (ssa_cc_trans_exp t exp)) ∧
(ssa_cc_trans_exp t (Op wop ls) =
Op wop (MAP (ssa_cc_trans_exp t) ls)) ∧
(ssa_cc_trans_exp t (Shift sh exp nexp) =
Shift sh (ssa_cc_trans_exp t exp) nexp) ∧
(ssa_cc_trans_exp t expr = expr)
Termination
WF_REL_TAC `measure (exp_size ARB o SND)`
\\ REPEAT STRIP_TAC \\ IMP_RES_TAC MEM_IMP_exp_size
\\ TRY (FIRST_X_ASSUM (ASSUME_TAC o Q.SPEC `ARB`))
\\ DECIDE_TAC
End
(*Attempt to pull out "renaming" moves
This takes a current name map and updates the names of all the vars
Intended for Alloc,Call cutset restoration moves
*)
Definition list_next_var_rename_move_def:
list_next_var_rename_move ssa n ls =
let cur_ls = MAP (option_lookup ssa) ls in
let (new_ls,ssa',n') = list_next_var_rename ls ssa n in
(Move0 (ZIP(new_ls,cur_ls)),ssa',n')
End
(* force the renaming map to send x -> y unless
x is already remapped *)
Definition force_rename_def:
(force_rename [] ssa = ssa) ∧
(force_rename ((x,y)::xs) ssa =
force_rename xs (insert x y ssa))
End
Definition mk_prio_def:
mk_prio el er =
if el = Skip then SOME (INL())
else if er = Skip then SOME (INR())
else NONE
End
Definition ssa_cc_trans_def:
(ssa_cc_trans Skip ssa na = (Skip,ssa,na)) ∧
(ssa_cc_trans (Move pri ls) ssa na =
let ls_1 = MAP FST ls in
let ls_2 = MAP SND ls in
let ren_ls2 = MAP (option_lookup ssa) ls_2 in
let (ren_ls1,ssa',na') = list_next_var_rename ls_1 ssa na in
let force =
FILTER (λ(x,y). ¬ MEM x ls_1) (ZIP(ls_2,ren_ls1)) in
(Move pri (ZIP(ren_ls1,ren_ls2)),force_rename force ssa',na')) ∧
(ssa_cc_trans (StoreConsts a b c d ws) ssa na =
let c1 = option_lookup ssa c in
let d1 = option_lookup ssa d in
let (d2,ssa',na') = next_var_rename d ssa na in
let (c2,ssa'',na'') = next_var_rename c ssa' na' in
let prog = Seq (Move1 [(4,c1);(6,d1)])
(Seq (StoreConsts 0 2 4 6 ws)
(Move1 [(c2,4);(d2,6)])) in
(prog, ssa'',na'')
) ∧
(ssa_cc_trans (Inst i) ssa na =
let (i',ssa',na') = ssa_cc_trans_inst i ssa na in
(i',ssa',na')) ∧
(ssa_cc_trans (Assign num exp) ssa na=
let exp' = ssa_cc_trans_exp ssa exp in
let (num',ssa',na') = next_var_rename num ssa na in
(Assign num' exp',ssa',na')) ∧
(ssa_cc_trans (Get num store) ssa na=
let (num',ssa',na') = next_var_rename num ssa na in
(Get num' store,ssa',na')) ∧
(ssa_cc_trans (Store exp num) ssa na=
let exp' = ssa_cc_trans_exp ssa exp in
let num' = option_lookup ssa num in
(Store exp' num',ssa,na)) ∧
(ssa_cc_trans (Seq s1 s2) ssa na=
let (s1',ssa',na') = ssa_cc_trans s1 ssa na in
let (s2',ssa'',na'') = ssa_cc_trans s2 ssa' na' in
(Seq s1' s2',ssa'',na'')) ∧
(ssa_cc_trans (MustTerminate s1) ssa na =
let (s1',ssa',na') = ssa_cc_trans s1 ssa na in
(MustTerminate s1',ssa',na')) ∧
(*Tricky case 1: we need to merge the ssa results from both branches by
unSSA-ing the phi functions
*)
(ssa_cc_trans (If cmp r1 ri e2 e3) ssa na =
let r1' = option_lookup ssa r1 in
let ri' = dtcase ri of Reg r => Reg (option_lookup ssa r)
| Imm v => Imm v in
(*ssa is the copy for both branches,
however, we can use new na2 and ns2*)
let (e2',ssa2,na2) = ssa_cc_trans e2 ssa na in
(*ssa2 is the ssa map for the first branch*)
let (e3',ssa3,na3) = ssa_cc_trans e3 ssa na2 in
(*ssa3 is the ssa map for the second branch, notice we
continued using na2 here though!*)
(* prioritizing original skips *)
let prio = mk_prio e2' e3' in
let (e2_cons,e3_cons,na_fin,ssa_fin) =
fix_inconsistencies prio ssa2 ssa3 na3 in
(If cmp r1' ri' (Seq e2' e2_cons) (Seq e3' e3_cons),ssa_fin,na_fin)) ∧
(*For cutsets, we must restart the ssa mapping to maintain consistency*)
(ssa_cc_trans (Alloc num numset) ssa na =
let ls = MAP FST (toAList numset) in
(*This trick allows us to not keep the "next stack" variable by
simply starting from the next available stack location
Assuming na is an alloc var of course..*)
let (stack_mov,ssa',na') = list_next_var_rename_move ssa (na+2) ls in
let num' = option_lookup ssa' num in
let stack_set = apply_nummap_key (option_lookup ssa') numset in
(*Restart the ssa map*)
let ssa_cut = inter ssa' numset in
let (ret_mov,ssa'',na'') =
list_next_var_rename_move ssa_cut (na'+2) ls in
let prog = (Seq (stack_mov)
(Seq (Move1 [(2,num')])
(Seq (Alloc 2 stack_set) (ret_mov)))) in
(prog,ssa'',na'')) ∧
(ssa_cc_trans (Raise num) ssa na =
let num' = option_lookup ssa num in
let mov = Move1 [(2,num')] in
(Seq mov (Raise 2),ssa,na)) ∧
(ssa_cc_trans (OpCurrHeap b dst src) ssa na=
let src' = option_lookup ssa src in
let (dst',ssa',na') = next_var_rename dst ssa na in
(OpCurrHeap b dst' src',ssa',na')) ∧
(ssa_cc_trans (Return num1 num2) ssa na=
let num1' = option_lookup ssa num1 in
let num2' = option_lookup ssa num2 in
let mov = Move1 [(2,num2')] in
(Seq mov (Return num1' 2),ssa,na)) ∧
(ssa_cc_trans Tick ssa na = (Tick,ssa,na)) ∧
(ssa_cc_trans (Set n exp) ssa na =
let exp' = ssa_cc_trans_exp ssa exp in
(Set n exp',ssa,na)) ∧
(ssa_cc_trans (LocValue r l1) ssa na =
let (r',ssa',na') = next_var_rename r ssa na in
(LocValue r' l1,ssa',na')) ∧
(ssa_cc_trans (Install ptr len dptr dlen numset) ssa na =
let ls = MAP FST (toAList numset) in
let (stack_mov,ssa',na') = list_next_var_rename_move ssa (na+2) ls in
let stack_set = apply_nummap_key (option_lookup ssa') numset in
let ptr' = option_lookup ssa' ptr in
let len' = option_lookup ssa' len in
let dptr' = option_lookup ssa' dptr in
let dlen' = option_lookup ssa' dlen in
let ssa_cut = inter ssa' numset in
let (ptr'',ssa'',na'') = next_var_rename ptr ssa_cut (na'+2) in
let (ret_mov,ssa''',na''') =
list_next_var_rename_move ssa'' na'' ls in
let prog = (Seq (stack_mov)
(Seq (Move1 [(2,ptr');(4,len')])
(Seq (Install 2 4 dptr' dlen' stack_set)
(Seq (Move1 [(ptr'',2)]) ret_mov)))) in
(prog,ssa''',na''')) ∧
(ssa_cc_trans (CodeBufferWrite r1 r2) ssa na =
let r1' = option_lookup ssa r1 in
let r2' = option_lookup ssa r2 in
(CodeBufferWrite r1' r2',ssa,na)) ∧
(ssa_cc_trans (DataBufferWrite r1 r2) ssa na =
let r1' = option_lookup ssa r1 in
let r2' = option_lookup ssa r2 in
(DataBufferWrite r1' r2',ssa,na)) ∧
(ssa_cc_trans (FFI ffi_index ptr1 len1 ptr2 len2 numset) ssa na =
let ls = MAP FST (toAList numset) in
let (stack_mov,ssa',na') = list_next_var_rename_move ssa (na+2) ls in
let stack_set = apply_nummap_key (option_lookup ssa') numset in
let cptr1 = option_lookup ssa' ptr1 in
let clen1 = option_lookup ssa' len1 in
let cptr2 = option_lookup ssa' ptr2 in
let clen2 = option_lookup ssa' len2 in
let ssa_cut = inter ssa' numset in
let (ret_mov,ssa'',na'') =
list_next_var_rename_move ssa_cut (na'+2) ls in
let prog = (Seq (stack_mov)
(Seq (Move1 [(2,cptr1);(4,clen1);(6,cptr2);(8,clen2)])
(Seq (FFI ffi_index 2 4 6 8 stack_set) (ret_mov)))) in
(prog,ssa'',na'')) ∧
(ssa_cc_trans (Call NONE dest args h) ssa na =
let names = MAP (option_lookup ssa) args in
let conv_args = GENLIST (\x.2*x) (LENGTH names) in
let move_args = (Move1 (ZIP (conv_args,names))) in
let prog = Seq move_args (Call NONE dest conv_args h) in
(prog,ssa,na)) ∧
(ssa_cc_trans (Call (SOME(ret,numset,ret_handler,l1,l2)) dest args h) ssa na =
let ls = MAP FST (toAList numset) in
let (stack_mov,ssa',na') = list_next_var_rename_move ssa (na+2) ls in
let stack_set = apply_nummap_key (option_lookup ssa') numset in
let names = MAP (option_lookup ssa) args in
let conv_args = GENLIST (\x.2*(x+1)) (LENGTH names) in
let move_args = (Move1 (ZIP (conv_args,names))) in
let ssa_cut = inter ssa' numset in
let (ret_mov,ssa'',na'') =
list_next_var_rename_move ssa_cut (na'+2) ls in
(*ret_mov restores the cutset*)
(*This recurses on the returning handler*)
let (ret',ssa_2_p,na_2_p) = next_var_rename ret ssa'' na'' in
let (ren_ret_handler,ssa_2,na_2) =
ssa_cc_trans ret_handler ssa_2_p na_2_p in
let mov_ret_handler =
(Seq ret_mov (Seq (Move1 [ret',2]) (ren_ret_handler))) in
(dtcase h of
NONE =>
let prog =
(Seq stack_mov (Seq move_args
(Call (SOME(2,stack_set,mov_ret_handler,l1,l2))
dest conv_args NONE))) in
(prog,ssa_2,na_2)
| SOME(n,h,l1',l2') =>
let (n',ssa_3_p,na_3_p) = next_var_rename n ssa'' na_2 in
let (ren_exc_handler,ssa_3,na_3) =
(ssa_cc_trans h ssa_3_p na_3_p) in
let mov_exc_handler =
(Seq ret_mov (Seq(Move1 [n',2]) (ren_exc_handler))) in
let prio = mk_prio mov_ret_handler mov_exc_handler in
let (ret_cons,exc_cons,na_fin,ssa_fin) =
fix_inconsistencies prio ssa_2 ssa_3 na_3 in
let cons_ret_handler = Seq mov_ret_handler ret_cons in
let cons_exc_handler = Seq mov_exc_handler exc_cons in
let prog =
(Seq stack_mov (Seq move_args
(Call (SOME(2,stack_set,cons_ret_handler,l1,l2))
dest conv_args (SOME(2,cons_exc_handler,l1',l2'))))) in
(prog,ssa_fin,na_fin))) /\
(ssa_cc_trans (ShareInst op v exp) ssa na =
let exp' = ssa_cc_trans_exp ssa exp in
if op = Store ∨ op = Store8 ∨ op = Store32
then
(ShareInst op (option_lookup ssa v) exp',ssa,na)
else
let (v',ssa',na') = next_var_rename v ssa na in
(ShareInst op v' exp',ssa',na'))
End
(*Recursively applying colours to a program*)
Definition apply_colour_exp_def:
(apply_colour_exp f (Var num) = Var (f num)) /\
(apply_colour_exp f (Load exp) = Load (apply_colour_exp f exp)) /\
(apply_colour_exp f (Op wop ls) = Op wop (MAP (apply_colour_exp f) ls)) /\
(apply_colour_exp f (Shift sh exp nexp) = Shift sh (apply_colour_exp f exp) nexp) /\
(apply_colour_exp f expr = expr)
Termination
WF_REL_TAC `measure (exp_size ARB o SND)`
\\ REPEAT STRIP_TAC \\ IMP_RES_TAC MEM_IMP_exp_size
\\ TRY (FIRST_X_ASSUM (ASSUME_TAC o Q.SPEC `ARB`))
\\ DECIDE_TAC
End
Definition apply_colour_imm_def:
(apply_colour_imm f (Reg n) = Reg (f n)) ∧
(apply_colour_imm f x = x)
End
Definition apply_colour_inst_def:
(apply_colour_inst f Skip = Skip) ∧
(apply_colour_inst f (Const reg w) = Const (f reg) w) ∧
(apply_colour_inst f (Arith (Binop bop r1 r2 ri)) =
Arith (Binop bop (f r1) (f r2) (apply_colour_imm f ri))) ∧
(apply_colour_inst f (Arith (Shift shift r1 r2 n)) =
Arith (Shift shift (f r1) (f r2) n)) ∧
(apply_colour_inst f (Arith (Div r1 r2 r3)) =
Arith (Div (f r1) (f r2) (f r3))) ∧
(apply_colour_inst f (Arith (AddCarry r1 r2 r3 r4)) =
Arith (AddCarry (f r1) (f r2) (f r3) (f r4))) ∧
(apply_colour_inst f (Arith (AddOverflow r1 r2 r3 r4)) =
Arith (AddOverflow (f r1) (f r2) (f r3) (f r4))) ∧
(apply_colour_inst f (Arith (SubOverflow r1 r2 r3 r4)) =
Arith (SubOverflow (f r1) (f r2) (f r3) (f r4))) ∧
(apply_colour_inst f (Arith (LongMul r1 r2 r3 r4)) =
Arith (LongMul (f r1) (f r2) (f r3) (f r4))) ∧
(apply_colour_inst f (Arith (LongDiv r1 r2 r3 r4 r5)) =
Arith (LongDiv (f r1) (f r2) (f r3) (f r4) (f r5))) ∧
(apply_colour_inst f (Mem Load r (Addr a w)) =
Mem Load (f r) (Addr (f a) w)) ∧
(apply_colour_inst f (Mem Store r (Addr a w)) =
Mem Store (f r) (Addr (f a) w)) ∧
(apply_colour_inst f (Mem Load8 r (Addr a w)) =
Mem Load8 (f r) (Addr (f a) w)) ∧
(apply_colour_inst f (Mem Store8 r (Addr a w)) =
Mem Store8 (f r) (Addr (f a) w)) ∧
(apply_colour_inst f (FP (FPLess r f1 f2)) = FP (FPLess (f r) f1 f2)) ∧
(apply_colour_inst f (FP (FPLessEqual r f1 f2)) = FP (FPLessEqual (f r) f1 f2)) ∧
(apply_colour_inst f (FP (FPEqual r f1 f2)) = FP (FPEqual (f r) f1 f2)) ∧
(apply_colour_inst f (FP (FPMovToReg r1 r2 d)) = FP (FPMovToReg (f r1) (f r2) d)) ∧
(apply_colour_inst f (FP (FPMovFromReg d r1 r2)) = FP (FPMovFromReg d (f r1) (f r2))) ∧
(apply_colour_inst f x = x)
End (*Catchall -- for future instructions to be added*)
Definition apply_colour_def:
(apply_colour f Skip = Skip) ∧
(apply_colour f (Move pri ls) =
Move pri (ZIP (MAP (f o FST) ls, MAP (f o SND) ls))) ∧
(apply_colour f (Inst i) = Inst (apply_colour_inst f i)) ∧
(apply_colour f (Assign num exp) = Assign (f num) (apply_colour_exp f exp)) ∧
(apply_colour f (Get num store) = Get (f num) store) ∧
(apply_colour f (Store exp num) = Store (apply_colour_exp f exp) (f num)) ∧
(apply_colour f (Call ret dest args h) =
let ret = dtcase ret of NONE => NONE
| SOME (v,cutset,ret_handler,l1,l2) =>
SOME (f v,apply_nummap_key f cutset,apply_colour f ret_handler,l1,l2) in
let args = MAP f args in
let h = dtcase h of NONE => NONE
| SOME (v,prog,l1,l2) => SOME (f v, apply_colour f prog,l1,l2) in
Call ret dest args h) ∧
(apply_colour f (Seq s1 s2) = Seq (apply_colour f s1) (apply_colour f s2)) ∧
(apply_colour f (MustTerminate s1) = MustTerminate (apply_colour f s1)) ∧
(apply_colour f (If cmp r1 ri e2 e3) =
If cmp (f r1) (apply_colour_imm f ri) (apply_colour f e2) (apply_colour f e3)) ∧
(apply_colour f (Install r1 r2 r3 r4 numset) =
Install (f r1) (f r2) (f r3) (f r4) (apply_nummap_key f numset)) ∧
(apply_colour f (CodeBufferWrite r1 r2) =
CodeBufferWrite (f r1) (f r2)) ∧
(apply_colour f (DataBufferWrite r1 r2) =
DataBufferWrite (f r1) (f r2)) ∧
(apply_colour f (FFI ffi_index ptr1 len1 ptr2 len2 numset) =
FFI ffi_index (f ptr1) (f len1) (f ptr2) (f len2) (apply_nummap_key f numset)) ∧
(apply_colour f (LocValue r l1) =
LocValue (f r) l1) ∧
(apply_colour f (Alloc num numset) =
Alloc (f num) (apply_nummap_key f numset)) ∧
(apply_colour f (StoreConsts a b c d ws) =
StoreConsts (f a) (f b) (f c) (f d) ws) ∧
(apply_colour f (Raise num) = Raise (f num)) ∧
(apply_colour f (Return num1 num2) = Return (f num1) (f num2)) ∧
(apply_colour f Tick = Tick) ∧
(apply_colour f (Set n exp) = Set n (apply_colour_exp f exp)) ∧
(apply_colour f (OpCurrHeap b n1 n2) = OpCurrHeap b (f n1) (f n2)) ∧
(apply_colour f (ShareInst op v exp) = ShareInst op (f v) (apply_colour_exp f exp)) ∧
(apply_colour f p = p )
End
val _ = export_rewrites ["apply_nummap_key_def","apply_colour_exp_def"
,"apply_colour_inst_def","apply_colour_def"
,"apply_colour_imm_def"];
(* Liveness Analysis*)
(*Writes made by any inst as a sptree*)
Definition get_writes_inst_def:
(get_writes_inst (Const reg w) = insert reg () LN) ∧
(get_writes_inst (Arith (Binop bop r1 r2 ri)) = insert r1 () LN) ∧
(get_writes_inst (Arith (Shift shift r1 r2 n)) = insert r1 () LN) ∧
(get_writes_inst (Arith (Div r1 r2 r3)) = insert r1 () LN) ∧
(get_writes_inst (Arith (AddCarry r1 r2 r3 r4)) = insert r4 () (insert r1 () LN)) ∧
(get_writes_inst (Arith (AddOverflow r1 r2 r3 r4)) = insert r4 () (insert r1 () LN)) ∧
(get_writes_inst (Arith (SubOverflow r1 r2 r3 r4)) = insert r4 () (insert r1 () LN)) ∧
(get_writes_inst (Arith (LongMul r1 r2 r3 r4)) = insert r2 () (insert r1 () LN)) ∧
(get_writes_inst (Arith (LongDiv r1 r2 r3 r4 r5)) = insert r2 () (insert r1 () LN)) ∧
(get_writes_inst (Mem Load r (Addr a w)) = insert r () LN) ∧
(get_writes_inst (Mem Load8 r (Addr a w)) = insert r () LN) ∧
(get_writes_inst (FP (FPLess r f1 f2)) = insert r () LN) ∧
(get_writes_inst (FP (FPLessEqual r f1 f2)) = insert r () LN) ∧
(get_writes_inst (FP (FPEqual r f1 f2)) = insert r () LN) ∧
(get_writes_inst (FP (FPMovToReg r1 r2 d) :'a inst) =
if dimindex(:'a) = 64
then insert r1 () LN
else insert r2 () (insert r1 () LN)) ∧
(get_writes_inst inst = LN)
End
(*Liveness for instructions, follows liveness equations
live-sets are num_sets a.k.a. unit-sptrees*)
Definition get_live_inst_def:
(get_live_inst Skip live:num_set = live) ∧
(get_live_inst (Const reg w) live = delete reg live) ∧
(get_live_inst (Arith (Binop bop r1 r2 ri)) live =
dtcase ri of Reg r3 => insert r2 () (insert r3 () (delete r1 live))
| _ => insert r2 () (delete r1 live)) ∧
(get_live_inst (Arith (Shift shift r1 r2 n)) live =
insert r2 () (delete r1 live)) ∧
(get_live_inst (Arith (Div r1 r2 r3)) live =
(insert r3 () (insert r2 () (delete r1 live)))) ∧
(get_live_inst (Arith (AddCarry r1 r2 r3 r4)) live =
(*r4 is live anyway*)
insert r4 () (insert r3 () (insert r2 () (delete r1 live)))) ∧
(get_live_inst (Arith (AddOverflow r1 r2 r3 r4)) live =
insert r3 () (insert r2 () (delete r4 (delete r1 live)))) ∧
(get_live_inst (Arith (SubOverflow r1 r2 r3 r4)) live =
insert r3 () (insert r2 () (delete r4 (delete r1 live)))) ∧
(get_live_inst (Arith (LongMul r1 r2 r3 r4)) live =
insert r4 () (insert r3 () (delete r2 (delete r1 live)))) ∧
(get_live_inst (Arith (LongDiv r1 r2 r3 r4 r5)) live =
insert r5 () (insert r4 () (insert r3 () (delete r2 (delete r1 live))))) ∧
(get_live_inst (Mem Load r (Addr a w)) live =
insert a () (delete r live)) ∧
(get_live_inst (Mem Store r (Addr a w)) live =
insert a () (insert r () live)) ∧
(get_live_inst (Mem Load8 r (Addr a w)) live =
insert a () (delete r live)) ∧
(get_live_inst (Mem Store8 r (Addr a w)) live =
insert a () (insert r () live)) ∧
(get_live_inst (FP (FPLess r f1 f2)) live = delete r live) ∧
(get_live_inst (FP (FPLessEqual r f1 f2)) live = delete r live) ∧
(get_live_inst (FP (FPEqual r f1 f2)) live = delete r live) ∧
(get_live_inst (FP (FPMovToReg r1 r2 d): 'a inst) live =
if dimindex(:'a) = 64
then delete r1 live
else delete r1 (delete r2 live)) ∧
(get_live_inst (FP (FPMovFromReg d r1 r2)) live =
if dimindex(:'a) = 64
then insert r1 () live
else insert r2 () (insert r1 () live)) ∧
(*Catchall -- for future instructions to be added*)
(get_live_inst x live = live)
End
Definition big_union_def:
big_union ls = FOLDR (λx y. union x y) LN ls
End
Definition get_live_exp_def:
(get_live_exp (Var num) = insert num () LN ) ∧
(get_live_exp (Load exp) = get_live_exp exp) ∧
(get_live_exp (Op wop ls) =
big_union (MAP get_live_exp ls)) ∧
(get_live_exp (Shift sh exp nexp) = get_live_exp exp) ∧
(get_live_exp expr = LN)
Termination
WF_REL_TAC `measure (exp_size ARB)`>>
rw[]>>
imp_res_tac MEM_IMP_exp_size>>
FIRST_X_ASSUM (ASSUME_TAC o Q.SPEC `ARB`) >> DECIDE_TAC
End
Definition numset_list_insert_def:
(numset_list_insert [] t = t) ∧
(numset_list_insert (x::xs) t = insert x () (numset_list_insert xs t))
End
Definition get_live_def:
(get_live Skip live = live) ∧
(*All SNDs are read and all FSTs are written*)
(get_live (Move pri ls) live =
let killed = FOLDR delete live (MAP FST ls) in
numset_list_insert (MAP SND ls) killed) ∧
(get_live (Inst i) live = get_live_inst i live) ∧
(*num is written, exp is read*)
(get_live (Assign num exp) live =
let sub = get_live_exp exp in
union sub (delete num live)) ∧
(get_live (Get num store) live = delete num live) ∧
(*Everything is read*)
(get_live (Store exp num) live =
insert num () (union (get_live_exp exp) live))∧
(*Find liveset just before s2 which is the input liveset to s1*)
(get_live (Seq s1 s2) live =
get_live s1 (get_live s2 live)) ∧
(get_live (MustTerminate s1) live =
get_live s1 live) ∧
(*First case where branching appears:
We get the livesets for e2 and e3, union them, add the if variable
then pass the resulting liveset upwards
*)
(get_live (If cmp r1 ri e2 e3) live =
let e2_live = get_live e2 live in
let e3_live = get_live e3 live in
let union_live = union e2_live e3_live in
dtcase ri of Reg r2 => insert r2 () (insert r1 () union_live)
| _ => insert r1 () union_live) ∧
(get_live (Alloc num numset) live = insert num () numset) ∧
(get_live (StoreConsts a b c d ws) live =
insert c () (insert d () (delete a (delete b live)))) ∧
(get_live (Install r1 r2 r3 r4 numset) live =
list_insert [r1;r2;r3;r4] numset) ∧
(get_live (CodeBufferWrite r1 r2) live =
list_insert [r1;r2] live) ∧
(get_live (DataBufferWrite r1 r2) live =
list_insert [r1;r2] live) ∧
(get_live (FFI ffi_index ptr1 len1 ptr2 len2 numset) live =
insert ptr1 () (insert len1 ()
(insert ptr2 () (insert len2 () numset)))) ∧
(get_live (StoreConsts a b c d ws) live =
(insert c () (insert d () live))) ∧
(get_live (Raise num) live = insert num () live) ∧
(get_live (Return num1 num2) live = insert num1 () (insert num2 () live)) ∧
(get_live Tick live = live) ∧
(get_live (LocValue r l1) live = delete r live) ∧
(get_live (Set n exp) live = union (get_live_exp exp) live) ∧
(get_live (OpCurrHeap b n1 n2) live = insert n2 () (delete n1 live)) ∧
(get_live (ShareInst mop v exp) live =
let sub = get_live_exp exp in
if mop = Store ∨ mop = Store8 ∨ mop = Store32
then union sub (insert v () live)
else union sub (delete v live)) ∧
(*Cut-set must be live, args input must be live
For tail calls, there shouldn't be a liveset since control flow will
never return into the same instance
Otherwise, both args + cutsets live
*)
(get_live (Call NONE dest args h) live = numset_list_insert args LN) ∧
(get_live (Call (SOME(_,cutset,_)) dest args h) live =
union cutset (numset_list_insert args LN))
End
(* Dead instruction removal *)
Definition remove_dead_inst_def:
(remove_dead_inst Skip (live:num_set) = T) ∧
(remove_dead_inst (Const reg w) live = (lookup reg live = NONE)) ∧
(remove_dead_inst (Arith (Binop bop r1 r2 ri)) live = (lookup r1 live = NONE)) ∧
(remove_dead_inst (Arith (Shift shift r1 r2 n)) live = (lookup r1 live = NONE)) ∧
(remove_dead_inst (Arith (Div r1 r2 r3)) live = (lookup r1 live = NONE)) ∧
(remove_dead_inst (Arith (AddCarry r1 r2 r3 r4)) live =
(lookup r1 live = NONE ∧ lookup r4 live = NONE)) ∧
(remove_dead_inst (Arith (AddOverflow r1 r2 r3 r4)) live =
(lookup r1 live = NONE ∧ lookup r4 live = NONE)) ∧
(remove_dead_inst (Arith (SubOverflow r1 r2 r3 r4)) live =
(lookup r1 live = NONE ∧ lookup r4 live = NONE)) ∧
(remove_dead_inst (Arith (LongMul r1 r2 r3 r4)) live =
(lookup r1 live = NONE ∧ lookup r2 live = NONE)) ∧
(remove_dead_inst (Arith (LongDiv r1 r2 r3 r4 r5)) live =
(lookup r1 live = NONE ∧ lookup r2 live = NONE)) ∧
(remove_dead_inst (Mem Load r (Addr a w)) live = (lookup r live = NONE)) ∧
(remove_dead_inst (Mem Load8 r (Addr a w)) live = (lookup r live = NONE)) ∧
(remove_dead_inst (FP (FPLess r f1 f2)) live = (lookup r live = NONE)) ∧
(remove_dead_inst (FP (FPLessEqual r f1 f2)) live = (lookup r live = NONE)) ∧
(remove_dead_inst (FP (FPEqual r f1 f2)) live = (lookup r live = NONE)) ∧
(remove_dead_inst (FP (FPMovToReg r1 r2 d) :'a inst) live =
if dimindex(:'a) = 64 then lookup r1 live = NONE
else (lookup r1 live = NONE ∧ (lookup r2 live = NONE))) ∧
(*Catchall -- for other instructions*)
(remove_dead_inst x live = F)
End
(*Delete dead code, w.r.t. a set of live variables*)
Definition remove_dead_def:
(remove_dead Skip live = (Skip,live)) ∧
(remove_dead (Move pri ls) live =
let ls = FILTER (λx,y. lookup x live = SOME ()) ls in
if ls = [] then (Skip,live)
else
let killed = FOLDR delete live (MAP FST ls) in
(Move pri ls,numset_list_insert (MAP SND ls) killed)) ∧
(remove_dead (Inst i) live =
if remove_dead_inst i live then (Skip,live)
else (Inst i,get_live_inst i live)) ∧
(remove_dead (Assign num exp) live =
(if lookup num live = NONE then
(Skip,live)
else
(Assign num exp, get_live (Assign num exp) live))) ∧
(remove_dead (Get num store) live =
if lookup num live = NONE then
(Skip,live)
else (Get num store,delete num live)) ∧
(remove_dead (OpCurrHeap b num src) live =
if lookup num live = NONE then
(Skip,live)
else (OpCurrHeap b num src,insert src () (delete num live))) ∧
(remove_dead (LocValue r l1) live =
if lookup r live = NONE then
(Skip,live)
else (LocValue r l1,delete r live)) ∧
(remove_dead (Seq s1 s2) live =
let (s2,s2live) = remove_dead s2 live in
let (s1,s1live) = remove_dead s1 s2live in
let prog =
if s1 = Skip then
if s2 = Skip then Skip
else s2
else
if s2 = Skip then s1
else Seq s1 s2
in (prog,s1live)) ∧
(remove_dead (MustTerminate s1) live =
(* This can technically be optimized away if it was a Skip,
but we should never use MustTerminate to wrap completely dead code
*)
let (s1,s1live) = remove_dead s1 live in
(MustTerminate s1,s1live)) ∧
(remove_dead (If cmp r1 ri e2 e3) live =
let (e2,e2_live) = remove_dead e2 live in
let (e3,e3_live) = remove_dead e3 live in
let union_live = union e2_live e3_live in
let liveset =
dtcase ri of Reg r2 => insert r2 () (insert r1 () union_live)
| _ => insert r1 () union_live in
let prog =
if e2 = Skip ∧ e3 = Skip then Skip
else If cmp r1 ri e2 e3 in
(prog,liveset)) ∧
(remove_dead (Call(SOME(v,cutset,ret_handler,l1,l2))dest args h) live =
(*top level*)
let args_set = numset_list_insert args LN in
let live_set = union cutset args_set in
let (ret_handler,_) = remove_dead ret_handler live in
let h =
(dtcase h of
NONE => NONE
| SOME(v',prog,l1,l2) =>
SOME(v',FST (remove_dead prog live),l1,l2)) in
(Call (SOME (v,cutset,ret_handler,l1,l2)) dest args h,live_set)) ∧
(* we should not remove the ShareInst Load instructions.
* It produces a ffi event even if the variable is not in
* the live set *)
(remove_dead prog live = (prog,get_live prog live))
End
Definition remove_dead_prog_def:
remove_dead_prog prog = FST (remove_dead prog LN)
End
(*Single step immediate writes by a prog*)
Definition get_writes_def:
(get_writes (Move pri ls) = numset_list_insert (MAP FST ls) LN)∧
(get_writes (Inst i) = get_writes_inst i) ∧
(get_writes (Assign num exp) = insert num () LN)∧
(get_writes (Get num store) = insert num () LN) ∧
(get_writes (LocValue r l1) = insert r () LN) ∧
(get_writes (Install r1 _ _ _ _) = insert r1 () LN) ∧
(get_writes (OpCurrHeap b r1 _) = insert r1 () LN) ∧
(get_writes (StoreConsts a b c d _) = insert a () (insert b () (insert c () (insert d () LN)))) ∧
(get_writes (ShareInst Load v _) = insert v () LN) ∧
(get_writes (ShareInst Load8 v _) = insert v () LN) ∧
(get_writes (ShareInst Load32 v _) = insert v () LN) ∧
(get_writes prog = LN)
End
Theorem get_writes_pmatch:
!inst.
get_writes inst =
case inst of
| Move pri ls => numset_list_insert (MAP FST ls) LN
| Inst i => get_writes_inst i
| Assign num exp => insert num () LN
| Get num store => insert num () LN
| LocValue r l1 => insert r () LN
| Install r1 _ _ _ _ => insert r1 () LN
| OpCurrHeap b r1 _ => insert r1 () LN
| StoreConsts a b c d _ => insert a () (insert b () (insert c () (insert d () LN)))
| ShareInst Load v _ => insert v () LN
| ShareInst Load8 v _ => insert v () LN
| ShareInst Load32 v _ => insert v () LN
| prog => LN
Proof
rpt strip_tac
>> CONV_TAC(RAND_CONV patternMatchesLib.PMATCH_ELIM_CONV)
>> every_case_tac >> fs[get_writes_def]
QED
(* Old representation *)
(* Definition get_clash_sets_def:
(get_clash_sets (Seq s1 s2) live =
let (hd,ls) = get_clash_sets s2 live in
let (hd',ls') = get_clash_sets s1 hd in
(hd',(ls' ++ ls))) ∧
(get_clash_sets (MustTerminate s1) live =
get_clash_sets s1 live) ∧
(get_clash_sets (If cmp r1 ri e2 e3) live =
let (h2,ls2) = get_clash_sets e2 live in
let (h3,ls3) = get_clash_sets e3 live in
let union_live = union h2 h3 in
let merged = dtcase ri of Reg r2 => insert r2 () (insert r1 () union_live)
| _ => insert r1 () union_live in
(merged,ls2++ls3)) ∧
(get_clash_sets (Call(SOME(v,cutset,ret_handler,l1,l2))dest args h) live =
(*top level*)
let args_set = numset_list_insert args LN in
let (hd,ls) = get_clash_sets ret_handler live in
(*Outer liveset*)
let live_set = union cutset args_set in
(*Returning clash set*)
let ret_clash = insert v () cutset in
(dtcase h of
NONE => (live_set,ret_clash::hd::ls)
| SOME(v',prog,l1,l2) =>
let (hd',ls') = get_clash_sets prog live in
(*Handler clash set*)
let h_clash = insert v' () cutset in
(live_set,h_clash::ret_clash::hd::hd'::ls++ls'))) ∧
(*Catchall for cases where we dont have in sub programs live sets*)
(get_clash_sets prog live =
let i_set = union (get_writes prog) live in
(get_live prog live,[i_set]))
End
*)
(* Potentially more efficient liveset representation for checking / allocation*)
Definition get_delta_inst_def:
(get_delta_inst Skip = Delta [] []) ∧
(get_delta_inst (Const reg w) = Delta [reg] []) ∧
(get_delta_inst (Arith (Binop bop r1 r2 ri)) =
dtcase ri of Reg r3 => Delta [r1] [r2;r3]
| _ => Delta [r1] [r2]) ∧
(get_delta_inst (Arith (Shift shift r1 r2 n)) = Delta [r1] [r2]) ∧
(get_delta_inst (Arith (Div r1 r2 r3)) = Delta [r1] [r3;r2]) ∧
(get_delta_inst (Arith (AddCarry r1 r2 r3 r4)) = Delta [r1;r4] [r4;r3;r2]) ∧
(get_delta_inst (Arith (AddOverflow r1 r2 r3 r4)) = Delta [r1;r4] [r3;r2]) ∧
(get_delta_inst (Arith (SubOverflow r1 r2 r3 r4)) = Delta [r1;r4] [r3;r2]) ∧
(get_delta_inst (Arith (LongMul r1 r2 r3 r4)) = Delta [r1;r2] [r4;r3]) ∧
(get_delta_inst (Arith (LongDiv r1 r2 r3 r4 r5)) = Delta [r1;r2] [r5;r4;r3]) ∧
(get_delta_inst (Mem Load r (Addr a w)) = Delta [r] [a]) ∧
(get_delta_inst (Mem Store r (Addr a w)) = Delta [] [r;a]) ∧
(get_delta_inst (Mem Load8 r (Addr a w)) = Delta [r] [a]) ∧
(get_delta_inst (Mem Store8 r (Addr a w)) = Delta [] [r;a]) ∧
(get_delta_inst (FP (FPLess r f1 f2)) = Delta [r] []) ∧
(get_delta_inst (FP (FPLessEqual r f1 f2)) = Delta [r] []) ∧
(get_delta_inst (FP (FPEqual r f1 f2)) = Delta [r] []) ∧
(get_delta_inst (FP (FPMovToReg r1 r2 d):'a inst) =
if dimindex(:'a) = 64
then Delta [r1] []
else Delta [r1;r2] []) ∧
(get_delta_inst (FP (FPMovFromReg d r1 r2)) =
if dimindex(:'a) = 64
then Delta [] [r1]
else Delta [] [r1;r2]) ∧
(*Catchall -- for future instructions to be added*)
(get_delta_inst x = Delta [] [])
End
Definition get_reads_exp_def:
(get_reads_exp (Var num) = [num]) ∧
(get_reads_exp (Load exp) = get_reads_exp exp) ∧
(get_reads_exp (Op wop ls) =
FLAT (MAP get_reads_exp ls)) ∧
(get_reads_exp (Shift sh exp nexp) = get_reads_exp exp) ∧
(get_reads_exp expr = [])
Termination
WF_REL_TAC `measure (exp_size ARB)`
\\ REPEAT STRIP_TAC \\ IMP_RES_TAC MEM_IMP_exp_size
\\ TRY (FIRST_X_ASSUM (ASSUME_TAC o Q.SPEC `ARB`))
\\ DECIDE_TAC
End
Definition get_clash_tree_def:
(get_clash_tree Skip = Delta [] []) ∧
(get_clash_tree (Move pri ls) =
Delta (MAP FST ls) (MAP SND ls)) ∧
(get_clash_tree (Inst i) = get_delta_inst i) ∧
(get_clash_tree (Assign num exp) = Delta [num] (get_reads_exp exp)) ∧
(get_clash_tree (Get num store) = Delta [num] []) ∧
(get_clash_tree (Store exp num) = Delta [] (num::get_reads_exp exp)) ∧
(get_clash_tree (Seq s1 s2) = Seq (get_clash_tree s1) (get_clash_tree s2)) ∧
(get_clash_tree (If cmp r1 ri e2 e3) =
let e2t = get_clash_tree e2 in
let e3t = get_clash_tree e3 in
dtcase ri of
Reg r2 => Seq (Delta [] [r1;r2]) (Branch NONE e2t e3t)
| _ => Seq (Delta [] [r1]) (Branch NONE e2t e3t)) ∧
(get_clash_tree (MustTerminate s) =
get_clash_tree s) ∧
(get_clash_tree (Alloc num numset) =
Seq (Delta [] [num]) (Set numset)) ∧
(get_clash_tree (Install r1 r2 r3 r4 numset) =
Seq (Delta [] [r4;r3;r2;r1]) (Seq (Set numset) (Delta [r1] []))) ∧
(get_clash_tree (CodeBufferWrite r1 r2) =
Delta [] [r2;r1]) ∧
(get_clash_tree (DataBufferWrite r1 r2) =
Delta [] [r2;r1]) ∧