astgen: improve the ensure_unused_result elision

This commit is contained in:
Andrew Kelley
2021-03-22 18:57:46 -07:00
parent 2f391df2a7
commit 568f333681
4 changed files with 212 additions and 170 deletions

View File

@@ -1398,163 +1398,6 @@ pub const WipZirCode = struct {
return result;
}
/// Returns `true` if and only if the instruction *always* has a void type, or
/// *always* has a NoReturn type. Function calls return false because
/// the answer depends on their type.
/// This is used to elide unnecessary `ensure_result_used` instructions.
pub fn isVoidOrNoReturn(wzc: WipZirCode, inst_ref: zir.Inst.Ref) bool {
if (inst_ref >= wzc.ref_start_index) {
const inst = inst_ref - wzc.ref_start_index;
const tags = wzc.instructions.items(.tag);
switch (tags[inst]) {
.@"const" => {
const tv = wzc.instructions.items(.data)[inst].@"const";
return switch (tv.ty.zigTypeTag()) {
.NoReturn, .Void => true,
else => false,
};
},
.add,
.addwrap,
.alloc,
.alloc_mut,
.alloc_inferred,
.alloc_inferred_mut,
.array_cat,
.array_mul,
.array_type,
.array_type_sentinel,
.indexable_ptr_len,
.as,
.as_node,
.@"asm",
.asm_volatile,
.bit_and,
.bitcast,
.bitcast_ref,
.bitcast_result_ptr,
.bit_or,
.block,
.block_comptime,
.bool_br_and,
.bool_br_or,
.bool_not,
.bool_and,
.bool_or,
.call,
.call_compile_time,
.call_none,
.cmp_lt,
.cmp_lte,
.cmp_eq,
.cmp_gte,
.cmp_gt,
.cmp_neq,
.coerce_result_ptr,
.decl_ref,
.decl_val,
.deref_node,
.div,
.elem_ptr,
.elem_val,
.elem_ptr_node,
.elem_val_node,
.floatcast,
.field_ptr,
.field_val,
.field_ptr_named,
.field_val_named,
.fn_type,
.fn_type_var_args,
.fn_type_cc,
.fn_type_cc_var_args,
.int,
.intcast,
.int_type,
.is_non_null,
.is_null,
.is_non_null_ptr,
.is_null_ptr,
.is_err,
.is_err_ptr,
.mod_rem,
.mul,
.mulwrap,
.param_type,
.ptrtoint,
.ref,
.ret_ptr,
.ret_type,
.shl,
.shr,
.str,
.sub,
.subwrap,
.negate,
.negate_wrap,
.typeof,
.xor,
.optional_type,
.optional_type_from_ptr_elem,
.optional_payload_safe,
.optional_payload_unsafe,
.optional_payload_safe_ptr,
.optional_payload_unsafe_ptr,
.err_union_payload_safe,
.err_union_payload_unsafe,
.err_union_payload_safe_ptr,
.err_union_payload_unsafe_ptr,
.err_union_code,
.err_union_code_ptr,
.ptr_type,
.ptr_type_simple,
.enum_literal,
.enum_literal_small,
.merge_error_sets,
.error_union_type,
.bit_not,
.error_set,
.error_value,
.slice_start,
.slice_end,
.slice_sentinel,
.import,
.typeof_peer,
=> return false,
.breakpoint,
.dbg_stmt_node,
.ensure_result_used,
.ensure_result_non_error,
.set_eval_branch_quota,
.compile_log,
.ensure_err_payload_void,
.@"break",
.break_void_tok,
.break_flat,
.condbr,
.compile_error,
.ret_node,
.ret_tok,
.ret_coerce,
.@"unreachable",
.loop,
.elided,
.store,
.store_to_block_ptr,
.store_to_inferred_ptr,
.resolve_inferred_alloc,
=> return true,
}
}
return switch (inst_ref) {
@enumToInt(zir.Const.unused) => unreachable,
@enumToInt(zir.Const.void_value), @enumToInt(zir.Const.unreachable_value) => true,
else => false,
};
}
pub fn deinit(wzc: *WipZirCode) void {
wzc.instructions.deinit(wzc.gpa);
wzc.extra.deinit(wzc.gpa);