# Authors:
# Jason Ekstrand (jason@jlekstrand.net)
+from __future__ import print_function
+
from collections import OrderedDict
import nir_algebraic
import itertools
(('fge', ('fneg', ('b2f', a)), 0.0), ('inot', a)),
+ (('fne', ('fadd', ('b2f', a), ('b2f', b)), 0.0), ('ior', a, b)),
+ (('fne', ('fmax', ('b2f', a), ('b2f', b)), 0.0), ('ior', a, b)),
+ (('fne', ('bcsel', a, 1.0, ('b2f', b)) , 0.0), ('ior', a, b)),
+ (('fne', ('b2f', a), ('fneg', ('b2f', b))), ('ior', a, b)),
+
+ # -(b2f(a) + b2f(b)) < 0
+ # 0 < b2f(a) + b2f(b)
+ # 0 != b2f(a) + b2f(b) b2f must be 0 or 1, so the sum is non-negative
+ # a || b
+ (('flt', ('fneg', ('fadd', ('b2f', a), ('b2f', b))), 0.0), ('ior', a, b)),
+ (('flt', 0.0, ('fadd', ('b2f', a), ('b2f', b))), ('ior', a, b)),
+
+ # Some optimizations (below) convert things like (a < b || c < b) into
+ # (min(a, c) < b). However, this interfers with the previous optimizations
+ # that try to remove comparisons with negated sums of b2f. This just
+ # breaks that apart.
+ (('flt', ('fmin', c, ('fneg', ('fadd', ('b2f', a), ('b2f', b)))), 0.0),
+ ('ior', ('flt', c, 0.0), ('ior', a, b))),
+
(('~flt', ('fadd', a, b), a), ('flt', b, 0.0)),
(('~fge', ('fadd', a, b), a), ('fge', b, 0.0)),
(('~feq', ('fadd', a, b), a), ('feq', b, 0.0)),
(('ieq', ('b2i', a), 0), ('inot', a)),
(('ine', ('b2i', a), 0), a),
+ (('fne', ('u2f32', a), 0.0), ('ine', a, 0)),
+ (('feq', ('u2f32', a), 0.0), ('ieq', a, 0)),
+ (('fge', ('u2f32', a), 0.0), True),
+ (('fge', 0.0, ('u2f32', a)), ('uge', 0, a)), # ieq instead?
+ (('flt', ('u2f32', a), 0.0), False),
+ (('flt', 0.0, ('u2f32', a)), ('ult', 0, a)), # ine instead?
+ (('fne', ('i2f32', a), 0.0), ('ine', a, 0)),
+ (('feq', ('i2f32', a), 0.0), ('ieq', a, 0)),
+ (('fge', ('i2f32', a), 0.0), ('ige', a, 0)),
+ (('fge', 0.0, ('i2f32', a)), ('ige', 0, a)),
+ (('flt', ('i2f32', a), 0.0), ('ilt', a, 0)),
+ (('flt', 0.0, ('i2f32', a)), ('ilt', 0, a)),
+
# 0.0 < fabs(a)
# fabs(a) > 0.0
# fabs(a) != 0.0 because fabs(a) must be >= 0
# a != 0.0
- (('flt', 0.0, ('fabs', a)), ('fne', a, 0.0)),
+ (('~flt', 0.0, ('fabs', a)), ('fne', a, 0.0)),
+
+ # -fabs(a) < 0.0
+ # fabs(a) > 0.0
+ (('~flt', ('fneg', ('fabs', a)), 0.0), ('fne', a, 0.0)),
(('fmax', ('b2f(is_used_once)', a), ('b2f', b)), ('b2f', ('ior', a, b))),
(('fmax', ('fneg(is_used_once)', ('b2f(is_used_once)', a)), ('fneg', ('b2f', b))), ('fneg', ('b2f', ('ior', a, b)))),
(('~bcsel', ('fge', b, a), b, a), ('fmax', a, b)),
(('bcsel', ('inot', a), b, c), ('bcsel', a, c, b)),
(('bcsel', a, ('bcsel', a, b, c), d), ('bcsel', a, b, d)),
+ (('bcsel', a, b, ('bcsel', a, c, d)), ('bcsel', a, b, d)),
+ (('bcsel', a, ('bcsel', b, c, d), ('bcsel(is_used_once)', b, c, 'e')), ('bcsel', b, c, ('bcsel', a, d, 'e'))),
+ (('bcsel', a, ('bcsel(is_used_once)', b, c, d), ('bcsel', b, c, 'e')), ('bcsel', b, c, ('bcsel', a, d, 'e'))),
+ (('bcsel', a, ('bcsel', b, c, d), ('bcsel(is_used_once)', b, 'e', d)), ('bcsel', b, ('bcsel', a, c, 'e'), d)),
+ (('bcsel', a, ('bcsel(is_used_once)', b, c, d), ('bcsel', b, 'e', d)), ('bcsel', b, ('bcsel', a, c, 'e'), d)),
(('bcsel', a, True, 'b@bool'), ('ior', a, b)),
(('fmin', a, a), a),
(('fmax', a, a), a),
(('imax', a, a), a),
(('umin', a, a), a),
(('umax', a, a), a),
+ (('fmax', a, ('fneg', a)), ('fabs', a)),
+ (('imax', a, ('ineg', a)), ('iabs', a)),
(('fmin', a, ('fneg', a)), ('fneg', ('fabs', a))),
(('imin', a, ('ineg', a)), ('ineg', ('iabs', a))),
(('fmin', a, ('fneg', ('fabs', a))), ('fneg', ('fabs', a))),
(('iand', ('uge(is_used_once)', a, b), ('uge', a, c)), ('uge', a, ('umax', b, c))),
(('iand', ('uge(is_used_once)', a, c), ('uge', b, c)), ('uge', ('umin', a, b), c)),
+ (('ior', 'a@bool', ('ieq', a, False)), True),
+ (('ior', 'a@bool', ('inot', a)), True),
+
(('iand', ('ieq', 'a@32', 0), ('ieq', 'b@32', 0)), ('ieq', ('ior', 'a@32', 'b@32'), 0)),
# These patterns can result when (a < b || a < c) => (a < min(b, c))
(('ixor', a, a), 0),
(('ixor', a, 0), a),
(('inot', ('inot', a)), a),
+ (('ior', ('iand', a, b), b), b),
+ (('ior', ('ior', a, b), b), ('ior', a, b)),
+ (('iand', ('ior', a, b), b), b),
+ (('iand', ('iand', a, b), b), ('iand', a, b)),
# DeMorgan's Laws
(('iand', ('inot', a), ('inot', b)), ('inot', ('ior', a, b))),
(('ior', ('inot', a), ('inot', b)), ('inot', ('iand', a, b))),
(('iabs', ('b2i', a)), ('b2i', a)),
(('inot', ('f2b', a)), ('feq', a, 0.0)),
+ # Ironically, mark these as imprecise because removing the conversions may
+ # preserve more precision than doing the conversions (e.g.,
+ # uint(float(0x81818181u)) == 0x81818200).
+ (('~f2i32', ('i2f32', 'a@32')), a),
+ (('~f2i32', ('u2f32', 'a@32')), a),
+ (('~f2u32', ('i2f32', 'a@32')), a),
+ (('~f2u32', ('u2f32', 'a@32')), a),
+
# Packing and then unpacking does nothing
(('unpack_64_2x32_split_x', ('pack_64_2x32_split', a, b)), a),
(('unpack_64_2x32_split_y', ('pack_64_2x32_split', a, b)), b),
(('b2f@32', a), ('iand', a, 1.0), 'options->lower_b2f'),
]
-print nir_algebraic.AlgebraicPass("nir_opt_algebraic", optimizations).render()
-print nir_algebraic.AlgebraicPass("nir_opt_algebraic_before_ffma",
- before_ffma_optimizations).render()
-print nir_algebraic.AlgebraicPass("nir_opt_algebraic_late",
- late_optimizations).render()
+print(nir_algebraic.AlgebraicPass("nir_opt_algebraic", optimizations).render())
+print(nir_algebraic.AlgebraicPass("nir_opt_algebraic_before_ffma",
+ before_ffma_optimizations).render())
+print(nir_algebraic.AlgebraicPass("nir_opt_algebraic_late",
+ late_optimizations).render())