[pypy-commit] pypy float-opt: optimize float division with reciprocal multiplication
amintos
noreply at buildbot.pypy.org
Fri Nov 7 23:13:45 CET 2014
Author: Toni Mattis <solaris at 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):
More information about the pypy-commit
mailing list