nir: split exact bit into no_contract/reassoc/transform

Just like float control2.

Reviewed-by: Alyssa Rosenzweig <alyssa.rosenzweig@intel.com>
Reviewed-by: Rhys Perry <pendingchaos02@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/40872>
This commit is contained in:
Georg Lehmann 2026-04-09 17:25:36 +02:00 committed by Marge Bot
parent db38d1a98c
commit a42ac8dec6
3 changed files with 55 additions and 4 deletions

View file

@ -1460,7 +1460,7 @@ typedef enum {
/**
* Operation is associative mathematically (as real numbers), but not
* associative with floating-point math. This can be treated as associative
* iff the operation's exact bit is not set.
* iff the operation's nir_fp_no_reassoc bit is not set.
*/
NIR_OP_IS_INEXACT_ASSOCIATIVE = (1 << 3),
} nir_op_algebraic_property;
@ -1533,7 +1533,7 @@ nir_op_is_selection(nir_op op)
return (nir_op_infos[op].algebraic_properties & NIR_OP_IS_SELECTION) != 0;
}
#define NIR_FP_MATH_CONTROL_BIT_COUNT 4
#define NIR_FP_MATH_CONTROL_BIT_COUNT 6
/**
* Floating point fast math control.
*
@ -1559,6 +1559,23 @@ typedef enum {
*/
nir_fp_preserve_nan = BITFIELD_BIT(2),
/* If not set, allow all optimizations that result in a value closer
* to the infinitely precise result than the original pattern.
* One common example here is fma fusing.
*/
nir_fp_no_contract = BITFIELD_BIT(3),
/* If not set, allow to treat opcodes with NIR_OP_IS_INEXACT_ASSOCIATIVE
* as associative.
*/
nir_fp_no_reassoc = BITFIELD_BIT(4),
/* If not set, allow any optimization that would be valid for real numbers.
*
* Must be set if nir_fp_no_contract or nir_fp_no_reassoc are set.
*/
nir_fp_no_transform = BITFIELD_BIT(5),
/** Indicates that this ALU instruction generates an exact value
*
* This is kind of a mixture of GLSL "precise" and "invariant" and not
@ -1567,8 +1584,13 @@ typedef enum {
* it must ensure that the resulting value is bit-for-bit identical to the
* original, with the exception of undefindness allowed by other
* nir_fp_math_control bits and NaN patterns.
*
* The sub bits allow more fine grained control over the kind of inexact
* optimizations allowed.
*/
nir_fp_exact = BITFIELD_BIT(3),
nir_fp_exact = nir_fp_no_contract |
nir_fp_no_reassoc |
nir_fp_no_transform,
nir_fp_preserve_sz_inf_nan = nir_fp_preserve_signed_zero |
nir_fp_preserve_inf |
@ -1645,6 +1667,24 @@ nir_alu_instr_is_exact(const nir_alu_instr *alu)
return alu->fp_math_ctrl & nir_fp_exact;
}
static inline bool
nir_alu_instr_no_contract(const nir_alu_instr *alu)
{
return alu->fp_math_ctrl & nir_fp_no_contract;
}
static inline bool
nir_alu_instr_no_reassoc(const nir_alu_instr *alu)
{
return alu->fp_math_ctrl & nir_fp_no_reassoc;
}
static inline bool
nir_alu_instr_no_transform(const nir_alu_instr *alu)
{
return alu->fp_math_ctrl & nir_fp_no_transform;
}
static inline unsigned
nir_op_valid_fp_math_ctrl(nir_op op, unsigned fp_math_ctrl)
{

View file

@ -488,7 +488,16 @@ print_fp_math_ctrl(unsigned fp_math_ctrl, print_state *state)
FILE *fp = state->fp;
if (fp_math_ctrl & nir_fp_exact) {
fprintf(fp, "exact");
if ((fp_math_ctrl & nir_fp_exact) == nir_fp_exact) {
fprintf(fp, "exact");
} else if (fp_math_ctrl & nir_fp_no_contract) {
fprintf(fp, "no-contract");
} else if (fp_math_ctrl & nir_fp_no_reassoc) {
fprintf(fp, "no-reassoc");
} else if (fp_math_ctrl & nir_fp_no_transform) {
fprintf(fp, "no-transform");
}
if (fp_math_ctrl & ~nir_fp_exact)
fprintf(fp, ", ");
}

View file

@ -299,6 +299,8 @@ validate_alu_instr(nir_alu_instr *instr, validate_state *state)
validate_def(&instr->def, state);
validate_assert(state, (instr->fp_math_ctrl & ~nir_op_infos[instr->op].valid_fp_math_ctrl) == 0);
validate_assert(state, nir_alu_instr_no_transform(instr) || !nir_alu_instr_no_contract(instr));
validate_assert(state, nir_alu_instr_no_transform(instr) || !nir_alu_instr_no_reassoc(instr));
}
static void