Skip to content

Commit

Permalink
generate better asm for int_of_float, float_of_int, truncate & abs_float
Browse files Browse the repository at this point in the history
  • Loading branch information
glyh committed Oct 24, 2024
1 parent de93444 commit e4cf588
Show file tree
Hide file tree
Showing 11 changed files with 136 additions and 32 deletions.
14 changes: 0 additions & 14 deletions notes.md

This file was deleted.

21 changes: 21 additions & 0 deletions src/closureps_eval/interpreter.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,27 @@ pub fn CloPSInterpreter::eval(
}
continue rest
}
Prim(IntOfFloat, [f], bind, rest) => {
match self.eval_v!(f) {
Double(f) => self.cur_env[bind] = Int(f.to_int())
val => @util.die("unexpected input \{val} for `int_of_float`")
}
continue rest
}
Prim(FloatOfInt, [i], bind, rest) => {
match self.eval_v!(i) {
Int(i) => self.cur_env[bind] = Double(i.to_double())
val => @util.die("unexpected input \{val} for `float_of_int`")
}
continue rest
}
Prim(AbsFloat, [f], bind, rest) => {
match self.eval_v!(f) {
Double(f) => self.cur_env[bind] = Double(@double.abs(f))
val => @util.die("unexpected input \{val} for `int_of_float`")
}
continue rest
}
Prim(_) => @util.die("malformed prim call \{expr}")
MakeArray(len, elem, kont_closure) =>
match (self.eval_v!(len), self.eval_v!(elem)) {
Expand Down
3 changes: 3 additions & 0 deletions src/cps/cps_ir.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ pub enum PrimOp {
Math(@top.Op, @precps.Numeric)
Eq
Le
IntOfFloat
FloatOfInt
AbsFloat
} derive(Show)

pub enum Cps {
Expand Down
64 changes: 49 additions & 15 deletions src/cps/precps2cps.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -84,21 +84,6 @@ pub fn CpsEnv::precps2cps(self : CpsEnv, s : P, c : Cont) -> Cps {

self.precps2cps_list(elements, c1)
}
// (a1, a2, a3, .., an, (r) -> Unit)
App(ret_ty, f, args) => {
let k_ref = self.new_tmp(Fun([ret_ty], Unit))
let x_ref = self.new_tmp(ret_ty)
fn c1(f : Value) {
fn c2(es : @immut/list.T[Value]) {
App(f, es.iter().append(Var(k_ref)).map(fix_label_to_var).collect())
}

self.precps2cps_list(args, c2)
}

Fix(k_ref, [x_ref], c(Var(x_ref)), self.precps2cps(f, c1))
}

// WARN: Array Creation must come with an external call and thus continuation
Prim(ret_ty, MakeArray, rands) => {
let k_ref = self.new_tmp(Fun([ret_ty], Unit))
Expand Down Expand Up @@ -132,6 +117,55 @@ pub fn CpsEnv::precps2cps(self : CpsEnv, s : P, c : Cont) -> Cps {

self.precps2cps_list(rands, c1)
}
// (a1, a2, a3, .., an, (r) -> Unit)
App(ret_ty, f, args) => {
fn generate_app() {
let k_ref = self.new_tmp(Fun([ret_ty], Unit))
let x_ref = self.new_tmp(ret_ty)
fn c1(f : Value) {
fn c2(es : @immut/list.T[Value]) {
App(f, es.iter().append(Var(k_ref)).map(fix_label_to_var).collect())
}

self.precps2cps_list(args, c2)
}

Fix(k_ref, [x_ref], c(Var(x_ref)), self.precps2cps(f, c1))
}

guard let Var(_, var) | Label(_, var) = f else {
_ => return generate_app()
}
guard var.id < 0 else { return generate_app() }
guard let Some(name) = var.name else { _ => return generate_app() }
match name {
"int_of_float" | "truncate" => {
fn c1(a : @immut/list.T[Value]) {
let tmp = self.new_tmp(ret_ty)
Prim(IntOfFloat, a.iter().collect(), tmp, c(Var(tmp)))
}

self.precps2cps_list(args, c1)
}
"float_of_int" => {
fn c1(a : @immut/list.T[Value]) {
let tmp = self.new_tmp(ret_ty)
Prim(FloatOfInt, a.iter().collect(), tmp, c(Var(tmp)))
}

self.precps2cps_list(args, c1)
}
"abs_float" => {
fn c1(a : @immut/list.T[Value]) {
let tmp = self.new_tmp(ret_ty)
Prim(AbsFloat, a.iter().collect(), tmp, c(Var(tmp)))
}

self.precps2cps_list(args, c1)
}
_ => generate_app()
}
}
KthTuple(ret_ty, offset, tup) => {
fn c1(v : Value) {
let tmp = self.new_tmp(ret_ty)
Expand Down
3 changes: 2 additions & 1 deletion src/externals.mbt
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// TODO:
// Maybe generate primitives for create_*_array
pub let externals_list : Array[(String, Type)] = [
("read_int", Fun([], Int)),
("print_int", Fun([Int], Unit)),
Expand All @@ -9,7 +11,6 @@ pub let externals_list : Array[(String, Type)] = [
("truncate", Fun([Double], Int)),
("floor", Fun([Double], Double)),
("abs_float", Fun([Double], Double)),
("abs_float", Fun([Double], Double)),
("sqrt", Fun([Double], Double)),
("sin", Fun([Double], Double)),
("cos", Fun([Double], Double)),
Expand Down
15 changes: 15 additions & 0 deletions src/js/clops2js.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,21 @@ pub fn JsEmitter::emit_cps(self : JsEmitter, cps : @cps.Cps) -> String {
"const \{emit_var(bind)} = \{lhs_emit} <= \{rhs_emit};"
continue rest
}
Prim(IntOfFloat, [f], bind, rest) => {
let f_emit = emit_val(f)
output += line_start + "const \{emit_var(bind)} = Math.trunc(\{f_emit});"
continue rest
}
Prim(FloatOfInt, [i], bind, rest) => {
let i_emit = emit_val(i)
output += line_start + "const \{emit_var(bind)} = \{i_emit};"
continue rest
}
Prim(AbsFloat, [f], bind, rest) => {
let f_emit = emit_val(f)
output += line_start + "const \{emit_var(bind)} = Math.abs(\{f_emit});"
continue rest
}
Prim(_) as expr => @util.die("malformed prim call \{expr}")
MakeArray(len, elem, kont_closure) => {
let len_emit = emit_val(len)
Expand Down
24 changes: 22 additions & 2 deletions src/riscv/codegen.mbt
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// TODO:
// 1. aggressively throw free variables of current continuation closure on stored registers
enum RegTy {
I32
PTR64
Expand Down Expand Up @@ -165,13 +167,16 @@ fn CodegenBlock::insert_asm(self : CodegenBlock, asm : RvAsm) -> Unit {
| FeqD(reg, _, _)
| FleD(reg, _, _)
| Seqz(reg, _)
| FmvXD(reg, _) | La(reg, _) | Li(reg, _) | Neg(reg, _) | Mv(reg, _) =>
| FmvXD(reg, _)
| La(reg, _) | Li(reg, _) | Neg(reg, _) | Mv(reg, _) | Fcvtwd(reg, _) =>
self.dirtied.insert(I(reg))
FaddD(freg, _, _)
| FsubD(freg, _, _)
| FmulD(freg, _, _)
| FdivD(freg, _, _)
| Fld(freg, _) | FmvDX(freg, _) | FnegD(freg, _) | FmvD(freg, _) =>
| Fld(freg, _)
| FmvDX(freg, _)
| FnegD(freg, _) | FmvD(freg, _) | Fcvtdw(freg, _) | Fsgnjxd(freg, _, _) =>
self.dirtied.insert(F(freg))
_ => ()
}
Expand Down Expand Up @@ -662,6 +667,21 @@ fn CodegenBlock::codegen(self : CodegenBlock) -> Unit {
let reg_v = self.pull_val_i(v)
self.assign_i(bind, fn { reg_bind => [Neg(reg_bind, reg_v)] })
}
Prim(bind, IntOfFloat, [f]) => {
let reg_v = self.pull_val_f(f)
self.assign_i(bind, fn { reg_bind => [Fcvtwd(reg_bind, reg_v)] })
}
Prim(bind, FloatOfInt, [i]) => {
let reg_v = self.pull_val_i(i)
self.assign_f(bind, fn { reg_bind => [Fcvtdw(reg_bind, reg_v)] })
}
Prim(bind, AbsFloat, [f]) => {
let reg_v = self.pull_val_f(f)
self.assign_f(
bind,
fn { reg_bind => [Fsgnjxd(reg_bind, reg_v, reg_v)] },
)
}
// TODO: may generate more higher quality asm if idx is known at compile time
Prim(bind, Get, [arr, idx]) => {
let reg_idx = self.pull_val_i(idx)
Expand Down
3 changes: 3 additions & 0 deletions src/riscv/extern_stub.mbt
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// TODO: if S reg being occupied for free vars of continuation
// we can't use them for temporary storage here.

fn collect_externals(cfg : @ssacfg.SsaCfg) -> @hashset.T[Var] {
let out = @hashset.new()
fn collect_label_var(v : Var) {
Expand Down
6 changes: 6 additions & 0 deletions src/riscv/rv_asm.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ pub enum RvAsm {
FleD(Reg, FReg, FReg)
FmvDX(FReg, Reg)
FmvXD(Reg, FReg)
Fcvtdw(FReg, Reg)
Fcvtwd(Reg, FReg)
Fsgnjxd(FReg, FReg, FReg)
// pseudo instructions
Nop
La(Reg, Label)
Expand Down Expand Up @@ -235,6 +238,9 @@ impl Show for RvAsm with output(self, logger) {
FleD(rd, rs1, rs2) => write3(logger, "fle.d", rd, rs1, rs2)
FmvDX(rd, rs1) => write2(logger, "fmv.d.x", rd, rs1)
FmvXD(rd, rs1) => write2(logger, "fmv.x.d", rd, rs1)
Fcvtdw(rd, rs1) => write2(logger, "fcvt.d.w", rd, rs1)
Fcvtwd(rd, rs1) => write2(logger, "fcvt.w.d", rd, rs1)
Fsgnjxd(rd, rs1, rs2) => write3(logger, "fsgnjx.d", rd, rs1, rs2)
Nop => logger.write_string("nop")
La(rd, label) => {
logger.write_string("la ")
Expand Down
12 changes: 12 additions & 0 deletions src/ssacfg/clops2ssacfg.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,18 @@ fn SsaCfg::cps2block(
cur_block.insts.push(KthTuple(bind, tup, idx))
continue rest
}
Prim(IntOfFloat, args, bind, rest) => {
cur_block.insts.push(Prim(bind, IntOfFloat, args))
continue rest
}
Prim(FloatOfInt, args, bind, rest) => {
cur_block.insts.push(Prim(bind, FloatOfInt, args))
continue rest
}
Prim(AbsFloat, args, bind, rest) => {
cur_block.insts.push(Prim(bind, AbsFloat, args))
continue rest
}
Prim(Not, args, bind, rest) => {
cur_block.insts.push(Prim(bind, Not, args))
continue rest
Expand Down
3 changes: 3 additions & 0 deletions src/ssacfg/ssa_ir.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ pub enum PrimOp {
Math(@typing.Op, @precps.Numeric)
Eq
Le
IntOfFloat
FloatOfInt
AbsFloat
} derive(Show)

pub enum Inst {
Expand Down

0 comments on commit e4cf588

Please sign in to comment.