v2 = self.getvalue(op.getarg(1)) if v2.is_constant() and v2.box.getint() == 1: self.make_equal_to(op.result, v1) return elif v1.is_constant() and v1.box.getint() == 0: self.make_constant_int(op.result, 0) return if v1.intbound.known_ge(IntBound(0, 0)) and v2.is_constant(): val = v2.box.getint() if val & (val - 1) == 0 and val > 0: # val == 2**shift op = op.copy_and_change(rop.INT_RSHIFT, args = [op.getarg(0), ConstInt(highest_bit(val))]) self.emit_operation(op) def optimize_MARK_OPAQUE_PTR(self, op): value = self.getvalue(op.getarg(0)) self.optimizer.opaque_pointers[value] = True def optimize_CAST_PTR_TO_INT(self, op): self.pure(rop.CAST_INT_TO_PTR, [op.result], op.getarg(0)) self.emit_operation(op) def optimize_CAST_INT_TO_PTR(self, op): self.pure(rop.CAST_PTR_TO_INT, [op.result], op.getarg(0)) self.emit_operation(op) dispatch_opt = make_dispatcher_method(OptRewrite, 'optimize_', default=OptRewrite.emit_operation) optimize_guards = _findall(OptRewrite, 'optimize_', 'GUARD')
def optimize_GETARRAYITEM_GC_PURE(self, op): indexvalue = self.getvalue(op.getarg(1)) if indexvalue.is_constant(): arrayvalue = self.getvalue(op.getarg(0)) arrayvalue.make_len_gt(MODE_ARRAY, op.getdescr(), indexvalue.box.getint()) self.optimize_default(op) def optimize_STRGETITEM(self, op): indexvalue = self.getvalue(op.getarg(1)) if indexvalue.is_constant(): arrayvalue = self.getvalue(op.getarg(0)) arrayvalue.make_len_gt(MODE_STR, op.getdescr(), indexvalue.box.getint()) self.optimize_default(op) def optimize_UNICODEGETITEM(self, op): indexvalue = self.getvalue(op.getarg(1)) if indexvalue.is_constant(): arrayvalue = self.getvalue(op.getarg(0)) arrayvalue.make_len_gt(MODE_UNICODE, op.getdescr(), indexvalue.box.getint()) self.optimize_default(op) dispatch_opt = make_dispatcher_method(Optimizer, 'optimize_', default=Optimizer.optimize_default)
# already between the tracing and now. In this case, we are # simply ignoring the QUASIIMMUT_FIELD hint and compiling it # as a regular getfield. if not qmutdescr.is_still_valid(): self._remove_guard_not_invalidated = True return # record as an out-of-line guard if self.optimizer.quasi_immutable_deps is None: self.optimizer.quasi_immutable_deps = {} self.optimizer.quasi_immutable_deps[qmutdescr.qmut] = None # perform the replacement in the list of operations fieldvalue = self.getvalue(qmutdescr.constantfieldbox) cf = self.field_cache(qmutdescr.fielddescr) cf.force_lazy_setfield(self) cf.remember_field_value(structvalue, fieldvalue) self._remove_guard_not_invalidated = False def optimize_GUARD_NOT_INVALIDATED(self, op): if self._remove_guard_not_invalidated: return if self._seen_guard_not_invalidated: return self._seen_guard_not_invalidated = True self.emit_operation(op) dispatch_opt = make_dispatcher_method(OptHeap, 'optimize_', default=OptHeap.emit_operation) OptHeap.propagate_forward = dispatch_opt
pass def optimize_LABEL(self, op): if not self.unroll: descr = op.getdescr() if isinstance(descr, JitCellToken): return self.optimize_JUMP(op.copy_and_change(rop.JUMP)) self.last_label_descr = op.getdescr() self.emit_operation(op) def optimize_JUMP(self, op): if not self.unroll: descr = op.getdescr() assert isinstance(descr, JitCellToken) if not descr.target_tokens: assert self.last_label_descr is not None target_token = self.last_label_descr assert isinstance(target_token, TargetToken) assert target_token.targeting_jitcell_token is descr op.setdescr(self.last_label_descr) else: assert len(descr.target_tokens) == 1 op.setdescr(descr.target_tokens[0]) self.emit_operation(op) dispatch_opt = make_dispatcher_method(OptSimplify, 'optimize_', default=OptSimplify.emit_operation) OptSimplify.propagate_forward = dispatch_opt
self.propagate_bounds_backward(op.getarg(1)) def propagate_bounds_INT_MUL(self, op): v1 = self.getvalue(op.getarg(0)) v2 = self.getvalue(op.getarg(1)) r = self.getvalue(op.result) b = r.intbound.div_bound(v2.intbound) if v1.intbound.intersect(b): self.propagate_bounds_backward(op.getarg(0)) b = r.intbound.div_bound(v1.intbound) if v2.intbound.intersect(b): self.propagate_bounds_backward(op.getarg(1)) def propagate_bounds_INT_LSHIFT(self, op): v1 = self.getvalue(op.getarg(0)) v2 = self.getvalue(op.getarg(1)) r = self.getvalue(op.result) b = r.intbound.rshift_bound(v2.intbound) if v1.intbound.intersect(b): self.propagate_bounds_backward(op.getarg(0)) propagate_bounds_INT_ADD_OVF = propagate_bounds_INT_ADD propagate_bounds_INT_SUB_OVF = propagate_bounds_INT_SUB propagate_bounds_INT_MUL_OVF = propagate_bounds_INT_MUL dispatch_opt = make_dispatcher_method(OptIntBounds, 'optimize_', default=OptIntBounds.opt_default) dispatch_bounds_ops = make_dispatcher_method(OptIntBounds, 'propagate_bounds_')
elif kind == 'f' or kind == 'I' or kind == 'U': # longlongs are treated as floats, see # e.g. llsupport/descr.py:getDescrClass is_float = True elif kind == 'u' or kind == 's': # they're all False pass else: raise NotImplementedError("unsupported ffitype or kind: %s" % kind) # fieldsize = rffi.getintfield(ffitype, 'c_size') return self.optimizer.cpu.interiorfielddescrof_dynamic( offset, width, fieldsize, is_pointer, is_float, is_signed ) def propagate_forward(self, op): if self.logops is not None: debug_print(self.logops.repr_of_resop(op)) dispatch_opt(self, op) def _get_oopspec(self, op): effectinfo = op.getdescr().get_extra_info() return effectinfo.oopspecindex def _get_funcval(self, op): return self.getvalue(op.getarg(1)) dispatch_opt = make_dispatcher_method(OptFfiCall, 'optimize_', default=OptFfiCall.emit_operation)
if v2.intbound.intersect(b): self.propagate_bounds_backward(op.getarg(1)) def propagate_bounds_INT_MUL(self, op): v1 = self.getvalue(op.getarg(0)) v2 = self.getvalue(op.getarg(1)) r = self.getvalue(op.result) b = r.intbound.div_bound(v2.intbound) if v1.intbound.intersect(b): self.propagate_bounds_backward(op.getarg(0)) b = r.intbound.div_bound(v1.intbound) if v2.intbound.intersect(b): self.propagate_bounds_backward(op.getarg(1)) def propagate_bounds_INT_LSHIFT(self, op): v1 = self.getvalue(op.getarg(0)) v2 = self.getvalue(op.getarg(1)) r = self.getvalue(op.result) b = r.intbound.rshift_bound(v2.intbound) if v1.intbound.intersect(b): self.propagate_bounds_backward(op.getarg(0)) propagate_bounds_INT_ADD_OVF = propagate_bounds_INT_ADD propagate_bounds_INT_SUB_OVF = propagate_bounds_INT_SUB propagate_bounds_INT_MUL_OVF = propagate_bounds_INT_MUL dispatch_opt = make_dispatcher_method(OptIntBounds, 'optimize_', default=OptIntBounds.opt_default) dispatch_bounds_ops = make_dispatcher_method(OptIntBounds, 'propagate_bounds_')
if v2.is_constant() and v2.box.getint() == 1: self.make_equal_to(op.result, v1) return elif v1.is_constant() and v1.box.getint() == 0: self.make_constant_int(op.result, 0) return if v1.intbound.known_ge(IntBound(0, 0)) and v2.is_constant(): val = v2.box.getint() if val & (val - 1) == 0 and val > 0: # val == 2**shift op = op.copy_and_change( rop.INT_RSHIFT, args=[op.getarg(0), ConstInt(highest_bit(val))]) self.emit_operation(op) def optimize_CAST_PTR_TO_INT(self, op): self.pure(rop.CAST_INT_TO_PTR, [op.result], op.getarg(0)) self.emit_operation(op) def optimize_CAST_INT_TO_PTR(self, op): self.pure(rop.CAST_PTR_TO_INT, [op.result], op.getarg(0)) self.emit_operation(op) def optimize_SAME_AS(self, op): self.make_equal_to(op.result, self.getvalue(op.getarg(0))) dispatch_opt = make_dispatcher_method(OptRewrite, 'optimize_', default=OptRewrite.emit_operation) optimize_guards = _findall(OptRewrite, 'optimize_', 'GUARD')
jump(pv1, pv2) """ with raises(InvalidLoop): self.optimize_loop(ops, ops) class OptRenameStrlen(Optimization): def propagate_forward(self, op): dispatch_opt(self, op) def optimize_STRLEN(self, op): newop = op.clone() newop.result = op.result.clonebox() self.emit_operation(newop) self.make_equal_to(op.result, self.getvalue(newop.result)) dispatch_opt = make_dispatcher_method(OptRenameStrlen, 'optimize_', default=OptRenameStrlen.emit_operation) class BaseTestOptimizerRenamingBoxes(BaseTestMultiLabel): def _do_optimize_loop(self, loop, call_pure_results): from pypy.jit.metainterp.optimizeopt.unroll import optimize_unroll from pypy.jit.metainterp.optimizeopt.util import args_dict from pypy.jit.metainterp.optimizeopt.pure import OptPure self.loop = loop loop.call_pure_results = args_dict() metainterp_sd = FakeMetaInterpStaticData(self.cpu) optimize_unroll(metainterp_sd, loop, [OptRenameStrlen(), OptPure()], True) def test_optimizer_renaming_boxes(self): ops = """
def optimize_RECORD_KNOWN_CLASS(self, op): pass def optimize_LABEL(self, op): if not self.unroll: descr = op.getdescr() if isinstance(descr, JitCellToken): return self.optimize_JUMP(op.copy_and_change(rop.JUMP)) self.last_label_descr = op.getdescr() self.emit_operation(op) def optimize_JUMP(self, op): if not self.unroll: descr = op.getdescr() assert isinstance(descr, JitCellToken) if not descr.target_tokens: assert self.last_label_descr is not None target_token = self.last_label_descr assert isinstance(target_token, TargetToken) assert target_token.targeting_jitcell_token is descr op.setdescr(self.last_label_descr) else: assert len(descr.target_tokens) == 1 op.setdescr(descr.target_tokens[0]) self.emit_operation(op) dispatch_opt = make_dispatcher_method(OptSimplify, "optimize_", default=OptSimplify.emit_operation) OptSimplify.propagate_forward = dispatch_opt
v1.vstart.force_box(self), v1.vlength.force_box(self), v2.force_box(self)], resultbox, mode) return True return False def generate_modified_call(self, oopspecindex, args, result, mode): oopspecindex += mode.OS_offset cic = self.optimizer.metainterp_sd.callinfocollection calldescr, func = cic.callinfo_for_oopspec(oopspecindex) op = ResOperation(rop.CALL, [ConstInt(func)] + args, result, descr=calldescr) self.emit_operation(op) def propagate_forward(self, op): dispatch_opt(self, op) dispatch_opt = make_dispatcher_method(OptString, 'optimize_', default=OptString.emit_operation) def _findall_call_oopspec(): prefix = 'opt_call_stroruni_' result = [] for name in dir(OptString): if name.startswith(prefix): value = getattr(EffectInfo, 'OS_' + name[len(prefix):]) assert isinstance(value, int) and value != 0 result.append((value, getattr(OptString, name))) return unrolling_iterable(result) opt_call_oopspec_ops = _findall_call_oopspec()
def generate_modified_call(self, oopspecindex, args, result, mode): oopspecindex += mode.OS_offset cic = self.optimizer.metainterp_sd.callinfocollection calldescr, func = cic.callinfo_for_oopspec(oopspecindex) op = ResOperation(rop.CALL, [ConstInt(func)] + args, result, descr=calldescr) self.emit_operation(op) def propagate_forward(self, op): dispatch_opt(self, op) dispatch_opt = make_dispatcher_method(OptString, 'optimize_', default=OptString.emit_operation) def _findall_call_oopspec(): prefix = 'opt_call_stroruni_' result = [] for name in dir(OptString): if name.startswith(prefix): value = getattr(EffectInfo, 'OS_' + name[len(prefix):]) assert isinstance(value, int) and value != 0 result.append((value, getattr(OptString, name))) return unrolling_iterable(result) opt_call_oopspec_ops = _findall_call_oopspec()
is_signed = True elif kind == 'f' or kind == 'I' or kind == 'U': # longlongs are treated as floats, see # e.g. llsupport/descr.py:getDescrClass is_float = True elif kind == 'u' or kind == 's': # they're all False pass else: raise NotImplementedError("unsupported ffitype or kind: %s" % kind) # fieldsize = rffi.getintfield(ffitype, 'c_size') return self.optimizer.cpu.interiorfielddescrof_dynamic( offset, width, fieldsize, is_pointer, is_float, is_signed ) def propagate_forward(self, op): if self.logops is not None: debug_print(self.logops.repr_of_resop(op)) dispatch_opt(self, op) def _get_oopspec(self, op): effectinfo = op.getdescr().get_extra_info() return effectinfo.oopspecindex def _get_funcval(self, op): return self.getvalue(op.getarg(1)) dispatch_opt = make_dispatcher_method(OptFfiCall, 'optimize_', default=OptFfiCall.emit_operation)
# check that the value is still correct; it could have changed # already between the tracing and now. In this case, we are # simply ignoring the QUASIIMMUT_FIELD hint and compiling it # as a regular getfield. if not qmutdescr.is_still_valid(): self._remove_guard_not_invalidated = True return # record as an out-of-line guard if self.optimizer.quasi_immutable_deps is None: self.optimizer.quasi_immutable_deps = {} self.optimizer.quasi_immutable_deps[qmutdescr.qmut] = None # perform the replacement in the list of operations fieldvalue = self.getvalue(qmutdescr.constantfieldbox) cf = self.field_cache(qmutdescr.fielddescr) cf.force_lazy_setfield(self) cf.remember_field_value(structvalue, fieldvalue) self._remove_guard_not_invalidated = False def optimize_GUARD_NOT_INVALIDATED(self, op): if self._remove_guard_not_invalidated: return if self._seen_guard_not_invalidated: return self._seen_guard_not_invalidated = True self.emit_operation(op) dispatch_opt = make_dispatcher_method(OptHeap, 'optimize_', default=OptHeap.emit_operation) OptHeap.propagate_forward = dispatch_opt
indexbox = self.get_constant_box(op.getarg(1)) if indexbox is not None: descr = op.getdescr() fieldvalue = value.getinteriorfield( indexbox.getint(), descr, None ) if fieldvalue is None: fieldvalue = self.new_const(descr) self.make_equal_to(op.result, fieldvalue) return value.ensure_nonnull() self.emit_operation(op) def optimize_SETINTERIORFIELD_GC(self, op): value = self.getvalue(op.getarg(0)) if value.is_virtual(): indexbox = self.get_constant_box(op.getarg(1)) if indexbox is not None: value.setinteriorfield( indexbox.getint(), op.getdescr(), self.getvalue(op.getarg(2)) ) return value.ensure_nonnull() self.emit_operation(op) dispatch_opt = make_dispatcher_method(OptVirtualize, 'optimize_', default=OptVirtualize.emit_operation) OptVirtualize.propagate_forward = dispatch_opt
if key not in self.pure_operations: self.pure_operations[key] = op def has_pure_result(self, opnum, args, descr): op = ResOperation(opnum, args, None, descr) key = self.optimizer.make_args_key(op) op = self.pure_operations.get(key, None) if op is None: return False return op.getdescr() is descr def get_pure_result(self, key): return self.pure_operations.get(key, None) def remember_emitting_pure(self, op): self.emitted_pure_operations[op] = True def produce_potential_short_preamble_ops(self, sb): for op in self.emitted_pure_operations: if op.getopnum() == rop.GETARRAYITEM_GC_PURE or \ op.getopnum() == rop.STRGETITEM or \ op.getopnum() == rop.UNICODEGETITEM: if not self.getvalue(op.getarg(1)).is_constant(): continue sb.add_potential(op) dispatch_opt = make_dispatcher_method(OptPure, 'optimize_', default=OptPure.optimize_default)