authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-03-18 14:03:06-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-03-18 14:04:02-07:00
log5e5b35f1077d5cf77a89aee5dde939de35f2e247
treebdc9a4d88d63c21f1d482724291d627eea6a3d73
parenta6f5aa71ac1e8c9a27ecfa6a50f0445a50545a5d

stage1: small memory optimization for simple pointer types

Avoid storing extra IR instruction data for simple pointer types.

4 files changed, 183 insertions(+), 1 deletions(-)

src/stage1/all_types.hpp+17
......@@ -391,6 +391,8 @@ enum LazyValueId {
391391 LazyValueIdAlignOf,
392392 LazyValueIdSizeOf,
393393 LazyValueIdPtrType,
394 LazyValueIdPtrTypeSimple,
395 LazyValueIdPtrTypeSimpleConst,
394396 LazyValueIdOptType,
395397 LazyValueIdSliceType,
396398 LazyValueIdFnType,
......@@ -467,6 +469,13 @@ struct LazyValuePtrType {
467469 bool is_allowzero;
468470};
469471
472struct LazyValuePtrTypeSimple {
473 LazyValue base;
474
475 IrAnalyze *ira;
476 IrInstGen *elem_type;
477};
478
470479struct LazyValueOptType {
471480 LazyValue base;
472481
......@@ -2625,6 +2634,8 @@ enum IrInstSrcId {
26252634 IrInstSrcIdHasField,
26262635 IrInstSrcIdSetEvalBranchQuota,
26272636 IrInstSrcIdPtrType,
2637 IrInstSrcIdPtrTypeSimple,
2638 IrInstSrcIdPtrTypeSimpleConst,
26282639 IrInstSrcIdAlignCast,
26292640 IrInstSrcIdImplicitCast,
26302641 IrInstSrcIdResolveResult,
......@@ -3296,6 +3307,12 @@ struct IrInstSrcArrayType {
32963307 IrInstSrc *child_type;
32973308};
32983309
3310struct IrInstSrcPtrTypeSimple {
3311 IrInstSrc base;
3312
3313 IrInstSrc *child_type;
3314};
3315
32993316struct IrInstSrcPtrType {
33003317 IrInstSrc base;
33013318
src/stage1/analyze.cpp+48-1
......@@ -1237,6 +1237,22 @@ Error type_val_resolve_zero_bits(CodeGen *g, ZigValue *type_val, ZigType *parent
12371237 parent_type_val, is_zero_bits);
12381238 }
12391239 }
1240 case LazyValueIdPtrTypeSimple:
1241 case LazyValueIdPtrTypeSimpleConst: {
1242 LazyValuePtrTypeSimple *lazy_ptr_type = reinterpret_cast<LazyValuePtrTypeSimple *>(type_val->data.x_lazy);
1243
1244 if (parent_type_val == lazy_ptr_type->elem_type->value) {
1245 // Does a struct which contains a pointer field to itself have bits? Yes.
1246 *is_zero_bits = false;
1247 return ErrorNone;
1248 } else {
1249 if (parent_type_val == nullptr) {
1250 parent_type_val = type_val;
1251 }
1252 return type_val_resolve_zero_bits(g, lazy_ptr_type->elem_type->value, parent_type,
1253 parent_type_val, is_zero_bits);
1254 }
1255 }
12401256 case LazyValueIdArrayType: {
12411257 LazyValueArrayType *lazy_array_type =
12421258 reinterpret_cast<LazyValueArrayType *>(type_val->data.x_lazy);
......@@ -1285,6 +1301,8 @@ Error type_val_resolve_is_opaque_type(CodeGen *g, ZigValue *type_val, bool *is_o
12851301 zig_unreachable();
12861302 case LazyValueIdSliceType:
12871303 case LazyValueIdPtrType:
1304 case LazyValueIdPtrTypeSimple:
1305 case LazyValueIdPtrTypeSimpleConst:
12881306 case LazyValueIdFnType:
12891307 case LazyValueIdOptType:
12901308 case LazyValueIdErrUnionType:
......@@ -1313,6 +1331,11 @@ static ReqCompTime type_val_resolve_requires_comptime(CodeGen *g, ZigValue *type
13131331 LazyValuePtrType *lazy_ptr_type = reinterpret_cast<LazyValuePtrType *>(type_val->data.x_lazy);
13141332 return type_val_resolve_requires_comptime(g, lazy_ptr_type->elem_type->value);
13151333 }
1334 case LazyValueIdPtrTypeSimple:
1335 case LazyValueIdPtrTypeSimpleConst: {
1336 LazyValuePtrTypeSimple *lazy_ptr_type = reinterpret_cast<LazyValuePtrTypeSimple *>(type_val->data.x_lazy);
1337 return type_val_resolve_requires_comptime(g, lazy_ptr_type->elem_type->value);
1338 }
13161339 case LazyValueIdOptType: {
13171340 LazyValueOptType *lazy_opt_type = reinterpret_cast<LazyValueOptType *>(type_val->data.x_lazy);
13181341 return type_val_resolve_requires_comptime(g, lazy_opt_type->payload_type->value);
......@@ -1413,6 +1436,24 @@ start_over:
14131436 }
14141437 return ErrorNone;
14151438 }
1439 case LazyValueIdPtrTypeSimple:
1440 case LazyValueIdPtrTypeSimpleConst: {
1441 LazyValuePtrTypeSimple *lazy_ptr_type = reinterpret_cast<LazyValuePtrTypeSimple *>(type_val->data.x_lazy);
1442 bool is_zero_bits;
1443 if ((err = type_val_resolve_zero_bits(g, lazy_ptr_type->elem_type->value, nullptr,
1444 nullptr, &is_zero_bits)))
1445 {
1446 return err;
1447 }
1448 if (is_zero_bits) {
1449 *abi_size = 0;
1450 *size_in_bits = 0;
1451 } else {
1452 *abi_size = g->builtin_types.entry_usize->abi_size;
1453 *size_in_bits = g->builtin_types.entry_usize->size_in_bits;
1454 }
1455 return ErrorNone;
1456 }
14161457 case LazyValueIdFnType:
14171458 *abi_size = g->builtin_types.entry_usize->abi_size;
14181459 *size_in_bits = g->builtin_types.entry_usize->size_in_bits;
......@@ -1449,6 +1490,8 @@ Error type_val_resolve_abi_align(CodeGen *g, AstNode *source_node, ZigValue *typ
14491490 zig_unreachable();
14501491 case LazyValueIdSliceType:
14511492 case LazyValueIdPtrType:
1493 case LazyValueIdPtrTypeSimple:
1494 case LazyValueIdPtrTypeSimpleConst:
14521495 case LazyValueIdFnType:
14531496 *abi_align = g->builtin_types.entry_usize->abi_align;
14541497 return ErrorNone;
......@@ -1506,7 +1549,9 @@ static OnePossibleValue type_val_resolve_has_one_possible_value(CodeGen *g, ZigV
15061549 return OnePossibleValueYes;
15071550 return type_val_resolve_has_one_possible_value(g, lazy_array_type->elem_type->value);
15081551 }
1509 case LazyValueIdPtrType: {
1552 case LazyValueIdPtrType:
1553 case LazyValueIdPtrTypeSimple:
1554 case LazyValueIdPtrTypeSimpleConst: {
15101555 Error err;
15111556 bool zero_bits;
15121557 if ((err = type_val_resolve_zero_bits(g, type_val, nullptr, nullptr, &zero_bits))) {
......@@ -5758,6 +5803,8 @@ static bool can_mutate_comptime_var_state(ZigValue *value) {
57585803 case LazyValueIdAlignOf:
57595804 case LazyValueIdSizeOf:
57605805 case LazyValueIdPtrType:
5806 case LazyValueIdPtrTypeSimple:
5807 case LazyValueIdPtrTypeSimpleConst:
57615808 case LazyValueIdOptType:
57625809 case LazyValueIdSliceType:
57635810 case LazyValueIdFnType:
src/stage1/ir.cpp+99
......@@ -487,6 +487,9 @@ static void destroy_instruction_src(IrInstSrc *inst) {
487487 return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcTagName *>(inst));
488488 case IrInstSrcIdPtrType:
489489 return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcPtrType *>(inst));
490 case IrInstSrcIdPtrTypeSimple:
491 case IrInstSrcIdPtrTypeSimpleConst:
492 return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcPtrTypeSimple *>(inst));
490493 case IrInstSrcIdDeclRef:
491494 return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcDeclRef *>(inst));
492495 case IrInstSrcIdPanic:
......@@ -2609,11 +2612,35 @@ static IrInstGen *ir_build_br_gen(IrAnalyze *ira, IrInst *source_instr, IrBasicB
26092612 return &inst->base;
26102613}
26112614
2615static IrInstSrc *ir_build_ptr_type_simple(IrBuilderSrc *irb, Scope *scope, AstNode *source_node,
2616 IrInstSrc *child_type, bool is_const)
2617{
2618 IrInstSrcPtrTypeSimple *inst = heap::c_allocator.create<IrInstSrcPtrTypeSimple>();
2619 inst->base.id = is_const ? IrInstSrcIdPtrTypeSimpleConst : IrInstSrcIdPtrTypeSimple;
2620 inst->base.base.scope = scope;
2621 inst->base.base.source_node = source_node;
2622 inst->base.base.debug_id = exec_next_debug_id(irb->exec);
2623 inst->base.owner_bb = irb->current_basic_block;
2624 ir_instruction_append(irb->current_basic_block, &inst->base);
2625
2626 inst->child_type = child_type;
2627
2628 ir_ref_instruction(child_type, irb->current_basic_block);
2629
2630 return &inst->base;
2631}
2632
26122633static IrInstSrc *ir_build_ptr_type(IrBuilderSrc *irb, Scope *scope, AstNode *source_node,
26132634 IrInstSrc *child_type, bool is_const, bool is_volatile, PtrLen ptr_len,
26142635 IrInstSrc *sentinel, IrInstSrc *align_value,
26152636 uint32_t bit_offset_start, uint32_t host_int_bytes, bool is_allow_zero)
26162637{
2638 if (!is_volatile && ptr_len == PtrLenSingle && sentinel == nullptr && align_value == nullptr &&
2639 bit_offset_start == 0 && host_int_bytes == 0 && is_allow_zero == 0)
2640 {
2641 return ir_build_ptr_type_simple(irb, scope, source_node, child_type, is_const);
2642 }
2643
26172644 IrInstSrcPtrType *inst = ir_build_instruction<IrInstSrcPtrType>(irb, scope, source_node);
26182645 inst->sentinel = sentinel;
26192646 inst->align_value = align_value;
......@@ -30878,6 +30905,24 @@ static IrInstGen *ir_analyze_instruction_ptr_to_int(IrAnalyze *ira, IrInstSrcPtr
3087830905 return ir_build_ptr_to_int_gen(ira, &instruction->base.base, target);
3087930906}
3088030907
30908static IrInstGen *ir_analyze_instruction_ptr_type_simple(IrAnalyze *ira,
30909 IrInstSrcPtrTypeSimple *instruction, bool is_const)
30910{
30911 IrInstGen *result = ir_const(ira, &instruction->base.base, ira->codegen->builtin_types.entry_type);
30912 result->value->special = ConstValSpecialLazy;
30913
30914 LazyValuePtrTypeSimple *lazy_ptr_type = heap::c_allocator.create<LazyValuePtrTypeSimple>();
30915 lazy_ptr_type->ira = ira; ira_ref(ira);
30916 result->value->data.x_lazy = &lazy_ptr_type->base;
30917 lazy_ptr_type->base.id = is_const ? LazyValueIdPtrTypeSimpleConst : LazyValueIdPtrTypeSimple;
30918
30919 lazy_ptr_type->elem_type = instruction->child_type->child;
30920 if (ir_resolve_type_lazy(ira, lazy_ptr_type->elem_type) == nullptr)
30921 return ira->codegen->invalid_inst_gen;
30922
30923 return result;
30924}
30925
3088130926static IrInstGen *ir_analyze_instruction_ptr_type(IrAnalyze *ira, IrInstSrcPtrType *instruction) {
3088230927 IrInstGen *result = ir_const(ira, &instruction->base.base, ira->codegen->builtin_types.entry_type);
3088330928 result->value->special = ConstValSpecialLazy;
......@@ -32384,6 +32429,10 @@ static IrInstGen *ir_analyze_instruction_base(IrAnalyze *ira, IrInstSrc *instruc
3238432429 return ir_analyze_instruction_set_eval_branch_quota(ira, (IrInstSrcSetEvalBranchQuota *)instruction);
3238532430 case IrInstSrcIdPtrType:
3238632431 return ir_analyze_instruction_ptr_type(ira, (IrInstSrcPtrType *)instruction);
32432 case IrInstSrcIdPtrTypeSimple:
32433 return ir_analyze_instruction_ptr_type_simple(ira, (IrInstSrcPtrTypeSimple *)instruction, false);
32434 case IrInstSrcIdPtrTypeSimpleConst:
32435 return ir_analyze_instruction_ptr_type_simple(ira, (IrInstSrcPtrTypeSimple *)instruction, true);
3238732436 case IrInstSrcIdAlignCast:
3238832437 return ir_analyze_instruction_align_cast(ira, (IrInstSrcAlignCast *)instruction);
3238932438 case IrInstSrcIdImplicitCast:
......@@ -32757,6 +32806,8 @@ bool ir_inst_src_has_side_effects(IrInstSrc *instruction) {
3275732806 case IrInstSrcIdPanic:
3275832807 case IrInstSrcIdSetEvalBranchQuota:
3275932808 case IrInstSrcIdPtrType:
32809 case IrInstSrcIdPtrTypeSimple:
32810 case IrInstSrcIdPtrTypeSimpleConst:
3276032811 case IrInstSrcIdSetAlignStack:
3276132812 case IrInstSrcIdExport:
3276232813 case IrInstSrcIdExtern:
......@@ -33264,6 +33315,54 @@ static Error ir_resolve_lazy_raw(AstNode *source_node, ZigValue *val) {
3326433315 // We can't free the lazy value here, because multiple other ZigValues might be pointing to it.
3326533316 return ErrorNone;
3326633317 }
33318 case LazyValueIdPtrTypeSimple: {
33319 LazyValuePtrTypeSimple *lazy_ptr_type = reinterpret_cast<LazyValuePtrTypeSimple *>(val->data.x_lazy);
33320 IrAnalyze *ira = lazy_ptr_type->ira;
33321
33322 ZigType *elem_type = ir_resolve_type(ira, lazy_ptr_type->elem_type);
33323 if (type_is_invalid(elem_type))
33324 return ErrorSemanticAnalyzeFail;
33325
33326 if (elem_type->id == ZigTypeIdUnreachable) {
33327 ir_add_error(ira, &lazy_ptr_type->elem_type->base,
33328 buf_create_from_str("pointer to noreturn not allowed"));
33329 return ErrorSemanticAnalyzeFail;
33330 }
33331
33332 assert(val->type->id == ZigTypeIdMetaType);
33333 val->data.x_type = get_pointer_to_type_extra2(ira->codegen, elem_type,
33334 false, false, PtrLenSingle, 0,
33335 0, 0,
33336 false, VECTOR_INDEX_NONE, nullptr, nullptr);
33337 val->special = ConstValSpecialStatic;
33338
33339 // We can't free the lazy value here, because multiple other ZigValues might be pointing to it.
33340 return ErrorNone;
33341 }
33342 case LazyValueIdPtrTypeSimpleConst: {
33343 LazyValuePtrTypeSimple *lazy_ptr_type = reinterpret_cast<LazyValuePtrTypeSimple *>(val->data.x_lazy);
33344 IrAnalyze *ira = lazy_ptr_type->ira;
33345
33346 ZigType *elem_type = ir_resolve_type(ira, lazy_ptr_type->elem_type);
33347 if (type_is_invalid(elem_type))
33348 return ErrorSemanticAnalyzeFail;
33349
33350 if (elem_type->id == ZigTypeIdUnreachable) {
33351 ir_add_error(ira, &lazy_ptr_type->elem_type->base,
33352 buf_create_from_str("pointer to noreturn not allowed"));
33353 return ErrorSemanticAnalyzeFail;
33354 }
33355
33356 assert(val->type->id == ZigTypeIdMetaType);
33357 val->data.x_type = get_pointer_to_type_extra2(ira->codegen, elem_type,
33358 true, false, PtrLenSingle, 0,
33359 0, 0,
33360 false, VECTOR_INDEX_NONE, nullptr, nullptr);
33361 val->special = ConstValSpecialStatic;
33362
33363 // We can't free the lazy value here, because multiple other ZigValues might be pointing to it.
33364 return ErrorNone;
33365 }
3326733366 case LazyValueIdArrayType: {
3326833367 LazyValueArrayType *lazy_array_type = reinterpret_cast<LazyValueArrayType *>(val->data.x_lazy);
3326933368 IrAnalyze *ira = lazy_array_type->ira;
src/stage1/ir_print.cpp+19
......@@ -300,6 +300,10 @@ const char* ir_inst_src_type_str(IrInstSrcId id) {
300300 return "SrcSetEvalBranchQuota";
301301 case IrInstSrcIdPtrType:
302302 return "SrcPtrType";
303 case IrInstSrcIdPtrTypeSimple:
304 return "SrcPtrTypeSimple";
305 case IrInstSrcIdPtrTypeSimpleConst:
306 return "SrcPtrTypeSimpleConst";
303307 case IrInstSrcIdAlignCast:
304308 return "SrcAlignCast";
305309 case IrInstSrcIdImplicitCast:
......@@ -2245,6 +2249,15 @@ static void ir_print_ptr_type(IrPrintSrc *irp, IrInstSrcPtrType *instruction) {
22452249 ir_print_other_inst_src(irp, instruction->child_type);
22462250}
22472251
2252static void ir_print_ptr_type_simple(IrPrintSrc *irp, IrInstSrcPtrTypeSimple *instruction,
2253 bool is_const)
2254{
2255 fprintf(irp->f, "&");
2256 const char *const_str = is_const ? "const " : "";
2257 fprintf(irp->f, "*%s", const_str);
2258 ir_print_other_inst_src(irp, instruction->child_type);
2259}
2260
22482261static void ir_print_decl_ref(IrPrintSrc *irp, IrInstSrcDeclRef *instruction) {
22492262 const char *ptr_str = (instruction->lval != LValNone) ? "ptr " : "";
22502263 fprintf(irp->f, "declref %s%s", ptr_str, buf_ptr(instruction->tld->name));
......@@ -2917,6 +2930,12 @@ static void ir_print_inst_src(IrPrintSrc *irp, IrInstSrc *instruction, bool trai
29172930 case IrInstSrcIdPtrType:
29182931 ir_print_ptr_type(irp, (IrInstSrcPtrType *)instruction);
29192932 break;
2933 case IrInstSrcIdPtrTypeSimple:
2934 ir_print_ptr_type_simple(irp, (IrInstSrcPtrTypeSimple *)instruction, false);
2935 break;
2936 case IrInstSrcIdPtrTypeSimpleConst:
2937 ir_print_ptr_type_simple(irp, (IrInstSrcPtrTypeSimple *)instruction, true);
2938 break;
29202939 case IrInstSrcIdDeclRef:
29212940 ir_print_decl_ref(irp, (IrInstSrcDeclRef *)instruction);
29222941 break;