def _optimize_CALL_INT_PY_DIV(self, op): arg1 = op.getarg(1) b1 = self.getintbound(arg1) arg2 = op.getarg(2) b2 = self.getintbound(arg2) if b1.equal(0): self.make_constant_int(op, 0) self.last_emitted_operation = REMOVED return True if not b2.is_constant(): return False val = b2.getint() if val <= 0: return False if val == 1: self.make_equal_to(op, arg1) self.last_emitted_operation = REMOVED return True elif val & (val - 1) == 0: # val == 2**shift from rpython.jit.metainterp.history import DONT_CHANGE op = self.replace_op_with(op, rop.INT_RSHIFT, args=[arg1, ConstInt(highest_bit(val))], descr=DONT_CHANGE) # <- xxx rename? means "kill" self.optimizer.send_extra_operation(op) return True else: from rpython.jit.metainterp.optimizeopt import intdiv known_nonneg = b1.known_nonnegative() operations = intdiv.division_operations(arg1, val, known_nonneg) newop = None for newop in operations: self.optimizer.send_extra_operation(newop) self.make_equal_to(op, newop) return True
def optimize_INT_MUL(self, op): arg1 = get_box_replacement(op.getarg(0)) b1 = self.getintbound(arg1) arg2 = get_box_replacement(op.getarg(1)) b2 = self.getintbound(arg2) # If one side of the op is 1 the result is the other side. if b1.equal(1): self.make_equal_to(op, arg2) elif b2.equal(1): self.make_equal_to(op, arg1) elif b1.equal(0) or b2.equal(0): self.make_constant_int(op, 0) else: for lhs, rhs in [(arg1, arg2), (arg2, arg1)]: lh_info = self.getintbound(lhs) if lh_info.is_constant(): x = lh_info.getint() # x & (x - 1) == 0 is a quick test for power of 2 if x & (x - 1) == 0: new_rhs = ConstInt(highest_bit(lh_info.getint())) op = self.replace_op_with(op, rop.INT_LSHIFT, args=[rhs, new_rhs]) break return self.emit(op)
def optimize_INT_FLOORDIV(self, op): v1 = self.getvalue(op.getarg(0)) 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.getintbound().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_INT_FLOORDIV(self, op): arg0 = op.getarg(0) b1 = self.getintbound(arg0) arg1 = op.getarg(1) b2 = self.getintbound(arg1) if b2.is_constant() and b2.getint() == 1: self.make_equal_to(op, arg0) return elif b1.is_constant() and b1.getint() == 0: self.make_constant_int(op, 0) return if b1.known_ge(IntBound(0, 0)) and b2.is_constant(): val = b2.getint() if val & (val - 1) == 0 and val > 0: # val == 2**shift op = self.replace_op_with(op, rop.INT_RSHIFT, args = [op.getarg(0), ConstInt(highest_bit(val))]) self.emit_operation(op)
def optimize_INT_FLOORDIV(self, op): v1 = self.getvalue(op.getarg(0)) 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.getintbound().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 cpu_simplify_scale(cpu, index_box, factor, offset): # Returns (factor, offset, index_box, [ops]) where index_box is either # a non-constant BoxInt or None. if isinstance(index_box, ConstInt): return 1, index_box.value * factor + offset, None, False else: if factor != 1 and factor not in cpu.load_supported_factors: # the factor is supported by the cpu # x & (x - 1) == 0 is a quick test for power of 2 assert factor > 0 if (factor & (factor - 1)) == 0: index_box = ResOperation(rop.INT_LSHIFT, [index_box, ConstInt(highest_bit(factor))]) else: index_box = ResOperation(rop.INT_MUL, [index_box, ConstInt(factor)]) return 1, offset, index_box, True return factor, offset, index_box, False
def _emit_mul_if_factor_offset_not_supported(self, index_box, factor, offset): # Returns (factor, offset, index_box) where index_box is either # a non-constant BoxInt or None. if isinstance(index_box, ConstInt): return 1, index_box.value * factor + offset, None else: if factor != 1 and factor not in self.cpu.load_supported_factors: # the factor is supported by the cpu # x & (x - 1) == 0 is a quick test for power of 2 assert factor > 0 if (factor & (factor - 1)) == 0: index_box = ResOperation(rop.INT_LSHIFT, [index_box, ConstInt(highest_bit(factor))]) else: index_box = ResOperation(rop.INT_MUL, [index_box, ConstInt(factor)]) self.emit_op(index_box) factor = 1 return factor, offset, index_box
def optimize_INT_FLOORDIV(self, op): arg0 = op.getarg(0) b1 = self.getintbound(arg0) arg1 = op.getarg(1) b2 = self.getintbound(arg1) if b2.is_constant() and b2.getint() == 1: self.make_equal_to(op, arg0) return elif b1.is_constant() and b1.getint() == 0: self.make_constant_int(op, 0) return if b1.known_ge(IntBound(0, 0)) and b2.is_constant(): val = b2.getint() if val & (val - 1) == 0 and val > 0: # val == 2**shift op = self.replace_op_with( op, rop.INT_RSHIFT, args=[op.getarg(0), ConstInt(highest_bit(val))]) self.emit_operation(op)
def optimize_INT_MUL(self, op): v1 = self.getvalue(op.getarg(0)) v2 = self.getvalue(op.getarg(1)) # If one side of the op is 1 the result is the other side. if v1.is_constant() and v1.box.getint() == 1: self.make_equal_to(op.result, v2) elif v2.is_constant() and v2.box.getint() == 1: self.make_equal_to(op.result, v1) elif (v1.is_constant() and v1.box.getint() == 0) or \ (v2.is_constant() and v2.box.getint() == 0): self.make_constant_int(op.result, 0) else: for lhs, rhs in [(v1, v2), (v2, v1)]: if lhs.is_constant(): x = lhs.box.getint() # x & (x - 1) == 0 is a quick test for power of 2 if x & (x - 1) == 0: new_rhs = ConstInt(highest_bit(lhs.box.getint())) op = op.copy_and_change(rop.INT_LSHIFT, args=[rhs.box, new_rhs]) break self.emit_operation(op)
def _optimize_CALL_INT_PY_DIV(self, op): arg1 = op.getarg(1) b1 = self.getintbound(arg1) arg2 = op.getarg(2) b2 = self.getintbound(arg2) if b1.is_constant() and b1.getint() == 0: self.make_constant_int(op, 0) self.last_emitted_operation = REMOVED return True # This is Python's integer division: 'x // (2**shift)' can always # be replaced with 'x >> shift', even for negative values of x if not b2.is_constant(): return False val = b2.getint() if val <= 0: return False if val == 1: self.make_equal_to(op, arg1) self.last_emitted_operation = REMOVED return True elif val & (val - 1) == 0: # val == 2**shift from rpython.jit.metainterp.history import DONT_CHANGE op = self.replace_op_with( op, rop.INT_RSHIFT, args=[arg1, ConstInt(highest_bit(val))], descr=DONT_CHANGE ) # <- xxx rename? means "kill" self.optimizer.send_extra_operation(op) return True else: from rpython.jit.metainterp.optimizeopt import intdiv known_nonneg = b1.known_ge(IntBound(0, 0)) operations = intdiv.division_operations(arg1, val, known_nonneg) newop = None for newop in operations: self.optimizer.send_extra_operation(newop) self.make_equal_to(op, newop) return True
def optimize_INT_MUL(self, op): arg1 = self.get_box_replacement(op.getarg(0)) b1 = self.getintbound(arg1) arg2 = self.get_box_replacement(op.getarg(1)) b2 = self.getintbound(arg2) # If one side of the op is 1 the result is the other side. if b1.equal(1): self.make_equal_to(op, arg2) elif b2.equal(1): self.make_equal_to(op, arg1) elif b1.equal(0) or b2.equal(0): self.make_constant_int(op, 0) else: for lhs, rhs in [(arg1, arg2), (arg2, arg1)]: lh_info = self.getintbound(lhs) if lh_info.is_constant(): x = lh_info.getint() # x & (x - 1) == 0 is a quick test for power of 2 if x & (x - 1) == 0: new_rhs = ConstInt(highest_bit(lh_info.getint())) op = self.replace_op_with(op, rop.INT_LSHIFT, args=[rhs, new_rhs]) break self.emit_operation(op)