diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/compiler/nir/nir_range_analysis.c | 53 |
1 files changed, 22 insertions, 31 deletions
diff --git a/src/compiler/nir/nir_range_analysis.c b/src/compiler/nir/nir_range_analysis.c index 3acaa4774ae..5b0c39e4922 100644 --- a/src/compiler/nir/nir_range_analysis.c +++ b/src/compiler/nir/nir_range_analysis.c @@ -31,12 +31,6 @@ * the result. */ -static bool -is_not_zero(enum ssa_ranges r) -{ - return r == gt_zero || r == lt_zero || r == ne_zero; -} - static void * pack_data(const struct ssa_result_range r) { @@ -271,7 +265,11 @@ analyze_expression(const nir_alu_instr *instr, unsigned src, ASSERT_TABLE_IS_COMMUTATIVE(fadd_table); ASSERT_TABLE_IS_DIAGONAL(fadd_table); - /* ge_zero: ge_zero * ge_zero + /* Due to flush-to-zero semanatics of floating-point numbers with very + * small mangnitudes, we can never really be sure a result will be + * non-zero. + * + * ge_zero: ge_zero * ge_zero * | ge_zero * gt_zero * | ge_zero * eq_zero * | le_zero * lt_zero @@ -280,9 +278,7 @@ analyze_expression(const nir_alu_instr *instr, unsigned src, * | gt_zero * ge_zero # Multiplication is commutative * | eq_zero * ge_zero # Multiplication is commutative * | a * a # Left source == right source - * ; - * - * gt_zero: gt_zero * gt_zero + * | gt_zero * gt_zero * | lt_zero * lt_zero * ; * @@ -291,19 +287,10 @@ analyze_expression(const nir_alu_instr *instr, unsigned src, * | lt_zero * ge_zero # Multiplication is commutative * | le_zero * ge_zero # Multiplication is commutative * | le_zero * gt_zero - * ; - * - * lt_zero: lt_zero * gt_zero + * | lt_zero * gt_zero * | gt_zero * lt_zero # Multiplication is commutative * ; * - * ne_zero: ne_zero * gt_zero - * | ne_zero * lt_zero - * | gt_zero * ne_zero # Multiplication is commutative - * | lt_zero * ne_zero # Multiplication is commutative - * | ne_zero * ne_zero - * ; - * * eq_zero: eq_zero * <any> * <any> * eq_zero # Multiplication is commutative * @@ -312,11 +299,11 @@ analyze_expression(const nir_alu_instr *instr, unsigned src, static const enum ssa_ranges fmul_table[last_range + 1][last_range + 1] = { /* left\right unknown lt_zero le_zero gt_zero ge_zero ne_zero eq_zero */ /* unknown */ { _______, _______, _______, _______, _______, _______, eq_zero }, - /* lt_zero */ { _______, gt_zero, ge_zero, lt_zero, le_zero, ne_zero, eq_zero }, + /* lt_zero */ { _______, ge_zero, ge_zero, le_zero, le_zero, _______, eq_zero }, /* le_zero */ { _______, ge_zero, ge_zero, le_zero, le_zero, _______, eq_zero }, - /* gt_zero */ { _______, lt_zero, le_zero, gt_zero, ge_zero, ne_zero, eq_zero }, + /* gt_zero */ { _______, le_zero, le_zero, ge_zero, ge_zero, _______, eq_zero }, /* ge_zero */ { _______, le_zero, le_zero, ge_zero, ge_zero, _______, eq_zero }, - /* ne_zero */ { _______, ne_zero, _______, ne_zero, _______, ne_zero, eq_zero }, + /* ne_zero */ { _______, _______, _______, _______, _______, _______, eq_zero }, /* eq_zero */ { eq_zero, eq_zero, eq_zero, eq_zero, eq_zero, eq_zero, eq_zero } }; @@ -601,11 +588,13 @@ analyze_expression(const nir_alu_instr *instr, unsigned src, /* x * x => ge_zero */ if (left.range != eq_zero && nir_alu_srcs_equal(alu, alu, 0, 1)) { - /* x * x => ge_zero or gt_zero depending on the range of x. */ - r.range = is_not_zero(left.range) ? gt_zero : ge_zero; + /* Even if x > 0, the result of x*x can be zero when x is, for + * example, a subnormal number. + */ + r.range = ge_zero; } else if (left.range != eq_zero && nir_alu_srcs_negative_equal(alu, alu, 0, 1)) { - /* -x * x => le_zero or lt_zero depending on the range of x. */ - r.range = is_not_zero(left.range) ? lt_zero : le_zero; + /* -x * x => le_zero. */ + r.range = le_zero; } else r.range = fmul_table[left.range][right.range]; @@ -732,11 +721,13 @@ analyze_expression(const nir_alu_instr *instr, unsigned src, enum ssa_ranges fmul_range; if (first.range != eq_zero && nir_alu_srcs_equal(alu, alu, 0, 1)) { - /* x * x => ge_zero or gt_zero depending on the range of x. */ - fmul_range = is_not_zero(first.range) ? gt_zero : ge_zero; + /* See handling of nir_op_fmul for explanation of why ge_zero is the + * range. + */ + fmul_range = ge_zero; } else if (first.range != eq_zero && nir_alu_srcs_negative_equal(alu, alu, 0, 1)) { - /* -x * x => le_zero or lt_zero depending on the range of x. */ - fmul_range = is_not_zero(first.range) ? lt_zero : le_zero; + /* -x * x => le_zero */ + fmul_range = le_zero; } else fmul_range = fmul_table[first.range][second.range]; |