diff --git a/mypyc/ir/rtypes.py b/mypyc/ir/rtypes.py index fe5abe4fb1b9..3438ea76c2d1 100644 --- a/mypyc/ir/rtypes.py +++ b/mypyc/ir/rtypes.py @@ -681,3 +681,21 @@ def is_optional_type(rtype: RType) -> bool: name='PyVarObject', names=['ob_base', 'ob_size'], types=[PyObject, c_pyssize_t_rprimitive]) + +setentry = RStruct( + name='setentry', + names=['key', 'hash'], + types=[pointer_rprimitive, c_pyssize_t_rprimitive]) + +smalltable = RStruct( + name='smalltable', + names=[], + types=[setentry] * 8) + +PySetObject = RStruct( + name='PySetObject', + names=['ob_base', 'fill', 'used', 'mask', 'table', 'hash', 'finger', + 'smalltable', 'weakreflist'], + types=[PyObject, c_pyssize_t_rprimitive, c_pyssize_t_rprimitive, c_pyssize_t_rprimitive, + pointer_rprimitive, c_pyssize_t_rprimitive, c_pyssize_t_rprimitive, smalltable, + pointer_rprimitive]) diff --git a/mypyc/irbuild/builder.py b/mypyc/irbuild/builder.py index 53bd50f2a845..e770a31ba85b 100644 --- a/mypyc/irbuild/builder.py +++ b/mypyc/irbuild/builder.py @@ -238,8 +238,8 @@ def binary_int_op(self, type: RType, lhs: Value, rhs: Value, op: int, line: int) def compare_tagged(self, lhs: Value, rhs: Value, op: str, line: int) -> Value: return self.builder.compare_tagged(lhs, rhs, op, line) - def list_len(self, val: Value, line: int) -> Value: - return self.builder.list_len(val, line) + def builtin_len(self, val: Value, line: int) -> Value: + return self.builder.builtin_len(val, line) @property def environment(self) -> Environment: @@ -511,7 +511,7 @@ def process_iterator_tuple_assignment(self, if target.star_idx is not None: post_star_vals = target.items[split_idx + 1:] iter_list = self.call_c(to_list, [iterator], line) - iter_list_len = self.list_len(iter_list, line) + iter_list_len = self.builtin_len(iter_list, line) post_star_len = self.add(LoadInt(len(post_star_vals))) condition = self.binary_op(post_star_len, iter_list_len, '<=', line) diff --git a/mypyc/irbuild/for_helpers.py b/mypyc/irbuild/for_helpers.py index a1e3583aa1d0..7b3aa0dc952a 100644 --- a/mypyc/irbuild/for_helpers.py +++ b/mypyc/irbuild/for_helpers.py @@ -332,14 +332,7 @@ def gen_cleanup(self) -> None: def load_len(self, expr: Union[Value, AssignmentTarget]) -> Value: """A helper to get collection length, used by several subclasses.""" - val = self.builder.read(expr, self.line) - if is_list_rprimitive(val.type): - return self.builder.builder.list_len(self.builder.read(expr, self.line), self.line) - return self.builder.builder.builtin_call( - [self.builder.read(expr, self.line)], - 'builtins.len', - self.line, - ) + return self.builder.builder.builtin_len(self.builder.read(expr, self.line), self.line) class ForIterable(ForGenerator): diff --git a/mypyc/irbuild/ll_builder.py b/mypyc/irbuild/ll_builder.py index 216f3f582a96..43766f988f5f 100644 --- a/mypyc/irbuild/ll_builder.py +++ b/mypyc/irbuild/ll_builder.py @@ -27,7 +27,8 @@ from mypyc.ir.rtypes import ( RType, RUnion, RInstance, optional_value_type, int_rprimitive, float_rprimitive, bool_rprimitive, list_rprimitive, str_rprimitive, is_none_rprimitive, object_rprimitive, - c_pyssize_t_rprimitive, is_short_int_rprimitive, is_tagged, PyVarObject, short_int_rprimitive + c_pyssize_t_rprimitive, is_short_int_rprimitive, is_tagged, PyVarObject, short_int_rprimitive, + is_list_rprimitive, is_tuple_rprimitive, is_dict_rprimitive, is_set_rprimitive, PySetObject ) from mypyc.ir.func_ir import FuncDecl, FuncSignature from mypyc.ir.class_ir import ClassIR, all_concrete_classes @@ -45,10 +46,10 @@ ) from mypyc.primitives.tuple_ops import list_tuple_op, new_tuple_op from mypyc.primitives.dict_ops import ( - dict_update_in_display_op, dict_new_op, dict_build_op + dict_update_in_display_op, dict_new_op, dict_build_op, dict_size_op ) from mypyc.primitives.generic_ops import ( - py_getattr_op, py_call_op, py_call_with_kwargs_op, py_method_call_op + py_getattr_op, py_call_op, py_call_with_kwargs_op, py_method_call_op, generic_len_op ) from mypyc.primitives.misc_ops import ( none_op, none_object_op, false_op, fast_isinstance_op, bool_op, type_is_op @@ -704,7 +705,7 @@ def add_bool_branch(self, value: Value, true: BasicBlock, false: BasicBlock) -> zero = self.add(LoadInt(0)) value = self.binary_op(value, zero, '!=', value.line) elif is_same_type(value.type, list_rprimitive): - length = self.list_len(value, value.line) + length = self.builtin_len(value, value.line) zero = self.add(LoadInt(0)) value = self.binary_op(length, zero, '!=', value.line) elif (isinstance(value.type, RInstance) and value.type.class_ir.is_ext_class @@ -811,12 +812,29 @@ def matching_call_c(self, def binary_int_op(self, type: RType, lhs: Value, rhs: Value, op: int, line: int) -> Value: return self.add(BinaryIntOp(type, lhs, rhs, op, line)) - def list_len(self, val: Value, line: int) -> Value: - elem_address = self.add(GetElementPtr(val, PyVarObject, 'ob_size')) - size_value = self.add(LoadMem(c_pyssize_t_rprimitive, elem_address)) - offset = self.add(LoadInt(1, -1, rtype=c_pyssize_t_rprimitive)) - return self.binary_int_op(short_int_rprimitive, size_value, offset, - BinaryIntOp.LEFT_SHIFT, -1) + def builtin_len(self, val: Value, line: int) -> Value: + typ = val.type + if is_list_rprimitive(typ) or is_tuple_rprimitive(typ): + elem_address = self.add(GetElementPtr(val, PyVarObject, 'ob_size')) + size_value = self.add(LoadMem(c_pyssize_t_rprimitive, elem_address)) + offset = self.add(LoadInt(1, line, rtype=c_pyssize_t_rprimitive)) + return self.binary_int_op(short_int_rprimitive, size_value, offset, + BinaryIntOp.LEFT_SHIFT, line) + elif is_dict_rprimitive(typ): + size_value = self.call_c(dict_size_op, [val], line) + offset = self.add(LoadInt(1, line, rtype=c_pyssize_t_rprimitive)) + return self.binary_int_op(short_int_rprimitive, size_value, offset, + BinaryIntOp.LEFT_SHIFT, line) + elif is_set_rprimitive(typ): + elem_address = self.add(GetElementPtr(val, PySetObject, 'used')) + size_value = self.add(LoadMem(c_pyssize_t_rprimitive, elem_address)) + offset = self.add(LoadInt(1, line, rtype=c_pyssize_t_rprimitive)) + return self.binary_int_op(short_int_rprimitive, size_value, offset, + BinaryIntOp.LEFT_SHIFT, line) + # generic case + else: + return self.call_c(generic_len_op, [val], line) + # Internal helpers def decompose_union_helper(self, diff --git a/mypyc/irbuild/specialize.py b/mypyc/irbuild/specialize.py index bb6b146f413e..f99798db1aea 100644 --- a/mypyc/irbuild/specialize.py +++ b/mypyc/irbuild/specialize.py @@ -22,7 +22,7 @@ ) from mypyc.ir.rtypes import ( RType, RTuple, str_rprimitive, list_rprimitive, dict_rprimitive, set_rprimitive, - bool_rprimitive, is_dict_rprimitive, is_list_rprimitive, + bool_rprimitive, is_dict_rprimitive ) from mypyc.primitives.dict_ops import dict_keys_op, dict_values_op, dict_items_op from mypyc.primitives.misc_ops import true_op, false_op @@ -75,9 +75,9 @@ def translate_len( # though we still need to evaluate it. builder.accept(expr.args[0]) return builder.add(LoadInt(len(expr_rtype.types))) - elif is_list_rprimitive(expr_rtype): + else: obj = builder.accept(expr.args[0]) - return builder.list_len(obj, -1) + return builder.builtin_len(obj, -1) return None diff --git a/mypyc/primitives/dict_ops.py b/mypyc/primitives/dict_ops.py index 47a2712709c1..04cea8a7e0f0 100644 --- a/mypyc/primitives/dict_ops.py +++ b/mypyc/primitives/dict_ops.py @@ -1,8 +1,6 @@ """Primitive dict ops.""" -from typing import List - -from mypyc.ir.ops import EmitterInterface, ERR_FALSE, ERR_MAGIC, ERR_NEVER, ERR_NEG_INT +from mypyc.ir.ops import ERR_FALSE, ERR_MAGIC, ERR_NEVER, ERR_NEG_INT from mypyc.ir.rtypes import ( dict_rprimitive, object_rprimitive, bool_rprimitive, int_rprimitive, list_rprimitive, dict_next_rtuple_single, dict_next_rtuple_pair, c_pyssize_t_rprimitive, @@ -10,7 +8,7 @@ ) from mypyc.primitives.registry import ( - name_ref_op, method_op, func_op, + name_ref_op, method_op, simple_emit, name_emit, c_custom_op, c_method_op, c_function_op, c_binary_op ) @@ -168,21 +166,6 @@ c_function_name='CPyDict_Items', error_kind=ERR_MAGIC) - -def emit_len(emitter: EmitterInterface, args: List[str], dest: str) -> None: - temp = emitter.temp_name() - emitter.emit_declaration('Py_ssize_t %s;' % temp) - emitter.emit_line('%s = PyDict_Size(%s);' % (temp, args[0])) - emitter.emit_line('%s = CPyTagged_ShortFromSsize_t(%s);' % (dest, temp)) - - -# len(dict) -func_op(name='builtins.len', - arg_types=[dict_rprimitive], - result_type=int_rprimitive, - error_kind=ERR_NEVER, - emit=emit_len) - # PyDict_Next() fast iteration dict_key_iter_op = c_custom_op( arg_types=[dict_rprimitive], @@ -226,3 +209,9 @@ def emit_len(emitter: EmitterInterface, args: List[str], dest: str) -> None: return_type=bool_rprimitive, c_function_name='CPyDict_CheckSize', error_kind=ERR_FALSE) + +dict_size_op = c_custom_op( + arg_types=[dict_rprimitive], + return_type=c_pyssize_t_rprimitive, + c_function_name='PyDict_Size', + error_kind=ERR_NEVER) diff --git a/mypyc/primitives/generic_ops.py b/mypyc/primitives/generic_ops.py index 39d8f6cd279f..21ca44c12f5d 100644 --- a/mypyc/primitives/generic_ops.py +++ b/mypyc/primitives/generic_ops.py @@ -12,7 +12,7 @@ from mypyc.ir.ops import ERR_NEVER, ERR_MAGIC, ERR_NEG_INT from mypyc.ir.rtypes import object_rprimitive, int_rprimitive, bool_rprimitive, c_int_rprimitive from mypyc.primitives.registry import ( - binary_op, unary_op, func_op, custom_op, call_emit, simple_emit, + binary_op, unary_op, custom_op, call_emit, simple_emit, call_negative_magic_emit, negative_int_emit, c_binary_op, c_unary_op, c_method_op, c_function_op, c_custom_op ) @@ -226,12 +226,11 @@ emit=simple_emit('{dest} = CPyObject_CallMethodObjArgs({comma_args}, NULL);')) # len(obj) -func_op(name='builtins.len', - arg_types=[object_rprimitive], - result_type=int_rprimitive, - error_kind=ERR_NEVER, - emit=call_emit('CPyObject_Size'), - priority=0) +generic_len_op = c_custom_op( + arg_types=[object_rprimitive], + return_type=int_rprimitive, + c_function_name='CPyObject_Size', + error_kind=ERR_NEVER) # iter(obj) iter_op = c_function_op(name='builtins.iter', diff --git a/mypyc/primitives/set_ops.py b/mypyc/primitives/set_ops.py index fd929829b2ed..51c100ce9bd4 100644 --- a/mypyc/primitives/set_ops.py +++ b/mypyc/primitives/set_ops.py @@ -3,11 +3,10 @@ from mypyc.primitives.registry import ( func_op, simple_emit, c_function_op, c_method_op, c_binary_op ) -from mypyc.ir.ops import ERR_MAGIC, ERR_FALSE, ERR_NEVER, ERR_NEG_INT, EmitterInterface +from mypyc.ir.ops import ERR_MAGIC, ERR_FALSE, ERR_NEG_INT from mypyc.ir.rtypes import ( - object_rprimitive, bool_rprimitive, set_rprimitive, int_rprimitive, c_int_rprimitive + object_rprimitive, bool_rprimitive, set_rprimitive, c_int_rprimitive ) -from typing import List # Construct an empty set. @@ -35,23 +34,6 @@ c_function_name='PyFrozenSet_New', error_kind=ERR_MAGIC) - -def emit_len(emitter: EmitterInterface, args: List[str], dest: str) -> None: - temp = emitter.temp_name() - emitter.emit_declaration('Py_ssize_t %s;' % temp) - emitter.emit_line('%s = PySet_GET_SIZE(%s);' % (temp, args[0])) - emitter.emit_line('%s = CPyTagged_ShortFromSsize_t(%s);' % (dest, temp)) - - -# len(set) -func_op( - name='builtins.len', - arg_types=[set_rprimitive], - result_type=int_rprimitive, - error_kind=ERR_NEVER, - emit=emit_len, -) - # item in set c_binary_op( name='in', diff --git a/mypyc/primitives/tuple_ops.py b/mypyc/primitives/tuple_ops.py index 4373fd5da18e..02746e7dd462 100644 --- a/mypyc/primitives/tuple_ops.py +++ b/mypyc/primitives/tuple_ops.py @@ -4,14 +4,10 @@ objects, i.e. tuple_rprimitive (RPrimitive), not RTuple. """ -from typing import List - -from mypyc.ir.ops import ( - EmitterInterface, ERR_NEVER, ERR_MAGIC -) +from mypyc.ir.ops import ERR_MAGIC from mypyc.ir.rtypes import tuple_rprimitive, int_rprimitive, list_rprimitive, object_rprimitive from mypyc.primitives.registry import ( - func_op, c_method_op, custom_op, simple_emit, c_function_op + c_method_op, custom_op, simple_emit, c_function_op ) @@ -33,22 +29,6 @@ format_str='{dest} = ({comma_args}) :: tuple', emit=simple_emit('{dest} = PyTuple_Pack({num_args}{comma_if_args}{comma_args});')) - -def emit_len(emitter: EmitterInterface, args: List[str], dest: str) -> None: - temp = emitter.temp_name() - emitter.emit_declaration('Py_ssize_t %s;' % temp) - emitter.emit_line('%s = PyTuple_GET_SIZE(%s);' % (temp, args[0])) - emitter.emit_line('%s = CPyTagged_ShortFromSsize_t(%s);' % (dest, temp)) - - -# len(tuple) -tuple_len_op = func_op( - name='builtins.len', - arg_types=[tuple_rprimitive], - result_type=int_rprimitive, - error_kind=ERR_NEVER, - emit=emit_len) - # Construct tuple from a list. list_tuple_op = c_function_op( name='builtins.tuple', diff --git a/mypyc/test-data/irbuild-dict.test b/mypyc/test-data/irbuild-dict.test index 064406c9f808..8296219a83d3 100644 --- a/mypyc/test-data/irbuild-dict.test +++ b/mypyc/test-data/irbuild-dict.test @@ -145,40 +145,42 @@ def increment(d: Dict[str, int]) -> Dict[str, int]: def increment(d): d :: dict r0 :: short_int - r1 :: int - r2 :: object - r3 :: tuple[bool, int, object] - r4 :: int - r5 :: bool - r6 :: object - k, r7 :: str - r8 :: object - r9, r10 :: object - r11 :: int32 - r12, r13 :: bool + r1 :: native_int + r2 :: short_int + r3 :: object + r4 :: tuple[bool, int, object] + r5 :: int + r6 :: bool + r7 :: object + k, r8 :: str + r9 :: object + r10, r11 :: object + r12 :: int32 + r13, r14 :: bool L0: r0 = 0 - r1 = len d :: dict - r2 = CPyDict_GetKeysIter(d) + r1 = PyDict_Size(d) + r2 = r1 << 1 + r3 = CPyDict_GetKeysIter(d) L1: - r3 = CPyDict_NextKey(r2, r0) - r4 = r3[1] - r0 = r4 - r5 = r3[0] - if r5 goto L2 else goto L4 :: bool + r4 = CPyDict_NextKey(r3, r0) + r5 = r4[1] + r0 = r5 + r6 = r4[0] + if r6 goto L2 else goto L4 :: bool L2: - r6 = r3[2] - r7 = cast(str, r6) - k = r7 - r8 = CPyDict_GetItem(d, k) - r9 = box(short_int, 2) - r10 = PyNumber_InPlaceAdd(r8, r9) - r11 = CPyDict_SetItem(d, k, r10) + r7 = r4[2] + r8 = cast(str, r7) + k = r8 + r9 = CPyDict_GetItem(d, k) + r10 = box(short_int, 2) + r11 = PyNumber_InPlaceAdd(r9, r10) + r12 = CPyDict_SetItem(d, k, r11) L3: - r12 = CPyDict_CheckSize(d, r1) + r13 = CPyDict_CheckSize(d, r2) goto L1 L4: - r13 = CPy_NoErrOccured() + r14 = CPy_NoErrOccured() L5: return d @@ -217,86 +219,90 @@ def print_dict_methods(d1: Dict[int, int], d2: Dict[int, int]) -> None: def print_dict_methods(d1, d2): d1, d2 :: dict r0 :: short_int - r1 :: int - r2 :: object - r3 :: tuple[bool, int, object] - r4 :: int - r5 :: bool - r6 :: object - v, r7 :: int - r8 :: object - r9 :: int32 - r10 :: bool - r11 :: None - r12, r13 :: bool - r14 :: short_int - r15 :: int - r16 :: object - r17 :: tuple[bool, int, object, object] - r18 :: int - r19 :: bool - r20, r21 :: object - r22, r23, k :: int - r24, r25, r26, r27, r28 :: object - r29 :: int32 - r30, r31 :: bool - r32 :: None + r1 :: native_int + r2 :: short_int + r3 :: object + r4 :: tuple[bool, int, object] + r5 :: int + r6 :: bool + r7 :: object + v, r8 :: int + r9 :: object + r10 :: int32 + r11 :: bool + r12 :: None + r13, r14 :: bool + r15 :: short_int + r16 :: native_int + r17 :: short_int + r18 :: object + r19 :: tuple[bool, int, object, object] + r20 :: int + r21 :: bool + r22, r23 :: object + r24, r25, k :: int + r26, r27, r28, r29, r30 :: object + r31 :: int32 + r32, r33 :: bool + r34 :: None L0: r0 = 0 - r1 = len d1 :: dict - r2 = CPyDict_GetValuesIter(d1) + r1 = PyDict_Size(d1) + r2 = r1 << 1 + r3 = CPyDict_GetValuesIter(d1) L1: - r3 = CPyDict_NextValue(r2, r0) - r4 = r3[1] - r0 = r4 - r5 = r3[0] - if r5 goto L2 else goto L6 :: bool + r4 = CPyDict_NextValue(r3, r0) + r5 = r4[1] + r0 = r5 + r6 = r4[0] + if r6 goto L2 else goto L6 :: bool L2: - r6 = r3[2] - r7 = unbox(int, r6) - v = r7 - r8 = box(int, v) - r9 = PyDict_Contains(d2, r8) - r10 = truncate r9: int32 to builtins.bool - if r10 goto L3 else goto L4 :: bool + r7 = r4[2] + r8 = unbox(int, r7) + v = r8 + r9 = box(int, v) + r10 = PyDict_Contains(d2, r9) + r11 = truncate r10: int32 to builtins.bool + if r11 goto L3 else goto L4 :: bool L3: - r11 = None - return r11 + r12 = None + return r12 L4: L5: - r12 = CPyDict_CheckSize(d1, r1) + r13 = CPyDict_CheckSize(d1, r2) goto L1 L6: - r13 = CPy_NoErrOccured() + r14 = CPy_NoErrOccured() L7: - r14 = 0 - r15 = len d2 :: dict - r16 = CPyDict_GetItemsIter(d2) + r15 = 0 + r16 = PyDict_Size(d2) + r17 = r16 << 1 + r18 = CPyDict_GetItemsIter(d2) L8: - r17 = CPyDict_NextItem(r16, r14) - r18 = r17[1] - r14 = r18 - r19 = r17[0] - if r19 goto L9 else goto L11 :: bool + r19 = CPyDict_NextItem(r18, r15) + r20 = r19[1] + r15 = r20 + r21 = r19[0] + if r21 goto L9 else goto L11 :: bool L9: - r20 = r17[2] - r21 = r17[3] - r22 = unbox(int, r20) - r23 = unbox(int, r21) - k = r22 - v = r23 - r24 = box(int, k) - r25 = CPyDict_GetItem(d2, r24) - r26 = box(int, v) - r27 = PyNumber_InPlaceAdd(r25, r26) - r28 = box(int, k) - r29 = CPyDict_SetItem(d2, r28, r27) + r22 = r19[2] + r23 = r19[3] + r24 = unbox(int, r22) + r25 = unbox(int, r23) + k = r24 + v = r25 + r26 = box(int, k) + r27 = CPyDict_GetItem(d2, r26) + r28 = box(int, v) + r29 = PyNumber_InPlaceAdd(r27, r28) + r30 = box(int, k) + r31 = CPyDict_SetItem(d2, r30, r29) L10: - r30 = CPyDict_CheckSize(d2, r15) + r32 = CPyDict_CheckSize(d2, r17) goto L8 L11: - r31 = CPy_NoErrOccured() + r33 = CPy_NoErrOccured() L12: - r32 = None - return r32 + r34 = None + return r34 diff --git a/mypyc/test-data/irbuild-set.test b/mypyc/test-data/irbuild-set.test index 02ec9f3b9a33..7a8e8edf2fc1 100644 --- a/mypyc/test-data/irbuild-set.test +++ b/mypyc/test-data/irbuild-set.test @@ -57,7 +57,9 @@ def f(): r4 :: int32 r5 :: object r6 :: int32 - r7 :: int + r7 :: ptr + r8 :: native_int + r9 :: short_int L0: r0 = set r1 = box(short_int, 2) @@ -66,8 +68,10 @@ L0: r4 = PySet_Add(r0, r3) r5 = box(short_int, 6) r6 = PySet_Add(r0, r5) - r7 = len r0 :: set - return r7 + r7 = get_element_ptr r0 used :: PySetObject + r8 = load_mem r7 :: native_int* + r9 = r8 << 1 + return r9 [case testSetContains] from typing import Set diff --git a/mypyc/test-data/irbuild-statements.test b/mypyc/test-data/irbuild-statements.test index 39b5958cede9..4140d42e9998 100644 --- a/mypyc/test-data/irbuild-statements.test +++ b/mypyc/test-data/irbuild-statements.test @@ -366,42 +366,44 @@ def f(d: Dict[int, int]) -> None: def f(d): d :: dict r0 :: short_int - r1 :: int - r2 :: object - r3 :: tuple[bool, int, object] - r4 :: int - r5 :: bool - r6 :: object - key, r7 :: int - r8, r9 :: object - r10 :: int - r11, r12 :: bool - r13 :: None + r1 :: native_int + r2 :: short_int + r3 :: object + r4 :: tuple[bool, int, object] + r5 :: int + r6 :: bool + r7 :: object + key, r8 :: int + r9, r10 :: object + r11 :: int + r12, r13 :: bool + r14 :: None L0: r0 = 0 - r1 = len d :: dict - r2 = CPyDict_GetKeysIter(d) + r1 = PyDict_Size(d) + r2 = r1 << 1 + r3 = CPyDict_GetKeysIter(d) L1: - r3 = CPyDict_NextKey(r2, r0) - r4 = r3[1] - r0 = r4 - r5 = r3[0] - if r5 goto L2 else goto L4 :: bool + r4 = CPyDict_NextKey(r3, r0) + r5 = r4[1] + r0 = r5 + r6 = r4[0] + if r6 goto L2 else goto L4 :: bool L2: - r6 = r3[2] - r7 = unbox(int, r6) - key = r7 - r8 = box(int, key) - r9 = CPyDict_GetItem(d, r8) - r10 = unbox(int, r9) + r7 = r4[2] + r8 = unbox(int, r7) + key = r8 + r9 = box(int, key) + r10 = CPyDict_GetItem(d, r9) + r11 = unbox(int, r10) L3: - r11 = CPyDict_CheckSize(d, r1) + r12 = CPyDict_CheckSize(d, r2) goto L1 L4: - r12 = CPy_NoErrOccured() + r13 = CPy_NoErrOccured() L5: - r13 = None - return r13 + r14 = None + return r14 [case testForDictContinue] from typing import Dict @@ -418,67 +420,69 @@ def sum_over_even_values(d): d :: dict s :: int r0 :: short_int - r1 :: int - r2 :: object - r3 :: tuple[bool, int, object] - r4 :: int - r5 :: bool - r6 :: object - key, r7 :: int - r8, r9 :: object - r10 :: int + r1 :: native_int + r2 :: short_int + r3 :: object + r4 :: tuple[bool, int, object] + r5 :: int + r6 :: bool + r7 :: object + key, r8 :: int + r9, r10 :: object r11 :: int - r12 :: bool - r13 :: native_int - r14, r15, r16, r17 :: bool - r18, r19 :: object - r20, r21 :: int - r22, r23 :: bool + r12 :: int + r13 :: bool + r14 :: native_int + r15, r16, r17, r18 :: bool + r19, r20 :: object + r21, r22 :: int + r23, r24 :: bool L0: s = 0 r0 = 0 - r1 = len d :: dict - r2 = CPyDict_GetKeysIter(d) + r1 = PyDict_Size(d) + r2 = r1 << 1 + r3 = CPyDict_GetKeysIter(d) L1: - r3 = CPyDict_NextKey(r2, r0) - r4 = r3[1] - r0 = r4 - r5 = r3[0] - if r5 goto L2 else goto L9 :: bool + r4 = CPyDict_NextKey(r3, r0) + r5 = r4[1] + r0 = r5 + r6 = r4[0] + if r6 goto L2 else goto L9 :: bool L2: - r6 = r3[2] - r7 = unbox(int, r6) - key = r7 - r8 = box(int, key) - r9 = CPyDict_GetItem(d, r8) - r10 = unbox(int, r9) - r11 = CPyTagged_Remainder(r10, 4) - r13 = r11 & 1 - r14 = r13 == 0 - if r14 goto L3 else goto L4 :: bool + r7 = r4[2] + r8 = unbox(int, r7) + key = r8 + r9 = box(int, key) + r10 = CPyDict_GetItem(d, r9) + r11 = unbox(int, r10) + r12 = CPyTagged_Remainder(r11, 4) + r14 = r12 & 1 + r15 = r14 == 0 + if r15 goto L3 else goto L4 :: bool L3: - r15 = r11 != 0 - r12 = r15 + r16 = r12 != 0 + r13 = r16 goto L5 L4: - r16 = CPyTagged_IsEq_(r11, 0) - r17 = !r16 - r12 = r17 + r17 = CPyTagged_IsEq_(r12, 0) + r18 = !r17 + r13 = r18 L5: - if r12 goto L6 else goto L7 :: bool + if r13 goto L6 else goto L7 :: bool L6: goto L8 L7: - r18 = box(int, key) - r19 = CPyDict_GetItem(d, r18) - r20 = unbox(int, r19) - r21 = CPyTagged_Add(s, r20) - s = r21 + r19 = box(int, key) + r20 = CPyDict_GetItem(d, r19) + r21 = unbox(int, r20) + r22 = CPyTagged_Add(s, r21) + s = r22 L8: - r22 = CPyDict_CheckSize(d, r1) + r23 = CPyDict_CheckSize(d, r2) goto L1 L9: - r23 = CPy_NoErrOccured() + r24 = CPy_NoErrOccured() L10: return s diff --git a/mypyc/test-data/irbuild-tuple.test b/mypyc/test-data/irbuild-tuple.test index 1c626955e33d..41c6bedf9d88 100644 --- a/mypyc/test-data/irbuild-tuple.test +++ b/mypyc/test-data/irbuild-tuple.test @@ -64,10 +64,14 @@ def f(x: Tuple[int, ...]) -> int: [out] def f(x): x :: tuple - r0 :: int + r0 :: ptr + r1 :: native_int + r2 :: short_int L0: - r0 = len x :: tuple - return r0 + r0 = get_element_ptr x ob_size :: PyVarObject + r1 = load_mem r0 :: native_int* + r2 = r1 << 1 + return r2 [case testSequenceTupleForced] from typing import Tuple @@ -121,46 +125,33 @@ def f(xs: Tuple[str, ...]) -> None: def f(xs): xs :: tuple r0 :: short_int - r1 :: int - r2 :: bool - r3 :: native_int + r1 :: ptr + r2 :: native_int + r3 :: short_int r4 :: bool - r5 :: native_int - r6, r7, r8, r9 :: bool - r10 :: object - x, r11 :: str - r12 :: short_int - r13 :: None + r5 :: object + x, r6 :: str + r7 :: short_int + r8 :: None L0: r0 = 0 L1: - r1 = len xs :: tuple - r3 = r0 & 1 - r4 = r3 == 0 - r5 = r1 & 1 - r6 = r5 == 0 - r7 = r4 & r6 - if r7 goto L2 else goto L3 :: bool + r1 = get_element_ptr xs ob_size :: PyVarObject + r2 = load_mem r1 :: native_int* + r3 = r2 << 1 + r4 = r0 < r3 :: signed + if r4 goto L2 else goto L4 :: bool L2: - r8 = r0 < r1 :: signed - r2 = r8 - goto L4 + r5 = CPySequenceTuple_GetItem(xs, r0) + r6 = cast(str, r5) + x = r6 L3: - r9 = CPyTagged_IsLt_(r0, r1) - r2 = r9 -L4: - if r2 goto L5 else goto L7 :: bool -L5: - r10 = CPySequenceTuple_GetItem(xs, r0) - r11 = cast(str, r10) - x = r11 -L6: - r12 = r0 + 2 - r0 = r12 + r7 = r0 + 2 + r0 = r7 goto L1 -L7: - r13 = None - return r13 +L4: + r8 = None + return r8 [case testNamedTupleAttribute] from typing import NamedTuple diff --git a/mypyc/test-data/refcount.test b/mypyc/test-data/refcount.test index d3f79322c8b2..39db7d05f017 100644 --- a/mypyc/test-data/refcount.test +++ b/mypyc/test-data/refcount.test @@ -777,51 +777,52 @@ def f(d: Dict[int, int]) -> None: def f(d): d :: dict r0 :: short_int - r1 :: int - r2 :: object - r3 :: tuple[bool, int, object] - r4 :: int - r5 :: bool - r6 :: object - key, r7 :: int - r8, r9 :: object - r10 :: int - r11, r12 :: bool - r13 :: None + r1 :: native_int + r2 :: short_int + r3 :: object + r4 :: tuple[bool, int, object] + r5 :: int + r6 :: bool + r7 :: object + key, r8 :: int + r9, r10 :: object + r11 :: int + r12, r13 :: bool + r14 :: None L0: r0 = 0 - r1 = len d :: dict - r2 = CPyDict_GetKeysIter(d) + r1 = PyDict_Size(d) + r2 = r1 << 1 + r3 = CPyDict_GetKeysIter(d) L1: - r3 = CPyDict_NextKey(r2, r0) - r4 = r3[1] - r0 = r4 - r5 = r3[0] - if r5 goto L2 else goto L6 :: bool + r4 = CPyDict_NextKey(r3, r0) + r5 = r4[1] + r0 = r5 + r6 = r4[0] + if r6 goto L2 else goto L6 :: bool L2: - r6 = r3[2] - dec_ref r3 - r7 = unbox(int, r6) - dec_ref r6 - key = r7 - r8 = box(int, key) - r9 = CPyDict_GetItem(d, r8) - dec_ref r8 - r10 = unbox(int, r9) + r7 = r4[2] + dec_ref r4 + r8 = unbox(int, r7) + dec_ref r7 + key = r8 + r9 = box(int, key) + r10 = CPyDict_GetItem(d, r9) dec_ref r9 - dec_ref r10 :: int + r11 = unbox(int, r10) + dec_ref r10 + dec_ref r11 :: int L3: - r11 = CPyDict_CheckSize(d, r1) + r12 = CPyDict_CheckSize(d, r2) goto L1 L4: - r12 = CPy_NoErrOccured() + r13 = CPy_NoErrOccured() L5: - r13 = None - return r13 + r14 = None + return r14 L6: - dec_ref r1 :: int - dec_ref r2 dec_ref r3 + dec_ref r4 goto L4 [case testBorrowRefs]