Author: Toni Mattis <sola...@live.de> Branch: float-opt Changeset: r74391:937254cbc554 Date: 2014-11-06 16:56 +0100 http://bitbucket.org/pypy/pypy/changeset/937254cbc554/
Log: optimize float division with reciprocal multiplication diff --git a/rpython/jit/metainterp/optimizeopt/rewrite.py b/rpython/jit/metainterp/optimizeopt/rewrite.py --- a/rpython/jit/metainterp/optimizeopt/rewrite.py +++ b/rpython/jit/metainterp/optimizeopt/rewrite.py @@ -1,7 +1,7 @@ from rpython.jit.codewriter.effectinfo import EffectInfo from rpython.jit.metainterp import compile from rpython.jit.metainterp.history import (Const, ConstInt, BoxInt, BoxFloat, - BoxPtr, make_hashable_int) + BoxPtr, make_hashable_int, ConstFloat) from rpython.jit.metainterp.optimize import InvalidLoop from rpython.jit.metainterp.optimizeopt.intutils import IntBound from rpython.jit.metainterp.optimizeopt.optimizer import (Optimization, REMOVED, @@ -10,7 +10,7 @@ from rpython.jit.metainterp.resoperation import (opboolinvers, opboolreflex, rop, ResOperation) from rpython.rlib.rarithmetic import highest_bit - +from rpython.rlib.longlong2float import float2longlong class OptRewrite(Optimization): """Rewrite operations into equivalent, cheaper operations. @@ -231,6 +231,25 @@ self.emit_operation(op) self.pure(rop.FLOAT_MUL, [arg2, arg1], op.result) + def optimize_FLOAT_TRUEDIV(self, op): + arg1 = op.getarg(0) + arg2 = op.getarg(1) + v2 = self.getvalue(arg2) + + # replace "x / const" by "x * (1/const)" if possible + if v2.is_constant(): + bits = float2longlong(v2.box.getfloat()) + fraction = bits & ((1 << 52) - 1) + exponent = (bits >> 52) & 0x7ff + + # This optimization is valid for powers of two (fraction == 0) + # but not for zeroes and some subnormals (exponent == 0). + # Checking for zero-fraction also avoids NaNs: + if fraction == 0 and exponent != 0: + reciprocal = ConstFloat(1.0 / v2.box.getfloat()) + op = op.copy_and_change(rop.FLOAT_MUL, args=[arg1, reciprocal]) + self.emit_operation(op) + def optimize_FLOAT_NEG(self, op): v1 = op.getarg(0) self.emit_operation(op) diff --git a/rpython/jit/metainterp/optimizeopt/test/test_optimizebasic.py b/rpython/jit/metainterp/optimizeopt/test/test_optimizebasic.py --- a/rpython/jit/metainterp/optimizeopt/test/test_optimizebasic.py +++ b/rpython/jit/metainterp/optimizeopt/test/test_optimizebasic.py @@ -2364,6 +2364,28 @@ """ self.optimize_loop(ops, expected) + def test_float_division_by_multiplication(self): + ops = """ + [f0] + f1 = float_truediv(f0, 2.0) + f2 = float_truediv(f1, 3.0) + f3 = float_truediv(f2, -0.25) + f4 = float_truediv(f3, 0.0) + f5 = escape(f4) + jump(f5) + """ + + expected = """ + [f0] + f1 = float_mul(f0, 0.5) + f2 = float_truediv(f1, 3.0) + f3 = float_mul(f2, -4.0) + f4 = float_truediv(f3, 0.0) + f5 = escape(f4) + jump(f5) + """ + self.optimize_loop(ops, expected) + # ---------- def _verify_fail_args(self, boxes, oparse, text): _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit