From 253f2bd7be39e201db78960be456ac0f8c61b05f Mon Sep 17 00:00:00 2001 From: Damien George Date: Sun, 4 Feb 2018 13:35:21 +1100 Subject: [PATCH] py/compile: Combine compiler-opt of 2 and 3 tuple-to-tuple assignment. This patch combines the compiler optimisation code for double and triple tuple-to-tuple assignment, taking it from two separate if-blocks to one combined if-block. This can be done because the code for both of these optimisations has a lot in common. Combining them together reduces code size for ports that have the triple-tuple optimisation enabled (and doesn't change code size for ports that have it disabled). --- py/compile.c | 85 ++++++++++++++++++++++++++------------------------- py/mpconfig.h | 2 +- 2 files changed, 44 insertions(+), 43 deletions(-) diff --git a/py/compile.c b/py/compile.c index 52d10ee5e..42ae8a829 100644 --- a/py/compile.c +++ b/py/compile.c @@ -1941,51 +1941,52 @@ STATIC void compile_expr_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { } } else { plain_assign: - if (MICROPY_COMP_DOUBLE_TUPLE_ASSIGN - && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_testlist_star_expr) - && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_star_expr) - && MP_PARSE_NODE_STRUCT_NUM_NODES((mp_parse_node_struct_t*)pns->nodes[1]) == 2 - && MP_PARSE_NODE_STRUCT_NUM_NODES((mp_parse_node_struct_t*)pns->nodes[0]) == 2) { - // optimisation for a, b = c, d - mp_parse_node_struct_t *pns10 = (mp_parse_node_struct_t*)pns->nodes[1]; + #if MICROPY_COMP_DOUBLE_TUPLE_ASSIGN + if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_testlist_star_expr) + && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_star_expr)) { mp_parse_node_struct_t *pns0 = (mp_parse_node_struct_t*)pns->nodes[0]; - if (MP_PARSE_NODE_IS_STRUCT_KIND(pns0->nodes[0], PN_star_expr) - || MP_PARSE_NODE_IS_STRUCT_KIND(pns0->nodes[1], PN_star_expr)) { - // can't optimise when it's a star expression on the lhs - goto no_optimisation; + pns1 = (mp_parse_node_struct_t*)pns->nodes[1]; + uint32_t n_pns0 = MP_PARSE_NODE_STRUCT_NUM_NODES(pns0); + // Can only optimise a tuple-to-tuple assignment when all of the following hold: + // - equal number of items in LHS and RHS tuples + // - 2 or 3 items in the tuples + // - there are no star expressions in the LHS tuple + if (n_pns0 == MP_PARSE_NODE_STRUCT_NUM_NODES(pns1) + && (n_pns0 == 2 + #if MICROPY_COMP_TRIPLE_TUPLE_ASSIGN + || n_pns0 == 3 + #endif + ) + && !MP_PARSE_NODE_IS_STRUCT_KIND(pns0->nodes[0], PN_star_expr) + && !MP_PARSE_NODE_IS_STRUCT_KIND(pns0->nodes[1], PN_star_expr) + #if MICROPY_COMP_TRIPLE_TUPLE_ASSIGN + && (n_pns0 == 2 || !MP_PARSE_NODE_IS_STRUCT_KIND(pns0->nodes[2], PN_star_expr)) + #endif + ) { + // Optimisation for a, b = c, d or a, b, c = d, e, f + compile_node(comp, pns1->nodes[0]); // rhs + compile_node(comp, pns1->nodes[1]); // rhs + #if MICROPY_COMP_TRIPLE_TUPLE_ASSIGN + if (n_pns0 == 3) { + compile_node(comp, pns1->nodes[2]); // rhs + EMIT(rot_three); + } + #endif + EMIT(rot_two); + c_assign(comp, pns0->nodes[0], ASSIGN_STORE); // lhs store + c_assign(comp, pns0->nodes[1], ASSIGN_STORE); // lhs store + #if MICROPY_COMP_TRIPLE_TUPLE_ASSIGN + if (n_pns0 == 3) { + c_assign(comp, pns0->nodes[2], ASSIGN_STORE); // lhs store + } + #endif + return; } - compile_node(comp, pns10->nodes[0]); // rhs - compile_node(comp, pns10->nodes[1]); // rhs - EMIT(rot_two); - c_assign(comp, pns0->nodes[0], ASSIGN_STORE); // lhs store - c_assign(comp, pns0->nodes[1], ASSIGN_STORE); // lhs store - } else if (MICROPY_COMP_TRIPLE_TUPLE_ASSIGN - && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_testlist_star_expr) - && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_star_expr) - && MP_PARSE_NODE_STRUCT_NUM_NODES((mp_parse_node_struct_t*)pns->nodes[1]) == 3 - && MP_PARSE_NODE_STRUCT_NUM_NODES((mp_parse_node_struct_t*)pns->nodes[0]) == 3) { - // optimisation for a, b, c = d, e, f - mp_parse_node_struct_t *pns10 = (mp_parse_node_struct_t*)pns->nodes[1]; - mp_parse_node_struct_t *pns0 = (mp_parse_node_struct_t*)pns->nodes[0]; - if (MP_PARSE_NODE_IS_STRUCT_KIND(pns0->nodes[0], PN_star_expr) - || MP_PARSE_NODE_IS_STRUCT_KIND(pns0->nodes[1], PN_star_expr) - || MP_PARSE_NODE_IS_STRUCT_KIND(pns0->nodes[2], PN_star_expr)) { - // can't optimise when it's a star expression on the lhs - goto no_optimisation; - } - compile_node(comp, pns10->nodes[0]); // rhs - compile_node(comp, pns10->nodes[1]); // rhs - compile_node(comp, pns10->nodes[2]); // rhs - EMIT(rot_three); - EMIT(rot_two); - c_assign(comp, pns0->nodes[0], ASSIGN_STORE); // lhs store - c_assign(comp, pns0->nodes[1], ASSIGN_STORE); // lhs store - c_assign(comp, pns0->nodes[2], ASSIGN_STORE); // lhs store - } else { - no_optimisation: - compile_node(comp, pns->nodes[1]); // rhs - c_assign(comp, pns->nodes[0], ASSIGN_STORE); // lhs store } + #endif + + compile_node(comp, pns->nodes[1]); // rhs + c_assign(comp, pns->nodes[0], ASSIGN_STORE); // lhs store } } else { goto plain_assign; diff --git a/py/mpconfig.h b/py/mpconfig.h index 763bb378e..f2a8c98cb 100644 --- a/py/mpconfig.h +++ b/py/mpconfig.h @@ -347,7 +347,7 @@ #endif // Whether to enable optimisation of: a, b, c = d, e, f -// Cost 156 bytes (Thumb2) +// Requires MICROPY_COMP_DOUBLE_TUPLE_ASSIGN and costs 68 bytes (Thumb2) #ifndef MICROPY_COMP_TRIPLE_TUPLE_ASSIGN #define MICROPY_COMP_TRIPLE_TUPLE_ASSIGN (0) #endif