mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-05 00:58:05 +02:00
nir: add is_a_number analysis for ffma
Foz-DB Navi21: Totals from 508 (0.64% of 79789) affected shaders: Instrs: 796183 -> 795838 (-0.04%) CodeSize: 4303420 -> 4303384 (-0.00%); split: -0.00%, +0.00% Latency: 7806095 -> 7805458 (-0.01%); split: -0.01%, +0.00% InvThroughput: 1377028 -> 1376824 (-0.01%); split: -0.01%, +0.00% Copies: 63297 -> 63299 (+0.00%); split: -0.00%, +0.00% PreVGPRs: 29818 -> 29819 (+0.00%) VALU: 562067 -> 561885 (-0.03%); split: -0.03%, +0.00% SALU: 89896 -> 89733 (-0.18%) Reviewed-by: Alyssa Rosenzweig <alyssa@rosenzweig.io> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/34125>
This commit is contained in:
parent
cb6d035925
commit
a6fd9f488a
1 changed files with 43 additions and 32 deletions
|
|
@ -527,6 +527,35 @@ get_fp_key(struct analysis_query *q)
|
|||
return ptr | type_encoding;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
fmul_is_a_number(const struct ssa_result_range left, const struct ssa_result_range right, bool mulz)
|
||||
{
|
||||
if (mulz) {
|
||||
/* nir_op_fmulz: unlike nir_op_fmul, 0 * ±Inf is a number. */
|
||||
return left.is_a_number && right.is_a_number;
|
||||
} else {
|
||||
/* Mulitpliation produces NaN for X * NaN and for 0 * ±Inf. If both
|
||||
* operands are numbers and either both are finite or one is finite and
|
||||
* the other cannot be zero, then the result must be a number.
|
||||
*/
|
||||
return (left.is_a_number && right.is_a_number) &&
|
||||
((left.is_finite && right.is_finite) ||
|
||||
(!is_not_zero(left.range) && right.is_finite) ||
|
||||
(left.is_finite && !is_not_zero(right.range)));
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool
|
||||
fadd_is_a_number(const struct ssa_result_range left, const struct ssa_result_range right)
|
||||
{
|
||||
/* X + Y is NaN if either operand is NaN or if one operand is +Inf and
|
||||
* the other is -Inf. If neither operand is NaN and at least one of the
|
||||
* operands is finite, then the result cannot be NaN.
|
||||
*/
|
||||
return left.is_a_number && right.is_a_number &&
|
||||
(left.is_finite || right.is_finite);
|
||||
}
|
||||
|
||||
/**
|
||||
* Analyze an expression to determine the range of its result
|
||||
*
|
||||
|
|
@ -814,13 +843,7 @@ process_fp_query(struct analysis_state *state, struct analysis_query *aq, uint32
|
|||
|
||||
r.is_integral = left.is_integral && right.is_integral;
|
||||
r.range = fadd_table[left.range][right.range];
|
||||
|
||||
/* X + Y is NaN if either operand is NaN or if one operand is +Inf and
|
||||
* the other is -Inf. If neither operand is NaN and at least one of the
|
||||
* operands is finite, then the result cannot be NaN.
|
||||
*/
|
||||
r.is_a_number = left.is_a_number && right.is_a_number &&
|
||||
(left.is_finite || right.is_finite);
|
||||
r.is_a_number = fadd_is_a_number(left, right);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -1032,23 +1055,12 @@ process_fp_query(struct analysis_state *state, struct analysis_query *aq, uint32
|
|||
} else if (left.range != eq_zero && nir_alu_srcs_negative_equal(alu, alu, 0, 1)) {
|
||||
/* -x * x => le_zero. */
|
||||
r.range = le_zero;
|
||||
} else
|
||||
r.range = fmul_table[left.range][right.range];
|
||||
|
||||
if (alu->op == nir_op_fmul) {
|
||||
/* Mulitpliation produces NaN for X * NaN and for 0 * ±Inf. If both
|
||||
* operands are numbers and either both are finite or one is finite and
|
||||
* the other cannot be zero, then the result must be a number.
|
||||
*/
|
||||
r.is_a_number = (left.is_a_number && right.is_a_number) &&
|
||||
((left.is_finite && right.is_finite) ||
|
||||
(!is_not_zero(left.range) && right.is_finite) ||
|
||||
(left.is_finite && !is_not_zero(right.range)));
|
||||
} else {
|
||||
/* nir_op_fmulz: unlike nir_op_fmul, 0 * ±Inf is a number. */
|
||||
r.is_a_number = left.is_a_number && right.is_a_number;
|
||||
r.range = fmul_table[left.range][right.range];
|
||||
}
|
||||
|
||||
r.is_a_number = fmul_is_a_number(left, right, alu->op == nir_op_fmulz);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -1359,26 +1371,25 @@ process_fp_query(struct analysis_state *state, struct analysis_query *aq, uint32
|
|||
const struct ssa_result_range second = unpack_data(src_res[1]);
|
||||
const struct ssa_result_range third = unpack_data(src_res[2]);
|
||||
|
||||
r.is_integral = first.is_integral && second.is_integral &&
|
||||
third.is_integral;
|
||||
|
||||
/* Various cases can result in NaN, so assume the worst. */
|
||||
r.is_a_number = false;
|
||||
|
||||
enum ssa_ranges fmul_range;
|
||||
struct ssa_result_range fmul_result;
|
||||
fmul_result.is_integral = first.is_integral && second.is_integral;
|
||||
fmul_result.is_finite = false;
|
||||
fmul_result.is_a_number = fmul_is_a_number(first, third, alu->op == nir_op_ffmaz);
|
||||
|
||||
if (first.range != eq_zero && nir_alu_srcs_equal(alu, alu, 0, 1)) {
|
||||
/* See handling of nir_op_fmul for explanation of why ge_zero is the
|
||||
* range.
|
||||
*/
|
||||
fmul_range = ge_zero;
|
||||
fmul_result.range = ge_zero;
|
||||
} else if (first.range != eq_zero && nir_alu_srcs_negative_equal(alu, alu, 0, 1)) {
|
||||
/* -x * x => le_zero */
|
||||
fmul_range = le_zero;
|
||||
fmul_result.range = le_zero;
|
||||
} else
|
||||
fmul_range = fmul_table[first.range][second.range];
|
||||
fmul_result.range = fmul_table[first.range][second.range];
|
||||
|
||||
r.range = fadd_table[fmul_range][third.range];
|
||||
r.range = fadd_table[fmul_result.range][third.range];
|
||||
r.is_integral = fmul_result.is_integral && third.is_integral;
|
||||
r.is_a_number = fadd_is_a_number(fmul_result, third);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue