Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optimize suitable R-type instructions into I-type #8

Merged
merged 1 commit into from
Dec 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading