guard hoisting
This commit is contained in:
149
streamline.cm
149
streamline.cm
@@ -219,6 +219,16 @@ var streamline = function(ir, log) {
|
||||
return null
|
||||
}
|
||||
|
||||
var seed_writes = function(slot_types, write_types) {
|
||||
var keys = array(write_types)
|
||||
var k = 0
|
||||
while (k < length(keys)) {
|
||||
slot_types[keys[k]] = write_types[keys[k]]
|
||||
k = k + 1
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
// =========================================================
|
||||
// Pass: infer_param_types — backward type inference
|
||||
// Scans typed operators to infer immutable parameter types.
|
||||
@@ -308,15 +318,137 @@ var streamline = function(ir, log) {
|
||||
return param_types
|
||||
}
|
||||
|
||||
// =========================================================
|
||||
// Pass: infer_slot_write_types — slot write-type invariance
|
||||
// Scans all instructions to find non-parameter slots where
|
||||
// every write produces the same type. These types persist
|
||||
// across label join points.
|
||||
// =========================================================
|
||||
var infer_slot_write_types = function(func) {
|
||||
var instructions = func.instructions
|
||||
var nr_args = func.nr_args != null ? func.nr_args : 0
|
||||
var num_instr = 0
|
||||
var write_types = null
|
||||
var result = null
|
||||
var keys = null
|
||||
var i = 0
|
||||
var k = 0
|
||||
var instr = null
|
||||
var op = null
|
||||
var slot = 0
|
||||
var typ = null
|
||||
var wt = null
|
||||
|
||||
if (instructions == null) {
|
||||
return {}
|
||||
}
|
||||
|
||||
num_instr = length(instructions)
|
||||
write_types = {}
|
||||
i = 0
|
||||
while (i < num_instr) {
|
||||
instr = instructions[i]
|
||||
if (!is_array(instr)) {
|
||||
i = i + 1
|
||||
continue
|
||||
}
|
||||
|
||||
op = instr[0]
|
||||
slot = -1
|
||||
typ = null
|
||||
|
||||
if (op == "int") {
|
||||
slot = instr[1]
|
||||
typ = T_INT
|
||||
} else if (op == "true" || op == "false") {
|
||||
slot = instr[1]
|
||||
typ = T_BOOL
|
||||
} else if (op == "null") {
|
||||
slot = instr[1]
|
||||
typ = T_NULL
|
||||
} else if (op == "access") {
|
||||
slot = instr[1]
|
||||
typ = access_value_type(instr[2])
|
||||
} else if (op == "array") {
|
||||
slot = instr[1]
|
||||
typ = T_ARRAY
|
||||
} else if (op == "record") {
|
||||
slot = instr[1]
|
||||
typ = T_RECORD
|
||||
} else if (op == "function") {
|
||||
slot = instr[1]
|
||||
typ = T_FUNCTION
|
||||
} else if (op == "length") {
|
||||
slot = instr[1]
|
||||
typ = T_INT
|
||||
} else if (int_result_ops[op] == true) {
|
||||
slot = instr[1]
|
||||
typ = T_INT
|
||||
} else if (float_result_ops[op] == true) {
|
||||
slot = instr[1]
|
||||
typ = T_FLOAT
|
||||
} else if (op == "neg_int" || op == "bitnot" || op == "bitand" ||
|
||||
op == "bitor" || op == "bitxor" || op == "shl" ||
|
||||
op == "shr" || op == "ushr") {
|
||||
slot = instr[1]
|
||||
typ = T_INT
|
||||
} else if (op == "neg_float") {
|
||||
slot = instr[1]
|
||||
typ = T_FLOAT
|
||||
} else if (op == "concat") {
|
||||
slot = instr[1]
|
||||
typ = T_TEXT
|
||||
} else if (bool_result_ops[op] == true) {
|
||||
slot = instr[1]
|
||||
typ = T_BOOL
|
||||
} else if (op == "eq" || op == "ne" || op == "lt" ||
|
||||
op == "le" || op == "gt" || op == "ge" || op == "in") {
|
||||
slot = instr[1]
|
||||
typ = T_BOOL
|
||||
} else if (op == "add" || op == "subtract" || op == "multiply" ||
|
||||
op == "divide" || op == "modulo" || op == "pow") {
|
||||
slot = instr[1]
|
||||
typ = T_UNKNOWN
|
||||
} else if (op == "move" || op == "load_field" || op == "load_index" ||
|
||||
op == "load_dynamic" || op == "pop" || op == "get") {
|
||||
slot = instr[1]
|
||||
typ = T_UNKNOWN
|
||||
} else if (op == "invoke" || op == "tail_invoke") {
|
||||
slot = instr[2]
|
||||
typ = T_UNKNOWN
|
||||
}
|
||||
|
||||
if (slot > 0 && slot > nr_args) {
|
||||
merge_backward(write_types, slot, typ != null ? typ : T_UNKNOWN)
|
||||
}
|
||||
|
||||
i = i + 1
|
||||
}
|
||||
|
||||
// Filter to only slots with known (non-unknown) types
|
||||
result = {}
|
||||
keys = array(write_types)
|
||||
k = 0
|
||||
while (k < length(keys)) {
|
||||
wt = write_types[keys[k]]
|
||||
if (wt != null && wt != T_UNKNOWN) {
|
||||
result[keys[k]] = wt
|
||||
}
|
||||
k = k + 1
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// =========================================================
|
||||
// Pass: eliminate_type_checks — language-level type narrowing
|
||||
// Eliminates is_<type>/jump pairs when type is known.
|
||||
// Reduces load_dynamic/store_dynamic to field/index forms.
|
||||
// =========================================================
|
||||
var eliminate_type_checks = function(func, param_types, log) {
|
||||
var eliminate_type_checks = function(func, param_types, write_types, log) {
|
||||
var instructions = func.instructions
|
||||
var nr_args = func.nr_args != null ? func.nr_args : 0
|
||||
var has_params = false
|
||||
var has_writes = false
|
||||
var num_instr = 0
|
||||
var slot_types = null
|
||||
var nc = 0
|
||||
@@ -351,11 +483,15 @@ var streamline = function(ir, log) {
|
||||
}
|
||||
j = j + 1
|
||||
}
|
||||
has_writes = length(array(write_types)) > 0
|
||||
|
||||
slot_types = {}
|
||||
if (has_params) {
|
||||
seed_params(slot_types, param_types, nr_args)
|
||||
}
|
||||
if (has_writes) {
|
||||
seed_writes(slot_types, write_types)
|
||||
}
|
||||
|
||||
i = 0
|
||||
while (i < num_instr) {
|
||||
@@ -366,6 +502,9 @@ var streamline = function(ir, log) {
|
||||
if (has_params) {
|
||||
seed_params(slot_types, param_types, nr_args)
|
||||
}
|
||||
if (has_writes) {
|
||||
seed_writes(slot_types, write_types)
|
||||
}
|
||||
i = i + 1
|
||||
continue
|
||||
}
|
||||
@@ -1130,6 +1269,7 @@ var streamline = function(ir, log) {
|
||||
// =========================================================
|
||||
var optimize_function = function(func, log) {
|
||||
var param_types = null
|
||||
var write_types = null
|
||||
var slot_types = null
|
||||
if (func.instructions == null || length(func.instructions) == 0) {
|
||||
return null
|
||||
@@ -1139,8 +1279,13 @@ var streamline = function(ir, log) {
|
||||
return param_types
|
||||
})
|
||||
if (verify_fn) verify_fn(func, "after infer_param_types")
|
||||
run_pass(func, "infer_slot_write_types", function() {
|
||||
write_types = infer_slot_write_types(func)
|
||||
return write_types
|
||||
})
|
||||
if (verify_fn) verify_fn(func, "after infer_slot_write_types")
|
||||
run_pass(func, "eliminate_type_checks", function() {
|
||||
slot_types = eliminate_type_checks(func, param_types, log)
|
||||
slot_types = eliminate_type_checks(func, param_types, write_types, log)
|
||||
return slot_types
|
||||
})
|
||||
if (verify_fn) verify_fn(func, "after eliminate_type_checks")
|
||||
|
||||
Reference in New Issue
Block a user