blob: 73bb3fee20dd2ff71f8f150b3d1803976e13c8a4 [file] [log] [blame]
#include "brw_nir.h"
#include "nir.h"
#include "nir_search.h"
#include "nir_search_helpers.h"
#ifndef NIR_OPT_ALGEBRAIC_STRUCT_DEFS
#define NIR_OPT_ALGEBRAIC_STRUCT_DEFS
struct transform {
const nir_search_expression *search;
const nir_search_value *replace;
unsigned condition_offset;
};
#endif
static const nir_search_variable search1_0 = {
{ nir_search_value_variable, 0 },
0, /* x */
false,
nir_type_invalid,
NULL,
};
static const nir_search_expression search1 = {
{ nir_search_value_expression, 0 },
false,
nir_op_fcos,
{ &search1_0.value },
NULL,
};
static const nir_search_variable replace1_0_0 = {
{ nir_search_value_variable, 0 },
0, /* x */
false,
nir_type_invalid,
NULL,
};
static const nir_search_expression replace1_0 = {
{ nir_search_value_expression, 0 },
false,
nir_op_fcos,
{ &replace1_0_0.value },
NULL,
};
static const nir_search_constant replace1_1 = {
{ nir_search_value_constant, 0 },
nir_type_float, { 0x3fefffc115df6556 /* 0.99997 */ },
};
static const nir_search_expression replace1 = {
{ nir_search_value_expression, 0 },
false,
nir_op_fmul,
{ &replace1_0.value, &replace1_1.value },
NULL,
};
static const struct transform brw_nir_apply_trig_workarounds_fcos_xforms[] = {
{ &search1, &replace1.value, 0 },
};
static const nir_search_variable search0_0 = {
{ nir_search_value_variable, 0 },
0, /* x */
false,
nir_type_invalid,
NULL,
};
static const nir_search_expression search0 = {
{ nir_search_value_expression, 0 },
false,
nir_op_fsin,
{ &search0_0.value },
NULL,
};
static const nir_search_variable replace0_0_0 = {
{ nir_search_value_variable, 0 },
0, /* x */
false,
nir_type_invalid,
NULL,
};
static const nir_search_expression replace0_0 = {
{ nir_search_value_expression, 0 },
false,
nir_op_fsin,
{ &replace0_0_0.value },
NULL,
};
static const nir_search_constant replace0_1 = {
{ nir_search_value_constant, 0 },
nir_type_float, { 0x3fefffc115df6556 /* 0.99997 */ },
};
static const nir_search_expression replace0 = {
{ nir_search_value_expression, 0 },
false,
nir_op_fmul,
{ &replace0_0.value, &replace0_1.value },
NULL,
};
static const struct transform brw_nir_apply_trig_workarounds_fsin_xforms[] = {
{ &search0, &replace0.value, 0 },
};
static bool
brw_nir_apply_trig_workarounds_block(nir_block *block, const bool *condition_flags,
void *mem_ctx)
{
bool progress = false;
nir_foreach_instr_reverse_safe(instr, block) {
if (instr->type != nir_instr_type_alu)
continue;
nir_alu_instr *alu = nir_instr_as_alu(instr);
if (!alu->dest.dest.is_ssa)
continue;
switch (alu->op) {
case nir_op_fcos:
for (unsigned i = 0; i < ARRAY_SIZE(brw_nir_apply_trig_workarounds_fcos_xforms); i++) {
const struct transform *xform = &brw_nir_apply_trig_workarounds_fcos_xforms[i];
if (condition_flags[xform->condition_offset] &&
nir_replace_instr(alu, xform->search, xform->replace,
mem_ctx)) {
progress = true;
break;
}
}
break;
case nir_op_fsin:
for (unsigned i = 0; i < ARRAY_SIZE(brw_nir_apply_trig_workarounds_fsin_xforms); i++) {
const struct transform *xform = &brw_nir_apply_trig_workarounds_fsin_xforms[i];
if (condition_flags[xform->condition_offset] &&
nir_replace_instr(alu, xform->search, xform->replace,
mem_ctx)) {
progress = true;
break;
}
}
break;
default:
break;
}
}
return progress;
}
static bool
brw_nir_apply_trig_workarounds_impl(nir_function_impl *impl, const bool *condition_flags)
{
void *mem_ctx = ralloc_parent(impl);
bool progress = false;
nir_foreach_block_reverse(block, impl) {
progress |= brw_nir_apply_trig_workarounds_block(block, condition_flags, mem_ctx);
}
if (progress)
nir_metadata_preserve(impl, nir_metadata_block_index |
nir_metadata_dominance);
return progress;
}
bool
brw_nir_apply_trig_workarounds(nir_shader *shader)
{
bool progress = false;
bool condition_flags[1];
const nir_shader_compiler_options *options = shader->options;
(void) options;
condition_flags[0] = true;
nir_foreach_function(function, shader) {
if (function->impl)
progress |= brw_nir_apply_trig_workarounds_impl(function->impl, condition_flags);
}
return progress;
}