authorgravatar for thejoshwolfe@gmail.comJosh Wolfe <thejoshwolfe@gmail.com> 2017-09-20 18:37:36-07:00
committergravatar for thejoshwolfe@gmail.comJosh Wolfe <thejoshwolfe@gmail.com> 2017-09-20 18:37:36-07:00
loge2f8bec7ac1834c6d6db73f0089483295298c8af
tree6ab350a362740ea5984f46a5d373a66e69d8279d
parent0228f8c9fd848ec86aa188229ee82dfb0698ae0d

optimize >>= operator for common case


1 files changed, 64 insertions(+), 48 deletions(-)

src/parsec.cpp+64-48
......@@ -987,59 +987,75 @@ static AstNode *trans_compound_assign_operator(Context *c, bool result_used, Ast
987987 return nullptr;
988988 case BO_ShrAssign: {
989989 BinOpType bin_op = BinOpTypeBitShiftRight;
990 // c: lhs >>= rhs;
991 // zig: {
992 // zig: const _ref = &lhs;
993 // zig: *_ref = result_type(operation_type(*_ref) >> u5(rhs));
994 // zig: *_ref
995 // zig: };
996 // where u5 is the appropriate type
997
998 // TODO: avoid mess when we don't need the assignment value for chained assignments or anything.
999 AstNode *child_block = trans_create_node(c, NodeTypeBlock);
1000
1001 // const _ref = &lhs;
1002 AstNode *lhs = trans_expr(c, true, child_block, stmt->getLHS(), TransLValue);
1003 if (lhs == nullptr) return nullptr;
1004 AstNode *addr_of_lhs = trans_create_node_addr_of(c, false, false, lhs);
1005 // TODO: avoid name collisions with generated variable names
1006 Buf* tmp_var_name = buf_create_from_str("_ref");
1007 AstNode *tmp_var_decl = trans_create_node_var_decl_local(c, true, tmp_var_name, nullptr, addr_of_lhs);
1008 child_block->data.block.statements.append(tmp_var_decl);
1009
1010 // *_ref = result_type(operation_type(*_ref) >> u5(rhs));
1011
1012 AstNode *rhs = trans_expr(c, true, child_block, stmt->getRHS(), TransRValue);
1013 if (rhs == nullptr) return nullptr;
990
1014991 const SourceLocation &rhs_location = stmt->getRHS()->getLocStart();
1015992 AstNode *rhs_type = qual_type_to_log2_int_ref(c, stmt->getComputationLHSType(), rhs_location);
1016993
1017 AstNode *assign_statement = trans_create_node_bin_op(c,
1018 trans_create_node_prefix_op(c, PrefixOpDereference,
1019 trans_create_node_symbol(c, tmp_var_name)),
1020 BinOpTypeAssign,
1021 trans_c_cast(c, rhs_location,
1022 stmt->getComputationResultType(),
1023 trans_create_node_bin_op(c,
1024 trans_c_cast(c, rhs_location,
1025 stmt->getComputationLHSType(),
1026 trans_create_node_prefix_op(c, PrefixOpDereference,
1027 trans_create_node_symbol(c, tmp_var_name))),
1028 bin_op,
1029 trans_create_node_fn_call_1(c,
1030 rhs_type,
1031 rhs))));
1032 child_block->data.block.statements.append(assign_statement);
1033
1034 if (result_used) {
1035 // *_ref
1036 child_block->data.block.statements.append(
994 bool use_intermediate_casts = stmt->getComputationLHSType().getTypePtr() != stmt->getComputationResultType().getTypePtr();
995 if (!use_intermediate_casts && !result_used) {
996 // simple common case, where the C and Zig are identical:
997 // lhs >>= rh* s
998 AstNode *lhs = trans_expr(c, true, block, stmt->getLHS(), TransLValue);
999 if (lhs == nullptr) return nullptr;
1000
1001 AstNode *rhs = trans_expr(c, true, block, stmt->getRHS(), TransRValue);
1002 if (rhs == nullptr) return nullptr;
1003 AstNode *coerced_rhs = trans_create_node_fn_call_1(c, rhs_type, rhs);
1004
1005 return trans_create_node_bin_op(c, lhs, BinOpTypeAssignBitShiftRight, coerced_rhs);
1006 } else {
1007 // need more complexity. worst case, this looks like this:
1008 // c: lhs >>= rhs
1009 // zig: {
1010 // zig: const _ref = &lhs;
1011 // zig: *_ref = result_type(operation_type(*_ref) >> u5(rhs));
1012 // zig: *_ref
1013 // zig: }
1014 // where u5 is the appropriate type
1015
1016 // TODO: avoid mess when we don't need the assignment value for chained assignments or anything.
1017 AstNode *child_block = trans_create_node(c, NodeTypeBlock);
1018
1019 // const _ref = &lhs;
1020 AstNode *lhs = trans_expr(c, true, child_block, stmt->getLHS(), TransLValue);
1021 if (lhs == nullptr) return nullptr;
1022 AstNode *addr_of_lhs = trans_create_node_addr_of(c, false, false, lhs);
1023 // TODO: avoid name collisions with generated variable names
1024 Buf* tmp_var_name = buf_create_from_str("_ref");
1025 AstNode *tmp_var_decl = trans_create_node_var_decl_local(c, true, tmp_var_name, nullptr, addr_of_lhs);
1026 child_block->data.block.statements.append(tmp_var_decl);
1027
1028 // *_ref = result_type(operation_type(*_ref) >> u5(rhs));
1029
1030 AstNode *rhs = trans_expr(c, true, child_block, stmt->getRHS(), TransRValue);
1031 if (rhs == nullptr) return nullptr;
1032 AstNode *coerced_rhs = trans_create_node_fn_call_1(c, rhs_type, rhs);
1033
1034 AstNode *assign_statement = trans_create_node_bin_op(c,
10371035 trans_create_node_prefix_op(c, PrefixOpDereference,
1038 trans_create_node_symbol(c, tmp_var_name)));
1039 child_block->data.block.last_statement_is_result_expression = true;
1040 }
1036 trans_create_node_symbol(c, tmp_var_name)),
1037 BinOpTypeAssign,
1038 trans_c_cast(c, rhs_location,
1039 stmt->getComputationResultType(),
1040 trans_create_node_bin_op(c,
1041 trans_c_cast(c, rhs_location,
1042 stmt->getComputationLHSType(),
1043 trans_create_node_prefix_op(c, PrefixOpDereference,
1044 trans_create_node_symbol(c, tmp_var_name))),
1045 bin_op,
1046 coerced_rhs)));
1047 child_block->data.block.statements.append(assign_statement);
1048
1049 if (result_used) {
1050 // *_ref
1051 child_block->data.block.statements.append(
1052 trans_create_node_prefix_op(c, PrefixOpDereference,
1053 trans_create_node_symbol(c, tmp_var_name)));
1054 child_block->data.block.last_statement_is_result_expression = true;
1055 }
10411056
1042 return child_block;
1057 return child_block;
1058 }
10431059 }
10441060 case BO_AndAssign:
10451061 emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_AndAssign");