Skip to content

Commit ed167bd

Browse files
AdUhTkJmmengzhuo
authored andcommitted
Separate 3-address code and SSA generation
1 parent b2f841a commit ed167bd

File tree

14 files changed

+928
-477
lines changed

14 files changed

+928
-477
lines changed

src/riscv_generate.ml

Lines changed: 366 additions & 394 deletions
Large diffs are not rendered by default.

src/riscv_opt.ml

Lines changed: 55 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,23 @@
11
(** Does all sorts of optimizations. *)
22

33
open Riscv_ssa
4+
module Vec = Basic_vec
45

56
(** Instruction in SSA form; feel free to change it to anything you'd like *)
67
type instruction = Riscv_ssa.t
78

89
(** Note: `body` does not include the label before instructions. *)
910
type basic_block = {
10-
mutable body: instruction Basic_vec.t;
11-
succ: string Basic_vec.t;
12-
pred: string Basic_vec.t;
11+
mutable body: instruction Vec.t;
12+
succ: string Vec.t;
13+
mutable pred: string Vec.t;
1314
}
1415

1516
let make () =
1617
{
17-
body = Basic_vec.empty ();
18-
succ = Basic_vec.empty ();
19-
pred = Basic_vec.empty ();
18+
body = Vec.empty ();
19+
succ = Vec.empty ();
20+
pred = Vec.empty ();
2021
}
2122

2223

@@ -33,7 +34,7 @@ let (params: (string, var list) Hashtbl.t) = Hashtbl.create 256
3334
let block_of name = Hashtbl.find basic_blocks name
3435

3536
(** Get the body of a basic block. *)
36-
let body_of name = (block_of name).body |> Basic_vec.to_list
37+
let body_of name = (block_of name).body |> Vec.to_list
3738

3839
(**
3940
Builds control flow graph.
@@ -47,48 +48,50 @@ let build_cfg fn body =
4748
(* The first basic block in each function is unnamed, *)
4849
(* so we take the function name as its name. *)
4950
let name = ref fn in
50-
let vec = ref (Basic_vec.empty ()) in
51+
let vec = ref (Vec.empty ()) in
5152

5253
(* There might be multiple jumps at end of each basic block. *)
5354
(* Clean them up. *)
54-
let tidy (vec: instruction Basic_vec.t) =
55-
let rec iter () =
56-
let len = Basic_vec.length vec in
57-
if len <= 1 then ()
58-
59-
(* Check penultimate instruction, and pop the last according to it *)
60-
else let x = Basic_vec.get vec (len - 2) in
55+
let tidy (vec: instruction Vec.t) =
56+
let tidied = Vec.empty () in
57+
let len = Vec.length vec in
58+
let rec iter i =
59+
Vec.push tidied (Vec.get vec i);
60+
61+
if i = len - 1 then ()
62+
63+
else let x = Vec.get vec i in
6164
match x with
62-
| Jump _ -> Basic_vec.pop vec |> ignore; iter ()
63-
| Branch _ -> Basic_vec.pop vec |> ignore; iter ()
64-
| Return _ -> Basic_vec.pop vec |> ignore; iter ()
65-
| JumpIndirect _ -> Basic_vec.pop vec |> ignore; iter ()
66-
| _ -> ()
65+
| Jump _
66+
| Branch _
67+
| Return _
68+
| JumpIndirect _ -> ()
69+
| _ -> iter (i + 1)
6770
in
68-
iter ();
69-
vec
71+
iter 0;
72+
tidied
7073
in
7174

7275
let separate_basic_block (inst: instruction) =
7376
(match inst with
7477
| Label label ->
7578
Hashtbl.add basic_blocks !name (make ());
76-
Basic_vec.append (block_of !name).body (tidy !vec);
79+
Vec.append (block_of !name).body (tidy !vec);
7780

78-
(* Clear the instructions; Basic_vec does not offer clear() or something alike *)
79-
vec := Basic_vec.empty ();
81+
(* Clear the instructions; Vec does not offer clear() or something alike *)
82+
vec := Vec.empty ();
8083
name := label
8184

82-
| x -> Basic_vec.push !vec x)
85+
| x -> Vec.push !vec x)
8386
in
8487
List.iter separate_basic_block body;
8588

8689
(* The last basic block is missed by `separate_basic_block` *)
8790
(* Manually add it *)
8891
Hashtbl.add basic_blocks !name (make ());
89-
Basic_vec.append (block_of !name).body (!vec);
92+
Vec.append (block_of !name).body (!vec);
9093

91-
Hashtbl.add exit_fn fn (Basic_vec.empty ());
94+
Hashtbl.add exit_fn fn (Vec.empty ());
9295

9396
(* Find successors of each block. *)
9497

@@ -98,23 +101,29 @@ let build_cfg fn body =
98101
(* So we just look at them. *)
99102
let rec find_succ name =
100103
let block = block_of name in
101-
if Basic_vec.is_empty block.succ then
104+
if Vec.is_empty block.succ then
102105
let successors =
103-
(match Basic_vec.last block.body with
106+
(match Vec.last block.body with
104107
| Jump target -> [target]
105108
| Branch { ifso; ifnot } -> [ifso; ifnot]
106-
| Return _ -> Basic_vec.push (Hashtbl.find exit_fn fn) name; []
109+
| Return _ -> Vec.push (Hashtbl.find exit_fn fn) name; []
107110
| JumpIndirect { possibilities; _ } -> possibilities
108111
| _ -> failwith "riscv_opt.ml: malformed SSA")
109112
in
110-
Basic_vec.append block.succ (Basic_vec.of_list successors);
113+
Vec.append block.succ (Vec.of_list successors);
111114
List.iter find_succ successors
112115
in
113116
find_succ fn;
114117

115118
(* Find predecessors *)
116119
Hashtbl.iter (fun name block ->
117-
Basic_vec.iter (fun succ -> Basic_vec.push (block_of succ).pred name) block.succ
120+
Vec.iter (fun succ -> Vec.push (block_of succ).pred name) block.succ
121+
) basic_blocks;
122+
123+
(* Deduplicate *)
124+
Hashtbl.iter (fun name block ->
125+
block.pred <-
126+
block.pred |> Vec.to_list |> Stringset.of_list |> Stringset.to_seq |> List.of_seq |> Vec.of_list
118127
) basic_blocks
119128

120129

@@ -147,16 +156,16 @@ let map_fn f ssa =
147156

148157
(** Find all basic blocks in function `fn`, in depth-first order. *)
149158
let get_blocks fn =
150-
let blocks = Basic_vec.empty () in
159+
let blocks = Vec.empty () in
151160
let visited = ref Stringset.empty in
152161
let rec aux x =
153162
if not (Stringset.mem x !visited) then
154-
(Basic_vec.push blocks x;
163+
(Vec.push blocks x;
155164
visited := Stringset.add x !visited;
156-
Basic_vec.iter aux (block_of x).succ)
165+
Vec.iter aux (block_of x).succ)
157166
in
158167
aux fn;
159-
blocks |> Basic_vec.to_list
168+
blocks |> Vec.to_list
160169

161170
(**
162171
Liveness analysis.
@@ -204,7 +213,7 @@ let liveness_analysis fn =
204213
let phidef = ref Stringset.empty in
205214
let phiuse = ref Stringset.empty in
206215

207-
Basic_vec.iter (fun inst ->
216+
Vec.iter (fun inst ->
208217
match inst with
209218
| Phi { rd; rs } ->
210219
phidef += rd.name;
@@ -225,7 +234,7 @@ let liveness_analysis fn =
225234

226235
(* Keep doing until fixed point is reached *)
227236
let rec iterate worklist =
228-
let last_item = Basic_vec.pop_opt worklist in
237+
let last_item = Vec.pop_opt worklist in
229238
match last_item with
230239
| None -> ()
231240
| Some fn ->
@@ -238,7 +247,7 @@ let liveness_analysis fn =
238247
let new_live_out =
239248
Stringset.union (List.fold_left (fun x s ->
240249
Stringset.union x (Stringset.diff (Hashtbl.find live_in s) (Hashtbl.find phidefs s))
241-
) Stringset.empty (Basic_vec.to_list block.succ)) (Hashtbl.find phiuses name)
250+
) Stringset.empty (Vec.to_list block.succ)) (Hashtbl.find phiuses name)
242251
in
243252

244253
Hashtbl.replace live_out name new_live_out;
@@ -253,21 +262,21 @@ let liveness_analysis fn =
253262
(* Push all of them into worklist *)
254263
if not (Stringset.equal old_live_in new_live_in) then
255264
(Hashtbl.replace live_in name new_live_in;
256-
Basic_vec.append worklist block.pred)
265+
Vec.append worklist block.pred)
257266
) blocks;
258267
iterate worklist
259268
in
260269
(* Must clone a vector, otherwise `exit_fn` will become empty *)
261-
iterate (Hashtbl.find exit_fn fn |> Basic_vec.to_list |> Basic_vec.of_list);
270+
iterate (Hashtbl.find exit_fn fn |> Vec.to_list |> Vec.of_list);
262271

263272
live_out
264273

265274
(** Converts the optimized control flow graph back into SSA. *)
266275
let ssa_of_cfg fn =
267-
let inst = Basic_vec.empty () in
276+
let inst = Vec.empty () in
268277
let blocks = get_blocks fn in
269278
List.iter (fun x ->
270-
Basic_vec.push inst (Riscv_ssa.Label x);
271-
Basic_vec.append inst (block_of x).body
279+
Vec.push inst (Riscv_ssa.Label x);
280+
Vec.append inst (block_of x).body
272281
) blocks;
273-
inst |> Basic_vec.to_list
282+
inst |> Vec.to_list

src/riscv_opt_gather.ml

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,20 @@
22
open Riscv_opt
33
open Riscv_ssa
44

5-
let opt ssa =
5+
let opt tac =
66
List.iter (fun top -> match top with
77
| FnDecl { fn; args } -> Hashtbl.add params fn args
8-
| _ -> ()) ssa;
9-
iter_fn2 build_cfg ssa;
8+
| _ -> ()) tac;
9+
10+
iter_fn2 build_cfg tac;
11+
let ssa = Riscv_tac2ssa.ssa_of_tac tac in
1012

1113
for i = 1 to 3 do
1214
Riscv_opt_inline.inline ssa;
1315
Riscv_opt_peephole.peephole ssa;
1416
Riscv_opt_escape.lower_malloc ssa;
1517
done;
16-
18+
1719
let s = map_fn ssa_of_cfg ssa in
1820
let out = Printf.sprintf "%s.ssa" !Driver_config.Linkcore_Opt.output_file in
1921
Basic_io.write out (String.concat "\n" (List.map Riscv_ssa.to_string s));

0 commit comments

Comments
 (0)