diff options
| author | gingerBill <bill@gingerbill.org> | 2021-06-09 23:05:37 +0100 |
|---|---|---|
| committer | gingerBill <bill@gingerbill.org> | 2021-06-09 23:05:37 +0100 |
| commit | b0e21bd616d6111e301378475f493ddf9c75391f (patch) | |
| tree | a133a755729ff95c31115a862bbc6b6452db9942 /src/llvm_backend.cpp | |
| parent | 7b88bed098397b73bce8bf1202b61012f3efda21 (diff) | |
Allow trivial optimizations for switch statements of `typeid`
Diffstat (limited to 'src/llvm_backend.cpp')
| -rw-r--r-- | src/llvm_backend.cpp | 30 |
1 files changed, 21 insertions, 9 deletions
diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index 7a79857bd..0d79be730 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -4730,8 +4730,14 @@ bool lb_switch_stmt_can_be_trivial_jump_table(AstSwitchStmt *ss, bool *default_f if (ss->tag == nullptr) { return false; } + bool is_typeid = false; TypeAndValue tv = type_and_value_of_expr(ss->tag); - if (!is_type_integer(core_type(tv.type))) { + if (is_type_integer(core_type(tv.type))) { + // okay + } else if (is_type_typeid(tv.type)) { + // okay + is_typeid = true; + } else { return false; } @@ -4751,7 +4757,8 @@ bool lb_switch_stmt_can_be_trivial_jump_table(AstSwitchStmt *ss, bool *default_f return false; } if (expr->tav.mode == Addressing_Type) { - return false; + GB_ASSERT(is_typeid); + continue; } tv = type_and_value_of_expr(expr); if (tv.mode != Addressing_Constant) { @@ -4780,18 +4787,14 @@ void lb_build_switch_stmt(lbProcedure *p, AstSwitchStmt *ss, Scope *scope) { } lbBlock *done = lb_create_block(p, "switch.done"); // NOTE(bill): Append later - ast_node(body, BlockStmt, ss->body); - isize case_count = body->stmts.count; Slice<Ast *> default_stmts = {}; lbBlock *default_fall = nullptr; lbBlock *default_block = nullptr; - lbBlock *fall = nullptr; - bool default_found = false; bool is_trivial = lb_switch_stmt_can_be_trivial_jump_table(ss, &default_found); @@ -4815,6 +4818,7 @@ void lb_build_switch_stmt(lbProcedure *p, AstSwitchStmt *ss, Scope *scope) { switch_instr = LLVMBuildSwitch(p->builder, tag.value, end_block, cast(unsigned)num_cases); } + for_array(i, body->stmts) { Ast *clause = body->stmts[i]; ast_node(cc, CaseClause, clause); @@ -4847,10 +4851,18 @@ void lb_build_switch_stmt(lbProcedure *p, AstSwitchStmt *ss, Scope *scope) { Ast *expr = unparen_expr(cc->list[j]); if (switch_instr != nullptr) { - GB_ASSERT(expr->tav.mode == Addressing_Constant); - GB_ASSERT(!is_ast_range(expr)); + lbValue on_val = {}; + if (expr->tav.mode == Addressing_Type) { + GB_ASSERT(is_type_typeid(tag.type)); + lbValue e = lb_typeid(p->module, expr->tav.type); + on_val = lb_emit_conv(p, e, tag.type); + } else { + GB_ASSERT(expr->tav.mode == Addressing_Constant); + GB_ASSERT(!is_ast_range(expr)); + + on_val = lb_build_expr(p, expr); + } - lbValue on_val = lb_build_expr(p, expr); GB_ASSERT(LLVMIsConstant(on_val.value)); LLVMAddCase(switch_instr, on_val.value, body->block); continue; |