aboutsummaryrefslogtreecommitdiff
path: root/mesalib/src/glsl
diff options
context:
space:
mode:
authormarha <marha@users.sourceforge.net>2015-03-22 14:10:47 +0100
committermarha <marha@users.sourceforge.net>2015-03-22 14:10:47 +0100
commit3bc24b271f45f9f33484b8cf53b44f33f7e8a237 (patch)
tree193651a94adb3804e800747e993d07b92688e4d4 /mesalib/src/glsl
parentc646056120fe14e4c4ccf81bac5d78d61225a8e8 (diff)
parent82c8df11062f72a7d467e26cedbbd8b322ff7a70 (diff)
downloadvcxsrv-3bc24b271f45f9f33484b8cf53b44f33f7e8a237.tar.gz
vcxsrv-3bc24b271f45f9f33484b8cf53b44f33f7e8a237.tar.bz2
vcxsrv-3bc24b271f45f9f33484b8cf53b44f33f7e8a237.zip
Merge remote-tracking branch 'origin/released'
Conflicts: mesalib/src/mapi/glapi/glapi.h mesalib/src/mapi/glapi/glapi_nop.c mesalib/src/mesa/main/bufferobj.c
Diffstat (limited to 'mesalib/src/glsl')
-rw-r--r--mesalib/src/glsl/SConscript20
-rw-r--r--mesalib/src/glsl/ast_to_hir.cpp6
-rwxr-xr-xmesalib/src/glsl/builtin_functions.cpp2
-rw-r--r--mesalib/src/glsl/glsl_parser.yy4
-rw-r--r--mesalib/src/glsl/ir.h4
-rwxr-xr-xmesalib/src/glsl/ir_constant_expression.cpp18
-rw-r--r--mesalib/src/glsl/linker.cpp5
-rw-r--r--mesalib/src/glsl/list.h4
-rw-r--r--mesalib/src/glsl/nir/glsl_to_nir.cpp61
-rw-r--r--mesalib/src/glsl/nir/glsl_to_nir.h4
-rw-r--r--mesalib/src/glsl/nir/nir.c12
-rw-r--r--mesalib/src/glsl/nir/nir.h23
-rw-r--r--mesalib/src/glsl/nir/nir_constant_expressions.py15
-rw-r--r--mesalib/src/glsl/nir/nir_intrinsics.h2
-rw-r--r--mesalib/src/glsl/nir/nir_lower_io.c90
-rw-r--r--mesalib/src/glsl/nir/nir_lower_system_values.c6
-rw-r--r--mesalib/src/glsl/nir/nir_lower_vars_to_ssa.c123
-rw-r--r--mesalib/src/glsl/nir/nir_opcodes.py2
-rw-r--r--mesalib/src/glsl/nir/nir_opt_algebraic.py4
-rw-r--r--mesalib/src/glsl/nir/nir_opt_peephole_select.c112
-rw-r--r--mesalib/src/glsl/nir/nir_print.c20
-rw-r--r--mesalib/src/glsl/nir/nir_validate.c16
-rw-r--r--mesalib/src/glsl/nir/nir_worklist.c10
-rw-r--r--mesalib/src/glsl/nir/nir_worklist.h4
-rw-r--r--mesalib/src/glsl/opt_algebraic.cpp15
25 files changed, 309 insertions, 273 deletions
diff --git a/mesalib/src/glsl/SConscript b/mesalib/src/glsl/SConscript
index 26de455f0..284b37584 100644
--- a/mesalib/src/glsl/SConscript
+++ b/mesalib/src/glsl/SConscript
@@ -24,22 +24,26 @@ env.Prepend(LIBS = [mesautil])
# Make glcpp-parse.h and glsl_parser.h reachable from the include path.
env.Append(CPPPATH = [Dir('.').abspath, Dir('glcpp').abspath])
-env.Append(YACCFLAGS = '-d -p "glcpp_parser_"')
+glcpp_env = env.Clone()
+glcpp_env.Append(YACCFLAGS = [
+ '-d',
+ '-p', 'glcpp_parser_'
+])
-parser_env = env.Clone()
-parser_env.Append(YACCFLAGS = [
+glsl_env = env.Clone()
+glsl_env.Append(YACCFLAGS = [
'--defines=%s' % File('glsl_parser.h').abspath,
'-p', '_mesa_glsl_',
])
# without this line scons will expect "glsl_parser.hpp" instead of
# "glsl_parser.h", causing glsl_parser.cpp to be regenerated every time
-parser_env['YACCHXXFILESUFFIX'] = '.h'
+glsl_env['YACCHXXFILESUFFIX'] = '.h'
-glcpp_lexer = env.CFile('glcpp/glcpp-lex.c', 'glcpp/glcpp-lex.l')
-glcpp_parser = env.CFile('glcpp/glcpp-parse.c', 'glcpp/glcpp-parse.y')
-glsl_lexer = parser_env.CXXFile('glsl_lexer.cpp', 'glsl_lexer.ll')
-glsl_parser = parser_env.CXXFile('glsl_parser.cpp', 'glsl_parser.yy')
+glcpp_lexer = glcpp_env.CFile('glcpp/glcpp-lex.c', 'glcpp/glcpp-lex.l')
+glcpp_parser = glcpp_env.CFile('glcpp/glcpp-parse.c', 'glcpp/glcpp-parse.y')
+glsl_lexer = glsl_env.CXXFile('glsl_lexer.cpp', 'glsl_lexer.ll')
+glsl_parser = glsl_env.CXXFile('glsl_parser.cpp', 'glsl_parser.yy')
# common generated sources
glsl_sources = [
diff --git a/mesalib/src/glsl/ast_to_hir.cpp b/mesalib/src/glsl/ast_to_hir.cpp
index acb5c763c..d387b2e35 100644
--- a/mesalib/src/glsl/ast_to_hir.cpp
+++ b/mesalib/src/glsl/ast_to_hir.cpp
@@ -1617,6 +1617,12 @@ ast_expression::do_hir(exec_list *instructions,
&& cond_val != NULL) {
result = cond_val->value.b[0] ? op[1] : op[2];
} else {
+ /* The copy to conditional_tmp reads the whole array. */
+ if (type->is_array()) {
+ mark_whole_array_access(op[1]);
+ mark_whole_array_access(op[2]);
+ }
+
ir_variable *const tmp =
new(ctx) ir_variable(type, "conditional_tmp", ir_var_temporary);
instructions->push_tail(tmp);
diff --git a/mesalib/src/glsl/builtin_functions.cpp b/mesalib/src/glsl/builtin_functions.cpp
index 28bcfdb3c..e46db8552 100755
--- a/mesalib/src/glsl/builtin_functions.cpp
+++ b/mesalib/src/glsl/builtin_functions.cpp
@@ -201,7 +201,7 @@ static bool
shader_packing_or_es3(const _mesa_glsl_parse_state *state)
{
return state->ARB_shading_language_packing_enable ||
- state->is_version(400, 300);
+ state->is_version(420, 300);
}
static bool
diff --git a/mesalib/src/glsl/glsl_parser.yy b/mesalib/src/glsl/glsl_parser.yy
index 4a2ebeb40..d33fcfe6b 100644
--- a/mesalib/src/glsl/glsl_parser.yy
+++ b/mesalib/src/glsl/glsl_parser.yy
@@ -35,6 +35,10 @@
#include "glsl_types.h"
#include "main/context.h"
+#ifdef _MSC_VER
+#pragma warning( disable : 4065 ) // switch statement contains 'default' but no 'case' labels
+#endif
+
#undef yyerror
static void yyerror(YYLTYPE *loc, _mesa_glsl_parse_state *st, const char *msg)
diff --git a/mesalib/src/glsl/ir.h b/mesalib/src/glsl/ir.h
index 25f2ecada..fdc22edf1 100644
--- a/mesalib/src/glsl/ir.h
+++ b/mesalib/src/glsl/ir.h
@@ -119,6 +119,7 @@ public:
/*@{*/
class ir_rvalue *as_rvalue()
{
+ assume(this != NULL);
if (ir_type == ir_type_dereference_array ||
ir_type == ir_type_dereference_record ||
ir_type == ir_type_dereference_variable ||
@@ -132,6 +133,7 @@ public:
class ir_dereference *as_dereference()
{
+ assume(this != NULL);
if (ir_type == ir_type_dereference_array ||
ir_type == ir_type_dereference_record ||
ir_type == ir_type_dereference_variable)
@@ -141,6 +143,7 @@ public:
class ir_jump *as_jump()
{
+ assume(this != NULL);
if (ir_type == ir_type_loop_jump ||
ir_type == ir_type_return ||
ir_type == ir_type_discard)
@@ -151,6 +154,7 @@ public:
#define AS_CHILD(TYPE) \
class ir_##TYPE * as_##TYPE() \
{ \
+ assume(this != NULL); \
return ir_type == ir_type_##TYPE ? (ir_##TYPE *) this : NULL; \
}
AS_CHILD(variable)
diff --git a/mesalib/src/glsl/ir_constant_expression.cpp b/mesalib/src/glsl/ir_constant_expression.cpp
index e24cad98d..d198276c6 100755
--- a/mesalib/src/glsl/ir_constant_expression.cpp
+++ b/mesalib/src/glsl/ir_constant_expression.cpp
@@ -35,6 +35,7 @@
#include <math.h>
#include "main/core.h" /* for MAX2, MIN2, CLAMP */
+#include "util/rounding.h" /* for _mesa_roundeven */
#include "ir.h"
#include "glsl_types.h"
#include "program/hash_table.h"
@@ -238,8 +239,8 @@ pack_snorm_1x8(float x)
* We must first cast the float to an int, because casting a negative
* float to a uint is undefined.
*/
- return (uint8_t) (int8_t)
- _mesa_round_to_even(CLAMP(x, -1.0f, +1.0f) * 127.0f);
+ return (uint8_t) (int)
+ _mesa_roundevenf(CLAMP(x, -1.0f, +1.0f) * 127.0f);
}
/**
@@ -260,8 +261,8 @@ pack_snorm_1x16(float x)
* We must first cast the float to an int, because casting a negative
* float to a uint is undefined.
*/
- return (uint16_t) (int16_t)
- _mesa_round_to_even(CLAMP(x, -1.0f, +1.0f) * 32767.0f);
+ return (uint16_t) (int)
+ _mesa_roundevenf(CLAMP(x, -1.0f, +1.0f) * 32767.0f);
}
/**
@@ -315,7 +316,7 @@ pack_unorm_1x8(float x)
*
* packUnorm4x8: round(clamp(c, 0, +1) * 255.0)
*/
- return (uint8_t) _mesa_round_to_even(CLAMP(x, 0.0f, 1.0f) * 255.0f);
+ return (uint8_t) (int) _mesa_roundevenf(CLAMP(x, 0.0f, 1.0f) * 255.0f);
}
/**
@@ -333,7 +334,8 @@ pack_unorm_1x16(float x)
*
* packUnorm2x16: round(clamp(c, 0, +1) * 65535.0)
*/
- return (uint16_t) _mesa_round_to_even(CLAMP(x, 0.0f, 1.0f) * 65535.0f);
+ return (uint16_t) (int)
+ _mesa_roundevenf(CLAMP(x, 0.0f, 1.0f) * 65535.0f);
}
/**
@@ -726,9 +728,9 @@ ir_expression::constant_expression_value(struct hash_table *variable_context)
case ir_unop_round_even:
for (unsigned c = 0; c < op[0]->type->components(); c++) {
if (op[0]->type->base_type == GLSL_TYPE_DOUBLE)
- data.d[c] = _mesa_round_to_even(op[0]->value.d[c]);
+ data.d[c] = _mesa_roundeven(op[0]->value.d[c]);
else
- data.f[c] = _mesa_round_to_even(op[0]->value.f[c]);
+ data.f[c] = _mesa_roundevenf(op[0]->value.f[c]);
}
break;
diff --git a/mesalib/src/glsl/linker.cpp b/mesalib/src/glsl/linker.cpp
index 0c4467779..4349f0973 100644
--- a/mesalib/src/glsl/linker.cpp
+++ b/mesalib/src/glsl/linker.cpp
@@ -2542,8 +2542,9 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
goto done;
}
- prog->ARB_fragment_coord_conventions_enable |=
- prog->Shaders[i]->ARB_fragment_coord_conventions_enable;
+ if (prog->Shaders[i]->ARB_fragment_coord_conventions_enable) {
+ prog->ARB_fragment_coord_conventions_enable = true;
+ }
gl_shader_stage shader_type = prog->Shaders[i]->Stage;
shader_list[shader_type][num_shaders[shader_type]] = prog->Shaders[i];
diff --git a/mesalib/src/glsl/list.h b/mesalib/src/glsl/list.h
index 8554a4652..d855240cb 100644
--- a/mesalib/src/glsl/list.h
+++ b/mesalib/src/glsl/list.h
@@ -692,7 +692,7 @@ inline void exec_node::insert_before(exec_list *before)
exec_node_data(__type, (__list)->head, __field), \
* __next = \
exec_node_data(__type, (__node)->__field.next, __field); \
- __next != NULL; \
+ (__node)->__field.next != NULL; \
__node = __next, __next = \
exec_node_data(__type, (__next)->__field.next, __field))
@@ -701,7 +701,7 @@ inline void exec_node::insert_before(exec_list *before)
exec_node_data(__type, (__list)->tail_pred, __field), \
* __prev = \
exec_node_data(__type, (__node)->__field.prev, __field); \
- __prev != NULL; \
+ (__node)->__field.prev != NULL; \
__node = __prev, __prev = \
exec_node_data(__type, (__prev)->__field.prev, __field))
diff --git a/mesalib/src/glsl/nir/glsl_to_nir.cpp b/mesalib/src/glsl/nir/glsl_to_nir.cpp
index adef19c80..357944da6 100644
--- a/mesalib/src/glsl/nir/glsl_to_nir.cpp
+++ b/mesalib/src/glsl/nir/glsl_to_nir.cpp
@@ -43,7 +43,7 @@ namespace {
class nir_visitor : public ir_visitor
{
public:
- nir_visitor(nir_shader *shader, bool supports_ints);
+ nir_visitor(nir_shader *shader, gl_shader_stage stage);
~nir_visitor();
virtual void visit(ir_variable *);
@@ -83,6 +83,7 @@ private:
bool supports_ints;
nir_shader *shader;
+ gl_shader_stage stage;
nir_function_impl *impl;
exec_list *cf_node_list;
nir_instr *result; /* result of the expression tree last visited */
@@ -124,59 +125,24 @@ private:
}; /* end of anonymous namespace */
-static const nir_shader_compiler_options default_options = {
-};
-
nir_shader *
-glsl_to_nir(exec_list *ir, _mesa_glsl_parse_state *state,
- bool native_integers)
+glsl_to_nir(struct gl_shader *sh, const nir_shader_compiler_options *options)
{
- const nir_shader_compiler_options *options;
-
- if (state) {
- struct gl_context *ctx = state->ctx;
- struct gl_shader_compiler_options *gl_options =
- &ctx->Const.ShaderCompilerOptions[state->stage];
-
- if (!gl_options->NirOptions) {
- nir_shader_compiler_options *new_options =
- rzalloc(ctx, nir_shader_compiler_options);
- options = gl_options->NirOptions = new_options;
-
- if (gl_options->EmitNoPow)
- new_options->lower_fpow = true;
- } else {
- options = gl_options->NirOptions;
- }
- } else {
- options = &default_options;
- }
-
nir_shader *shader = nir_shader_create(NULL, options);
- if (state) {
- shader->num_user_structures = state->num_user_structures;
- shader->user_structures = ralloc_array(shader, glsl_type *,
- shader->num_user_structures);
- memcpy(shader->user_structures, state->user_structures,
- shader->num_user_structures * sizeof(glsl_type *));
- } else {
- shader->num_user_structures = 0;
- shader->user_structures = NULL;
- }
-
- nir_visitor v1(shader, native_integers);
+ nir_visitor v1(shader, sh->Stage);
nir_function_visitor v2(&v1);
- v2.run(ir);
- visit_exec_list(ir, &v1);
+ v2.run(sh->ir);
+ visit_exec_list(sh->ir, &v1);
return shader;
}
-nir_visitor::nir_visitor(nir_shader *shader, bool supports_ints)
+nir_visitor::nir_visitor(nir_shader *shader, gl_shader_stage stage)
{
- this->supports_ints = supports_ints;
+ this->supports_ints = shader->options->native_integers;
this->shader = shader;
+ this->stage = stage;
this->is_global = true;
this->var_table = _mesa_hash_table_create(NULL, _mesa_hash_pointer,
_mesa_key_pointer_equal);
@@ -285,7 +251,8 @@ nir_visitor::visit(ir_variable *ir)
break;
case ir_var_shader_in:
- if (ir->data.location == VARYING_SLOT_FACE) {
+ if (stage == MESA_SHADER_FRAGMENT &&
+ ir->data.location == VARYING_SLOT_FACE) {
/* For whatever reason, GLSL IR makes gl_FrontFacing an input */
var->data.location = SYSTEM_VALUE_FRONT_FACE;
var->data.mode = nir_var_system_value;
@@ -385,15 +352,15 @@ nir_visitor::visit(ir_variable *ir)
break;
case nir_var_shader_in:
- _mesa_hash_table_insert(shader->inputs, var->name, var);
+ exec_list_push_tail(&shader->inputs, &var->node);
break;
case nir_var_shader_out:
- _mesa_hash_table_insert(shader->outputs, var->name, var);
+ exec_list_push_tail(&shader->outputs, &var->node);
break;
case nir_var_uniform:
- _mesa_hash_table_insert(shader->uniforms, var->name, var);
+ exec_list_push_tail(&shader->uniforms, &var->node);
break;
case nir_var_system_value:
diff --git a/mesalib/src/glsl/nir/glsl_to_nir.h b/mesalib/src/glsl/nir/glsl_to_nir.h
index 58b2cee6a..3801e8c55 100644
--- a/mesalib/src/glsl/nir/glsl_to_nir.h
+++ b/mesalib/src/glsl/nir/glsl_to_nir.h
@@ -32,8 +32,8 @@
extern "C" {
#endif
-nir_shader *glsl_to_nir(exec_list * ir, _mesa_glsl_parse_state *state,
- bool native_integers);
+nir_shader *glsl_to_nir(struct gl_shader *sh,
+ const nir_shader_compiler_options *options);
#ifdef __cplusplus
}
diff --git a/mesalib/src/glsl/nir/nir.c b/mesalib/src/glsl/nir/nir.c
index ab57fd4e2..6459d5108 100644
--- a/mesalib/src/glsl/nir/nir.c
+++ b/mesalib/src/glsl/nir/nir.c
@@ -33,18 +33,12 @@ nir_shader_create(void *mem_ctx, const nir_shader_compiler_options *options)
{
nir_shader *shader = ralloc(mem_ctx, nir_shader);
- shader->uniforms = _mesa_hash_table_create(shader, _mesa_key_hash_string,
- _mesa_key_string_equal);
- shader->inputs = _mesa_hash_table_create(shader, _mesa_key_hash_string,
- _mesa_key_string_equal);
- shader->outputs = _mesa_hash_table_create(shader, _mesa_key_hash_string,
- _mesa_key_string_equal);
+ exec_list_make_empty(&shader->uniforms);
+ exec_list_make_empty(&shader->inputs);
+ exec_list_make_empty(&shader->outputs);
shader->options = options;
- shader->num_user_structures = 0;
- shader->user_structures = NULL;
-
exec_list_make_empty(&shader->functions);
exec_list_make_empty(&shader->registers);
exec_list_make_empty(&shader->globals);
diff --git a/mesalib/src/glsl/nir/nir.h b/mesalib/src/glsl/nir/nir.h
index d5df59609..29fe94243 100644
--- a/mesalib/src/glsl/nir/nir.h
+++ b/mesalib/src/glsl/nir/nir.h
@@ -1370,17 +1370,23 @@ typedef struct nir_shader_compiler_options {
bool lower_fsqrt;
/** lowers fneg and ineg to fsub and isub. */
bool lower_negate;
+
+ /**
+ * Does the driver support real 32-bit integers? (Otherwise, integers
+ * are simulated by floats.)
+ */
+ bool native_integers;
} nir_shader_compiler_options;
typedef struct nir_shader {
/** hash table of name -> uniform nir_variable */
- struct hash_table *uniforms;
+ struct exec_list uniforms;
/** hash table of name -> input nir_variable */
- struct hash_table *inputs;
+ struct exec_list inputs;
/** hash table of name -> output nir_variable */
- struct hash_table *outputs;
+ struct exec_list outputs;
/** Set of driver-specific options for the shader.
*
@@ -1400,10 +1406,6 @@ typedef struct nir_shader {
/** list of global register in the shader */
struct exec_list registers;
- /** structures used in this shader */
- unsigned num_user_structures;
- struct glsl_type **user_structures;
-
/** next available global register index */
unsigned reg_alloc;
@@ -1575,6 +1577,13 @@ void nir_lower_global_vars_to_local(nir_shader *shader);
void nir_lower_locals_to_regs(nir_shader *shader);
+void nir_assign_var_locations_scalar(struct exec_list *var_list,
+ unsigned *size);
+void nir_assign_var_locations_scalar_direct_first(nir_shader *shader,
+ struct exec_list *var_list,
+ unsigned *direct_size,
+ unsigned *size);
+
void nir_lower_io(nir_shader *shader);
void nir_lower_vars_to_ssa(nir_shader *shader);
diff --git a/mesalib/src/glsl/nir/nir_constant_expressions.py b/mesalib/src/glsl/nir/nir_constant_expressions.py
index 22bc4f095..bf82fe533 100644
--- a/mesalib/src/glsl/nir/nir_constant_expressions.py
+++ b/mesalib/src/glsl/nir/nir_constant_expressions.py
@@ -28,6 +28,7 @@ template = """\
#include <math.h>
#include "main/core.h"
+#include "util/rounding.h" /* for _mesa_roundeven */
#include "nir_constant_expressions.h"
#if defined(_MSC_VER) && (_MSC_VER < 1800)
@@ -68,8 +69,8 @@ pack_snorm_1x8(float x)
* We must first cast the float to an int, because casting a negative
* float to a uint is undefined.
*/
- return (uint8_t) (int8_t)
- _mesa_round_to_even(CLAMP(x, -1.0f, +1.0f) * 127.0f);
+ return (uint8_t) (int)
+ _mesa_roundevenf(CLAMP(x, -1.0f, +1.0f) * 127.0f);
}
/**
@@ -90,8 +91,8 @@ pack_snorm_1x16(float x)
* We must first cast the float to an int, because casting a negative
* float to a uint is undefined.
*/
- return (uint16_t) (int16_t)
- _mesa_round_to_even(CLAMP(x, -1.0f, +1.0f) * 32767.0f);
+ return (uint16_t) (int)
+ _mesa_roundevenf(CLAMP(x, -1.0f, +1.0f) * 32767.0f);
}
/**
@@ -145,7 +146,8 @@ pack_unorm_1x8(float x)
*
* packUnorm4x8: round(clamp(c, 0, +1) * 255.0)
*/
- return (uint8_t) _mesa_round_to_even(CLAMP(x, 0.0f, 1.0f) * 255.0f);
+ return (uint8_t) (int)
+ _mesa_roundevenf(CLAMP(x, 0.0f, 1.0f) * 255.0f);
}
/**
@@ -163,7 +165,8 @@ pack_unorm_1x16(float x)
*
* packUnorm2x16: round(clamp(c, 0, +1) * 65535.0)
*/
- return (uint16_t) _mesa_round_to_even(CLAMP(x, 0.0f, 1.0f) * 65535.0f);
+ return (uint16_t) (int)
+ _mesa_roundevenf(CLAMP(x, 0.0f, 1.0f) * 65535.0f);
}
/**
diff --git a/mesalib/src/glsl/nir/nir_intrinsics.h b/mesalib/src/glsl/nir/nir_intrinsics.h
index 3bf102fc1..8e28765c1 100644
--- a/mesalib/src/glsl/nir/nir_intrinsics.h
+++ b/mesalib/src/glsl/nir/nir_intrinsics.h
@@ -95,6 +95,8 @@ ATOMIC(read, NIR_INTRINSIC_CAN_ELIMINATE)
SYSTEM_VALUE(front_face, 1)
SYSTEM_VALUE(vertex_id, 1)
+SYSTEM_VALUE(vertex_id_zero_base, 1)
+SYSTEM_VALUE(base_vertex, 1)
SYSTEM_VALUE(instance_id, 1)
SYSTEM_VALUE(sample_id, 1)
SYSTEM_VALUE(sample_pos, 2)
diff --git a/mesalib/src/glsl/nir/nir_lower_io.c b/mesalib/src/glsl/nir/nir_lower_io.c
index 207f8daa1..03eed04e1 100644
--- a/mesalib/src/glsl/nir/nir_lower_io.c
+++ b/mesalib/src/glsl/nir/nir_lower_io.c
@@ -76,15 +76,12 @@ type_size(const struct glsl_type *type)
return 0;
}
-static void
-assign_var_locations(struct hash_table *ht, unsigned *size)
+void
+nir_assign_var_locations_scalar(struct exec_list *var_list, unsigned *size)
{
unsigned location = 0;
- struct hash_entry *entry;
- hash_table_foreach(ht, entry) {
- nir_variable *var = (nir_variable *) entry->data;
-
+ foreach_list_typed(nir_variable, var, node, var_list) {
/*
* UBO's have their own address spaces, so don't count them towards the
* number of global uniforms
@@ -99,14 +96,6 @@ assign_var_locations(struct hash_table *ht, unsigned *size)
*size = location;
}
-static void
-assign_var_locations_shader(nir_shader *shader)
-{
- assign_var_locations(shader->inputs, &shader->num_inputs);
- assign_var_locations(shader->outputs, &shader->num_outputs);
- assign_var_locations(shader->uniforms, &shader->num_uniforms);
-}
-
static bool
deref_has_indirect(nir_deref_var *deref)
{
@@ -121,6 +110,77 @@ deref_has_indirect(nir_deref_var *deref)
return false;
}
+static bool
+mark_indirect_uses_block(nir_block *block, void *void_state)
+{
+ struct set *indirect_set = void_state;
+
+ nir_foreach_instr(block, instr) {
+ if (instr->type != nir_instr_type_intrinsic)
+ continue;
+
+ nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
+
+ for (unsigned i = 0;
+ i < nir_intrinsic_infos[intrin->intrinsic].num_variables; i++) {
+ if (deref_has_indirect(intrin->variables[i]))
+ _mesa_set_add(indirect_set, intrin->variables[i]->var);
+ }
+ }
+
+ return true;
+}
+
+/* Identical to nir_assign_var_locations_packed except that it assigns
+ * locations to the variables that are used 100% directly first and then
+ * assigns locations to variables that are used indirectly.
+ */
+void
+nir_assign_var_locations_scalar_direct_first(nir_shader *shader,
+ struct exec_list *var_list,
+ unsigned *direct_size,
+ unsigned *size)
+{
+ struct set *indirect_set = _mesa_set_create(NULL, _mesa_hash_pointer,
+ _mesa_key_pointer_equal);
+
+ nir_foreach_overload(shader, overload) {
+ if (overload->impl)
+ nir_foreach_block(overload->impl, mark_indirect_uses_block,
+ indirect_set);
+ }
+
+ unsigned location = 0;
+
+ foreach_list_typed(nir_variable, var, node, var_list) {
+ if (var->data.mode == nir_var_uniform && var->interface_type != NULL)
+ continue;
+
+ if (_mesa_set_search(indirect_set, var))
+ continue;
+
+ var->data.driver_location = location;
+ location += type_size(var->type);
+ }
+
+ *direct_size = location;
+
+ foreach_list_typed(nir_variable, var, node, var_list) {
+ if (var->data.mode == nir_var_uniform && var->interface_type != NULL)
+ continue;
+
+ if (!_mesa_set_search(indirect_set, var))
+ continue;
+
+ var->data.driver_location = location;
+ location += type_size(var->type);
+ }
+
+ *size = location;
+
+ _mesa_set_destroy(indirect_set, NULL);
+}
+
static unsigned
get_io_offset(nir_deref_var *deref, nir_instr *instr, nir_src *indirect,
struct lower_io_state *state)
@@ -307,8 +367,6 @@ nir_lower_io_impl(nir_function_impl *impl)
void
nir_lower_io(nir_shader *shader)
{
- assign_var_locations_shader(shader);
-
nir_foreach_overload(shader, overload) {
if (overload->impl)
nir_lower_io_impl(overload->impl);
diff --git a/mesalib/src/glsl/nir/nir_lower_system_values.c b/mesalib/src/glsl/nir/nir_lower_system_values.c
index 328d4f1ab..a6eec653e 100644
--- a/mesalib/src/glsl/nir/nir_lower_system_values.c
+++ b/mesalib/src/glsl/nir/nir_lower_system_values.c
@@ -49,6 +49,12 @@ convert_instr(nir_intrinsic_instr *instr)
case SYSTEM_VALUE_VERTEX_ID:
op = nir_intrinsic_load_vertex_id;
break;
+ case SYSTEM_VALUE_VERTEX_ID_ZERO_BASE:
+ op = nir_intrinsic_load_vertex_id_zero_base;
+ break;
+ case SYSTEM_VALUE_BASE_VERTEX:
+ op = nir_intrinsic_load_base_vertex;
+ break;
case SYSTEM_VALUE_INSTANCE_ID:
op = nir_intrinsic_load_instance_id;
break;
diff --git a/mesalib/src/glsl/nir/nir_lower_vars_to_ssa.c b/mesalib/src/glsl/nir/nir_lower_vars_to_ssa.c
index 9e9a418e3..86e6ab416 100644
--- a/mesalib/src/glsl/nir/nir_lower_vars_to_ssa.c
+++ b/mesalib/src/glsl/nir/nir_lower_vars_to_ssa.c
@@ -35,6 +35,13 @@ struct deref_node {
bool lower_to_ssa;
+ /* Only valid for things that end up in the direct list.
+ * Note that multiple nir_deref_vars may correspond to this node, but they
+ * will all be equivalent, so any is as good as the other.
+ */
+ nir_deref_var *deref;
+ struct exec_node direct_derefs_link;
+
struct set *loads;
struct set *stores;
struct set *copies;
@@ -69,7 +76,7 @@ struct lower_variables_state {
* wildcards and no indirects, these are precisely the derefs that we
* can actually consider lowering.
*/
- struct hash_table *direct_deref_nodes;
+ struct exec_list direct_deref_nodes;
/* Controls whether get_deref_node will add variables to the
* direct_deref_nodes table. This is turned on when we are initially
@@ -83,88 +90,6 @@ struct lower_variables_state {
struct hash_table *phi_table;
};
-/* The following two functions implement a hash and equality check for
- * variable dreferences. When the hash or equality function encounters an
- * array, all indirects are treated as equal and are never equal to a
- * direct dereference or a wildcard.
- */
-static uint32_t
-hash_deref(const void *void_deref)
-{
- uint32_t hash = _mesa_fnv32_1a_offset_bias;
-
- const nir_deref_var *deref_var = void_deref;
- hash = _mesa_fnv32_1a_accumulate(hash, deref_var->var);
-
- for (const nir_deref *deref = deref_var->deref.child;
- deref; deref = deref->child) {
- switch (deref->deref_type) {
- case nir_deref_type_array: {
- nir_deref_array *deref_array = nir_deref_as_array(deref);
-
- hash = _mesa_fnv32_1a_accumulate(hash, deref_array->deref_array_type);
-
- if (deref_array->deref_array_type == nir_deref_array_type_direct)
- hash = _mesa_fnv32_1a_accumulate(hash, deref_array->base_offset);
- break;
- }
- case nir_deref_type_struct: {
- nir_deref_struct *deref_struct = nir_deref_as_struct(deref);
- hash = _mesa_fnv32_1a_accumulate(hash, deref_struct->index);
- break;
- }
- default:
- assert("Invalid deref chain");
- }
- }
-
- return hash;
-}
-
-static bool
-derefs_equal(const void *void_a, const void *void_b)
-{
- const nir_deref_var *a_var = void_a;
- const nir_deref_var *b_var = void_b;
-
- if (a_var->var != b_var->var)
- return false;
-
- for (const nir_deref *a = a_var->deref.child, *b = b_var->deref.child;
- a != NULL; a = a->child, b = b->child) {
- if (a->deref_type != b->deref_type)
- return false;
-
- switch (a->deref_type) {
- case nir_deref_type_array: {
- nir_deref_array *a_arr = nir_deref_as_array(a);
- nir_deref_array *b_arr = nir_deref_as_array(b);
-
- if (a_arr->deref_array_type != b_arr->deref_array_type)
- return false;
-
- if (a_arr->deref_array_type == nir_deref_array_type_direct &&
- a_arr->base_offset != b_arr->base_offset)
- return false;
- break;
- }
- case nir_deref_type_struct:
- if (nir_deref_as_struct(a)->index != nir_deref_as_struct(b)->index)
- return false;
- break;
- default:
- assert("Invalid deref chain");
- return false;
- }
-
- assert((a->child == NULL) == (b->child == NULL));
- if((a->child == NULL) != (b->child == NULL))
- return false;
- }
-
- return true;
-}
-
static int
type_get_length(const struct glsl_type *type)
{
@@ -195,6 +120,8 @@ deref_node_create(struct deref_node *parent,
struct deref_node *node = rzalloc_size(mem_ctx, size);
node->type = type;
node->parent = parent;
+ node->deref = NULL;
+ exec_node_init(&node->direct_derefs_link);
return node;
}
@@ -297,8 +224,14 @@ get_deref_node(nir_deref_var *deref, struct lower_variables_state *state)
assert(node);
- if (is_direct && state->add_to_direct_deref_nodes)
- _mesa_hash_table_insert(state->direct_deref_nodes, deref, node);
+ /* Only insert if it isn't already in the list. */
+ if (is_direct && state->add_to_direct_deref_nodes &&
+ node->direct_derefs_link.next == NULL) {
+ node->deref = deref;
+ assert(deref->var != NULL);
+ exec_list_push_tail(&state->direct_deref_nodes,
+ &node->direct_derefs_link);
+ }
return node;
}
@@ -917,10 +850,8 @@ insert_phi_nodes(struct lower_variables_state *state)
unsigned w_start, w_end;
unsigned iter_count = 0;
- struct hash_entry *deref_entry;
- hash_table_foreach(state->direct_deref_nodes, deref_entry) {
- struct deref_node *node = deref_entry->data;
-
+ foreach_list_typed(struct deref_node, node, direct_derefs_link,
+ &state->direct_deref_nodes) {
if (node->stores == NULL)
continue;
@@ -1014,8 +945,7 @@ nir_lower_vars_to_ssa_impl(nir_function_impl *impl)
state.deref_var_nodes = _mesa_hash_table_create(state.dead_ctx,
_mesa_hash_pointer,
_mesa_key_pointer_equal);
- state.direct_deref_nodes = _mesa_hash_table_create(state.dead_ctx,
- hash_deref, derefs_equal);
+ exec_list_make_empty(&state.direct_deref_nodes);
state.phi_table = _mesa_hash_table_create(state.dead_ctx,
_mesa_hash_pointer,
_mesa_key_pointer_equal);
@@ -1035,18 +965,17 @@ nir_lower_vars_to_ssa_impl(nir_function_impl *impl)
/* We're about to iterate through direct_deref_nodes. Don't modify it. */
state.add_to_direct_deref_nodes = false;
- struct hash_entry *entry;
- hash_table_foreach(state.direct_deref_nodes, entry) {
- nir_deref_var *deref = (void *)entry->key;
- struct deref_node *node = entry->data;
+ foreach_list_typed_safe(struct deref_node, node, direct_derefs_link,
+ &state.direct_deref_nodes) {
+ nir_deref_var *deref = node->deref;
if (deref->var->data.mode != nir_var_local) {
- _mesa_hash_table_remove(state.direct_deref_nodes, entry);
+ exec_node_remove(&node->direct_derefs_link);
continue;
}
if (deref_may_be_aliased(deref, &state)) {
- _mesa_hash_table_remove(state.direct_deref_nodes, entry);
+ exec_node_remove(&node->direct_derefs_link);
continue;
}
diff --git a/mesalib/src/glsl/nir/nir_opcodes.py b/mesalib/src/glsl/nir/nir_opcodes.py
index 77f3bb826..062cd628b 100644
--- a/mesalib/src/glsl/nir/nir_opcodes.py
+++ b/mesalib/src/glsl/nir/nir_opcodes.py
@@ -183,7 +183,7 @@ unop("ftrunc", tfloat, "truncf(src0)")
unop("fceil", tfloat, "ceilf(src0)")
unop("ffloor", tfloat, "floorf(src0)")
unop("ffract", tfloat, "src0 - floorf(src0)")
-unop("fround_even", tfloat, "_mesa_round_to_even(src0)")
+unop("fround_even", tfloat, "_mesa_roundevenf(src0)")
# Trigonometric operations.
diff --git a/mesalib/src/glsl/nir/nir_opt_algebraic.py b/mesalib/src/glsl/nir/nir_opt_algebraic.py
index 7bf643134..ef855aa77 100644
--- a/mesalib/src/glsl/nir/nir_opt_algebraic.py
+++ b/mesalib/src/glsl/nir/nir_opt_algebraic.py
@@ -56,6 +56,10 @@ optimizations = [
(('iabs', ('ineg', a)), ('iabs', a)),
(('fadd', a, 0.0), a),
(('iadd', a, 0), a),
+ (('fadd', ('fmul', a, b), ('fmul', a, c)), ('fmul', a, ('fadd', b, c))),
+ (('iadd', ('imul', a, b), ('imul', a, c)), ('imul', a, ('iadd', b, c))),
+ (('fadd', ('fneg', a), a), 0.0),
+ (('iadd', ('ineg', a), a), 0),
(('fmul', a, 0.0), 0.0),
(('imul', a, 0), 0),
(('fmul', a, 1.0), a),
diff --git a/mesalib/src/glsl/nir/nir_opt_peephole_select.c b/mesalib/src/glsl/nir/nir_opt_peephole_select.c
index ab08f286f..b89451b09 100644
--- a/mesalib/src/glsl/nir/nir_opt_peephole_select.c
+++ b/mesalib/src/glsl/nir/nir_opt_peephole_select.c
@@ -52,36 +52,66 @@ struct peephole_select_state {
};
static bool
-are_all_move_to_phi(nir_block *block)
+block_check_for_allowed_instrs(nir_block *block)
{
nir_foreach_instr(block, instr) {
- if (instr->type != nir_instr_type_alu)
- return false;
+ switch (instr->type) {
+ case nir_instr_type_intrinsic: {
+ nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
+
+ switch (intrin->intrinsic) {
+ case nir_intrinsic_load_var:
+ switch (intrin->variables[0]->var->data.mode) {
+ case nir_var_shader_in:
+ case nir_var_uniform:
+ break;
+
+ default:
+ return false;
+ }
+ break;
+
+ default:
+ return false;
+ }
- /* It must be a move operation */
- nir_alu_instr *mov = nir_instr_as_alu(instr);
- if (mov->op != nir_op_fmov && mov->op != nir_op_imov)
- return false;
+ break;
+ }
- /* Can't handle saturate */
- if (mov->dest.saturate)
- return false;
+ case nir_instr_type_load_const:
+ break;
- /* It must be SSA */
- if (!mov->dest.dest.is_ssa)
- return false;
+ case nir_instr_type_alu: {
+ /* It must be a move operation */
+ nir_alu_instr *mov = nir_instr_as_alu(instr);
+ if (mov->op != nir_op_fmov && mov->op != nir_op_imov)
+ return false;
- /* It cannot have any if-uses */
- if (mov->dest.dest.ssa.if_uses->entries != 0)
- return false;
+ /* Can't handle saturate */
+ if (mov->dest.saturate)
+ return false;
+
+ /* It must be SSA */
+ if (!mov->dest.dest.is_ssa)
+ return false;
- /* The only uses of this definition must be phi's in the successor */
- struct set_entry *entry;
- set_foreach(mov->dest.dest.ssa.uses, entry) {
- const nir_instr *dest_instr = entry->key;
- if (dest_instr->type != nir_instr_type_phi ||
- dest_instr->block != block->successors[0])
+ /* It cannot have any if-uses */
+ if (mov->dest.dest.ssa.if_uses->entries != 0)
return false;
+
+ /* The only uses of this definition must be phi's in the successor */
+ struct set_entry *entry;
+ set_foreach(mov->dest.dest.ssa.uses, entry) {
+ const nir_instr *dest_instr = entry->key;
+ if (dest_instr->type != nir_instr_type_phi ||
+ dest_instr->block != block->successors[0])
+ return false;
+ }
+ break;
+ }
+
+ default:
+ return false;
}
}
@@ -119,8 +149,9 @@ nir_opt_peephole_select_block(nir_block *block, void *void_state)
nir_block *then_block = nir_cf_node_as_block(then_node);
nir_block *else_block = nir_cf_node_as_block(else_node);
- /* ... and those blocks must only contain move-to-phi. */
- if (!are_all_move_to_phi(then_block) || !are_all_move_to_phi(else_block))
+ /* ... and those blocks must only contain "allowed" instructions. */
+ if (!block_check_for_allowed_instrs(then_block) ||
+ !block_check_for_allowed_instrs(else_block))
return true;
/* At this point, we know that the previous CFG node is an if-then
@@ -129,6 +160,25 @@ nir_opt_peephole_select_block(nir_block *block, void *void_state)
* selects.
*/
+ nir_block *prev_block = nir_cf_node_as_block(nir_cf_node_prev(prev_node));
+ assert(prev_block->cf_node.type == nir_cf_node_block);
+
+ /* First, we move the remaining instructions from the blocks to the
+ * block before. We have already guaranteed that this is safe by
+ * calling block_check_for_allowed_instrs()
+ */
+ nir_foreach_instr_safe(then_block, instr) {
+ exec_node_remove(&instr->node);
+ instr->block = prev_block;
+ exec_list_push_tail(&prev_block->instr_list, &instr->node);
+ }
+
+ nir_foreach_instr_safe(else_block, instr) {
+ exec_node_remove(&instr->node);
+ instr->block = prev_block;
+ exec_list_push_tail(&prev_block->instr_list, &instr->node);
+ }
+
nir_foreach_instr_safe(block, instr) {
if (instr->type != nir_instr_type_phi)
break;
@@ -145,19 +195,7 @@ nir_opt_peephole_select_block(nir_block *block, void *void_state)
assert(src->src.is_ssa);
unsigned idx = src->pred == then_block ? 1 : 2;
-
- if (src->src.ssa->parent_instr->block == src->pred) {
- /* We already know that this instruction must be a move with
- * this phi's in this block as its only users.
- */
- nir_alu_instr *mov = nir_instr_as_alu(src->src.ssa->parent_instr);
- assert(mov->instr.type == nir_instr_type_alu);
- assert(mov->op == nir_op_fmov || mov->op == nir_op_imov);
-
- nir_alu_src_copy(&sel->src[idx], &mov->src[0], state->mem_ctx);
- } else {
- nir_src_copy(&sel->src[idx].src, &src->src, state->mem_ctx);
- }
+ nir_src_copy(&sel->src[idx].src, &src->src, state->mem_ctx);
}
nir_ssa_dest_init(&sel->instr, &sel->dest.dest,
diff --git a/mesalib/src/glsl/nir/nir_print.c b/mesalib/src/glsl/nir/nir_print.c
index 6a3c6a027..fa11a312e 100644
--- a/mesalib/src/glsl/nir/nir_print.c
+++ b/mesalib/src/glsl/nir/nir_print.c
@@ -228,7 +228,7 @@ print_var_decl(nir_variable *var, print_var_state *state, FILE *fp)
if (var->data.mode == nir_var_shader_in ||
var->data.mode == nir_var_shader_out ||
var->data.mode == nir_var_uniform) {
- fprintf(fp, " (%u)", var->data.driver_location);
+ fprintf(fp, " (%u, %u)", var->data.location, var->data.driver_location);
}
fprintf(fp, "\n");
@@ -844,22 +844,16 @@ nir_print_shader(nir_shader *shader, FILE *fp)
print_var_state state;
init_print_state(&state);
- for (unsigned i = 0; i < shader->num_user_structures; i++) {
- glsl_print_struct(shader->user_structures[i], fp);
- }
-
- struct hash_entry *entry;
-
- hash_table_foreach(shader->uniforms, entry) {
- print_var_decl((nir_variable *) entry->data, &state, fp);
+ foreach_list_typed(nir_variable, var, node, &shader->uniforms) {
+ print_var_decl(var, &state, fp);
}
- hash_table_foreach(shader->inputs, entry) {
- print_var_decl((nir_variable *) entry->data, &state, fp);
+ foreach_list_typed(nir_variable, var, node, &shader->inputs) {
+ print_var_decl(var, &state, fp);
}
- hash_table_foreach(shader->outputs, entry) {
- print_var_decl((nir_variable *) entry->data, &state, fp);
+ foreach_list_typed(nir_variable, var, node, &shader->outputs) {
+ print_var_decl(var, &state, fp);
}
foreach_list_typed(nir_variable, var, node, &shader->globals) {
diff --git a/mesalib/src/glsl/nir/nir_validate.c b/mesalib/src/glsl/nir/nir_validate.c
index a3fe9d620..f247ae069 100644
--- a/mesalib/src/glsl/nir/nir_validate.c
+++ b/mesalib/src/glsl/nir/nir_validate.c
@@ -931,17 +931,19 @@ nir_validate_shader(nir_shader *shader)
state.shader = shader;
- struct hash_entry *entry;
- hash_table_foreach(shader->uniforms, entry) {
- validate_var_decl((nir_variable *) entry->data, true, &state);
+ exec_list_validate(&shader->uniforms);
+ foreach_list_typed(nir_variable, var, node, &shader->uniforms) {
+ validate_var_decl(var, true, &state);
}
- hash_table_foreach(shader->inputs, entry) {
- validate_var_decl((nir_variable *) entry->data, true, &state);
+ exec_list_validate(&shader->inputs);
+ foreach_list_typed(nir_variable, var, node, &shader->inputs) {
+ validate_var_decl(var, true, &state);
}
- hash_table_foreach(shader->outputs, entry) {
- validate_var_decl((nir_variable *) entry->data, true, &state);
+ exec_list_validate(&shader->outputs);
+ foreach_list_typed(nir_variable, var, node, &shader->outputs) {
+ validate_var_decl(var, true, &state);
}
exec_list_validate(&shader->globals);
diff --git a/mesalib/src/glsl/nir/nir_worklist.c b/mesalib/src/glsl/nir/nir_worklist.c
index a8baae937..3087a1d23 100644
--- a/mesalib/src/glsl/nir/nir_worklist.c
+++ b/mesalib/src/glsl/nir/nir_worklist.c
@@ -82,7 +82,7 @@ nir_block_worklist_push_head(nir_block_worklist *w, nir_block *block)
}
nir_block *
-nir_block_worklist_peek_head(nir_block_worklist *w)
+nir_block_worklist_peek_head(const nir_block_worklist *w)
{
assert(w->count > 0);
@@ -114,18 +114,18 @@ nir_block_worklist_push_tail(nir_block_worklist *w, nir_block *block)
w->count++;
- unsigned tail = w->start = (w->start + w->count - 1) % w->size;
+ unsigned tail = (w->start + w->count - 1) % w->size;
w->blocks[tail] = block;
BITSET_SET(w->blocks_present, block->index);
}
nir_block *
-nir_block_worklist_peek_tail(nir_block_worklist *w)
+nir_block_worklist_peek_tail(const nir_block_worklist *w)
{
assert(w->count > 0);
- unsigned tail = w->start = (w->start + w->count - 1) % w->size;
+ unsigned tail = (w->start + w->count - 1) % w->size;
return w->blocks[tail];
}
@@ -135,7 +135,7 @@ nir_block_worklist_pop_tail(nir_block_worklist *w)
{
assert(w->count > 0);
- unsigned tail = w->start = (w->start + w->count - 1) % w->size;
+ unsigned tail = (w->start + w->count - 1) % w->size;
w->count--;
diff --git a/mesalib/src/glsl/nir/nir_worklist.h b/mesalib/src/glsl/nir/nir_worklist.h
index d5a8568e4..829bff24a 100644
--- a/mesalib/src/glsl/nir/nir_worklist.h
+++ b/mesalib/src/glsl/nir/nir_worklist.h
@@ -74,13 +74,13 @@ nir_block_worklist_is_empty(const nir_block_worklist *w)
void nir_block_worklist_push_head(nir_block_worklist *w, nir_block *block);
-nir_block *nir_block_worklist_peek_head(nir_block_worklist *w);
+nir_block *nir_block_worklist_peek_head(const nir_block_worklist *w);
nir_block *nir_block_worklist_pop_head(nir_block_worklist *w);
void nir_block_worklist_push_tail(nir_block_worklist *w, nir_block *block);
-nir_block *nir_block_worklist_peek_tail(nir_block_worklist *w);
+nir_block *nir_block_worklist_peek_tail(const nir_block_worklist *w);
nir_block *nir_block_worklist_pop_tail(nir_block_worklist *w);
diff --git a/mesalib/src/glsl/opt_algebraic.cpp b/mesalib/src/glsl/opt_algebraic.cpp
index c6040bff8..69c03ea8b 100644
--- a/mesalib/src/glsl/opt_algebraic.cpp
+++ b/mesalib/src/glsl/opt_algebraic.cpp
@@ -626,9 +626,18 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir)
if (!is_vec_zero(zero))
continue;
- return new(mem_ctx) ir_expression(ir->operation,
- add->operands[0],
- neg(add->operands[1]));
+ /* Depending of the zero position we want to optimize
+ * (0 cmp x+y) into (-x cmp y) or (x+y cmp 0) into (x cmp -y)
+ */
+ if (add_pos == 1) {
+ return new(mem_ctx) ir_expression(ir->operation,
+ neg(add->operands[0]),
+ add->operands[1]);
+ } else {
+ return new(mem_ctx) ir_expression(ir->operation,
+ add->operands[0],
+ neg(add->operands[1]));
+ }
}
break;