Skip to content

Commit

Permalink
Optimize suitable R-type instructions into I-type
Browse files Browse the repository at this point in the history
  • Loading branch information
AdUhTkJm authored and mengzhuo committed Dec 31, 2024
1 parent 482e318 commit 87a1857
Show file tree
Hide file tree
Showing 10 changed files with 246 additions and 84 deletions.
2 changes: 1 addition & 1 deletion src/driver_util.ml
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ let wasm_gen ~(elim_unused_let : bool) (core : Mcore.t) ~clam_callback =
let riscv_gen (core : Mcore.t) =
core
|> Riscv_generate.ssa_of_mcore
|> Riscv_opt.opt
|> Riscv_opt_gather.opt
|> Riscv.generate

let link_core ~(shrink_wasm : bool) ~(elim_unused_let : bool)
Expand Down
66 changes: 26 additions & 40 deletions src/riscv_generate.ml
Original file line number Diff line number Diff line change
Expand Up @@ -138,9 +138,7 @@ let deal_with_prim ssa rd (prim: Primitive.prim) args =
(match from, to_ with
| I32, U8 | U32, U8 ->
(* Discard higher bits by masking them away *)
let mask = new_temp T_int in
Basic_vec.push ssa (AssignInt { rd = mask; imm = 255L });
Basic_vec.push ssa (And { rd; rs1 = arg; rs2 = mask })
Basic_vec.push ssa (Andi { rd; rs = arg; imm = 255 })

| _ -> die())

Expand All @@ -153,7 +151,7 @@ let deal_with_prim ssa rd (prim: Primitive.prim) args =
let buf_size = if length = 0 then 0 else length * (sizeof (List.hd args).ty) in
Basic_vec.push ssa (Malloc { rd; size = 12 });
Basic_vec.push ssa (Malloc { rd = buf; size = buf_size });
Basic_vec.push ssa (AssignInt { rd = len; imm = Int64.of_int length; });
Basic_vec.push ssa (AssignInt { rd = len; imm = length; });
Basic_vec.push ssa (Store { rd = buf; rs = rd; offset = 0; byte = pointer_size });
Basic_vec.push ssa (Store { rd = len; rs = rd; offset = pointer_size; byte = 4 });

Expand All @@ -178,7 +176,7 @@ let deal_with_prim ssa rd (prim: Primitive.prim) args =
let offset = new_temp T_int in

(* Same as `rd = *(arr + sizeof(T) * index)` *)
Basic_vec.push ssa (AssignInt { rd = sz; imm = Int64.of_int size; });
Basic_vec.push ssa (AssignInt { rd = sz; imm = size; });
Basic_vec.push ssa (Mul { rd = offset; rs1 = sz; rs2 = index });
Basic_vec.push ssa (Add { rd = addr; rs1 = arr; rs2 = offset });
Basic_vec.push ssa (Load { rd; rs = addr; offset = 0; byte = size });
Expand All @@ -199,7 +197,7 @@ let deal_with_prim ssa rd (prim: Primitive.prim) args =
let sz = new_temp T_int in
let length = new_temp T_int in
(* Same as `rd = malloc(sizeof(T) * len)` *)
Basic_vec.push ssa (AssignInt { rd = sz; imm = Int64.of_int size; });
Basic_vec.push ssa (AssignInt { rd = sz; imm = size; });
Basic_vec.push ssa (Mul { rd = length; rs1 = sz; rs2 = len });
Basic_vec.push ssa (CallExtern { rd; fn = "malloc"; args = [length] })

Expand All @@ -218,7 +216,7 @@ let deal_with_prim ssa rd (prim: Primitive.prim) args =
let load = new_temp T_int in

Basic_vec.push ssa (Load { rd = vtb; rs = arg; offset = -pointer_size; byte = pointer_size });
Basic_vec.push ssa (AssignInt { rd = load; imm = Int64.of_int vtb_offset });
Basic_vec.push ssa (AssignInt { rd = load; imm = vtb_offset });
Basic_vec.push ssa (Add { rd = fn_addr; rs1 = vtb; rs2 = load });
(* The whole set of args (including self) is needed. *)
Basic_vec.push ssa (CallIndirect { rd; rs = fn_addr; args })
Expand Down Expand Up @@ -248,7 +246,7 @@ let deal_with_prim ssa rd (prim: Primitive.prim) args =
let two = new_temp T_int in
let offset = new_temp T_int in
let altered = new_temp T_string in
Basic_vec.push ssa (AssignInt { rd = two; imm = 2L });
Basic_vec.push ssa (AssignInt { rd = two; imm = 2 });
Basic_vec.push ssa (Mul { rd = offset; rs1 = i; rs2 = two });
Basic_vec.push ssa (Add { rd = altered; rs1 = str; rs2 = offset });
Basic_vec.push ssa (Load { rd; rs = altered; offset = 0; byte = 2 })
Expand All @@ -268,13 +266,11 @@ let deal_with_prim ssa rd (prim: Primitive.prim) args =
(* Let the pointer point to beginning of data, rather than the length section *)
let memory = new_temp T_bytes in
let unused = new_temp T_unit in
let int_sz = new_temp T_int in
let new_len = new_temp T_int in
Basic_vec.push ssa (AssignInt { rd = int_sz; imm = 4L });
Basic_vec.push ssa (Add { rd = new_len; rs1 = len; rs2 = int_sz });
Basic_vec.push ssa (Addi { rd = new_len; rs = len; imm = 4 });
Basic_vec.push ssa (CallExtern { rd = memory; fn = "malloc"; args = [ new_len ] });
Basic_vec.push ssa (Store { rd = len; rs = memory; offset = 0; byte = 4 });
Basic_vec.push ssa (Add { rd; rs1 = memory; rs2 = int_sz });
Basic_vec.push ssa (Addi { rd; rs = memory; imm = 4 });
Basic_vec.push ssa (CallExtern { rd = unused; fn = "memset"; args = [ rd; init; len ] });

| Pignore -> ()
Expand Down Expand Up @@ -391,7 +387,7 @@ let rec do_convert ssa (expr: Mcore.expr) =

(* Alter the vtable offset according to the trait *)
Basic_vec.push ssa (Load { rd = vtb; rs = obj; offset = 0; byte = pointer_size });
Basic_vec.push ssa (AssignInt { rd = load; imm = Int64.of_int delta });
Basic_vec.push ssa (AssignInt { rd = load; imm = delta });
Basic_vec.push ssa (Add { rd = altered; rs1 = vtb; rs2 = load });
Basic_vec.push ssa (Store { rd = altered; rs = obj; offset = 0; byte = pointer_size });
obj
Expand Down Expand Up @@ -419,7 +415,7 @@ let rec do_convert ssa (expr: Mcore.expr) =
Basic_vec.push ssa (Jump ifexit);

push_label ssa ifnot;
Basic_vec.push ssa (AssignInt { rd = t2; imm = 0L; });
Basic_vec.push ssa (AssignInt { rd = t2; imm = 0; });
Basic_vec.push ssa (Jump ifexit);

push_label ssa ifexit;
Expand All @@ -437,7 +433,7 @@ let rec do_convert ssa (expr: Mcore.expr) =
Basic_vec.push ssa (Branch { cond; ifso; ifnot });

push_label ssa ifso;
Basic_vec.push ssa (AssignInt { rd = t1; imm = 1L; });
Basic_vec.push ssa (AssignInt { rd = t1; imm = 1; });
Basic_vec.push ssa (Jump ifexit);

push_label ssa ifnot;
Expand Down Expand Up @@ -496,7 +492,7 @@ let rec do_convert ssa (expr: Mcore.expr) =

(* Before calling, we must advance the pointer to the correct offset *)
Basic_vec.push before (Load { rd = vtb; rs = arg; offset; byte });
Basic_vec.push before (AssignInt { rd = load; imm = Int64.of_int delta });
Basic_vec.push before (AssignInt { rd = load; imm = delta });
Basic_vec.push before (Add { rd = altered; rs1 = vtb; rs2 = load });
Basic_vec.push before (Store { rd = altered; rs = arg; offset; byte });

Expand Down Expand Up @@ -722,7 +718,7 @@ let rec do_convert ssa (expr: Mcore.expr) =
(* and let `rd` point at where fields start *)
(* in order to unite traited and untraited types *)
Basic_vec.push ssa (Malloc { rd = beginning; size = size + pointer_size });
Basic_vec.push ssa (AssignInt { rd = load; imm = Int64.of_int pointer_size });
Basic_vec.push ssa (AssignInt { rd = load; imm = pointer_size });
Basic_vec.push ssa (Add { rd; rs1 = beginning; rs2 = load });

(* Load in vtable *)
Expand Down Expand Up @@ -812,7 +808,7 @@ let rec do_convert ssa (expr: Mcore.expr) =

| Cexpr_const { c; ty; _ } ->
let rd = new_temp ty in
let instruction = (match c with
(match c with
(* Note each element of string is 2 bytes long. TODO *)
| C_string v ->
let label = Printf.sprintf "str_%d" !slot in
Expand All @@ -830,11 +826,9 @@ let rec do_convert ssa (expr: Mcore.expr) =

(* Let the pointer point to beginning of data, rather than the length section *)
let beginning = new_temp T_bytes in
let four = new_temp T_int in
Basic_vec.push ssa (ExtArray { label; values });
Basic_vec.push ssa (AssignLabel { rd = beginning; imm = label; });
Basic_vec.push ssa (AssignInt { rd = four; imm = 4L });
Add { rd; rs1 = beginning; rs2 = four }
Basic_vec.push ssa (Addi { rd; rs = beginning; imm = 4 })

| C_bytes { v; _ } ->
let label = Printf.sprintf "bytes_%d" !slot in
Expand All @@ -847,32 +841,24 @@ let rec do_convert ssa (expr: Mcore.expr) =

(* Let the pointer point to beginning of data, rather than the length section *)
let beginning = new_temp T_bytes in
let four = new_temp T_int in
Basic_vec.push ssa (ExtArray { label; values });
Basic_vec.push ssa (AssignLabel { rd = beginning; imm = label; });
Basic_vec.push ssa (AssignInt { rd = four; imm = 4L });
Add { rd; rs1 = beginning; rs2 = four }


Basic_vec.push ssa (Addi { rd; rs = beginning; imm = 4 })

| C_int64 { v; _ } | C_uint64 { v; _ } ->
Basic_vec.push ssa (AssignInt64 { rd; imm = v });
| C_bool imm ->
AssignInt { rd; imm = Int64.of_int (if imm then 1 else 0); }
Basic_vec.push ssa (AssignInt { rd; imm = if imm then 1 else 0; })
| C_char imm ->
AssignInt { rd; imm = Int64.of_int (Uchar.to_int imm); }
| C_int { v; _ } ->
AssignInt { rd; imm = Int64.of_int32 v; }
| C_int64 { v; _ } ->
AssignInt { rd; imm = v; }
| C_uint { v; _ } ->
AssignInt { rd; imm = Int64.of_int32 v; }
| C_uint64 { v; _ } ->
AssignInt { rd; imm = v; }
Basic_vec.push ssa (AssignInt { rd; imm = Uchar.to_int imm; })
| C_int { v; _ } | C_uint { v; _ } ->
Basic_vec.push ssa (AssignInt { rd; imm = Int32.to_int v; })
| C_float { v; _ } ->
AssignFP { rd; imm = v; }
Basic_vec.push ssa (AssignFP { rd; imm = v; })
| C_double { v; _ } ->
AssignFP { rd; imm = v; }
Basic_vec.push ssa (AssignFP { rd; imm = v; })
| C_bigint _ -> failwith "TODO: riscv_ssa.ml: bigint not supported"
) in
Basic_vec.push ssa instruction;
);
rd

let generate_vtables () =
Expand Down
22 changes: 8 additions & 14 deletions src/riscv_internals.ml
Original file line number Diff line number Diff line change
Expand Up @@ -52,17 +52,15 @@ is actually half of the argument `length`.
fn unsafe_bytes_sub_string (src, offset, length) {
; allocate space
li %1 4
add %2 length %1
addi %2 length 4
call dst malloc %2
; divide length by 2
li %6 1
shr %7 length %6
sw %7 dst
srli %1 length 1
sw %1 dst
; copy
add %3 dst %1
addi %3 dst 4
add %4 src offset
call %5 memcpy %3 %4 length
return %3
Expand All @@ -81,22 +79,18 @@ let unsafe_bytes_sub_string fn =
let _3 = new_temp T_bytes in
let _4 = new_temp T_bytes in
let _5 = new_temp T_unit in
let _6 = new_temp T_int in
let _7 = new_temp T_int in
let dst = new_temp T_bytes in
let body = [
(* Allocate space *)
AssignInt { rd = _1; imm = 4L };
Add { rd = _2; rs1 = length; rs2 = _1 };
Addi { rd = _2; rs = length; imm = 4 };
CallExtern { rd = dst; fn = "malloc"; args = [ _2 ] };

(* Divide length by 2 *)
AssignInt { rd = _6; imm = 1L };
Shr { rd = _7; rs1 = length; rs2 = _6 };
Store { rd = _7; rs = dst; offset = 0; byte = 4 };
Srli { rd = _1; rs = length; imm = 1 };
Store { rd = _1; rs = dst; offset = 0; byte = 4 };

(* Copy *)
Add { rd = _3; rs1 = dst; rs2 = _1 };
Addi { rd = _3; rs = dst; imm = 4 };
Add { rd = _4; rs1 = src; rs2 = offset };
CallExtern { rd = _5; fn = "memcpy"; args = [ _3; _4; length ] };
Return _3;
Expand Down
17 changes: 5 additions & 12 deletions src/riscv_opt.ml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ type instruction = Riscv_ssa.t

(** Note: `body` does not include the label before instructions. *)
type basic_block = {
body: instruction Basic_vec.t;
mutable body: instruction Basic_vec.t;
succ: string Basic_vec.t;
pred: string Basic_vec.t;
}
Expand Down Expand Up @@ -39,7 +39,7 @@ let build_cfg fn body =
(* The first basic block in each function is unnamed, *)
(* so we take the function name as its name. *)
let name = ref fn in
let vec = ref (Basic_vec.make ~dummy:Riscv_ssa.Nop 16) in
let vec = ref (Basic_vec.empty ()) in

(* There might be multiple jumps at end of each basic block. *)
(* Clean them up. *)
Expand Down Expand Up @@ -67,7 +67,7 @@ let build_cfg fn body =
Basic_vec.append (block_of !name).body (tidy !vec);

(* Clear the instructions; Basic_vec does not offer clear() or something alike *)
vec := Basic_vec.make ~dummy:Riscv_ssa.Nop 16;
vec := Basic_vec.empty ();
name := label

| x -> Basic_vec.push !vec x)
Expand Down Expand Up @@ -138,7 +138,7 @@ let map_fn f ssa =
(** Sets to store live variables or basic blocks. *)
module Varset = Set.Make(String)

(** Find all basic blocks in function `fn`. *)
(** Find all basic blocks in function `fn`, in depth-first order. *)
let get_blocks fn =
let blocks = Basic_vec.empty () in
let visited = ref Varset.empty in
Expand Down Expand Up @@ -218,11 +218,4 @@ let ssa_of_cfg fn =
Basic_vec.push inst (Riscv_ssa.Label x);
Basic_vec.append inst (block_of x).body
) blocks;
inst |> Basic_vec.to_list

let opt ssa =
iter_fn2 build_cfg ssa;
let s = map_fn ssa_of_cfg ssa in
let out = Printf.sprintf "%s.ssa" !Driver_config.Linkcore_Opt.output_file in
Basic_io.write out (String.concat "\n" (List.map Riscv_ssa.to_string s));
s
inst |> Basic_vec.to_list
13 changes: 13 additions & 0 deletions src/riscv_opt_gather.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
(** Gathers all optimizations. *)
open Riscv_opt

let opt ssa =
iter_fn2 build_cfg ssa;

(* Peephole *)
Riscv_opt_peephole.peephole ssa;

let s = map_fn ssa_of_cfg ssa in
let out = Printf.sprintf "%s.ssa" !Driver_config.Linkcore_Opt.output_file in
Basic_io.write out (String.concat "\n" (List.map Riscv_ssa.to_string s));
s
Loading

0 comments on commit 87a1857

Please sign in to comment.