summaryrefslogtreecommitdiffstats
path: root/src/glsl/nir
diff options
context:
space:
mode:
authorJason Ekstrand <[email protected]>2016-02-05 15:03:04 -0800
committerJason Ekstrand <[email protected]>2016-02-05 15:03:44 -0800
commit741744f691d6ef63e9f9a4c03136f969f2ffb0bf (patch)
tree7c9192a0648c2d90bb08efbc21ebcb7a6e2b873a /src/glsl/nir
parent9645b8eb1f1b79e537ad8ddb683507df7bc9da58 (diff)
parenteb63640c1d38a200a7b1540405051d3ff79d0d8a (diff)
Merge commit mesa-public/master into vulkan
This pulls in the patches that move all of the compiler stuff around
Diffstat (limited to 'src/glsl/nir')
-rw-r--r--src/glsl/nir/.gitignore5
-rw-r--r--src/glsl/nir/README118
-rw-r--r--src/glsl/nir/builtin_type_macros.h170
-rw-r--r--src/glsl/nir/glsl_to_nir.cpp2035
-rw-r--r--src/glsl/nir/glsl_to_nir.h41
-rw-r--r--src/glsl/nir/glsl_types.cpp1950
-rw-r--r--src/glsl/nir/glsl_types.h913
-rw-r--r--src/glsl/nir/nir.c1753
-rw-r--r--src/glsl/nir/nir.h2239
-rw-r--r--src/glsl/nir/nir_algebraic.py305
-rw-r--r--src/glsl/nir/nir_array.h96
-rw-r--r--src/glsl/nir/nir_builder.h441
-rw-r--r--src/glsl/nir/nir_builder_opcodes_h.py38
-rw-r--r--src/glsl/nir/nir_clone.c711
-rw-r--r--src/glsl/nir/nir_constant_expressions.h31
-rw-r--r--src/glsl/nir/nir_constant_expressions.py336
-rw-r--r--src/glsl/nir/nir_control_flow.c820
-rw-r--r--src/glsl/nir/nir_control_flow.h162
-rw-r--r--src/glsl/nir/nir_control_flow_private.h37
-rw-r--r--src/glsl/nir/nir_dominance.c354
-rw-r--r--src/glsl/nir/nir_from_ssa.c805
-rw-r--r--src/glsl/nir/nir_gather_info.c109
-rw-r--r--src/glsl/nir/nir_gs_count_vertices.c93
-rw-r--r--src/glsl/nir/nir_inline_functions.c153
-rw-r--r--src/glsl/nir/nir_instr_set.c522
-rw-r--r--src/glsl/nir/nir_instr_set.h62
-rw-r--r--src/glsl/nir/nir_intrinsics.c49
-rw-r--r--src/glsl/nir/nir_intrinsics.h367
-rw-r--r--src/glsl/nir/nir_liveness.c297
-rw-r--r--src/glsl/nir/nir_lower_alu_to_scalar.c264
-rw-r--r--src/glsl/nir/nir_lower_atomics.c167
-rw-r--r--src/glsl/nir/nir_lower_clip.c339
-rw-r--r--src/glsl/nir/nir_lower_global_vars_to_local.c113
-rw-r--r--src/glsl/nir/nir_lower_gs_intrinsics.c219
-rw-r--r--src/glsl/nir/nir_lower_idiv.c151
-rw-r--r--src/glsl/nir/nir_lower_indirect_derefs.c239
-rw-r--r--src/glsl/nir/nir_lower_io.c461
-rw-r--r--src/glsl/nir/nir_lower_load_const_to_scalar.c89
-rw-r--r--src/glsl/nir/nir_lower_locals_to_regs.c396
-rw-r--r--src/glsl/nir/nir_lower_outputs_to_temporaries.c136
-rw-r--r--src/glsl/nir/nir_lower_phis_to_scalar.c293
-rw-r--r--src/glsl/nir/nir_lower_returns.c246
-rw-r--r--src/glsl/nir/nir_lower_samplers.c198
-rw-r--r--src/glsl/nir/nir_lower_system_values.c166
-rw-r--r--src/glsl/nir/nir_lower_tex.c355
-rw-r--r--src/glsl/nir/nir_lower_to_source_mods.c196
-rw-r--r--src/glsl/nir/nir_lower_two_sided_color.c212
-rw-r--r--src/glsl/nir/nir_lower_var_copies.c190
-rw-r--r--src/glsl/nir/nir_lower_vars_to_ssa.c751
-rw-r--r--src/glsl/nir/nir_lower_vec_to_movs.c310
-rw-r--r--src/glsl/nir/nir_metadata.c90
-rw-r--r--src/glsl/nir/nir_move_vec_src_uses_to_dest.c197
-rw-r--r--src/glsl/nir/nir_normalize_cubemap_coords.c120
-rw-r--r--src/glsl/nir/nir_opcodes.py702
-rw-r--r--src/glsl/nir/nir_opcodes_c.py55
-rw-r--r--src/glsl/nir/nir_opcodes_h.py47
-rw-r--r--src/glsl/nir/nir_opt_algebraic.py354
-rw-r--r--src/glsl/nir/nir_opt_constant_folding.c201
-rw-r--r--src/glsl/nir/nir_opt_copy_propagate.c290
-rw-r--r--src/glsl/nir/nir_opt_cse.c93
-rw-r--r--src/glsl/nir/nir_opt_dce.c183
-rw-r--r--src/glsl/nir/nir_opt_dead_cf.c358
-rw-r--r--src/glsl/nir/nir_opt_gcm.c494
-rw-r--r--src/glsl/nir/nir_opt_global_to_local.c102
-rw-r--r--src/glsl/nir/nir_opt_peephole_select.c256
-rw-r--r--src/glsl/nir/nir_opt_remove_phis.c130
-rw-r--r--src/glsl/nir/nir_opt_undef.c104
-rw-r--r--src/glsl/nir/nir_phi_builder.c254
-rw-r--r--src/glsl/nir/nir_phi_builder.h84
-rw-r--r--src/glsl/nir/nir_print.c1089
-rw-r--r--src/glsl/nir/nir_remove_dead_variables.c156
-rw-r--r--src/glsl/nir/nir_repair_ssa.c157
-rw-r--r--src/glsl/nir/nir_search.c379
-rw-r--r--src/glsl/nir/nir_search.h99
-rw-r--r--src/glsl/nir/nir_split_var_copies.c285
-rw-r--r--src/glsl/nir/nir_sweep.c174
-rw-r--r--src/glsl/nir/nir_to_ssa.c536
-rw-r--r--src/glsl/nir/nir_types.cpp336
-rw-r--r--src/glsl/nir/nir_types.h126
-rw-r--r--src/glsl/nir/nir_validate.c1076
-rw-r--r--src/glsl/nir/nir_vla.h54
-rw-r--r--src/glsl/nir/nir_worklist.c144
-rw-r--r--src/glsl/nir/nir_worklist.h91
-rw-r--r--src/glsl/nir/shader_enums.c260
-rw-r--r--src/glsl/nir/shader_enums.h551
-rw-r--r--src/glsl/nir/spirv/GLSL.std.450.h127
-rw-r--r--src/glsl/nir/spirv/nir_spirv.h54
-rw-r--r--src/glsl/nir/spirv/spirv.h870
-rw-r--r--src/glsl/nir/spirv/spirv_to_nir.c2654
-rw-r--r--src/glsl/nir/spirv/vtn_alu.c448
-rw-r--r--src/glsl/nir/spirv/vtn_cfg.c768
-rw-r--r--src/glsl/nir/spirv/vtn_glsl450.c684
-rw-r--r--src/glsl/nir/spirv/vtn_private.h484
-rw-r--r--src/glsl/nir/spirv/vtn_variables.c1412
-rw-r--r--src/glsl/nir/spirv2nir.c55
-rw-r--r--src/glsl/nir/tests/control_flow_tests.cpp148
96 files changed, 0 insertions, 37834 deletions
diff --git a/src/glsl/nir/.gitignore b/src/glsl/nir/.gitignore
deleted file mode 100644
index 64828eba6d3..00000000000
--- a/src/glsl/nir/.gitignore
+++ /dev/null
@@ -1,5 +0,0 @@
-nir_builder_opcodes.h
-nir_opt_algebraic.c
-nir_opcodes.c
-nir_opcodes.h
-nir_constant_expressions.c
diff --git a/src/glsl/nir/README b/src/glsl/nir/README
deleted file mode 100644
index 2c81db9db61..00000000000
--- a/src/glsl/nir/README
+++ /dev/null
@@ -1,118 +0,0 @@
-New IR, or NIR, is an IR for Mesa intended to sit below GLSL IR and Mesa IR.
-Its design inherits from the various IR's that Mesa has used in the past, as
-well as Direct3D assembly, and it includes a few new ideas as well. It is a
-flat (in terms of using instructions instead of expressions), typeless IR,
-similar to TGSI and Mesa IR. It also supports SSA (although it doesn't require
-it).
-
-Variables
-=========
-
-NIR includes support for source-level GLSL variables through a structure mostly
-copied from GLSL IR. These will be used for linking and conversion from GLSL IR
-(and later, from an AST), but for the most part, they will be lowered to
-registers (see below) and loads/stores.
-
-Registers
-=========
-
-Registers are light-weight; they consist of a structure that only contains its
-size, its index for liveness analysis, and an optional name for debugging. In
-addition, registers can be local to a function or global to the entire shader;
-the latter will be used in ARB_shader_subroutine for passing parameters and
-getting return values from subroutines. Registers can also be an array, in which
-case they can be accessed indirectly. Each ALU instruction (add, subtract, etc.)
-works directly with registers or SSA values (see below).
-
-SSA
-========
-
-Everywhere a register can be loaded/stored, an SSA value can be used instead.
-The only exception is that arrays/indirect addressing are not supported with
-SSA; although research has been done on extensions of SSA to arrays before, it's
-usually for the purpose of parallelization (which we're not interested in), and
-adds some overhead in the form of adding copies or extra arrays (which is much
-more expensive than introducing copies between non-array registers). SSA uses
-point directly to their corresponding definition, which in turn points to the
-instruction it is part of. This creates an implicit use-def chain and avoids the
-need for an external structure for each SSA register.
-
-Functions
-=========
-
-Support for function calls is mostly similar to GLSL IR. Each shader contains a
-list of functions, and each function has a list of overloads. Each overload
-contains a list of parameters, and may contain an implementation which specifies
-the variables that correspond to the parameters and return value. Inlining a
-function, assuming it has a single return point, is as simple as copying its
-instructions, registers, and local variables into the target function and then
-inserting copies to and from the new parameters as appropriate. After functions
-are inlined and any non-subroutine functions are deleted, parameters and return
-variables will be converted to global variables and then global registers. We
-don't do this lowering earlier (i.e. the fortranizer idea) for a few reasons:
-
-- If we want to do optimizations before link time, we need to have the function
-signature available during link-time.
-
-- If we do any inlining before link time, then we might wind up with the
-inlined function and the non-inlined function using the same global
-variables/registers which would preclude optimization.
-
-Intrinsics
-=========
-
-Any operation (other than function calls and textures) which touches a variable
-or is not referentially transparent is represented by an intrinsic. Intrinsics
-are similar to the idea of a "builtin function," i.e. a function declaration
-whose implementation is provided by the backend, except they are more powerful
-in the following ways:
-
-- They can also load and store registers when appropriate, which limits the
-number of variables needed in later stages of the IR while obviating the need
-for a separate load/store variable instruction.
-
-- Intrinsics can be marked as side-effect free, which permits them to be
-treated like any other instruction when it comes to optimizations. This allows
-load intrinsics to be represented as intrinsics while still being optimized
-away by dead code elimination, common subexpression elimination, etc.
-
-Intrinsics are used for:
-
-- Atomic operations
-- Memory barriers
-- Subroutine calls
-- Geometry shader emitVertex and endPrimitive
-- Loading and storing variables (before lowering)
-- Loading and storing uniforms, shader inputs and outputs, etc (after lowering)
-- Copying variables (cases where in GLSL the destination is a structure or
-array)
-- The kitchen sink
-- ...
-
-Textures
-=========
-
-Unfortunately, there are far too many texture operations to represent each one
-of them with an intrinsic, so there's a special texture instruction similar to
-the GLSL IR one. The biggest difference is that, while the texture instruction
-has a sampler dereference field used just like in GLSL IR, this gets lowered to
-a texture unit index (with a possible indirect offset) while the type
-information of the original sampler is kept around for backends. Also, all the
-non-constant sources are stored in a single array to make it easier for
-optimization passes to iterate over all the sources.
-
-Control Flow
-=========
-
-Like in GLSL IR, control flow consists of a tree of "control flow nodes", which
-include if statements and loops, and jump instructions (break, continue, and
-return). Unlike GLSL IR, though, the leaves of the tree aren't statements but
-basic blocks. Each basic block also keeps track of its successors and
-predecessors, and function implementations keep track of the beginning basic
-block (the first basic block of the function) and the ending basic block (a fake
-basic block that every return statement points to). Together, these elements
-make up the control flow graph, in this case a redundant piece of information on
-top of the control flow tree that will be used by almost all the optimizations.
-There are helper functions to add and remove control flow nodes that also update
-the control flow graph, and so usually it doesn't need to be touched by passes
-that modify control flow nodes.
diff --git a/src/glsl/nir/builtin_type_macros.h b/src/glsl/nir/builtin_type_macros.h
deleted file mode 100644
index 7bd2e4e6558..00000000000
--- a/src/glsl/nir/builtin_type_macros.h
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * Copyright © 2013 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-/**
- * \file builtin_type_macros.h
- *
- * This contains definitions for all GLSL built-in types, regardless of what
- * language version or extension might provide them.
- */
-
-DECL_TYPE(error, GL_INVALID_ENUM, GLSL_TYPE_ERROR, 0, 0)
-DECL_TYPE(void, GL_INVALID_ENUM, GLSL_TYPE_VOID, 0, 0)
-
-DECL_TYPE(bool, GL_BOOL, GLSL_TYPE_BOOL, 1, 1)
-DECL_TYPE(bvec2, GL_BOOL_VEC2, GLSL_TYPE_BOOL, 2, 1)
-DECL_TYPE(bvec3, GL_BOOL_VEC3, GLSL_TYPE_BOOL, 3, 1)
-DECL_TYPE(bvec4, GL_BOOL_VEC4, GLSL_TYPE_BOOL, 4, 1)
-
-DECL_TYPE(int, GL_INT, GLSL_TYPE_INT, 1, 1)
-DECL_TYPE(ivec2, GL_INT_VEC2, GLSL_TYPE_INT, 2, 1)
-DECL_TYPE(ivec3, GL_INT_VEC3, GLSL_TYPE_INT, 3, 1)
-DECL_TYPE(ivec4, GL_INT_VEC4, GLSL_TYPE_INT, 4, 1)
-
-DECL_TYPE(uint, GL_UNSIGNED_INT, GLSL_TYPE_UINT, 1, 1)
-DECL_TYPE(uvec2, GL_UNSIGNED_INT_VEC2, GLSL_TYPE_UINT, 2, 1)
-DECL_TYPE(uvec3, GL_UNSIGNED_INT_VEC3, GLSL_TYPE_UINT, 3, 1)
-DECL_TYPE(uvec4, GL_UNSIGNED_INT_VEC4, GLSL_TYPE_UINT, 4, 1)
-
-DECL_TYPE(float, GL_FLOAT, GLSL_TYPE_FLOAT, 1, 1)
-DECL_TYPE(vec2, GL_FLOAT_VEC2, GLSL_TYPE_FLOAT, 2, 1)
-DECL_TYPE(vec3, GL_FLOAT_VEC3, GLSL_TYPE_FLOAT, 3, 1)
-DECL_TYPE(vec4, GL_FLOAT_VEC4, GLSL_TYPE_FLOAT, 4, 1)
-
-DECL_TYPE(mat2, GL_FLOAT_MAT2, GLSL_TYPE_FLOAT, 2, 2)
-DECL_TYPE(mat3, GL_FLOAT_MAT3, GLSL_TYPE_FLOAT, 3, 3)
-DECL_TYPE(mat4, GL_FLOAT_MAT4, GLSL_TYPE_FLOAT, 4, 4)
-
-DECL_TYPE(mat2x3, GL_FLOAT_MAT2x3, GLSL_TYPE_FLOAT, 3, 2)
-DECL_TYPE(mat2x4, GL_FLOAT_MAT2x4, GLSL_TYPE_FLOAT, 4, 2)
-DECL_TYPE(mat3x2, GL_FLOAT_MAT3x2, GLSL_TYPE_FLOAT, 2, 3)
-DECL_TYPE(mat3x4, GL_FLOAT_MAT3x4, GLSL_TYPE_FLOAT, 4, 3)
-DECL_TYPE(mat4x2, GL_FLOAT_MAT4x2, GLSL_TYPE_FLOAT, 2, 4)
-DECL_TYPE(mat4x3, GL_FLOAT_MAT4x3, GLSL_TYPE_FLOAT, 3, 4)
-
-DECL_TYPE(double, GL_DOUBLE, GLSL_TYPE_DOUBLE, 1, 1)
-DECL_TYPE(dvec2, GL_DOUBLE_VEC2, GLSL_TYPE_DOUBLE, 2, 1)
-DECL_TYPE(dvec3, GL_DOUBLE_VEC3, GLSL_TYPE_DOUBLE, 3, 1)
-DECL_TYPE(dvec4, GL_DOUBLE_VEC4, GLSL_TYPE_DOUBLE, 4, 1)
-
-DECL_TYPE(dmat2, GL_DOUBLE_MAT2, GLSL_TYPE_DOUBLE, 2, 2)
-DECL_TYPE(dmat3, GL_DOUBLE_MAT3, GLSL_TYPE_DOUBLE, 3, 3)
-DECL_TYPE(dmat4, GL_DOUBLE_MAT4, GLSL_TYPE_DOUBLE, 4, 4)
-
-DECL_TYPE(dmat2x3, GL_DOUBLE_MAT2x3, GLSL_TYPE_DOUBLE, 3, 2)
-DECL_TYPE(dmat2x4, GL_DOUBLE_MAT2x4, GLSL_TYPE_DOUBLE, 4, 2)
-DECL_TYPE(dmat3x2, GL_DOUBLE_MAT3x2, GLSL_TYPE_DOUBLE, 2, 3)
-DECL_TYPE(dmat3x4, GL_DOUBLE_MAT3x4, GLSL_TYPE_DOUBLE, 4, 3)
-DECL_TYPE(dmat4x2, GL_DOUBLE_MAT4x2, GLSL_TYPE_DOUBLE, 2, 4)
-DECL_TYPE(dmat4x3, GL_DOUBLE_MAT4x3, GLSL_TYPE_DOUBLE, 3, 4)
-
-DECL_TYPE(sampler1D, GL_SAMPLER_1D, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_1D, 0, 0, GLSL_TYPE_FLOAT)
-DECL_TYPE(sampler2D, GL_SAMPLER_2D, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_2D, 0, 0, GLSL_TYPE_FLOAT)
-DECL_TYPE(sampler3D, GL_SAMPLER_3D, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_3D, 0, 0, GLSL_TYPE_FLOAT)
-DECL_TYPE(samplerCube, GL_SAMPLER_CUBE, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_CUBE, 0, 0, GLSL_TYPE_FLOAT)
-DECL_TYPE(sampler1DArray, GL_SAMPLER_1D_ARRAY, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_1D, 0, 1, GLSL_TYPE_FLOAT)
-DECL_TYPE(sampler2DArray, GL_SAMPLER_2D_ARRAY, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_2D, 0, 1, GLSL_TYPE_FLOAT)
-DECL_TYPE(samplerCubeArray, GL_SAMPLER_CUBE_MAP_ARRAY, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_CUBE, 0, 1, GLSL_TYPE_FLOAT)
-DECL_TYPE(sampler2DRect, GL_SAMPLER_2D_RECT, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_RECT, 0, 0, GLSL_TYPE_FLOAT)
-DECL_TYPE(samplerBuffer, GL_SAMPLER_BUFFER, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_BUF, 0, 0, GLSL_TYPE_FLOAT)
-DECL_TYPE(sampler2DMS, GL_SAMPLER_2D_MULTISAMPLE, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_MS, 0, 0, GLSL_TYPE_FLOAT)
-DECL_TYPE(sampler2DMSArray, GL_SAMPLER_2D_MULTISAMPLE_ARRAY, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_MS, 0, 1, GLSL_TYPE_FLOAT)
-
-DECL_TYPE(isampler1D, GL_INT_SAMPLER_1D, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_1D, 0, 0, GLSL_TYPE_INT)
-DECL_TYPE(isampler2D, GL_INT_SAMPLER_2D, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_2D, 0, 0, GLSL_TYPE_INT)
-DECL_TYPE(isampler3D, GL_INT_SAMPLER_3D, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_3D, 0, 0, GLSL_TYPE_INT)
-DECL_TYPE(isamplerCube, GL_INT_SAMPLER_CUBE, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_CUBE, 0, 0, GLSL_TYPE_INT)
-DECL_TYPE(isampler1DArray, GL_INT_SAMPLER_1D_ARRAY, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_1D, 0, 1, GLSL_TYPE_INT)
-DECL_TYPE(isampler2DArray, GL_INT_SAMPLER_2D_ARRAY, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_2D, 0, 1, GLSL_TYPE_INT)
-DECL_TYPE(isamplerCubeArray, GL_INT_SAMPLER_CUBE_MAP_ARRAY, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_CUBE, 0, 1, GLSL_TYPE_INT)
-DECL_TYPE(isampler2DRect, GL_INT_SAMPLER_2D_RECT, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_RECT, 0, 0, GLSL_TYPE_INT)
-DECL_TYPE(isamplerBuffer, GL_INT_SAMPLER_BUFFER, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_BUF, 0, 0, GLSL_TYPE_INT)
-DECL_TYPE(isampler2DMS, GL_INT_SAMPLER_2D_MULTISAMPLE, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_MS, 0, 0, GLSL_TYPE_INT)
-DECL_TYPE(isampler2DMSArray, GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_MS, 0, 1, GLSL_TYPE_INT)
-
-DECL_TYPE(usampler1D, GL_UNSIGNED_INT_SAMPLER_1D, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_1D, 0, 0, GLSL_TYPE_UINT)
-DECL_TYPE(usampler2D, GL_UNSIGNED_INT_SAMPLER_2D, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_2D, 0, 0, GLSL_TYPE_UINT)
-DECL_TYPE(usampler3D, GL_UNSIGNED_INT_SAMPLER_3D, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_3D, 0, 0, GLSL_TYPE_UINT)
-DECL_TYPE(usamplerCube, GL_UNSIGNED_INT_SAMPLER_CUBE, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_CUBE, 0, 0, GLSL_TYPE_UINT)
-DECL_TYPE(usampler1DArray, GL_UNSIGNED_INT_SAMPLER_1D_ARRAY, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_1D, 0, 1, GLSL_TYPE_UINT)
-DECL_TYPE(usampler2DArray, GL_UNSIGNED_INT_SAMPLER_2D_ARRAY, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_2D, 0, 1, GLSL_TYPE_UINT)
-DECL_TYPE(usamplerCubeArray, GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_CUBE, 0, 1, GLSL_TYPE_UINT)
-DECL_TYPE(usampler2DRect, GL_UNSIGNED_INT_SAMPLER_2D_RECT, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_RECT, 0, 0, GLSL_TYPE_UINT)
-DECL_TYPE(usamplerBuffer, GL_UNSIGNED_INT_SAMPLER_BUFFER, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_BUF, 0, 0, GLSL_TYPE_UINT)
-DECL_TYPE(usampler2DMS, GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_MS, 0, 0, GLSL_TYPE_UINT)
-DECL_TYPE(usampler2DMSArray, GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_MS, 0, 1, GLSL_TYPE_UINT)
-
-DECL_TYPE(sampler1DShadow, GL_SAMPLER_1D_SHADOW, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_1D, 1, 0, GLSL_TYPE_FLOAT)
-DECL_TYPE(sampler2DShadow, GL_SAMPLER_2D_SHADOW, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_2D, 1, 0, GLSL_TYPE_FLOAT)
-DECL_TYPE(samplerCubeShadow, GL_SAMPLER_CUBE_SHADOW, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_CUBE, 1, 0, GLSL_TYPE_FLOAT)
-DECL_TYPE(sampler1DArrayShadow, GL_SAMPLER_1D_ARRAY_SHADOW, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_1D, 1, 1, GLSL_TYPE_FLOAT)
-DECL_TYPE(sampler2DArrayShadow, GL_SAMPLER_2D_ARRAY_SHADOW, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_2D, 1, 1, GLSL_TYPE_FLOAT)
-DECL_TYPE(samplerCubeArrayShadow, GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_CUBE, 1, 1, GLSL_TYPE_FLOAT)
-DECL_TYPE(sampler2DRectShadow, GL_SAMPLER_2D_RECT_SHADOW, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_RECT, 1, 0, GLSL_TYPE_FLOAT)
-
-DECL_TYPE(samplerExternalOES, GL_SAMPLER_EXTERNAL_OES, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_EXTERNAL, 0, 0, GLSL_TYPE_FLOAT)
-
-DECL_TYPE(image1D, GL_IMAGE_1D, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_1D, 0, 0, GLSL_TYPE_FLOAT)
-DECL_TYPE(image2D, GL_IMAGE_2D, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_2D, 0, 0, GLSL_TYPE_FLOAT)
-DECL_TYPE(image3D, GL_IMAGE_3D, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_3D, 0, 0, GLSL_TYPE_FLOAT)
-DECL_TYPE(image2DRect, GL_IMAGE_2D_RECT, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_RECT, 0, 0, GLSL_TYPE_FLOAT)
-DECL_TYPE(imageCube, GL_IMAGE_CUBE, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_CUBE, 0, 0, GLSL_TYPE_FLOAT)
-DECL_TYPE(imageBuffer, GL_IMAGE_BUFFER, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_BUF, 0, 0, GLSL_TYPE_FLOAT)
-DECL_TYPE(image1DArray, GL_IMAGE_1D_ARRAY, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_1D, 0, 1, GLSL_TYPE_FLOAT)
-DECL_TYPE(image2DArray, GL_IMAGE_2D_ARRAY, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_2D, 0, 1, GLSL_TYPE_FLOAT)
-DECL_TYPE(imageCubeArray, GL_IMAGE_CUBE_MAP_ARRAY, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_CUBE, 0, 1, GLSL_TYPE_FLOAT)
-DECL_TYPE(image2DMS, GL_IMAGE_2D_MULTISAMPLE, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_MS, 0, 0, GLSL_TYPE_FLOAT)
-DECL_TYPE(image2DMSArray, GL_IMAGE_2D_MULTISAMPLE_ARRAY, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_MS, 0, 1, GLSL_TYPE_FLOAT)
-DECL_TYPE(iimage1D, GL_INT_IMAGE_1D, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_1D, 0, 0, GLSL_TYPE_INT)
-DECL_TYPE(iimage2D, GL_INT_IMAGE_2D, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_2D, 0, 0, GLSL_TYPE_INT)
-DECL_TYPE(iimage3D, GL_INT_IMAGE_3D, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_3D, 0, 0, GLSL_TYPE_INT)
-DECL_TYPE(iimage2DRect, GL_INT_IMAGE_2D_RECT, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_RECT, 0, 0, GLSL_TYPE_INT)
-DECL_TYPE(iimageCube, GL_INT_IMAGE_CUBE, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_CUBE, 0, 0, GLSL_TYPE_INT)
-DECL_TYPE(iimageBuffer, GL_INT_IMAGE_BUFFER, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_BUF, 0, 0, GLSL_TYPE_INT)
-DECL_TYPE(iimage1DArray, GL_INT_IMAGE_1D_ARRAY, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_1D, 0, 1, GLSL_TYPE_INT)
-DECL_TYPE(iimage2DArray, GL_INT_IMAGE_2D_ARRAY, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_2D, 0, 1, GLSL_TYPE_INT)
-DECL_TYPE(iimageCubeArray, GL_INT_IMAGE_CUBE_MAP_ARRAY, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_CUBE, 0, 1, GLSL_TYPE_INT)
-DECL_TYPE(iimage2DMS, GL_INT_IMAGE_2D_MULTISAMPLE, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_MS, 0, 0, GLSL_TYPE_INT)
-DECL_TYPE(iimage2DMSArray, GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_MS, 0, 1, GLSL_TYPE_INT)
-DECL_TYPE(uimage1D, GL_UNSIGNED_INT_IMAGE_1D, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_1D, 0, 0, GLSL_TYPE_UINT)
-DECL_TYPE(uimage2D, GL_UNSIGNED_INT_IMAGE_2D, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_2D, 0, 0, GLSL_TYPE_UINT)
-DECL_TYPE(uimage3D, GL_UNSIGNED_INT_IMAGE_3D, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_3D, 0, 0, GLSL_TYPE_UINT)
-DECL_TYPE(uimage2DRect, GL_UNSIGNED_INT_IMAGE_2D_RECT, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_RECT, 0, 0, GLSL_TYPE_UINT)
-DECL_TYPE(uimageCube, GL_UNSIGNED_INT_IMAGE_CUBE, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_CUBE, 0, 0, GLSL_TYPE_UINT)
-DECL_TYPE(uimageBuffer, GL_UNSIGNED_INT_IMAGE_BUFFER, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_BUF, 0, 0, GLSL_TYPE_UINT)
-DECL_TYPE(uimage1DArray, GL_UNSIGNED_INT_IMAGE_1D_ARRAY, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_1D, 0, 1, GLSL_TYPE_UINT)
-DECL_TYPE(uimage2DArray, GL_UNSIGNED_INT_IMAGE_2D_ARRAY, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_2D, 0, 1, GLSL_TYPE_UINT)
-DECL_TYPE(uimageCubeArray, GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_CUBE, 0, 1, GLSL_TYPE_UINT)
-DECL_TYPE(uimage2DMS, GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_MS, 0, 0, GLSL_TYPE_UINT)
-DECL_TYPE(uimage2DMSArray, GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_MS, 0, 1, GLSL_TYPE_UINT)
-
-DECL_TYPE(atomic_uint, GL_UNSIGNED_INT_ATOMIC_COUNTER, GLSL_TYPE_ATOMIC_UINT, 1, 1)
-
-STRUCT_TYPE(gl_DepthRangeParameters)
-STRUCT_TYPE(gl_PointParameters)
-STRUCT_TYPE(gl_MaterialParameters)
-STRUCT_TYPE(gl_LightSourceParameters)
-STRUCT_TYPE(gl_LightModelParameters)
-STRUCT_TYPE(gl_LightModelProducts)
-STRUCT_TYPE(gl_LightProducts)
-STRUCT_TYPE(gl_FogParameters)
diff --git a/src/glsl/nir/glsl_to_nir.cpp b/src/glsl/nir/glsl_to_nir.cpp
deleted file mode 100644
index f29377cc260..00000000000
--- a/src/glsl/nir/glsl_to_nir.cpp
+++ /dev/null
@@ -1,2035 +0,0 @@
-/*
- * Copyright © 2014 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- *
- * Authors:
- * Connor Abbott ([email protected])
- *
- */
-
-#include "glsl_to_nir.h"
-#include "nir_control_flow.h"
-#include "nir_builder.h"
-#include "ir_visitor.h"
-#include "ir_hierarchical_visitor.h"
-#include "ir.h"
-#include "main/imports.h"
-
-/*
- * pass to lower GLSL IR to NIR
- *
- * This will lower variable dereferences to loads/stores of corresponding
- * variables in NIR - the variables will be converted to registers in a later
- * pass.
- */
-
-namespace {
-
-class nir_visitor : public ir_visitor
-{
-public:
- nir_visitor(nir_shader *shader, gl_shader *sh);
- ~nir_visitor();
-
- virtual void visit(ir_variable *);
- virtual void visit(ir_function *);
- virtual void visit(ir_function_signature *);
- virtual void visit(ir_loop *);
- virtual void visit(ir_if *);
- virtual void visit(ir_discard *);
- virtual void visit(ir_loop_jump *);
- virtual void visit(ir_return *);
- virtual void visit(ir_call *);
- virtual void visit(ir_assignment *);
- virtual void visit(ir_emit_vertex *);
- virtual void visit(ir_end_primitive *);
- virtual void visit(ir_expression *);
- virtual void visit(ir_swizzle *);
- virtual void visit(ir_texture *);
- virtual void visit(ir_constant *);
- virtual void visit(ir_dereference_variable *);
- virtual void visit(ir_dereference_record *);
- virtual void visit(ir_dereference_array *);
- virtual void visit(ir_barrier *);
-
- void create_function(ir_function_signature *ir);
-
-private:
- void add_instr(nir_instr *instr, unsigned num_components);
- nir_ssa_def *evaluate_rvalue(ir_rvalue *ir);
-
- nir_alu_instr *emit(nir_op op, unsigned dest_size, nir_ssa_def **srcs);
- nir_alu_instr *emit(nir_op op, unsigned dest_size, nir_ssa_def *src1);
- nir_alu_instr *emit(nir_op op, unsigned dest_size, nir_ssa_def *src1,
- nir_ssa_def *src2);
- nir_alu_instr *emit(nir_op op, unsigned dest_size, nir_ssa_def *src1,
- nir_ssa_def *src2, nir_ssa_def *src3);
-
- bool supports_ints;
-
- struct gl_shader *sh;
-
- nir_shader *shader;
- nir_function_impl *impl;
- nir_builder b;
- nir_ssa_def *result; /* result of the expression tree last visited */
-
- nir_deref_var *evaluate_deref(nir_instr *mem_ctx, ir_instruction *ir);
-
- /* the head of the dereference chain we're creating */
- nir_deref_var *deref_head;
- /* the tail of the dereference chain we're creating */
- nir_deref *deref_tail;
-
- nir_variable *var; /* variable created by ir_variable visitor */
-
- /* whether the IR we're operating on is per-function or global */
- bool is_global;
-
- /* map of ir_variable -> nir_variable */
- struct hash_table *var_table;
-
- /* map of ir_function_signature -> nir_function_overload */
- struct hash_table *overload_table;
-};
-
-/*
- * This visitor runs before the main visitor, calling create_function() for
- * each function so that the main visitor can resolve forward references in
- * calls.
- */
-
-class nir_function_visitor : public ir_hierarchical_visitor
-{
-public:
- nir_function_visitor(nir_visitor *v) : visitor(v)
- {
- }
- virtual ir_visitor_status visit_enter(ir_function *);
-
-private:
- nir_visitor *visitor;
-};
-
-}; /* end of anonymous namespace */
-
-nir_shader *
-glsl_to_nir(const struct gl_shader_program *shader_prog,
- gl_shader_stage stage,
- const nir_shader_compiler_options *options)
-{
- struct gl_shader *sh = shader_prog->_LinkedShaders[stage];
-
- nir_shader *shader = nir_shader_create(NULL, stage, options);
-
- nir_visitor v1(shader, sh);
- nir_function_visitor v2(&v1);
- v2.run(sh->ir);
- visit_exec_list(sh->ir, &v1);
-
- nir_function *main = NULL;
- nir_foreach_function(shader, func) {
- if (strcmp(func->name, "main") == 0) {
- main = func;
- break;
- }
- }
- assert(main);
-
- nir_lower_outputs_to_temporaries(shader, main);
-
- shader->info.name = ralloc_asprintf(shader, "GLSL%d", shader_prog->Name);
- if (shader_prog->Label)
- shader->info.label = ralloc_strdup(shader, shader_prog->Label);
- shader->info.num_textures = _mesa_fls(sh->Program->SamplersUsed);
- shader->info.num_ubos = sh->NumUniformBlocks;
- shader->info.num_abos = shader_prog->NumAtomicBuffers;
- shader->info.num_ssbos = sh->NumShaderStorageBlocks;
- shader->info.num_images = sh->NumImages;
- shader->info.inputs_read = sh->Program->InputsRead;
- shader->info.outputs_written = sh->Program->OutputsWritten;
- shader->info.patch_inputs_read = sh->Program->PatchInputsRead;
- shader->info.patch_outputs_written = sh->Program->PatchOutputsWritten;
- shader->info.system_values_read = sh->Program->SystemValuesRead;
- shader->info.uses_texture_gather = sh->Program->UsesGather;
- shader->info.uses_clip_distance_out =
- sh->Program->ClipDistanceArraySize != 0;
- shader->info.separate_shader = shader_prog->SeparateShader;
- shader->info.has_transform_feedback_varyings =
- shader_prog->TransformFeedback.NumVarying > 0;
-
- switch (stage) {
- case MESA_SHADER_TESS_CTRL:
- shader->info.tcs.vertices_out = shader_prog->TessCtrl.VerticesOut;
- break;
-
- case MESA_SHADER_GEOMETRY:
- shader->info.gs.vertices_in = shader_prog->Geom.VerticesIn;
- shader->info.gs.output_primitive = sh->Geom.OutputType;
- shader->info.gs.vertices_out = sh->Geom.VerticesOut;
- shader->info.gs.invocations = sh->Geom.Invocations;
- shader->info.gs.uses_end_primitive = shader_prog->Geom.UsesEndPrimitive;
- shader->info.gs.uses_streams = shader_prog->Geom.UsesStreams;
- break;
-
- case MESA_SHADER_FRAGMENT: {
- struct gl_fragment_program *fp =
- (struct gl_fragment_program *)sh->Program;
-
- shader->info.fs.uses_discard = fp->UsesKill;
- shader->info.fs.early_fragment_tests = sh->EarlyFragmentTests;
- shader->info.fs.depth_layout = fp->FragDepthLayout;
- break;
- }
-
- case MESA_SHADER_COMPUTE: {
- struct gl_compute_program *cp = (struct gl_compute_program *)sh->Program;
- shader->info.cs.local_size[0] = cp->LocalSize[0];
- shader->info.cs.local_size[1] = cp->LocalSize[1];
- shader->info.cs.local_size[2] = cp->LocalSize[2];
- break;
- }
-
- default:
- break; /* No stage-specific info */
- }
-
- return shader;
-}
-
-nir_visitor::nir_visitor(nir_shader *shader, gl_shader *sh)
-{
- this->supports_ints = shader->options->native_integers;
- this->shader = shader;
- this->sh = sh;
- this->is_global = true;
- this->var_table = _mesa_hash_table_create(NULL, _mesa_hash_pointer,
- _mesa_key_pointer_equal);
- this->overload_table = _mesa_hash_table_create(NULL, _mesa_hash_pointer,
- _mesa_key_pointer_equal);
-}
-
-nir_visitor::~nir_visitor()
-{
- _mesa_hash_table_destroy(this->var_table, NULL);
- _mesa_hash_table_destroy(this->overload_table, NULL);
-}
-
-nir_deref_var *
-nir_visitor::evaluate_deref(nir_instr *mem_ctx, ir_instruction *ir)
-{
- ir->accept(this);
- ralloc_steal(mem_ctx, this->deref_head);
- return this->deref_head;
-}
-
-static nir_constant *
-constant_copy(ir_constant *ir, void *mem_ctx)
-{
- if (ir == NULL)
- return NULL;
-
- nir_constant *ret = ralloc(mem_ctx, nir_constant);
-
- unsigned total_elems = ir->type->components();
- unsigned i;
-
- ret->num_elements = 0;
- switch (ir->type->base_type) {
- case GLSL_TYPE_UINT:
- for (i = 0; i < total_elems; i++)
- ret->value.u[i] = ir->value.u[i];
- break;
-
- case GLSL_TYPE_INT:
- for (i = 0; i < total_elems; i++)
- ret->value.i[i] = ir->value.i[i];
- break;
-
- case GLSL_TYPE_FLOAT:
- for (i = 0; i < total_elems; i++)
- ret->value.f[i] = ir->value.f[i];
- break;
-
- case GLSL_TYPE_BOOL:
- for (i = 0; i < total_elems; i++)
- ret->value.b[i] = ir->value.b[i];
- break;
-
- case GLSL_TYPE_STRUCT:
- ret->elements = ralloc_array(mem_ctx, nir_constant *,
- ir->type->length);
- ret->num_elements = ir->type->length;
-
- i = 0;
- foreach_in_list(ir_constant, field, &ir->components) {
- ret->elements[i] = constant_copy(field, mem_ctx);
- i++;
- }
- break;
-
- case GLSL_TYPE_ARRAY:
- ret->elements = ralloc_array(mem_ctx, nir_constant *,
- ir->type->length);
- ret->num_elements = ir->type->length;
-
- for (i = 0; i < ir->type->length; i++)
- ret->elements[i] = constant_copy(ir->array_elements[i], mem_ctx);
- break;
-
- default:
- unreachable("not reached");
- }
-
- return ret;
-}
-
-void
-nir_visitor::visit(ir_variable *ir)
-{
- nir_variable *var = ralloc(shader, nir_variable);
- var->type = ir->type;
- var->name = ralloc_strdup(var, ir->name);
-
- var->data.read_only = ir->data.read_only;
- var->data.centroid = ir->data.centroid;
- var->data.sample = ir->data.sample;
- var->data.patch = ir->data.patch;
- var->data.invariant = ir->data.invariant;
- var->data.location = ir->data.location;
-
- switch(ir->data.mode) {
- case ir_var_auto:
- case ir_var_temporary:
- if (is_global)
- var->data.mode = nir_var_global;
- else
- var->data.mode = nir_var_local;
- break;
-
- case ir_var_function_in:
- case ir_var_function_out:
- case ir_var_function_inout:
- case ir_var_const_in:
- var->data.mode = nir_var_local;
- break;
-
- case ir_var_shader_in:
- if (shader->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;
- } else if (shader->stage == MESA_SHADER_GEOMETRY &&
- ir->data.location == VARYING_SLOT_PRIMITIVE_ID) {
- /* For whatever reason, GLSL IR makes gl_PrimitiveIDIn an input */
- var->data.location = SYSTEM_VALUE_PRIMITIVE_ID;
- var->data.mode = nir_var_system_value;
- } else {
- var->data.mode = nir_var_shader_in;
- }
- break;
-
- case ir_var_shader_out:
- var->data.mode = nir_var_shader_out;
- break;
-
- case ir_var_uniform:
- var->data.mode = nir_var_uniform;
- break;
-
- case ir_var_shader_storage:
- var->data.mode = nir_var_shader_storage;
- break;
-
- case ir_var_system_value:
- var->data.mode = nir_var_system_value;
- break;
-
- default:
- unreachable("not reached");
- }
-
- var->data.interpolation = ir->data.interpolation;
- var->data.origin_upper_left = ir->data.origin_upper_left;
- var->data.pixel_center_integer = ir->data.pixel_center_integer;
- var->data.explicit_location = ir->data.explicit_location;
- var->data.explicit_index = ir->data.explicit_index;
- var->data.explicit_binding = ir->data.explicit_binding;
- var->data.has_initializer = ir->data.has_initializer;
- var->data.location_frac = ir->data.location_frac;
- var->data.from_named_ifc_block_array = ir->data.from_named_ifc_block_array;
- var->data.from_named_ifc_block_nonarray = ir->data.from_named_ifc_block_nonarray;
-
- switch (ir->data.depth_layout) {
- case ir_depth_layout_none:
- var->data.depth_layout = nir_depth_layout_none;
- break;
- case ir_depth_layout_any:
- var->data.depth_layout = nir_depth_layout_any;
- break;
- case ir_depth_layout_greater:
- var->data.depth_layout = nir_depth_layout_greater;
- break;
- case ir_depth_layout_less:
- var->data.depth_layout = nir_depth_layout_less;
- break;
- case ir_depth_layout_unchanged:
- var->data.depth_layout = nir_depth_layout_unchanged;
- break;
- default:
- unreachable("not reached");
- }
-
- var->data.index = ir->data.index;
- var->data.descriptor_set = 0;
- var->data.binding = ir->data.binding;
- var->data.offset = ir->data.offset;
- var->data.image.read_only = ir->data.image_read_only;
- var->data.image.write_only = ir->data.image_write_only;
- var->data.image.coherent = ir->data.image_coherent;
- var->data.image._volatile = ir->data.image_volatile;
- var->data.image.restrict_flag = ir->data.image_restrict;
- var->data.image.format = ir->data.image_format;
- var->data.max_array_access = ir->data.max_array_access;
-
- var->num_state_slots = ir->get_num_state_slots();
- if (var->num_state_slots > 0) {
- var->state_slots = ralloc_array(var, nir_state_slot,
- var->num_state_slots);
-
- ir_state_slot *state_slots = ir->get_state_slots();
- for (unsigned i = 0; i < var->num_state_slots; i++) {
- for (unsigned j = 0; j < 5; j++)
- var->state_slots[i].tokens[j] = state_slots[i].tokens[j];
- var->state_slots[i].swizzle = state_slots[i].swizzle;
- }
- } else {
- var->state_slots = NULL;
- }
-
- var->constant_initializer = constant_copy(ir->constant_initializer, var);
-
- var->interface_type = ir->get_interface_type();
-
- if (var->data.mode == nir_var_local)
- nir_function_impl_add_variable(impl, var);
- else
- nir_shader_add_variable(shader, var);
-
- _mesa_hash_table_insert(var_table, ir, var);
- this->var = var;
-}
-
-ir_visitor_status
-nir_function_visitor::visit_enter(ir_function *ir)
-{
- foreach_in_list(ir_function_signature, sig, &ir->signatures) {
- visitor->create_function(sig);
- }
- return visit_continue_with_parent;
-}
-
-void
-nir_visitor::create_function(ir_function_signature *ir)
-{
- if (ir->is_intrinsic)
- return;
-
- nir_function *func = nir_function_create(shader, ir->function_name());
-
- unsigned num_params = ir->parameters.length();
- func->num_params = num_params;
- func->params = ralloc_array(shader, nir_parameter, num_params);
-
- unsigned i = 0;
- foreach_in_list(ir_variable, param, &ir->parameters) {
- switch (param->data.mode) {
- case ir_var_function_in:
- func->params[i].param_type = nir_parameter_in;
- break;
-
- case ir_var_function_out:
- func->params[i].param_type = nir_parameter_out;
- break;
-
- case ir_var_function_inout:
- func->params[i].param_type = nir_parameter_inout;
- break;
-
- default:
- unreachable("not reached");
- }
-
- func->params[i].type = param->type;
- i++;
- }
-
- func->return_type = ir->return_type;
-
- _mesa_hash_table_insert(this->overload_table, ir, func);
-}
-
-void
-nir_visitor::visit(ir_function *ir)
-{
- foreach_in_list(ir_function_signature, sig, &ir->signatures)
- sig->accept(this);
-}
-
-void
-nir_visitor::visit(ir_function_signature *ir)
-{
- if (ir->is_intrinsic)
- return;
-
- struct hash_entry *entry =
- _mesa_hash_table_search(this->overload_table, ir);
-
- assert(entry);
- nir_function *func = (nir_function *) entry->data;
-
- if (ir->is_defined) {
- nir_function_impl *impl = nir_function_impl_create(func);
- this->impl = impl;
-
- unsigned num_params = func->num_params;
- impl->num_params = num_params;
- impl->params = ralloc_array(this->shader, nir_variable *, num_params);
- unsigned i = 0;
- foreach_in_list(ir_variable, param, &ir->parameters) {
- param->accept(this);
- impl->params[i] = this->var;
- i++;
- }
-
- if (func->return_type == glsl_type::void_type) {
- impl->return_var = NULL;
- } else {
- impl->return_var = ralloc(this->shader, nir_variable);
- impl->return_var->name = ralloc_strdup(impl->return_var,
- "return_var");
- impl->return_var->type = func->return_type;
- }
-
- this->is_global = false;
-
- nir_builder_init(&b, impl);
- b.cursor = nir_after_cf_list(&impl->body);
- visit_exec_list(&ir->body, this);
-
- this->is_global = true;
- } else {
- func->impl = NULL;
- }
-}
-
-void
-nir_visitor::visit(ir_loop *ir)
-{
- nir_loop *loop = nir_loop_create(this->shader);
- nir_builder_cf_insert(&b, &loop->cf_node);
-
- b.cursor = nir_after_cf_list(&loop->body);
- visit_exec_list(&ir->body_instructions, this);
- b.cursor = nir_after_cf_node(&loop->cf_node);
-}
-
-void
-nir_visitor::visit(ir_if *ir)
-{
- nir_src condition =
- nir_src_for_ssa(evaluate_rvalue(ir->condition));
-
- nir_if *if_stmt = nir_if_create(this->shader);
- if_stmt->condition = condition;
- nir_builder_cf_insert(&b, &if_stmt->cf_node);
-
- b.cursor = nir_after_cf_list(&if_stmt->then_list);
- visit_exec_list(&ir->then_instructions, this);
-
- b.cursor = nir_after_cf_list(&if_stmt->else_list);
- visit_exec_list(&ir->else_instructions, this);
-
- b.cursor = nir_after_cf_node(&if_stmt->cf_node);
-}
-
-void
-nir_visitor::visit(ir_discard *ir)
-{
- /*
- * discards aren't treated as control flow, because before we lower them
- * they can appear anywhere in the shader and the stuff after them may still
- * be executed (yay, crazy GLSL rules!). However, after lowering, all the
- * discards will be immediately followed by a return.
- */
-
- nir_intrinsic_instr *discard;
- if (ir->condition) {
- discard = nir_intrinsic_instr_create(this->shader,
- nir_intrinsic_discard_if);
- discard->src[0] =
- nir_src_for_ssa(evaluate_rvalue(ir->condition));
- } else {
- discard = nir_intrinsic_instr_create(this->shader, nir_intrinsic_discard);
- }
-
- nir_builder_instr_insert(&b, &discard->instr);
-}
-
-void
-nir_visitor::visit(ir_emit_vertex *ir)
-{
- nir_intrinsic_instr *instr =
- nir_intrinsic_instr_create(this->shader, nir_intrinsic_emit_vertex);
- instr->const_index[0] = ir->stream_id();
- nir_builder_instr_insert(&b, &instr->instr);
-}
-
-void
-nir_visitor::visit(ir_end_primitive *ir)
-{
- nir_intrinsic_instr *instr =
- nir_intrinsic_instr_create(this->shader, nir_intrinsic_end_primitive);
- instr->const_index[0] = ir->stream_id();
- nir_builder_instr_insert(&b, &instr->instr);
-}
-
-void
-nir_visitor::visit(ir_loop_jump *ir)
-{
- nir_jump_type type;
- switch (ir->mode) {
- case ir_loop_jump::jump_break:
- type = nir_jump_break;
- break;
- case ir_loop_jump::jump_continue:
- type = nir_jump_continue;
- break;
- default:
- unreachable("not reached");
- }
-
- nir_jump_instr *instr = nir_jump_instr_create(this->shader, type);
- nir_builder_instr_insert(&b, &instr->instr);
-}
-
-void
-nir_visitor::visit(ir_return *ir)
-{
- if (ir->value != NULL) {
- nir_intrinsic_instr *copy =
- nir_intrinsic_instr_create(this->shader, nir_intrinsic_copy_var);
-
- copy->variables[0] = nir_deref_var_create(copy, this->impl->return_var);
- copy->variables[1] = evaluate_deref(&copy->instr, ir->value);
- }
-
- nir_jump_instr *instr = nir_jump_instr_create(this->shader, nir_jump_return);
- nir_builder_instr_insert(&b, &instr->instr);
-}
-
-void
-nir_visitor::visit(ir_call *ir)
-{
- if (ir->callee->is_intrinsic) {
- nir_intrinsic_op op;
- if (strcmp(ir->callee_name(), "__intrinsic_atomic_read") == 0) {
- op = nir_intrinsic_atomic_counter_read_var;
- } else if (strcmp(ir->callee_name(), "__intrinsic_atomic_increment") == 0) {
- op = nir_intrinsic_atomic_counter_inc_var;
- } else if (strcmp(ir->callee_name(), "__intrinsic_atomic_predecrement") == 0) {
- op = nir_intrinsic_atomic_counter_dec_var;
- } else if (strcmp(ir->callee_name(), "__intrinsic_image_load") == 0) {
- op = nir_intrinsic_image_load;
- } else if (strcmp(ir->callee_name(), "__intrinsic_image_store") == 0) {
- op = nir_intrinsic_image_store;
- } else if (strcmp(ir->callee_name(), "__intrinsic_image_atomic_add") == 0) {
- op = nir_intrinsic_image_atomic_add;
- } else if (strcmp(ir->callee_name(), "__intrinsic_image_atomic_min") == 0) {
- op = nir_intrinsic_image_atomic_min;
- } else if (strcmp(ir->callee_name(), "__intrinsic_image_atomic_max") == 0) {
- op = nir_intrinsic_image_atomic_max;
- } else if (strcmp(ir->callee_name(), "__intrinsic_image_atomic_and") == 0) {
- op = nir_intrinsic_image_atomic_and;
- } else if (strcmp(ir->callee_name(), "__intrinsic_image_atomic_or") == 0) {
- op = nir_intrinsic_image_atomic_or;
- } else if (strcmp(ir->callee_name(), "__intrinsic_image_atomic_xor") == 0) {
- op = nir_intrinsic_image_atomic_xor;
- } else if (strcmp(ir->callee_name(), "__intrinsic_image_atomic_exchange") == 0) {
- op = nir_intrinsic_image_atomic_exchange;
- } else if (strcmp(ir->callee_name(), "__intrinsic_image_atomic_comp_swap") == 0) {
- op = nir_intrinsic_image_atomic_comp_swap;
- } else if (strcmp(ir->callee_name(), "__intrinsic_memory_barrier") == 0) {
- op = nir_intrinsic_memory_barrier;
- } else if (strcmp(ir->callee_name(), "__intrinsic_image_size") == 0) {
- op = nir_intrinsic_image_size;
- } else if (strcmp(ir->callee_name(), "__intrinsic_image_samples") == 0) {
- op = nir_intrinsic_image_samples;
- } else if (strcmp(ir->callee_name(), "__intrinsic_store_ssbo") == 0) {
- op = nir_intrinsic_store_ssbo;
- } else if (strcmp(ir->callee_name(), "__intrinsic_load_ssbo") == 0) {
- op = nir_intrinsic_load_ssbo;
- } else if (strcmp(ir->callee_name(), "__intrinsic_atomic_add_ssbo") == 0) {
- op = nir_intrinsic_ssbo_atomic_add;
- } else if (strcmp(ir->callee_name(), "__intrinsic_atomic_and_ssbo") == 0) {
- op = nir_intrinsic_ssbo_atomic_and;
- } else if (strcmp(ir->callee_name(), "__intrinsic_atomic_or_ssbo") == 0) {
- op = nir_intrinsic_ssbo_atomic_or;
- } else if (strcmp(ir->callee_name(), "__intrinsic_atomic_xor_ssbo") == 0) {
- op = nir_intrinsic_ssbo_atomic_xor;
- } else if (strcmp(ir->callee_name(), "__intrinsic_atomic_min_ssbo") == 0) {
- assert(ir->return_deref);
- if (ir->return_deref->type == glsl_type::int_type)
- op = nir_intrinsic_ssbo_atomic_imin;
- else if (ir->return_deref->type == glsl_type::uint_type)
- op = nir_intrinsic_ssbo_atomic_umin;
- else
- unreachable("Invalid type");
- } else if (strcmp(ir->callee_name(), "__intrinsic_atomic_max_ssbo") == 0) {
- assert(ir->return_deref);
- if (ir->return_deref->type == glsl_type::int_type)
- op = nir_intrinsic_ssbo_atomic_imax;
- else if (ir->return_deref->type == glsl_type::uint_type)
- op = nir_intrinsic_ssbo_atomic_umax;
- else
- unreachable("Invalid type");
- } else if (strcmp(ir->callee_name(), "__intrinsic_atomic_exchange_ssbo") == 0) {
- op = nir_intrinsic_ssbo_atomic_exchange;
- } else if (strcmp(ir->callee_name(), "__intrinsic_atomic_comp_swap_ssbo") == 0) {
- op = nir_intrinsic_ssbo_atomic_comp_swap;
- } else if (strcmp(ir->callee_name(), "__intrinsic_shader_clock") == 0) {
- op = nir_intrinsic_shader_clock;
- } else if (strcmp(ir->callee_name(), "__intrinsic_group_memory_barrier") == 0) {
- op = nir_intrinsic_group_memory_barrier;
- } else if (strcmp(ir->callee_name(), "__intrinsic_memory_barrier_atomic_counter") == 0) {
- op = nir_intrinsic_memory_barrier_atomic_counter;
- } else if (strcmp(ir->callee_name(), "__intrinsic_memory_barrier_buffer") == 0) {
- op = nir_intrinsic_memory_barrier_buffer;
- } else if (strcmp(ir->callee_name(), "__intrinsic_memory_barrier_image") == 0) {
- op = nir_intrinsic_memory_barrier_image;
- } else if (strcmp(ir->callee_name(), "__intrinsic_memory_barrier_shared") == 0) {
- op = nir_intrinsic_memory_barrier_shared;
- } else if (strcmp(ir->callee_name(), "__intrinsic_load_shared") == 0) {
- op = nir_intrinsic_load_shared;
- } else if (strcmp(ir->callee_name(), "__intrinsic_store_shared") == 0) {
- op = nir_intrinsic_store_shared;
- } else if (strcmp(ir->callee_name(), "__intrinsic_atomic_add_shared") == 0) {
- op = nir_intrinsic_shared_atomic_add;
- } else if (strcmp(ir->callee_name(), "__intrinsic_atomic_and_shared") == 0) {
- op = nir_intrinsic_shared_atomic_and;
- } else if (strcmp(ir->callee_name(), "__intrinsic_atomic_or_shared") == 0) {
- op = nir_intrinsic_shared_atomic_or;
- } else if (strcmp(ir->callee_name(), "__intrinsic_atomic_xor_shared") == 0) {
- op = nir_intrinsic_shared_atomic_xor;
- } else if (strcmp(ir->callee_name(), "__intrinsic_atomic_min_shared") == 0) {
- assert(ir->return_deref);
- if (ir->return_deref->type == glsl_type::int_type)
- op = nir_intrinsic_shared_atomic_imin;
- else if (ir->return_deref->type == glsl_type::uint_type)
- op = nir_intrinsic_shared_atomic_umin;
- else
- unreachable("Invalid type");
- } else if (strcmp(ir->callee_name(), "__intrinsic_atomic_max_shared") == 0) {
- assert(ir->return_deref);
- if (ir->return_deref->type == glsl_type::int_type)
- op = nir_intrinsic_shared_atomic_imax;
- else if (ir->return_deref->type == glsl_type::uint_type)
- op = nir_intrinsic_shared_atomic_umax;
- else
- unreachable("Invalid type");
- } else if (strcmp(ir->callee_name(), "__intrinsic_atomic_exchange_shared") == 0) {
- op = nir_intrinsic_shared_atomic_exchange;
- } else if (strcmp(ir->callee_name(), "__intrinsic_atomic_comp_swap_shared") == 0) {
- op = nir_intrinsic_shared_atomic_comp_swap;
- } else {
- unreachable("not reached");
- }
-
- nir_intrinsic_instr *instr = nir_intrinsic_instr_create(shader, op);
- nir_dest *dest = &instr->dest;
-
- switch (op) {
- case nir_intrinsic_atomic_counter_read_var:
- case nir_intrinsic_atomic_counter_inc_var:
- case nir_intrinsic_atomic_counter_dec_var: {
- ir_dereference *param =
- (ir_dereference *) ir->actual_parameters.get_head();
- instr->variables[0] = evaluate_deref(&instr->instr, param);
- nir_ssa_dest_init(&instr->instr, &instr->dest, 1, NULL);
- nir_builder_instr_insert(&b, &instr->instr);
- break;
- }
- case nir_intrinsic_image_load:
- case nir_intrinsic_image_store:
- case nir_intrinsic_image_atomic_add:
- case nir_intrinsic_image_atomic_min:
- case nir_intrinsic_image_atomic_max:
- case nir_intrinsic_image_atomic_and:
- case nir_intrinsic_image_atomic_or:
- case nir_intrinsic_image_atomic_xor:
- case nir_intrinsic_image_atomic_exchange:
- case nir_intrinsic_image_atomic_comp_swap:
- case nir_intrinsic_image_samples:
- case nir_intrinsic_image_size: {
- nir_ssa_undef_instr *instr_undef =
- nir_ssa_undef_instr_create(shader, 1);
- nir_builder_instr_insert(&b, &instr_undef->instr);
-
- /* Set the image variable dereference. */
- exec_node *param = ir->actual_parameters.get_head();
- ir_dereference *image = (ir_dereference *)param;
- const glsl_type *type =
- image->variable_referenced()->type->without_array();
-
- instr->variables[0] = evaluate_deref(&instr->instr, image);
- param = param->get_next();
-
- /* Set the intrinsic destination. */
- if (ir->return_deref) {
- const nir_intrinsic_info *info =
- &nir_intrinsic_infos[instr->intrinsic];
- nir_ssa_dest_init(&instr->instr, &instr->dest,
- info->dest_components, NULL);
- }
-
- if (op == nir_intrinsic_image_size ||
- op == nir_intrinsic_image_samples) {
- nir_builder_instr_insert(&b, &instr->instr);
- break;
- }
-
- /* Set the address argument, extending the coordinate vector to four
- * components.
- */
- nir_ssa_def *src_addr =
- evaluate_rvalue((ir_dereference *)param);
- nir_ssa_def *srcs[4];
-
- for (int i = 0; i < 4; i++) {
- if (i < type->coordinate_components())
- srcs[i] = nir_channel(&b, src_addr, i);
- else
- srcs[i] = &instr_undef->def;
- }
-
- instr->src[0] = nir_src_for_ssa(nir_vec(&b, srcs, 4));
- param = param->get_next();
-
- /* Set the sample argument, which is undefined for single-sample
- * images.
- */
- if (type->sampler_dimensionality == GLSL_SAMPLER_DIM_MS) {
- instr->src[1] =
- nir_src_for_ssa(evaluate_rvalue((ir_dereference *)param));
- param = param->get_next();
- } else {
- instr->src[1] = nir_src_for_ssa(&instr_undef->def);
- }
-
- /* Set the intrinsic parameters. */
- if (!param->is_tail_sentinel()) {
- instr->src[2] =
- nir_src_for_ssa(evaluate_rvalue((ir_dereference *)param));
- param = param->get_next();
- }
-
- if (!param->is_tail_sentinel()) {
- instr->src[3] =
- nir_src_for_ssa(evaluate_rvalue((ir_dereference *)param));
- param = param->get_next();
- }
- nir_builder_instr_insert(&b, &instr->instr);
- break;
- }
- case nir_intrinsic_memory_barrier:
- case nir_intrinsic_group_memory_barrier:
- case nir_intrinsic_memory_barrier_atomic_counter:
- case nir_intrinsic_memory_barrier_buffer:
- case nir_intrinsic_memory_barrier_image:
- case nir_intrinsic_memory_barrier_shared:
- nir_builder_instr_insert(&b, &instr->instr);
- break;
- case nir_intrinsic_shader_clock:
- nir_ssa_dest_init(&instr->instr, &instr->dest, 1, NULL);
- nir_builder_instr_insert(&b, &instr->instr);
- break;
- case nir_intrinsic_store_ssbo: {
- exec_node *param = ir->actual_parameters.get_head();
- ir_rvalue *block = ((ir_instruction *)param)->as_rvalue();
-
- param = param->get_next();
- ir_rvalue *offset = ((ir_instruction *)param)->as_rvalue();
-
- param = param->get_next();
- ir_rvalue *val = ((ir_instruction *)param)->as_rvalue();
-
- param = param->get_next();
- ir_constant *write_mask = ((ir_instruction *)param)->as_constant();
- assert(write_mask);
-
- instr->src[0] = nir_src_for_ssa(evaluate_rvalue(val));
- instr->src[1] = nir_src_for_ssa(evaluate_rvalue(block));
- instr->src[2] = nir_src_for_ssa(evaluate_rvalue(offset));
- instr->const_index[0] = write_mask->value.u[0];
- instr->num_components = val->type->vector_elements;
-
- nir_builder_instr_insert(&b, &instr->instr);
- break;
- }
- case nir_intrinsic_load_ssbo: {
- exec_node *param = ir->actual_parameters.get_head();
- ir_rvalue *block = ((ir_instruction *)param)->as_rvalue();
-
- param = param->get_next();
- ir_rvalue *offset = ((ir_instruction *)param)->as_rvalue();
-
- instr->src[0] = nir_src_for_ssa(evaluate_rvalue(block));
- instr->src[1] = nir_src_for_ssa(evaluate_rvalue(offset));
-
- const glsl_type *type = ir->return_deref->var->type;
- instr->num_components = type->vector_elements;
-
- /* Setup destination register */
- nir_ssa_dest_init(&instr->instr, &instr->dest,
- type->vector_elements, NULL);
-
- /* Insert the created nir instruction now since in the case of boolean
- * result we will need to emit another instruction after it
- */
- nir_builder_instr_insert(&b, &instr->instr);
-
- /*
- * In SSBO/UBO's, a true boolean value is any non-zero value, but we
- * consider a true boolean to be ~0. Fix this up with a != 0
- * comparison.
- */
- if (type->base_type == GLSL_TYPE_BOOL) {
- nir_alu_instr *load_ssbo_compare =
- nir_alu_instr_create(shader, nir_op_ine);
- load_ssbo_compare->src[0].src.is_ssa = true;
- load_ssbo_compare->src[0].src.ssa = &instr->dest.ssa;
- load_ssbo_compare->src[1].src =
- nir_src_for_ssa(nir_imm_int(&b, 0));
- for (unsigned i = 0; i < type->vector_elements; i++)
- load_ssbo_compare->src[1].swizzle[i] = 0;
- nir_ssa_dest_init(&load_ssbo_compare->instr,
- &load_ssbo_compare->dest.dest,
- type->vector_elements, NULL);
- load_ssbo_compare->dest.write_mask = (1 << type->vector_elements) - 1;
- nir_builder_instr_insert(&b, &load_ssbo_compare->instr);
- dest = &load_ssbo_compare->dest.dest;
- }
- break;
- }
- case nir_intrinsic_ssbo_atomic_add:
- case nir_intrinsic_ssbo_atomic_imin:
- case nir_intrinsic_ssbo_atomic_umin:
- case nir_intrinsic_ssbo_atomic_imax:
- case nir_intrinsic_ssbo_atomic_umax:
- case nir_intrinsic_ssbo_atomic_and:
- case nir_intrinsic_ssbo_atomic_or:
- case nir_intrinsic_ssbo_atomic_xor:
- case nir_intrinsic_ssbo_atomic_exchange:
- case nir_intrinsic_ssbo_atomic_comp_swap: {
- int param_count = ir->actual_parameters.length();
- assert(param_count == 3 || param_count == 4);
-
- /* Block index */
- exec_node *param = ir->actual_parameters.get_head();
- ir_instruction *inst = (ir_instruction *) param;
- instr->src[0] = nir_src_for_ssa(evaluate_rvalue(inst->as_rvalue()));
-
- /* Offset */
- param = param->get_next();
- inst = (ir_instruction *) param;
- instr->src[1] = nir_src_for_ssa(evaluate_rvalue(inst->as_rvalue()));
-
- /* data1 parameter (this is always present) */
- param = param->get_next();
- inst = (ir_instruction *) param;
- instr->src[2] = nir_src_for_ssa(evaluate_rvalue(inst->as_rvalue()));
-
- /* data2 parameter (only with atomic_comp_swap) */
- if (param_count == 4) {
- assert(op == nir_intrinsic_ssbo_atomic_comp_swap);
- param = param->get_next();
- inst = (ir_instruction *) param;
- instr->src[3] = nir_src_for_ssa(evaluate_rvalue(inst->as_rvalue()));
- }
-
- /* Atomic result */
- assert(ir->return_deref);
- nir_ssa_dest_init(&instr->instr, &instr->dest,
- ir->return_deref->type->vector_elements, NULL);
- nir_builder_instr_insert(&b, &instr->instr);
- break;
- }
- case nir_intrinsic_load_shared: {
- exec_node *param = ir->actual_parameters.get_head();
- ir_rvalue *offset = ((ir_instruction *)param)->as_rvalue();
-
- instr->const_index[0] = 0;
- instr->src[0] = nir_src_for_ssa(evaluate_rvalue(offset));
-
- const glsl_type *type = ir->return_deref->var->type;
- instr->num_components = type->vector_elements;
-
- /* Setup destination register */
- nir_ssa_dest_init(&instr->instr, &instr->dest,
- type->vector_elements, NULL);
-
- nir_builder_instr_insert(&b, &instr->instr);
- break;
- }
- case nir_intrinsic_store_shared: {
- exec_node *param = ir->actual_parameters.get_head();
- ir_rvalue *offset = ((ir_instruction *)param)->as_rvalue();
-
- param = param->get_next();
- ir_rvalue *val = ((ir_instruction *)param)->as_rvalue();
-
- param = param->get_next();
- ir_constant *write_mask = ((ir_instruction *)param)->as_constant();
- assert(write_mask);
-
- instr->const_index[0] = 0;
- instr->src[1] = nir_src_for_ssa(evaluate_rvalue(offset));
-
- instr->const_index[1] = write_mask->value.u[0];
-
- instr->src[0] = nir_src_for_ssa(evaluate_rvalue(val));
- instr->num_components = val->type->vector_elements;
-
- nir_builder_instr_insert(&b, &instr->instr);
- break;
- }
- case nir_intrinsic_shared_atomic_add:
- case nir_intrinsic_shared_atomic_imin:
- case nir_intrinsic_shared_atomic_umin:
- case nir_intrinsic_shared_atomic_imax:
- case nir_intrinsic_shared_atomic_umax:
- case nir_intrinsic_shared_atomic_and:
- case nir_intrinsic_shared_atomic_or:
- case nir_intrinsic_shared_atomic_xor:
- case nir_intrinsic_shared_atomic_exchange:
- case nir_intrinsic_shared_atomic_comp_swap: {
- int param_count = ir->actual_parameters.length();
- assert(param_count == 2 || param_count == 3);
-
- /* Offset */
- exec_node *param = ir->actual_parameters.get_head();
- ir_instruction *inst = (ir_instruction *) param;
- instr->src[0] = nir_src_for_ssa(evaluate_rvalue(inst->as_rvalue()));
-
- /* data1 parameter (this is always present) */
- param = param->get_next();
- inst = (ir_instruction *) param;
- instr->src[1] = nir_src_for_ssa(evaluate_rvalue(inst->as_rvalue()));
-
- /* data2 parameter (only with atomic_comp_swap) */
- if (param_count == 3) {
- assert(op == nir_intrinsic_shared_atomic_comp_swap);
- param = param->get_next();
- inst = (ir_instruction *) param;
- instr->src[2] =
- nir_src_for_ssa(evaluate_rvalue(inst->as_rvalue()));
- }
-
- /* Atomic result */
- assert(ir->return_deref);
- nir_ssa_dest_init(&instr->instr, &instr->dest,
- ir->return_deref->type->vector_elements, NULL);
- nir_builder_instr_insert(&b, &instr->instr);
- break;
- }
- default:
- unreachable("not reached");
- }
-
- if (ir->return_deref) {
- nir_intrinsic_instr *store_instr =
- nir_intrinsic_instr_create(shader, nir_intrinsic_store_var);
- store_instr->num_components = ir->return_deref->type->vector_elements;
- store_instr->const_index[0] = (1 << store_instr->num_components) - 1;
-
- store_instr->variables[0] =
- evaluate_deref(&store_instr->instr, ir->return_deref);
- store_instr->src[0] = nir_src_for_ssa(&dest->ssa);
-
- nir_builder_instr_insert(&b, &store_instr->instr);
- }
-
- return;
- }
-
- struct hash_entry *entry =
- _mesa_hash_table_search(this->overload_table, ir->callee);
- assert(entry);
- nir_function *callee = (nir_function *) entry->data;
-
- nir_call_instr *instr = nir_call_instr_create(this->shader, callee);
-
- unsigned i = 0;
- foreach_in_list(ir_dereference, param, &ir->actual_parameters) {
- instr->params[i] = evaluate_deref(&instr->instr, param);
- i++;
- }
-
- instr->return_deref = evaluate_deref(&instr->instr, ir->return_deref);
- nir_builder_instr_insert(&b, &instr->instr);
-}
-
-void
-nir_visitor::visit(ir_assignment *ir)
-{
- unsigned num_components = ir->lhs->type->vector_elements;
-
- if ((ir->rhs->as_dereference() || ir->rhs->as_constant()) &&
- (ir->write_mask == (1 << num_components) - 1 || ir->write_mask == 0)) {
- /* We're doing a plain-as-can-be copy, so emit a copy_var */
- nir_intrinsic_instr *copy =
- nir_intrinsic_instr_create(this->shader, nir_intrinsic_copy_var);
-
- copy->variables[0] = evaluate_deref(&copy->instr, ir->lhs);
- copy->variables[1] = evaluate_deref(&copy->instr, ir->rhs);
-
- if (ir->condition) {
- nir_if *if_stmt = nir_if_create(this->shader);
- if_stmt->condition = nir_src_for_ssa(evaluate_rvalue(ir->condition));
- nir_builder_cf_insert(&b, &if_stmt->cf_node);
- nir_instr_insert_after_cf_list(&if_stmt->then_list, &copy->instr);
- b.cursor = nir_after_cf_node(&if_stmt->cf_node);
- } else {
- nir_builder_instr_insert(&b, &copy->instr);
- }
- return;
- }
-
- assert(ir->rhs->type->is_scalar() || ir->rhs->type->is_vector());
-
- ir->lhs->accept(this);
- nir_deref_var *lhs_deref = this->deref_head;
- nir_ssa_def *src = evaluate_rvalue(ir->rhs);
-
- if (ir->write_mask != (1 << num_components) - 1 && ir->write_mask != 0) {
- /* GLSL IR will give us the input to the write-masked assignment in a
- * single packed vector. So, for example, if the writemask is xzw, then
- * we have to swizzle x -> x, y -> z, and z -> w and get the y component
- * from the load.
- */
- unsigned swiz[4];
- unsigned component = 0;
- for (unsigned i = 0; i < 4; i++) {
- swiz[i] = ir->write_mask & (1 << i) ? component++ : 0;
- }
- src = nir_swizzle(&b, src, swiz, num_components, !supports_ints);
- }
-
- nir_intrinsic_instr *store =
- nir_intrinsic_instr_create(this->shader, nir_intrinsic_store_var);
- store->num_components = ir->lhs->type->vector_elements;
- store->const_index[0] = ir->write_mask;
- nir_deref *store_deref = nir_copy_deref(store, &lhs_deref->deref);
- store->variables[0] = nir_deref_as_var(store_deref);
- store->src[0] = nir_src_for_ssa(src);
-
- if (ir->condition) {
- nir_if *if_stmt = nir_if_create(this->shader);
- if_stmt->condition = nir_src_for_ssa(evaluate_rvalue(ir->condition));
- nir_builder_cf_insert(&b, &if_stmt->cf_node);
- nir_instr_insert_after_cf_list(&if_stmt->then_list, &store->instr);
- b.cursor = nir_after_cf_node(&if_stmt->cf_node);
- } else {
- nir_builder_instr_insert(&b, &store->instr);
- }
-}
-
-/*
- * Given an instruction, returns a pointer to its destination or NULL if there
- * is no destination.
- *
- * Note that this only handles instructions we generate at this level.
- */
-static nir_dest *
-get_instr_dest(nir_instr *instr)
-{
- nir_alu_instr *alu_instr;
- nir_intrinsic_instr *intrinsic_instr;
- nir_tex_instr *tex_instr;
-
- switch (instr->type) {
- case nir_instr_type_alu:
- alu_instr = nir_instr_as_alu(instr);
- return &alu_instr->dest.dest;
-
- case nir_instr_type_intrinsic:
- intrinsic_instr = nir_instr_as_intrinsic(instr);
- if (nir_intrinsic_infos[intrinsic_instr->intrinsic].has_dest)
- return &intrinsic_instr->dest;
- else
- return NULL;
-
- case nir_instr_type_tex:
- tex_instr = nir_instr_as_tex(instr);
- return &tex_instr->dest;
-
- default:
- unreachable("not reached");
- }
-
- return NULL;
-}
-
-void
-nir_visitor::add_instr(nir_instr *instr, unsigned num_components)
-{
- nir_dest *dest = get_instr_dest(instr);
-
- if (dest)
- nir_ssa_dest_init(instr, dest, num_components, NULL);
-
- nir_builder_instr_insert(&b, instr);
-
- if (dest) {
- assert(dest->is_ssa);
- this->result = &dest->ssa;
- }
-}
-
-nir_ssa_def *
-nir_visitor::evaluate_rvalue(ir_rvalue* ir)
-{
- ir->accept(this);
- if (ir->as_dereference() || ir->as_constant()) {
- /*
- * A dereference is being used on the right hand side, which means we
- * must emit a variable load.
- */
-
- nir_intrinsic_instr *load_instr =
- nir_intrinsic_instr_create(this->shader, nir_intrinsic_load_var);
- load_instr->num_components = ir->type->vector_elements;
- load_instr->variables[0] = this->deref_head;
- ralloc_steal(load_instr, load_instr->variables[0]);
- add_instr(&load_instr->instr, ir->type->vector_elements);
- }
-
- return this->result;
-}
-
-void
-nir_visitor::visit(ir_expression *ir)
-{
- /* Some special cases */
- switch (ir->operation) {
- case ir_binop_ubo_load: {
- nir_intrinsic_instr *load =
- nir_intrinsic_instr_create(this->shader, nir_intrinsic_load_ubo);
- load->num_components = ir->type->vector_elements;
- load->src[0] = nir_src_for_ssa(evaluate_rvalue(ir->operands[0]));
- load->src[1] = nir_src_for_ssa(evaluate_rvalue(ir->operands[1]));
- add_instr(&load->instr, ir->type->vector_elements);
-
- /*
- * In UBO's, a true boolean value is any non-zero value, but we consider
- * a true boolean to be ~0. Fix this up with a != 0 comparison.
- */
-
- if (ir->type->base_type == GLSL_TYPE_BOOL)
- this->result = nir_ine(&b, &load->dest.ssa, nir_imm_int(&b, 0));
-
- return;
- }
-
- case ir_unop_interpolate_at_centroid:
- case ir_binop_interpolate_at_offset:
- case ir_binop_interpolate_at_sample: {
- ir_dereference *deref = ir->operands[0]->as_dereference();
- ir_swizzle *swizzle = NULL;
- if (!deref) {
- /* the api does not allow a swizzle here, but the varying packing code
- * may have pushed one into here.
- */
- swizzle = ir->operands[0]->as_swizzle();
- assert(swizzle);
- deref = swizzle->val->as_dereference();
- assert(deref);
- }
-
- deref->accept(this);
-
- nir_intrinsic_op op;
- if (this->deref_head->var->data.mode == nir_var_shader_in) {
- switch (ir->operation) {
- case ir_unop_interpolate_at_centroid:
- op = nir_intrinsic_interp_var_at_centroid;
- break;
- case ir_binop_interpolate_at_offset:
- op = nir_intrinsic_interp_var_at_offset;
- break;
- case ir_binop_interpolate_at_sample:
- op = nir_intrinsic_interp_var_at_sample;
- break;
- default:
- unreachable("Invalid interpolation intrinsic");
- }
- } else {
- /* This case can happen if the vertex shader does not write the
- * given varying. In this case, the linker will lower it to a
- * global variable. Since interpolating a variable makes no
- * sense, we'll just turn it into a load which will probably
- * eventually end up as an SSA definition.
- */
- assert(this->deref_head->var->data.mode == nir_var_global);
- op = nir_intrinsic_load_var;
- }
-
- nir_intrinsic_instr *intrin = nir_intrinsic_instr_create(shader, op);
- intrin->num_components = deref->type->vector_elements;
- intrin->variables[0] = this->deref_head;
- ralloc_steal(intrin, intrin->variables[0]);
-
- if (intrin->intrinsic == nir_intrinsic_interp_var_at_offset ||
- intrin->intrinsic == nir_intrinsic_interp_var_at_sample)
- intrin->src[0] = nir_src_for_ssa(evaluate_rvalue(ir->operands[1]));
-
- add_instr(&intrin->instr, deref->type->vector_elements);
-
- if (swizzle) {
- unsigned swiz[4] = {
- swizzle->mask.x, swizzle->mask.y, swizzle->mask.z, swizzle->mask.w
- };
-
- result = nir_swizzle(&b, result, swiz,
- swizzle->type->vector_elements, false);
- }
-
- return;
- }
-
- default:
- break;
- }
-
- nir_ssa_def *srcs[4];
- for (unsigned i = 0; i < ir->get_num_operands(); i++)
- srcs[i] = evaluate_rvalue(ir->operands[i]);
-
- glsl_base_type types[4];
- for (unsigned i = 0; i < ir->get_num_operands(); i++)
- if (supports_ints)
- types[i] = ir->operands[i]->type->base_type;
- else
- types[i] = GLSL_TYPE_FLOAT;
-
- glsl_base_type out_type;
- if (supports_ints)
- out_type = ir->type->base_type;
- else
- out_type = GLSL_TYPE_FLOAT;
-
- switch (ir->operation) {
- case ir_unop_bit_not: result = nir_inot(&b, srcs[0]); break;
- case ir_unop_logic_not:
- result = supports_ints ? nir_inot(&b, srcs[0]) : nir_fnot(&b, srcs[0]);
- break;
- case ir_unop_neg:
- result = (types[0] == GLSL_TYPE_FLOAT) ? nir_fneg(&b, srcs[0])
- : nir_ineg(&b, srcs[0]);
- break;
- case ir_unop_abs:
- result = (types[0] == GLSL_TYPE_FLOAT) ? nir_fabs(&b, srcs[0])
- : nir_iabs(&b, srcs[0]);
- break;
- case ir_unop_saturate:
- assert(types[0] == GLSL_TYPE_FLOAT);
- result = nir_fsat(&b, srcs[0]);
- break;
- case ir_unop_sign:
- result = (types[0] == GLSL_TYPE_FLOAT) ? nir_fsign(&b, srcs[0])
- : nir_isign(&b, srcs[0]);
- break;
- case ir_unop_rcp: result = nir_frcp(&b, srcs[0]); break;
- case ir_unop_rsq: result = nir_frsq(&b, srcs[0]); break;
- case ir_unop_sqrt: result = nir_fsqrt(&b, srcs[0]); break;
- case ir_unop_exp: unreachable("ir_unop_exp should have been lowered");
- case ir_unop_log: unreachable("ir_unop_log should have been lowered");
- case ir_unop_exp2: result = nir_fexp2(&b, srcs[0]); break;
- case ir_unop_log2: result = nir_flog2(&b, srcs[0]); break;
- case ir_unop_i2f:
- result = supports_ints ? nir_i2f(&b, srcs[0]) : nir_fmov(&b, srcs[0]);
- break;
- case ir_unop_u2f:
- result = supports_ints ? nir_u2f(&b, srcs[0]) : nir_fmov(&b, srcs[0]);
- break;
- case ir_unop_b2f:
- result = supports_ints ? nir_b2f(&b, srcs[0]) : nir_fmov(&b, srcs[0]);
- break;
- case ir_unop_f2i: result = nir_f2i(&b, srcs[0]); break;
- case ir_unop_f2u: result = nir_f2u(&b, srcs[0]); break;
- case ir_unop_f2b: result = nir_f2b(&b, srcs[0]); break;
- case ir_unop_i2b: result = nir_i2b(&b, srcs[0]); break;
- case ir_unop_b2i: result = nir_b2i(&b, srcs[0]); break;
- case ir_unop_i2u:
- case ir_unop_u2i:
- case ir_unop_bitcast_i2f:
- case ir_unop_bitcast_f2i:
- case ir_unop_bitcast_u2f:
- case ir_unop_bitcast_f2u:
- case ir_unop_subroutine_to_int:
- /* no-op */
- result = nir_imov(&b, srcs[0]);
- break;
- case ir_unop_trunc: result = nir_ftrunc(&b, srcs[0]); break;
- case ir_unop_ceil: result = nir_fceil(&b, srcs[0]); break;
- case ir_unop_floor: result = nir_ffloor(&b, srcs[0]); break;
- case ir_unop_fract: result = nir_ffract(&b, srcs[0]); break;
- case ir_unop_round_even: result = nir_fround_even(&b, srcs[0]); break;
- case ir_unop_sin: result = nir_fsin(&b, srcs[0]); break;
- case ir_unop_cos: result = nir_fcos(&b, srcs[0]); break;
- case ir_unop_dFdx: result = nir_fddx(&b, srcs[0]); break;
- case ir_unop_dFdy: result = nir_fddy(&b, srcs[0]); break;
- case ir_unop_dFdx_fine: result = nir_fddx_fine(&b, srcs[0]); break;
- case ir_unop_dFdy_fine: result = nir_fddy_fine(&b, srcs[0]); break;
- case ir_unop_dFdx_coarse: result = nir_fddx_coarse(&b, srcs[0]); break;
- case ir_unop_dFdy_coarse: result = nir_fddy_coarse(&b, srcs[0]); break;
- case ir_unop_pack_snorm_2x16:
- result = nir_pack_snorm_2x16(&b, srcs[0]);
- break;
- case ir_unop_pack_snorm_4x8:
- result = nir_pack_snorm_4x8(&b, srcs[0]);
- break;
- case ir_unop_pack_unorm_2x16:
- result = nir_pack_unorm_2x16(&b, srcs[0]);
- break;
- case ir_unop_pack_unorm_4x8:
- result = nir_pack_unorm_4x8(&b, srcs[0]);
- break;
- case ir_unop_pack_half_2x16:
- result = nir_pack_half_2x16(&b, srcs[0]);
- break;
- case ir_unop_unpack_snorm_2x16:
- result = nir_unpack_snorm_2x16(&b, srcs[0]);
- break;
- case ir_unop_unpack_snorm_4x8:
- result = nir_unpack_snorm_4x8(&b, srcs[0]);
- break;
- case ir_unop_unpack_unorm_2x16:
- result = nir_unpack_unorm_2x16(&b, srcs[0]);
- break;
- case ir_unop_unpack_unorm_4x8:
- result = nir_unpack_unorm_4x8(&b, srcs[0]);
- break;
- case ir_unop_unpack_half_2x16:
- result = nir_unpack_half_2x16(&b, srcs[0]);
- break;
- case ir_unop_bitfield_reverse:
- result = nir_bitfield_reverse(&b, srcs[0]);
- break;
- case ir_unop_bit_count:
- result = nir_bit_count(&b, srcs[0]);
- break;
- case ir_unop_find_msb:
- switch (types[0]) {
- case GLSL_TYPE_UINT:
- result = nir_ufind_msb(&b, srcs[0]);
- break;
- case GLSL_TYPE_INT:
- result = nir_ifind_msb(&b, srcs[0]);
- break;
- default:
- unreachable("Invalid type for findMSB()");
- }
- break;
- case ir_unop_find_lsb:
- result = nir_find_lsb(&b, srcs[0]);
- break;
-
- case ir_unop_noise:
- switch (ir->type->vector_elements) {
- case 1:
- switch (ir->operands[0]->type->vector_elements) {
- case 1: result = nir_fnoise1_1(&b, srcs[0]); break;
- case 2: result = nir_fnoise1_2(&b, srcs[0]); break;
- case 3: result = nir_fnoise1_3(&b, srcs[0]); break;
- case 4: result = nir_fnoise1_4(&b, srcs[0]); break;
- default: unreachable("not reached");
- }
- break;
- case 2:
- switch (ir->operands[0]->type->vector_elements) {
- case 1: result = nir_fnoise2_1(&b, srcs[0]); break;
- case 2: result = nir_fnoise2_2(&b, srcs[0]); break;
- case 3: result = nir_fnoise2_3(&b, srcs[0]); break;
- case 4: result = nir_fnoise2_4(&b, srcs[0]); break;
- default: unreachable("not reached");
- }
- break;
- case 3:
- switch (ir->operands[0]->type->vector_elements) {
- case 1: result = nir_fnoise3_1(&b, srcs[0]); break;
- case 2: result = nir_fnoise3_2(&b, srcs[0]); break;
- case 3: result = nir_fnoise3_3(&b, srcs[0]); break;
- case 4: result = nir_fnoise3_4(&b, srcs[0]); break;
- default: unreachable("not reached");
- }
- break;
- case 4:
- switch (ir->operands[0]->type->vector_elements) {
- case 1: result = nir_fnoise4_1(&b, srcs[0]); break;
- case 2: result = nir_fnoise4_2(&b, srcs[0]); break;
- case 3: result = nir_fnoise4_3(&b, srcs[0]); break;
- case 4: result = nir_fnoise4_4(&b, srcs[0]); break;
- default: unreachable("not reached");
- }
- break;
- default:
- unreachable("not reached");
- }
- break;
- case ir_unop_get_buffer_size: {
- nir_intrinsic_instr *load = nir_intrinsic_instr_create(
- this->shader,
- nir_intrinsic_get_buffer_size);
- load->num_components = ir->type->vector_elements;
- load->src[0] = nir_src_for_ssa(evaluate_rvalue(ir->operands[0]));
- add_instr(&load->instr, ir->type->vector_elements);
- return;
- }
-
- case ir_binop_add:
- result = (out_type == GLSL_TYPE_FLOAT) ? nir_fadd(&b, srcs[0], srcs[1])
- : nir_iadd(&b, srcs[0], srcs[1]);
- break;
- case ir_binop_sub:
- result = (out_type == GLSL_TYPE_FLOAT) ? nir_fsub(&b, srcs[0], srcs[1])
- : nir_isub(&b, srcs[0], srcs[1]);
- break;
- case ir_binop_mul:
- result = (out_type == GLSL_TYPE_FLOAT) ? nir_fmul(&b, srcs[0], srcs[1])
- : nir_imul(&b, srcs[0], srcs[1]);
- break;
- case ir_binop_div:
- if (out_type == GLSL_TYPE_FLOAT)
- result = nir_fdiv(&b, srcs[0], srcs[1]);
- else if (out_type == GLSL_TYPE_INT)
- result = nir_idiv(&b, srcs[0], srcs[1]);
- else
- result = nir_udiv(&b, srcs[0], srcs[1]);
- break;
- case ir_binop_mod:
- result = (out_type == GLSL_TYPE_FLOAT) ? nir_fmod(&b, srcs[0], srcs[1])
- : nir_umod(&b, srcs[0], srcs[1]);
- break;
- case ir_binop_min:
- if (out_type == GLSL_TYPE_FLOAT)
- result = nir_fmin(&b, srcs[0], srcs[1]);
- else if (out_type == GLSL_TYPE_INT)
- result = nir_imin(&b, srcs[0], srcs[1]);
- else
- result = nir_umin(&b, srcs[0], srcs[1]);
- break;
- case ir_binop_max:
- if (out_type == GLSL_TYPE_FLOAT)
- result = nir_fmax(&b, srcs[0], srcs[1]);
- else if (out_type == GLSL_TYPE_INT)
- result = nir_imax(&b, srcs[0], srcs[1]);
- else
- result = nir_umax(&b, srcs[0], srcs[1]);
- break;
- case ir_binop_pow: result = nir_fpow(&b, srcs[0], srcs[1]); break;
- case ir_binop_bit_and: result = nir_iand(&b, srcs[0], srcs[1]); break;
- case ir_binop_bit_or: result = nir_ior(&b, srcs[0], srcs[1]); break;
- case ir_binop_bit_xor: result = nir_ixor(&b, srcs[0], srcs[1]); break;
- case ir_binop_logic_and:
- result = supports_ints ? nir_iand(&b, srcs[0], srcs[1])
- : nir_fand(&b, srcs[0], srcs[1]);
- break;
- case ir_binop_logic_or:
- result = supports_ints ? nir_ior(&b, srcs[0], srcs[1])
- : nir_for(&b, srcs[0], srcs[1]);
- break;
- case ir_binop_logic_xor:
- result = supports_ints ? nir_ixor(&b, srcs[0], srcs[1])
- : nir_fxor(&b, srcs[0], srcs[1]);
- break;
- case ir_binop_lshift: result = nir_ishl(&b, srcs[0], srcs[1]); break;
- case ir_binop_rshift:
- result = (out_type == GLSL_TYPE_INT) ? nir_ishr(&b, srcs[0], srcs[1])
- : nir_ushr(&b, srcs[0], srcs[1]);
- break;
- case ir_binop_imul_high:
- result = (out_type == GLSL_TYPE_INT) ? nir_imul_high(&b, srcs[0], srcs[1])
- : nir_umul_high(&b, srcs[0], srcs[1]);
- break;
- case ir_binop_carry: result = nir_uadd_carry(&b, srcs[0], srcs[1]); break;
- case ir_binop_borrow: result = nir_usub_borrow(&b, srcs[0], srcs[1]); break;
- case ir_binop_less:
- if (supports_ints) {
- if (types[0] == GLSL_TYPE_FLOAT)
- result = nir_flt(&b, srcs[0], srcs[1]);
- else if (types[0] == GLSL_TYPE_INT)
- result = nir_ilt(&b, srcs[0], srcs[1]);
- else
- result = nir_ult(&b, srcs[0], srcs[1]);
- } else {
- result = nir_slt(&b, srcs[0], srcs[1]);
- }
- break;
- case ir_binop_greater:
- if (supports_ints) {
- if (types[0] == GLSL_TYPE_FLOAT)
- result = nir_flt(&b, srcs[1], srcs[0]);
- else if (types[0] == GLSL_TYPE_INT)
- result = nir_ilt(&b, srcs[1], srcs[0]);
- else
- result = nir_ult(&b, srcs[1], srcs[0]);
- } else {
- result = nir_slt(&b, srcs[1], srcs[0]);
- }
- break;
- case ir_binop_lequal:
- if (supports_ints) {
- if (types[0] == GLSL_TYPE_FLOAT)
- result = nir_fge(&b, srcs[1], srcs[0]);
- else if (types[0] == GLSL_TYPE_INT)
- result = nir_ige(&b, srcs[1], srcs[0]);
- else
- result = nir_uge(&b, srcs[1], srcs[0]);
- } else {
- result = nir_slt(&b, srcs[1], srcs[0]);
- }
- break;
- case ir_binop_gequal:
- if (supports_ints) {
- if (types[0] == GLSL_TYPE_FLOAT)
- result = nir_fge(&b, srcs[0], srcs[1]);
- else if (types[0] == GLSL_TYPE_INT)
- result = nir_ige(&b, srcs[0], srcs[1]);
- else
- result = nir_uge(&b, srcs[0], srcs[1]);
- } else {
- result = nir_slt(&b, srcs[0], srcs[1]);
- }
- break;
- case ir_binop_equal:
- if (supports_ints) {
- if (types[0] == GLSL_TYPE_FLOAT)
- result = nir_feq(&b, srcs[0], srcs[1]);
- else
- result = nir_ieq(&b, srcs[0], srcs[1]);
- } else {
- result = nir_seq(&b, srcs[0], srcs[1]);
- }
- break;
- case ir_binop_nequal:
- if (supports_ints) {
- if (types[0] == GLSL_TYPE_FLOAT)
- result = nir_fne(&b, srcs[0], srcs[1]);
- else
- result = nir_ine(&b, srcs[0], srcs[1]);
- } else {
- result = nir_sne(&b, srcs[0], srcs[1]);
- }
- break;
- case ir_binop_all_equal:
- if (supports_ints) {
- if (types[0] == GLSL_TYPE_FLOAT) {
- switch (ir->operands[0]->type->vector_elements) {
- case 1: result = nir_feq(&b, srcs[0], srcs[1]); break;
- case 2: result = nir_ball_fequal2(&b, srcs[0], srcs[1]); break;
- case 3: result = nir_ball_fequal3(&b, srcs[0], srcs[1]); break;
- case 4: result = nir_ball_fequal4(&b, srcs[0], srcs[1]); break;
- default:
- unreachable("not reached");
- }
- } else {
- switch (ir->operands[0]->type->vector_elements) {
- case 1: result = nir_ieq(&b, srcs[0], srcs[1]); break;
- case 2: result = nir_ball_iequal2(&b, srcs[0], srcs[1]); break;
- case 3: result = nir_ball_iequal3(&b, srcs[0], srcs[1]); break;
- case 4: result = nir_ball_iequal4(&b, srcs[0], srcs[1]); break;
- default:
- unreachable("not reached");
- }
- }
- } else {
- switch (ir->operands[0]->type->vector_elements) {
- case 1: result = nir_seq(&b, srcs[0], srcs[1]); break;
- case 2: result = nir_fall_equal2(&b, srcs[0], srcs[1]); break;
- case 3: result = nir_fall_equal3(&b, srcs[0], srcs[1]); break;
- case 4: result = nir_fall_equal4(&b, srcs[0], srcs[1]); break;
- default:
- unreachable("not reached");
- }
- }
- break;
- case ir_binop_any_nequal:
- if (supports_ints) {
- if (types[0] == GLSL_TYPE_FLOAT) {
- switch (ir->operands[0]->type->vector_elements) {
- case 1: result = nir_fne(&b, srcs[0], srcs[1]); break;
- case 2: result = nir_bany_fnequal2(&b, srcs[0], srcs[1]); break;
- case 3: result = nir_bany_fnequal3(&b, srcs[0], srcs[1]); break;
- case 4: result = nir_bany_fnequal4(&b, srcs[0], srcs[1]); break;
- default:
- unreachable("not reached");
- }
- } else {
- switch (ir->operands[0]->type->vector_elements) {
- case 1: result = nir_ine(&b, srcs[0], srcs[1]); break;
- case 2: result = nir_bany_inequal2(&b, srcs[0], srcs[1]); break;
- case 3: result = nir_bany_inequal3(&b, srcs[0], srcs[1]); break;
- case 4: result = nir_bany_inequal4(&b, srcs[0], srcs[1]); break;
- default:
- unreachable("not reached");
- }
- }
- } else {
- switch (ir->operands[0]->type->vector_elements) {
- case 1: result = nir_sne(&b, srcs[0], srcs[1]); break;
- case 2: result = nir_fany_nequal2(&b, srcs[0], srcs[1]); break;
- case 3: result = nir_fany_nequal3(&b, srcs[0], srcs[1]); break;
- case 4: result = nir_fany_nequal4(&b, srcs[0], srcs[1]); break;
- default:
- unreachable("not reached");
- }
- }
- break;
- case ir_binop_dot:
- switch (ir->operands[0]->type->vector_elements) {
- case 2: result = nir_fdot2(&b, srcs[0], srcs[1]); break;
- case 3: result = nir_fdot3(&b, srcs[0], srcs[1]); break;
- case 4: result = nir_fdot4(&b, srcs[0], srcs[1]); break;
- default:
- unreachable("not reached");
- }
- break;
-
- case ir_binop_ldexp: result = nir_ldexp(&b, srcs[0], srcs[1]); break;
- case ir_triop_fma:
- result = nir_ffma(&b, srcs[0], srcs[1], srcs[2]);
- break;
- case ir_triop_lrp:
- result = nir_flrp(&b, srcs[0], srcs[1], srcs[2]);
- break;
- case ir_triop_csel:
- if (supports_ints)
- result = nir_bcsel(&b, srcs[0], srcs[1], srcs[2]);
- else
- result = nir_fcsel(&b, srcs[0], srcs[1], srcs[2]);
- break;
- case ir_triop_bitfield_extract:
- result = (out_type == GLSL_TYPE_INT) ?
- nir_ibitfield_extract(&b, srcs[0], srcs[1], srcs[2]) :
- nir_ubitfield_extract(&b, srcs[0], srcs[1], srcs[2]);
- break;
- case ir_quadop_bitfield_insert:
- result = nir_bitfield_insert(&b, srcs[0], srcs[1], srcs[2], srcs[3]);
- break;
- case ir_quadop_vector:
- result = nir_vec(&b, srcs, ir->type->vector_elements);
- break;
-
- default:
- unreachable("not reached");
- }
-}
-
-void
-nir_visitor::visit(ir_swizzle *ir)
-{
- unsigned swizzle[4] = { ir->mask.x, ir->mask.y, ir->mask.z, ir->mask.w };
- result = nir_swizzle(&b, evaluate_rvalue(ir->val), swizzle,
- ir->type->vector_elements, !supports_ints);
-}
-
-void
-nir_visitor::visit(ir_texture *ir)
-{
- unsigned num_srcs;
- nir_texop op;
- switch (ir->op) {
- case ir_tex:
- op = nir_texop_tex;
- num_srcs = 1; /* coordinate */
- break;
-
- case ir_txb:
- case ir_txl:
- op = (ir->op == ir_txb) ? nir_texop_txb : nir_texop_txl;
- num_srcs = 2; /* coordinate, bias/lod */
- break;
-
- case ir_txd:
- op = nir_texop_txd; /* coordinate, dPdx, dPdy */
- num_srcs = 3;
- break;
-
- case ir_txf:
- op = nir_texop_txf;
- if (ir->lod_info.lod != NULL)
- num_srcs = 2; /* coordinate, lod */
- else
- num_srcs = 1; /* coordinate */
- break;
-
- case ir_txf_ms:
- op = nir_texop_txf_ms;
- num_srcs = 2; /* coordinate, sample_index */
- break;
-
- case ir_txs:
- op = nir_texop_txs;
- if (ir->lod_info.lod != NULL)
- num_srcs = 1; /* lod */
- else
- num_srcs = 0;
- break;
-
- case ir_lod:
- op = nir_texop_lod;
- num_srcs = 1; /* coordinate */
- break;
-
- case ir_tg4:
- op = nir_texop_tg4;
- num_srcs = 1; /* coordinate */
- break;
-
- case ir_query_levels:
- op = nir_texop_query_levels;
- num_srcs = 0;
- break;
-
- case ir_texture_samples:
- op = nir_texop_texture_samples;
- num_srcs = 0;
- break;
-
- case ir_samples_identical:
- op = nir_texop_samples_identical;
- num_srcs = 1; /* coordinate */
- break;
-
- default:
- unreachable("not reached");
- }
-
- if (ir->projector != NULL)
- num_srcs++;
- if (ir->shadow_comparitor != NULL)
- num_srcs++;
- if (ir->offset != NULL && ir->offset->as_constant() == NULL)
- num_srcs++;
-
- nir_tex_instr *instr = nir_tex_instr_create(this->shader, num_srcs);
-
- instr->op = op;
- instr->sampler_dim =
- (glsl_sampler_dim) ir->sampler->type->sampler_dimensionality;
- instr->is_array = ir->sampler->type->sampler_array;
- instr->is_shadow = ir->sampler->type->sampler_shadow;
- if (instr->is_shadow)
- instr->is_new_style_shadow = (ir->type->vector_elements == 1);
- switch (ir->type->base_type) {
- case GLSL_TYPE_FLOAT:
- instr->dest_type = nir_type_float;
- break;
- case GLSL_TYPE_INT:
- instr->dest_type = nir_type_int;
- break;
- case GLSL_TYPE_BOOL:
- case GLSL_TYPE_UINT:
- instr->dest_type = nir_type_uint;
- break;
- default:
- unreachable("not reached");
- }
-
- instr->sampler = evaluate_deref(&instr->instr, ir->sampler);
-
- unsigned src_number = 0;
-
- if (ir->coordinate != NULL) {
- instr->coord_components = ir->coordinate->type->vector_elements;
- instr->src[src_number].src =
- nir_src_for_ssa(evaluate_rvalue(ir->coordinate));
- instr->src[src_number].src_type = nir_tex_src_coord;
- src_number++;
- }
-
- if (ir->projector != NULL) {
- instr->src[src_number].src =
- nir_src_for_ssa(evaluate_rvalue(ir->projector));
- instr->src[src_number].src_type = nir_tex_src_projector;
- src_number++;
- }
-
- if (ir->shadow_comparitor != NULL) {
- instr->src[src_number].src =
- nir_src_for_ssa(evaluate_rvalue(ir->shadow_comparitor));
- instr->src[src_number].src_type = nir_tex_src_comparitor;
- src_number++;
- }
-
- if (ir->offset != NULL) {
- /* we don't support multiple offsets yet */
- assert(ir->offset->type->is_vector() || ir->offset->type->is_scalar());
-
- ir_constant *const_offset = ir->offset->as_constant();
- if (const_offset != NULL) {
- for (unsigned i = 0; i < const_offset->type->vector_elements; i++)
- instr->const_offset[i] = const_offset->value.i[i];
- } else {
- instr->src[src_number].src =
- nir_src_for_ssa(evaluate_rvalue(ir->offset));
- instr->src[src_number].src_type = nir_tex_src_offset;
- src_number++;
- }
- }
-
- switch (ir->op) {
- case ir_txb:
- instr->src[src_number].src =
- nir_src_for_ssa(evaluate_rvalue(ir->lod_info.bias));
- instr->src[src_number].src_type = nir_tex_src_bias;
- src_number++;
- break;
-
- case ir_txl:
- case ir_txf:
- case ir_txs:
- if (ir->lod_info.lod != NULL) {
- instr->src[src_number].src =
- nir_src_for_ssa(evaluate_rvalue(ir->lod_info.lod));
- instr->src[src_number].src_type = nir_tex_src_lod;
- src_number++;
- }
- break;
-
- case ir_txd:
- instr->src[src_number].src =
- nir_src_for_ssa(evaluate_rvalue(ir->lod_info.grad.dPdx));
- instr->src[src_number].src_type = nir_tex_src_ddx;
- src_number++;
- instr->src[src_number].src =
- nir_src_for_ssa(evaluate_rvalue(ir->lod_info.grad.dPdy));
- instr->src[src_number].src_type = nir_tex_src_ddy;
- src_number++;
- break;
-
- case ir_txf_ms:
- instr->src[src_number].src =
- nir_src_for_ssa(evaluate_rvalue(ir->lod_info.sample_index));
- instr->src[src_number].src_type = nir_tex_src_ms_index;
- src_number++;
- break;
-
- case ir_tg4:
- instr->component = ir->lod_info.component->as_constant()->value.u[0];
- break;
-
- default:
- break;
- }
-
- assert(src_number == num_srcs);
-
- add_instr(&instr->instr, nir_tex_instr_dest_size(instr));
-}
-
-void
-nir_visitor::visit(ir_constant *ir)
-{
- /*
- * We don't know if this variable is an an array or struct that gets
- * dereferenced, so do the safe thing an make it a variable with a
- * constant initializer and return a dereference.
- */
-
- nir_variable *var =
- nir_local_variable_create(this->impl, ir->type, "const_temp");
- var->data.read_only = true;
- var->constant_initializer = constant_copy(ir, var);
-
- this->deref_head = nir_deref_var_create(this->shader, var);
- this->deref_tail = &this->deref_head->deref;
-}
-
-void
-nir_visitor::visit(ir_dereference_variable *ir)
-{
- struct hash_entry *entry =
- _mesa_hash_table_search(this->var_table, ir->var);
- assert(entry);
- nir_variable *var = (nir_variable *) entry->data;
-
- nir_deref_var *deref = nir_deref_var_create(this->shader, var);
- this->deref_head = deref;
- this->deref_tail = &deref->deref;
-}
-
-void
-nir_visitor::visit(ir_dereference_record *ir)
-{
- ir->record->accept(this);
-
- int field_index = this->deref_tail->type->field_index(ir->field);
- assert(field_index >= 0);
-
- nir_deref_struct *deref = nir_deref_struct_create(this->deref_tail, field_index);
- deref->deref.type = ir->type;
- this->deref_tail->child = &deref->deref;
- this->deref_tail = &deref->deref;
-}
-
-void
-nir_visitor::visit(ir_dereference_array *ir)
-{
- nir_deref_array *deref = nir_deref_array_create(this->shader);
- deref->deref.type = ir->type;
-
- ir_constant *const_index = ir->array_index->as_constant();
- if (const_index != NULL) {
- deref->deref_array_type = nir_deref_array_type_direct;
- deref->base_offset = const_index->value.u[0];
- } else {
- deref->deref_array_type = nir_deref_array_type_indirect;
- deref->indirect =
- nir_src_for_ssa(evaluate_rvalue(ir->array_index));
- }
-
- ir->array->accept(this);
-
- this->deref_tail->child = &deref->deref;
- ralloc_steal(this->deref_tail, deref);
- this->deref_tail = &deref->deref;
-}
-
-void
-nir_visitor::visit(ir_barrier *ir)
-{
- nir_intrinsic_instr *instr =
- nir_intrinsic_instr_create(this->shader, nir_intrinsic_barrier);
- nir_builder_instr_insert(&b, &instr->instr);
-}
diff --git a/src/glsl/nir/glsl_to_nir.h b/src/glsl/nir/glsl_to_nir.h
deleted file mode 100644
index 29badcda08d..00000000000
--- a/src/glsl/nir/glsl_to_nir.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright © 2014 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- *
- * Authors:
- * Connor Abbott ([email protected])
- *
- */
-
-#include "nir.h"
-#include "../glsl_parser_extras.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-nir_shader *glsl_to_nir(const struct gl_shader_program *shader_prog,
- gl_shader_stage stage,
- const nir_shader_compiler_options *options);
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/src/glsl/nir/glsl_types.cpp b/src/glsl/nir/glsl_types.cpp
deleted file mode 100644
index 71095fa92e4..00000000000
--- a/src/glsl/nir/glsl_types.cpp
+++ /dev/null
@@ -1,1950 +0,0 @@
-/*
- * Copyright © 2009 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-#include <stdio.h>
-#include "main/macros.h"
-#include "glsl_parser_extras.h"
-#include "glsl_types.h"
-#include "util/hash_table.h"
-
-
-mtx_t glsl_type::mutex = _MTX_INITIALIZER_NP;
-hash_table *glsl_type::array_types = NULL;
-hash_table *glsl_type::record_types = NULL;
-hash_table *glsl_type::interface_types = NULL;
-hash_table *glsl_type::function_types = NULL;
-hash_table *glsl_type::subroutine_types = NULL;
-void *glsl_type::mem_ctx = NULL;
-
-void
-glsl_type::init_ralloc_type_ctx(void)
-{
- if (glsl_type::mem_ctx == NULL) {
- glsl_type::mem_ctx = ralloc_autofree_context();
- assert(glsl_type::mem_ctx != NULL);
- }
-}
-
-glsl_type::glsl_type(GLenum gl_type,
- glsl_base_type base_type, unsigned vector_elements,
- unsigned matrix_columns, const char *name) :
- gl_type(gl_type),
- base_type(base_type),
- sampler_dimensionality(0), sampler_shadow(0), sampler_array(0),
- sampler_type(0), interface_packing(0),
- vector_elements(vector_elements), matrix_columns(matrix_columns),
- length(0)
-{
- mtx_lock(&glsl_type::mutex);
-
- init_ralloc_type_ctx();
- assert(name != NULL);
- this->name = ralloc_strdup(this->mem_ctx, name);
-
- mtx_unlock(&glsl_type::mutex);
-
- /* Neither dimension is zero or both dimensions are zero.
- */
- assert((vector_elements == 0) == (matrix_columns == 0));
- memset(& fields, 0, sizeof(fields));
-}
-
-glsl_type::glsl_type(GLenum gl_type, glsl_base_type base_type,
- enum glsl_sampler_dim dim, bool shadow, bool array,
- unsigned type, const char *name) :
- gl_type(gl_type),
- base_type(base_type),
- sampler_dimensionality(dim), sampler_shadow(shadow),
- sampler_array(array), sampler_type(type), interface_packing(0),
- length(0)
-{
- mtx_lock(&glsl_type::mutex);
-
- init_ralloc_type_ctx();
- assert(name != NULL);
- this->name = ralloc_strdup(this->mem_ctx, name);
-
- mtx_unlock(&glsl_type::mutex);
-
- memset(& fields, 0, sizeof(fields));
-
- if (base_type == GLSL_TYPE_SAMPLER) {
- /* Samplers take no storage whatsoever. */
- matrix_columns = vector_elements = 0;
- } else {
- matrix_columns = vector_elements = 1;
- }
-}
-
-glsl_type::glsl_type(const glsl_struct_field *fields, unsigned num_fields,
- const char *name) :
- gl_type(0),
- base_type(GLSL_TYPE_STRUCT),
- sampler_dimensionality(0), sampler_shadow(0), sampler_array(0),
- sampler_type(0), interface_packing(0),
- vector_elements(0), matrix_columns(0),
- length(num_fields)
-{
- unsigned int i;
-
- mtx_lock(&glsl_type::mutex);
-
- init_ralloc_type_ctx();
- assert(name != NULL);
- this->name = ralloc_strdup(this->mem_ctx, name);
- this->fields.structure = ralloc_array(this->mem_ctx,
- glsl_struct_field, length);
-
- for (i = 0; i < length; i++) {
- this->fields.structure[i].type = fields[i].type;
- this->fields.structure[i].name = ralloc_strdup(this->fields.structure,
- fields[i].name);
- this->fields.structure[i].location = fields[i].location;
- this->fields.structure[i].interpolation = fields[i].interpolation;
- this->fields.structure[i].centroid = fields[i].centroid;
- this->fields.structure[i].sample = fields[i].sample;
- this->fields.structure[i].matrix_layout = fields[i].matrix_layout;
- this->fields.structure[i].patch = fields[i].patch;
- this->fields.structure[i].image_read_only = fields[i].image_read_only;
- this->fields.structure[i].image_write_only = fields[i].image_write_only;
- this->fields.structure[i].image_coherent = fields[i].image_coherent;
- this->fields.structure[i].image_volatile = fields[i].image_volatile;
- this->fields.structure[i].image_restrict = fields[i].image_restrict;
- this->fields.structure[i].precision = fields[i].precision;
- }
-
- mtx_unlock(&glsl_type::mutex);
-}
-
-glsl_type::glsl_type(const glsl_struct_field *fields, unsigned num_fields,
- enum glsl_interface_packing packing, const char *name) :
- gl_type(0),
- base_type(GLSL_TYPE_INTERFACE),
- sampler_dimensionality(0), sampler_shadow(0), sampler_array(0),
- sampler_type(0), interface_packing((unsigned) packing),
- vector_elements(0), matrix_columns(0),
- length(num_fields)
-{
- unsigned int i;
-
- mtx_lock(&glsl_type::mutex);
-
- init_ralloc_type_ctx();
- assert(name != NULL);
- this->name = ralloc_strdup(this->mem_ctx, name);
- this->fields.structure = ralloc_array(this->mem_ctx,
- glsl_struct_field, length);
- for (i = 0; i < length; i++) {
- this->fields.structure[i].type = fields[i].type;
- this->fields.structure[i].name = ralloc_strdup(this->fields.structure,
- fields[i].name);
- this->fields.structure[i].location = fields[i].location;
- this->fields.structure[i].interpolation = fields[i].interpolation;
- this->fields.structure[i].centroid = fields[i].centroid;
- this->fields.structure[i].sample = fields[i].sample;
- this->fields.structure[i].matrix_layout = fields[i].matrix_layout;
- this->fields.structure[i].patch = fields[i].patch;
- this->fields.structure[i].precision = fields[i].precision;
- }
-
- mtx_unlock(&glsl_type::mutex);
-}
-
-glsl_type::glsl_type(const glsl_type *return_type,
- const glsl_function_param *params, unsigned num_params) :
- gl_type(0),
- base_type(GLSL_TYPE_FUNCTION),
- sampler_dimensionality(0), sampler_shadow(0), sampler_array(0),
- sampler_type(0), interface_packing(0),
- vector_elements(0), matrix_columns(0),
- length(num_params)
-{
- unsigned int i;
-
- mtx_lock(&glsl_type::mutex);
-
- init_ralloc_type_ctx();
-
- this->fields.parameters = rzalloc_array(this->mem_ctx,
- glsl_function_param, num_params + 1);
-
- /* We store the return type as the first parameter */
- this->fields.parameters[0].type = return_type;
- this->fields.parameters[0].in = false;
- this->fields.parameters[0].out = true;
-
- /* We store the i'th parameter in slot i+1 */
- for (i = 0; i < length; i++) {
- this->fields.parameters[i + 1].type = params[i].type;
- this->fields.parameters[i + 1].in = params[i].in;
- this->fields.parameters[i + 1].out = params[i].out;
- }
-
- mtx_unlock(&glsl_type::mutex);
-}
-
-glsl_type::glsl_type(const char *subroutine_name) :
- gl_type(0),
- base_type(GLSL_TYPE_SUBROUTINE),
- sampler_dimensionality(0), sampler_shadow(0), sampler_array(0),
- sampler_type(0), interface_packing(0),
- vector_elements(1), matrix_columns(1),
- length(0)
-{
- mtx_lock(&glsl_type::mutex);
-
- init_ralloc_type_ctx();
- assert(subroutine_name != NULL);
- this->name = ralloc_strdup(this->mem_ctx, subroutine_name);
- mtx_unlock(&glsl_type::mutex);
-}
-
-bool
-glsl_type::contains_sampler() const
-{
- if (this->is_array()) {
- return this->fields.array->contains_sampler();
- } else if (this->is_record()) {
- for (unsigned int i = 0; i < this->length; i++) {
- if (this->fields.structure[i].type->contains_sampler())
- return true;
- }
- return false;
- } else {
- return this->is_sampler();
- }
-}
-
-
-bool
-glsl_type::contains_integer() const
-{
- if (this->is_array()) {
- return this->fields.array->contains_integer();
- } else if (this->is_record()) {
- for (unsigned int i = 0; i < this->length; i++) {
- if (this->fields.structure[i].type->contains_integer())
- return true;
- }
- return false;
- } else {
- return this->is_integer();
- }
-}
-
-bool
-glsl_type::contains_double() const
-{
- if (this->is_array()) {
- return this->fields.array->contains_double();
- } else if (this->is_record()) {
- for (unsigned int i = 0; i < this->length; i++) {
- if (this->fields.structure[i].type->contains_double())
- return true;
- }
- return false;
- } else {
- return this->is_double();
- }
-}
-
-bool
-glsl_type::contains_opaque() const {
- switch (base_type) {
- case GLSL_TYPE_SAMPLER:
- case GLSL_TYPE_IMAGE:
- case GLSL_TYPE_ATOMIC_UINT:
- return true;
- case GLSL_TYPE_ARRAY:
- return fields.array->contains_opaque();
- case GLSL_TYPE_STRUCT:
- for (unsigned int i = 0; i < length; i++) {
- if (fields.structure[i].type->contains_opaque())
- return true;
- }
- return false;
- default:
- return false;
- }
-}
-
-bool
-glsl_type::contains_subroutine() const
-{
- if (this->is_array()) {
- return this->fields.array->contains_subroutine();
- } else if (this->is_record()) {
- for (unsigned int i = 0; i < this->length; i++) {
- if (this->fields.structure[i].type->contains_subroutine())
- return true;
- }
- return false;
- } else {
- return this->is_subroutine();
- }
-}
-
-gl_texture_index
-glsl_type::sampler_index() const
-{
- const glsl_type *const t = (this->is_array()) ? this->fields.array : this;
-
- assert(t->is_sampler());
-
- switch (t->sampler_dimensionality) {
- case GLSL_SAMPLER_DIM_1D:
- return (t->sampler_array) ? TEXTURE_1D_ARRAY_INDEX : TEXTURE_1D_INDEX;
- case GLSL_SAMPLER_DIM_2D:
- return (t->sampler_array) ? TEXTURE_2D_ARRAY_INDEX : TEXTURE_2D_INDEX;
- case GLSL_SAMPLER_DIM_3D:
- return TEXTURE_3D_INDEX;
- case GLSL_SAMPLER_DIM_CUBE:
- return (t->sampler_array) ? TEXTURE_CUBE_ARRAY_INDEX : TEXTURE_CUBE_INDEX;
- case GLSL_SAMPLER_DIM_RECT:
- return TEXTURE_RECT_INDEX;
- case GLSL_SAMPLER_DIM_BUF:
- return TEXTURE_BUFFER_INDEX;
- case GLSL_SAMPLER_DIM_EXTERNAL:
- return TEXTURE_EXTERNAL_INDEX;
- case GLSL_SAMPLER_DIM_MS:
- return (t->sampler_array) ? TEXTURE_2D_MULTISAMPLE_ARRAY_INDEX : TEXTURE_2D_MULTISAMPLE_INDEX;
- default:
- assert(!"Should not get here.");
- return TEXTURE_BUFFER_INDEX;
- }
-}
-
-bool
-glsl_type::contains_image() const
-{
- if (this->is_array()) {
- return this->fields.array->contains_image();
- } else if (this->is_record()) {
- for (unsigned int i = 0; i < this->length; i++) {
- if (this->fields.structure[i].type->contains_image())
- return true;
- }
- return false;
- } else {
- return this->is_image();
- }
-}
-
-const glsl_type *glsl_type::get_base_type() const
-{
- switch (base_type) {
- case GLSL_TYPE_UINT:
- return uint_type;
- case GLSL_TYPE_INT:
- return int_type;
- case GLSL_TYPE_FLOAT:
- return float_type;
- case GLSL_TYPE_DOUBLE:
- return double_type;
- case GLSL_TYPE_BOOL:
- return bool_type;
- default:
- return error_type;
- }
-}
-
-
-const glsl_type *glsl_type::get_scalar_type() const
-{
- const glsl_type *type = this;
-
- /* Handle arrays */
- while (type->base_type == GLSL_TYPE_ARRAY)
- type = type->fields.array;
-
- /* Handle vectors and matrices */
- switch (type->base_type) {
- case GLSL_TYPE_UINT:
- return uint_type;
- case GLSL_TYPE_INT:
- return int_type;
- case GLSL_TYPE_FLOAT:
- return float_type;
- case GLSL_TYPE_DOUBLE:
- return double_type;
- case GLSL_TYPE_BOOL:
- return bool_type;
- default:
- /* Handle everything else */
- return type;
- }
-}
-
-
-void
-_mesa_glsl_release_types(void)
-{
- /* Should only be called during atexit (either when unloading shared
- * object, or if process terminates), so no mutex-locking should be
- * necessary.
- */
- if (glsl_type::array_types != NULL) {
- _mesa_hash_table_destroy(glsl_type::array_types, NULL);
- glsl_type::array_types = NULL;
- }
-
- if (glsl_type::record_types != NULL) {
- _mesa_hash_table_destroy(glsl_type::record_types, NULL);
- glsl_type::record_types = NULL;
- }
-
- if (glsl_type::interface_types != NULL) {
- _mesa_hash_table_destroy(glsl_type::interface_types, NULL);
- glsl_type::interface_types = NULL;
- }
-}
-
-
-glsl_type::glsl_type(const glsl_type *array, unsigned length) :
- base_type(GLSL_TYPE_ARRAY),
- sampler_dimensionality(0), sampler_shadow(0), sampler_array(0),
- sampler_type(0), interface_packing(0),
- vector_elements(0), matrix_columns(0),
- length(length), name(NULL)
-{
- this->fields.array = array;
- /* Inherit the gl type of the base. The GL type is used for
- * uniform/statevar handling in Mesa and the arrayness of the type
- * is represented by the size rather than the type.
- */
- this->gl_type = array->gl_type;
-
- /* Allow a maximum of 10 characters for the array size. This is enough
- * for 32-bits of ~0. The extra 3 are for the '[', ']', and terminating
- * NUL.
- */
- const unsigned name_length = strlen(array->name) + 10 + 3;
-
- mtx_lock(&glsl_type::mutex);
- char *const n = (char *) ralloc_size(this->mem_ctx, name_length);
- mtx_unlock(&glsl_type::mutex);
-
- if (length == 0)
- snprintf(n, name_length, "%s[]", array->name);
- else {
- /* insert outermost dimensions in the correct spot
- * otherwise the dimension order will be backwards
- */
- const char *pos = strchr(array->name, '[');
- if (pos) {
- int idx = pos - array->name;
- snprintf(n, idx+1, "%s", array->name);
- snprintf(n + idx, name_length - idx, "[%u]%s",
- length, array->name + idx);
- } else {
- snprintf(n, name_length, "%s[%u]", array->name, length);
- }
- }
-
- this->name = n;
-}
-
-
-const glsl_type *
-glsl_type::vec(unsigned components)
-{
- if (components == 0 || components > 4)
- return error_type;
-
- static const glsl_type *const ts[] = {
- float_type, vec2_type, vec3_type, vec4_type
- };
- return ts[components - 1];
-}
-
-const glsl_type *
-glsl_type::dvec(unsigned components)
-{
- if (components == 0 || components > 4)
- return error_type;
-
- static const glsl_type *const ts[] = {
- double_type, dvec2_type, dvec3_type, dvec4_type
- };
- return ts[components - 1];
-}
-
-const glsl_type *
-glsl_type::ivec(unsigned components)
-{
- if (components == 0 || components > 4)
- return error_type;
-
- static const glsl_type *const ts[] = {
- int_type, ivec2_type, ivec3_type, ivec4_type
- };
- return ts[components - 1];
-}
-
-
-const glsl_type *
-glsl_type::uvec(unsigned components)
-{
- if (components == 0 || components > 4)
- return error_type;
-
- static const glsl_type *const ts[] = {
- uint_type, uvec2_type, uvec3_type, uvec4_type
- };
- return ts[components - 1];
-}
-
-
-const glsl_type *
-glsl_type::bvec(unsigned components)
-{
- if (components == 0 || components > 4)
- return error_type;
-
- static const glsl_type *const ts[] = {
- bool_type, bvec2_type, bvec3_type, bvec4_type
- };
- return ts[components - 1];
-}
-
-
-const glsl_type *
-glsl_type::get_instance(unsigned base_type, unsigned rows, unsigned columns)
-{
- if (base_type == GLSL_TYPE_VOID)
- return void_type;
-
- if ((rows < 1) || (rows > 4) || (columns < 1) || (columns > 4))
- return error_type;
-
- /* Treat GLSL vectors as Nx1 matrices.
- */
- if (columns == 1) {
- switch (base_type) {
- case GLSL_TYPE_UINT:
- return uvec(rows);
- case GLSL_TYPE_INT:
- return ivec(rows);
- case GLSL_TYPE_FLOAT:
- return vec(rows);
- case GLSL_TYPE_DOUBLE:
- return dvec(rows);
- case GLSL_TYPE_BOOL:
- return bvec(rows);
- default:
- return error_type;
- }
- } else {
- if ((base_type != GLSL_TYPE_FLOAT && base_type != GLSL_TYPE_DOUBLE) || (rows == 1))
- return error_type;
-
- /* GLSL matrix types are named mat{COLUMNS}x{ROWS}. Only the following
- * combinations are valid:
- *
- * 1 2 3 4
- * 1
- * 2 x x x
- * 3 x x x
- * 4 x x x
- */
-#define IDX(c,r) (((c-1)*3) + (r-1))
-
- if (base_type == GLSL_TYPE_DOUBLE) {
- switch (IDX(columns, rows)) {
- case IDX(2,2): return dmat2_type;
- case IDX(2,3): return dmat2x3_type;
- case IDX(2,4): return dmat2x4_type;
- case IDX(3,2): return dmat3x2_type;
- case IDX(3,3): return dmat3_type;
- case IDX(3,4): return dmat3x4_type;
- case IDX(4,2): return dmat4x2_type;
- case IDX(4,3): return dmat4x3_type;
- case IDX(4,4): return dmat4_type;
- default: return error_type;
- }
- } else {
- switch (IDX(columns, rows)) {
- case IDX(2,2): return mat2_type;
- case IDX(2,3): return mat2x3_type;
- case IDX(2,4): return mat2x4_type;
- case IDX(3,2): return mat3x2_type;
- case IDX(3,3): return mat3_type;
- case IDX(3,4): return mat3x4_type;
- case IDX(4,2): return mat4x2_type;
- case IDX(4,3): return mat4x3_type;
- case IDX(4,4): return mat4_type;
- default: return error_type;
- }
- }
- }
-
- assert(!"Should not get here.");
- return error_type;
-}
-
-const glsl_type *
-glsl_type::get_sampler_instance(enum glsl_sampler_dim dim,
- bool shadow,
- bool array,
- glsl_base_type type)
-{
- switch (type) {
- case GLSL_TYPE_FLOAT:
- switch (dim) {
- case GLSL_SAMPLER_DIM_1D:
- if (shadow)
- return (array ? sampler1DArrayShadow_type : sampler1DShadow_type);
- else
- return (array ? sampler1DArray_type : sampler1D_type);
- case GLSL_SAMPLER_DIM_2D:
- if (shadow)
- return (array ? sampler2DArrayShadow_type : sampler2DShadow_type);
- else
- return (array ? sampler2DArray_type : sampler2D_type);
- case GLSL_SAMPLER_DIM_3D:
- if (shadow || array)
- return error_type;
- else
- return sampler3D_type;
- case GLSL_SAMPLER_DIM_CUBE:
- if (shadow)
- return (array ? samplerCubeArrayShadow_type : samplerCubeShadow_type);
- else
- return (array ? samplerCubeArray_type : samplerCube_type);
- case GLSL_SAMPLER_DIM_RECT:
- if (array)
- return error_type;
- if (shadow)
- return sampler2DRectShadow_type;
- else
- return sampler2DRect_type;
- case GLSL_SAMPLER_DIM_BUF:
- if (shadow || array)
- return error_type;
- else
- return samplerBuffer_type;
- case GLSL_SAMPLER_DIM_MS:
- if (shadow)
- return error_type;
- return (array ? sampler2DMSArray_type : sampler2DMS_type);
- case GLSL_SAMPLER_DIM_EXTERNAL:
- if (shadow || array)
- return error_type;
- else
- return samplerExternalOES_type;
- }
- case GLSL_TYPE_INT:
- if (shadow)
- return error_type;
- switch (dim) {
- case GLSL_SAMPLER_DIM_1D:
- return (array ? isampler1DArray_type : isampler1D_type);
- case GLSL_SAMPLER_DIM_2D:
- return (array ? isampler2DArray_type : isampler2D_type);
- case GLSL_SAMPLER_DIM_3D:
- if (array)
- return error_type;
- return isampler3D_type;
- case GLSL_SAMPLER_DIM_CUBE:
- return (array ? isamplerCubeArray_type : isamplerCube_type);
- case GLSL_SAMPLER_DIM_RECT:
- if (array)
- return error_type;
- return isampler2DRect_type;
- case GLSL_SAMPLER_DIM_BUF:
- if (array)
- return error_type;
- return isamplerBuffer_type;
- case GLSL_SAMPLER_DIM_MS:
- return (array ? isampler2DMSArray_type : isampler2DMS_type);
- case GLSL_SAMPLER_DIM_EXTERNAL:
- return error_type;
- }
- case GLSL_TYPE_UINT:
- if (shadow)
- return error_type;
- switch (dim) {
- case GLSL_SAMPLER_DIM_1D:
- return (array ? usampler1DArray_type : usampler1D_type);
- case GLSL_SAMPLER_DIM_2D:
- return (array ? usampler2DArray_type : usampler2D_type);
- case GLSL_SAMPLER_DIM_3D:
- if (array)
- return error_type;
- return usampler3D_type;
- case GLSL_SAMPLER_DIM_CUBE:
- return (array ? usamplerCubeArray_type : usamplerCube_type);
- case GLSL_SAMPLER_DIM_RECT:
- if (array)
- return error_type;
- return usampler2DRect_type;
- case GLSL_SAMPLER_DIM_BUF:
- if (array)
- return error_type;
- return usamplerBuffer_type;
- case GLSL_SAMPLER_DIM_MS:
- return (array ? usampler2DMSArray_type : usampler2DMS_type);
- case GLSL_SAMPLER_DIM_EXTERNAL:
- return error_type;
- }
- default:
- return error_type;
- }
-
- unreachable("switch statement above should be complete");
-}
-
-const glsl_type *
-glsl_type::get_image_instance(enum glsl_sampler_dim dim,
- bool array, glsl_base_type type)
-{
- switch (type) {
- case GLSL_TYPE_FLOAT:
- switch (dim) {
- case GLSL_SAMPLER_DIM_1D:
- return (array ? image1DArray_type : image1D_type);
- case GLSL_SAMPLER_DIM_2D:
- return (array ? image2DArray_type : image2D_type);
- case GLSL_SAMPLER_DIM_3D:
- return image3D_type;
- case GLSL_SAMPLER_DIM_CUBE:
- return (array ? imageCubeArray_type : imageCube_type);
- case GLSL_SAMPLER_DIM_RECT:
- if (array)
- return error_type;
- else
- return image2DRect_type;
- case GLSL_SAMPLER_DIM_BUF:
- if (array)
- return error_type;
- else
- return imageBuffer_type;
- case GLSL_SAMPLER_DIM_MS:
- return (array ? image2DMSArray_type : image2DMS_type);
- case GLSL_SAMPLER_DIM_EXTERNAL:
- return error_type;
- }
- case GLSL_TYPE_INT:
- switch (dim) {
- case GLSL_SAMPLER_DIM_1D:
- return (array ? iimage1DArray_type : iimage1D_type);
- case GLSL_SAMPLER_DIM_2D:
- return (array ? iimage2DArray_type : iimage2D_type);
- case GLSL_SAMPLER_DIM_3D:
- if (array)
- return error_type;
- return iimage3D_type;
- case GLSL_SAMPLER_DIM_CUBE:
- return (array ? iimageCubeArray_type : iimageCube_type);
- case GLSL_SAMPLER_DIM_RECT:
- if (array)
- return error_type;
- return iimage2DRect_type;
- case GLSL_SAMPLER_DIM_BUF:
- if (array)
- return error_type;
- return iimageBuffer_type;
- case GLSL_SAMPLER_DIM_MS:
- return (array ? iimage2DMSArray_type : iimage2DMS_type);
- case GLSL_SAMPLER_DIM_EXTERNAL:
- return error_type;
- }
- case GLSL_TYPE_UINT:
- switch (dim) {
- case GLSL_SAMPLER_DIM_1D:
- return (array ? uimage1DArray_type : uimage1D_type);
- case GLSL_SAMPLER_DIM_2D:
- return (array ? uimage2DArray_type : uimage2D_type);
- case GLSL_SAMPLER_DIM_3D:
- if (array)
- return error_type;
- return uimage3D_type;
- case GLSL_SAMPLER_DIM_CUBE:
- return (array ? uimageCubeArray_type : uimageCube_type);
- case GLSL_SAMPLER_DIM_RECT:
- if (array)
- return error_type;
- return uimage2DRect_type;
- case GLSL_SAMPLER_DIM_BUF:
- if (array)
- return error_type;
- return uimageBuffer_type;
- case GLSL_SAMPLER_DIM_MS:
- return (array ? uimage2DMSArray_type : uimage2DMS_type);
- case GLSL_SAMPLER_DIM_EXTERNAL:
- return error_type;
- }
- default:
- return error_type;
- }
-
- unreachable("switch statement above should be complete");
-}
-
-const glsl_type *
-glsl_type::get_array_instance(const glsl_type *base, unsigned array_size)
-{
- /* Generate a name using the base type pointer in the key. This is
- * done because the name of the base type may not be unique across
- * shaders. For example, two shaders may have different record types
- * named 'foo'.
- */
- char key[128];
- snprintf(key, sizeof(key), "%p[%u]", (void *) base, array_size);
-
- mtx_lock(&glsl_type::mutex);
-
- if (array_types == NULL) {
- array_types = _mesa_hash_table_create(NULL, _mesa_key_hash_string,
- _mesa_key_string_equal);
- }
-
- const struct hash_entry *entry = _mesa_hash_table_search(array_types, key);
- if (entry == NULL) {
- mtx_unlock(&glsl_type::mutex);
- const glsl_type *t = new glsl_type(base, array_size);
- mtx_lock(&glsl_type::mutex);
-
- entry = _mesa_hash_table_insert(array_types,
- ralloc_strdup(mem_ctx, key),
- (void *) t);
- }
-
- assert(((glsl_type *) entry->data)->base_type == GLSL_TYPE_ARRAY);
- assert(((glsl_type *) entry->data)->length == array_size);
- assert(((glsl_type *) entry->data)->fields.array == base);
-
- mtx_unlock(&glsl_type::mutex);
-
- return (glsl_type *) entry->data;
-}
-
-
-bool
-glsl_type::record_compare(const glsl_type *b) const
-{
- if (this->length != b->length)
- return false;
-
- if (this->interface_packing != b->interface_packing)
- return false;
-
- /* From the GLSL 4.20 specification (Sec 4.2):
- *
- * "Structures must have the same name, sequence of type names, and
- * type definitions, and field names to be considered the same type."
- *
- * GLSL ES behaves the same (Ver 1.00 Sec 4.2.4, Ver 3.00 Sec 4.2.5).
- *
- * Note that we cannot force type name check when comparing unnamed
- * structure types, these have a unique name assigned during parsing.
- */
- if (!this->is_anonymous() && !b->is_anonymous())
- if (strcmp(this->name, b->name) != 0)
- return false;
-
- for (unsigned i = 0; i < this->length; i++) {
- if (this->fields.structure[i].type != b->fields.structure[i].type)
- return false;
- if (strcmp(this->fields.structure[i].name,
- b->fields.structure[i].name) != 0)
- return false;
- if (this->fields.structure[i].matrix_layout
- != b->fields.structure[i].matrix_layout)
- return false;
- if (this->fields.structure[i].location
- != b->fields.structure[i].location)
- return false;
- if (this->fields.structure[i].interpolation
- != b->fields.structure[i].interpolation)
- return false;
- if (this->fields.structure[i].centroid
- != b->fields.structure[i].centroid)
- return false;
- if (this->fields.structure[i].sample
- != b->fields.structure[i].sample)
- return false;
- if (this->fields.structure[i].patch
- != b->fields.structure[i].patch)
- return false;
- if (this->fields.structure[i].image_read_only
- != b->fields.structure[i].image_read_only)
- return false;
- if (this->fields.structure[i].image_write_only
- != b->fields.structure[i].image_write_only)
- return false;
- if (this->fields.structure[i].image_coherent
- != b->fields.structure[i].image_coherent)
- return false;
- if (this->fields.structure[i].image_volatile
- != b->fields.structure[i].image_volatile)
- return false;
- if (this->fields.structure[i].image_restrict
- != b->fields.structure[i].image_restrict)
- return false;
- if (this->fields.structure[i].precision
- != b->fields.structure[i].precision)
- return false;
- }
-
- return true;
-}
-
-
-bool
-glsl_type::record_key_compare(const void *a, const void *b)
-{
- const glsl_type *const key1 = (glsl_type *) a;
- const glsl_type *const key2 = (glsl_type *) b;
-
- return strcmp(key1->name, key2->name) == 0 && key1->record_compare(key2);
-}
-
-
-/**
- * Generate an integer hash value for a glsl_type structure type.
- */
-unsigned
-glsl_type::record_key_hash(const void *a)
-{
- const glsl_type *const key = (glsl_type *) a;
- uintptr_t hash = key->length;
- unsigned retval;
-
- for (unsigned i = 0; i < key->length; i++) {
- /* casting pointer to uintptr_t */
- hash = (hash * 13 ) + (uintptr_t) key->fields.structure[i].type;
- }
-
- if (sizeof(hash) == 8)
- retval = (hash & 0xffffffff) ^ ((uint64_t) hash >> 32);
- else
- retval = hash;
-
- return retval;
-}
-
-
-const glsl_type *
-glsl_type::get_record_instance(const glsl_struct_field *fields,
- unsigned num_fields,
- const char *name)
-{
- const glsl_type key(fields, num_fields, name);
-
- mtx_lock(&glsl_type::mutex);
-
- if (record_types == NULL) {
- record_types = _mesa_hash_table_create(NULL, record_key_hash,
- record_key_compare);
- }
-
- const struct hash_entry *entry = _mesa_hash_table_search(record_types,
- &key);
- if (entry == NULL) {
- mtx_unlock(&glsl_type::mutex);
- const glsl_type *t = new glsl_type(fields, num_fields, name);
- mtx_lock(&glsl_type::mutex);
-
- entry = _mesa_hash_table_insert(record_types, t, (void *) t);
- }
-
- assert(((glsl_type *) entry->data)->base_type == GLSL_TYPE_STRUCT);
- assert(((glsl_type *) entry->data)->length == num_fields);
- assert(strcmp(((glsl_type *) entry->data)->name, name) == 0);
-
- mtx_unlock(&glsl_type::mutex);
-
- return (glsl_type *) entry->data;
-}
-
-
-const glsl_type *
-glsl_type::get_interface_instance(const glsl_struct_field *fields,
- unsigned num_fields,
- enum glsl_interface_packing packing,
- const char *block_name)
-{
- const glsl_type key(fields, num_fields, packing, block_name);
-
- mtx_lock(&glsl_type::mutex);
-
- if (interface_types == NULL) {
- interface_types = _mesa_hash_table_create(NULL, record_key_hash,
- record_key_compare);
- }
-
- const struct hash_entry *entry = _mesa_hash_table_search(interface_types,
- &key);
- if (entry == NULL) {
- mtx_unlock(&glsl_type::mutex);
- const glsl_type *t = new glsl_type(fields, num_fields,
- packing, block_name);
- mtx_lock(&glsl_type::mutex);
-
- entry = _mesa_hash_table_insert(interface_types, t, (void *) t);
- }
-
- assert(((glsl_type *) entry->data)->base_type == GLSL_TYPE_INTERFACE);
- assert(((glsl_type *) entry->data)->length == num_fields);
- assert(strcmp(((glsl_type *) entry->data)->name, block_name) == 0);
-
- mtx_unlock(&glsl_type::mutex);
-
- return (glsl_type *) entry->data;
-}
-
-const glsl_type *
-glsl_type::get_subroutine_instance(const char *subroutine_name)
-{
- const glsl_type key(subroutine_name);
-
- mtx_lock(&glsl_type::mutex);
-
- if (subroutine_types == NULL) {
- subroutine_types = _mesa_hash_table_create(NULL, record_key_hash,
- record_key_compare);
- }
-
- const struct hash_entry *entry = _mesa_hash_table_search(subroutine_types,
- &key);
- if (entry == NULL) {
- mtx_unlock(&glsl_type::mutex);
- const glsl_type *t = new glsl_type(subroutine_name);
- mtx_lock(&glsl_type::mutex);
-
- entry = _mesa_hash_table_insert(subroutine_types, t, (void *) t);
- }
-
- assert(((glsl_type *) entry->data)->base_type == GLSL_TYPE_SUBROUTINE);
- assert(strcmp(((glsl_type *) entry->data)->name, subroutine_name) == 0);
-
- mtx_unlock(&glsl_type::mutex);
-
- return (glsl_type *) entry->data;
-}
-
-
-static bool
-function_key_compare(const void *a, const void *b)
-{
- const glsl_type *const key1 = (glsl_type *) a;
- const glsl_type *const key2 = (glsl_type *) b;
-
- if (key1->length != key2->length)
- return 1;
-
- return memcmp(key1->fields.parameters, key2->fields.parameters,
- (key1->length + 1) * sizeof(*key1->fields.parameters)) == 0;
-}
-
-
-static uint32_t
-function_key_hash(const void *a)
-{
- const glsl_type *const key = (glsl_type *) a;
- char hash_key[128];
- unsigned size = 0;
-
- size = snprintf(hash_key, sizeof(hash_key), "%08x", key->length);
-
- for (unsigned i = 0; i < key->length; i++) {
- if (size >= sizeof(hash_key))
- break;
-
- size += snprintf(& hash_key[size], sizeof(hash_key) - size,
- "%p", (void *) key->fields.structure[i].type);
- }
-
- return _mesa_hash_string(hash_key);
-}
-
-const glsl_type *
-glsl_type::get_function_instance(const glsl_type *return_type,
- const glsl_function_param *params,
- unsigned num_params)
-{
- const glsl_type key(return_type, params, num_params);
-
- mtx_lock(&glsl_type::mutex);
-
- if (function_types == NULL) {
- function_types = _mesa_hash_table_create(NULL, function_key_hash,
- function_key_compare);
- }
-
- struct hash_entry *entry = _mesa_hash_table_search(function_types, &key);
- if (entry == NULL) {
- mtx_unlock(&glsl_type::mutex);
- const glsl_type *t = new glsl_type(return_type, params, num_params);
- mtx_lock(&glsl_type::mutex);
-
- entry = _mesa_hash_table_insert(function_types, t, (void *) t);
- }
-
- const glsl_type *t = (const glsl_type *)entry->data;
-
- assert(t->base_type == GLSL_TYPE_FUNCTION);
- assert(t->length == num_params);
-
- mtx_unlock(&glsl_type::mutex);
-
- return t;
-}
-
-
-const glsl_type *
-glsl_type::get_mul_type(const glsl_type *type_a, const glsl_type *type_b)
-{
- if (type_a == type_b) {
- return type_a;
- } else if (type_a->is_matrix() && type_b->is_matrix()) {
- /* Matrix multiply. The columns of A must match the rows of B. Given
- * the other previously tested constraints, this means the vector type
- * of a row from A must be the same as the vector type of a column from
- * B.
- */
- if (type_a->row_type() == type_b->column_type()) {
- /* The resulting matrix has the number of columns of matrix B and
- * the number of rows of matrix A. We get the row count of A by
- * looking at the size of a vector that makes up a column. The
- * transpose (size of a row) is done for B.
- */
- const glsl_type *const type =
- get_instance(type_a->base_type,
- type_a->column_type()->vector_elements,
- type_b->row_type()->vector_elements);
- assert(type != error_type);
-
- return type;
- }
- } else if (type_a->is_matrix()) {
- /* A is a matrix and B is a column vector. Columns of A must match
- * rows of B. Given the other previously tested constraints, this
- * means the vector type of a row from A must be the same as the
- * vector the type of B.
- */
- if (type_a->row_type() == type_b) {
- /* The resulting vector has a number of elements equal to
- * the number of rows of matrix A. */
- const glsl_type *const type =
- get_instance(type_a->base_type,
- type_a->column_type()->vector_elements,
- 1);
- assert(type != error_type);
-
- return type;
- }
- } else {
- assert(type_b->is_matrix());
-
- /* A is a row vector and B is a matrix. Columns of A must match rows
- * of B. Given the other previously tested constraints, this means
- * the type of A must be the same as the vector type of a column from
- * B.
- */
- if (type_a == type_b->column_type()) {
- /* The resulting vector has a number of elements equal to
- * the number of columns of matrix B. */
- const glsl_type *const type =
- get_instance(type_a->base_type,
- type_b->row_type()->vector_elements,
- 1);
- assert(type != error_type);
-
- return type;
- }
- }
-
- return error_type;
-}
-
-
-const glsl_type *
-glsl_type::field_type(const char *name) const
-{
- if (this->base_type != GLSL_TYPE_STRUCT
- && this->base_type != GLSL_TYPE_INTERFACE)
- return error_type;
-
- for (unsigned i = 0; i < this->length; i++) {
- if (strcmp(name, this->fields.structure[i].name) == 0)
- return this->fields.structure[i].type;
- }
-
- return error_type;
-}
-
-
-int
-glsl_type::field_index(const char *name) const
-{
- if (this->base_type != GLSL_TYPE_STRUCT
- && this->base_type != GLSL_TYPE_INTERFACE)
- return -1;
-
- for (unsigned i = 0; i < this->length; i++) {
- if (strcmp(name, this->fields.structure[i].name) == 0)
- return i;
- }
-
- return -1;
-}
-
-
-unsigned
-glsl_type::component_slots() const
-{
- switch (this->base_type) {
- case GLSL_TYPE_UINT:
- case GLSL_TYPE_INT:
- case GLSL_TYPE_FLOAT:
- case GLSL_TYPE_BOOL:
- return this->components();
-
- case GLSL_TYPE_DOUBLE:
- return 2 * this->components();
-
- case GLSL_TYPE_STRUCT:
- case GLSL_TYPE_INTERFACE: {
- unsigned size = 0;
-
- for (unsigned i = 0; i < this->length; i++)
- size += this->fields.structure[i].type->component_slots();
-
- return size;
- }
-
- case GLSL_TYPE_ARRAY:
- return this->length * this->fields.array->component_slots();
-
- case GLSL_TYPE_IMAGE:
- return 1;
- case GLSL_TYPE_SUBROUTINE:
- return 1;
-
- case GLSL_TYPE_FUNCTION:
- case GLSL_TYPE_SAMPLER:
- case GLSL_TYPE_ATOMIC_UINT:
- case GLSL_TYPE_VOID:
- case GLSL_TYPE_ERROR:
- break;
- }
-
- return 0;
-}
-
-unsigned
-glsl_type::record_location_offset(unsigned length) const
-{
- unsigned offset = 0;
- const glsl_type *t = this->without_array();
- if (t->is_record()) {
- assert(length <= t->length);
-
- for (unsigned i = 0; i < length; i++) {
- const glsl_type *st = t->fields.structure[i].type;
- const glsl_type *wa = st->without_array();
- if (wa->is_record()) {
- unsigned r_offset = wa->record_location_offset(wa->length);
- offset += st->is_array() ?
- st->arrays_of_arrays_size() * r_offset : r_offset;
- } else if (st->is_array() && st->fields.array->is_array()) {
- unsigned outer_array_size = st->length;
- const glsl_type *base_type = st->fields.array;
-
- /* For arrays of arrays the outer arrays take up a uniform
- * slot for each element. The innermost array elements share a
- * single slot so we ignore the innermost array when calculating
- * the offset.
- */
- while (base_type->fields.array->is_array()) {
- outer_array_size = outer_array_size * base_type->length;
- base_type = base_type->fields.array;
- }
- offset += outer_array_size;
- } else {
- /* We dont worry about arrays here because unless the array
- * contains a structure or another array it only takes up a single
- * uniform slot.
- */
- offset += 1;
- }
- }
- }
- return offset;
-}
-
-unsigned
-glsl_type::uniform_locations() const
-{
- unsigned size = 0;
-
- switch (this->base_type) {
- case GLSL_TYPE_UINT:
- case GLSL_TYPE_INT:
- case GLSL_TYPE_FLOAT:
- case GLSL_TYPE_DOUBLE:
- case GLSL_TYPE_BOOL:
- case GLSL_TYPE_SAMPLER:
- case GLSL_TYPE_IMAGE:
- case GLSL_TYPE_SUBROUTINE:
- return 1;
-
- case GLSL_TYPE_STRUCT:
- case GLSL_TYPE_INTERFACE:
- for (unsigned i = 0; i < this->length; i++)
- size += this->fields.structure[i].type->uniform_locations();
- return size;
- case GLSL_TYPE_ARRAY:
- return this->length * this->fields.array->uniform_locations();
- default:
- return 0;
- }
-}
-
-bool
-glsl_type::can_implicitly_convert_to(const glsl_type *desired,
- _mesa_glsl_parse_state *state) const
-{
- if (this == desired)
- return true;
-
- /* There is no conversion among matrix types. */
- if (this->matrix_columns > 1 || desired->matrix_columns > 1)
- return false;
-
- /* Vector size must match. */
- if (this->vector_elements != desired->vector_elements)
- return false;
-
- /* int and uint can be converted to float. */
- if (desired->is_float() && this->is_integer())
- return true;
-
- /* With GLSL 4.0 / ARB_gpu_shader5, int can be converted to uint.
- * Note that state may be NULL here, when resolving function calls in the
- * linker. By this time, all the state-dependent checks have already
- * happened though, so allow anything that's allowed in any shader version. */
- if ((!state || state->is_version(400, 0) || state->ARB_gpu_shader5_enable) &&
- desired->base_type == GLSL_TYPE_UINT && this->base_type == GLSL_TYPE_INT)
- return true;
-
- /* No implicit conversions from double. */
- if ((!state || state->has_double()) && this->is_double())
- return false;
-
- /* Conversions from different types to double. */
- if ((!state || state->has_double()) && desired->is_double()) {
- if (this->is_float())
- return true;
- if (this->is_integer())
- return true;
- }
-
- return false;
-}
-
-unsigned
-glsl_type::std140_base_alignment(bool row_major) const
-{
- unsigned N = is_double() ? 8 : 4;
-
- /* (1) If the member is a scalar consuming <N> basic machine units, the
- * base alignment is <N>.
- *
- * (2) If the member is a two- or four-component vector with components
- * consuming <N> basic machine units, the base alignment is 2<N> or
- * 4<N>, respectively.
- *
- * (3) If the member is a three-component vector with components consuming
- * <N> basic machine units, the base alignment is 4<N>.
- */
- if (this->is_scalar() || this->is_vector()) {
- switch (this->vector_elements) {
- case 1:
- return N;
- case 2:
- return 2 * N;
- case 3:
- case 4:
- return 4 * N;
- }
- }
-
- /* (4) If the member is an array of scalars or vectors, the base alignment
- * and array stride are set to match the base alignment of a single
- * array element, according to rules (1), (2), and (3), and rounded up
- * to the base alignment of a vec4. The array may have padding at the
- * end; the base offset of the member following the array is rounded up
- * to the next multiple of the base alignment.
- *
- * (6) If the member is an array of <S> column-major matrices with <C>
- * columns and <R> rows, the matrix is stored identically to a row of
- * <S>*<C> column vectors with <R> components each, according to rule
- * (4).
- *
- * (8) If the member is an array of <S> row-major matrices with <C> columns
- * and <R> rows, the matrix is stored identically to a row of <S>*<R>
- * row vectors with <C> components each, according to rule (4).
- *
- * (10) If the member is an array of <S> structures, the <S> elements of
- * the array are laid out in order, according to rule (9).
- */
- if (this->is_array()) {
- if (this->fields.array->is_scalar() ||
- this->fields.array->is_vector() ||
- this->fields.array->is_matrix()) {
- return MAX2(this->fields.array->std140_base_alignment(row_major), 16);
- } else {
- assert(this->fields.array->is_record() ||
- this->fields.array->is_array());
- return this->fields.array->std140_base_alignment(row_major);
- }
- }
-
- /* (5) If the member is a column-major matrix with <C> columns and
- * <R> rows, the matrix is stored identically to an array of
- * <C> column vectors with <R> components each, according to
- * rule (4).
- *
- * (7) If the member is a row-major matrix with <C> columns and <R>
- * rows, the matrix is stored identically to an array of <R>
- * row vectors with <C> components each, according to rule (4).
- */
- if (this->is_matrix()) {
- const struct glsl_type *vec_type, *array_type;
- int c = this->matrix_columns;
- int r = this->vector_elements;
-
- if (row_major) {
- vec_type = get_instance(base_type, c, 1);
- array_type = glsl_type::get_array_instance(vec_type, r);
- } else {
- vec_type = get_instance(base_type, r, 1);
- array_type = glsl_type::get_array_instance(vec_type, c);
- }
-
- return array_type->std140_base_alignment(false);
- }
-
- /* (9) If the member is a structure, the base alignment of the
- * structure is <N>, where <N> is the largest base alignment
- * value of any of its members, and rounded up to the base
- * alignment of a vec4. The individual members of this
- * sub-structure are then assigned offsets by applying this set
- * of rules recursively, where the base offset of the first
- * member of the sub-structure is equal to the aligned offset
- * of the structure. The structure may have padding at the end;
- * the base offset of the member following the sub-structure is
- * rounded up to the next multiple of the base alignment of the
- * structure.
- */
- if (this->is_record()) {
- unsigned base_alignment = 16;
- for (unsigned i = 0; i < this->length; i++) {
- bool field_row_major = row_major;
- const enum glsl_matrix_layout matrix_layout =
- glsl_matrix_layout(this->fields.structure[i].matrix_layout);
- if (matrix_layout == GLSL_MATRIX_LAYOUT_ROW_MAJOR) {
- field_row_major = true;
- } else if (matrix_layout == GLSL_MATRIX_LAYOUT_COLUMN_MAJOR) {
- field_row_major = false;
- }
-
- const struct glsl_type *field_type = this->fields.structure[i].type;
- base_alignment = MAX2(base_alignment,
- field_type->std140_base_alignment(field_row_major));
- }
- return base_alignment;
- }
-
- assert(!"not reached");
- return -1;
-}
-
-unsigned
-glsl_type::std140_size(bool row_major) const
-{
- unsigned N = is_double() ? 8 : 4;
-
- /* (1) If the member is a scalar consuming <N> basic machine units, the
- * base alignment is <N>.
- *
- * (2) If the member is a two- or four-component vector with components
- * consuming <N> basic machine units, the base alignment is 2<N> or
- * 4<N>, respectively.
- *
- * (3) If the member is a three-component vector with components consuming
- * <N> basic machine units, the base alignment is 4<N>.
- */
- if (this->is_scalar() || this->is_vector()) {
- return this->vector_elements * N;
- }
-
- /* (5) If the member is a column-major matrix with <C> columns and
- * <R> rows, the matrix is stored identically to an array of
- * <C> column vectors with <R> components each, according to
- * rule (4).
- *
- * (6) If the member is an array of <S> column-major matrices with <C>
- * columns and <R> rows, the matrix is stored identically to a row of
- * <S>*<C> column vectors with <R> components each, according to rule
- * (4).
- *
- * (7) If the member is a row-major matrix with <C> columns and <R>
- * rows, the matrix is stored identically to an array of <R>
- * row vectors with <C> components each, according to rule (4).
- *
- * (8) If the member is an array of <S> row-major matrices with <C> columns
- * and <R> rows, the matrix is stored identically to a row of <S>*<R>
- * row vectors with <C> components each, according to rule (4).
- */
- if (this->without_array()->is_matrix()) {
- const struct glsl_type *element_type;
- const struct glsl_type *vec_type;
- unsigned int array_len;
-
- if (this->is_array()) {
- element_type = this->without_array();
- array_len = this->arrays_of_arrays_size();
- } else {
- element_type = this;
- array_len = 1;
- }
-
- if (row_major) {
- vec_type = get_instance(element_type->base_type,
- element_type->matrix_columns, 1);
-
- array_len *= element_type->vector_elements;
- } else {
- vec_type = get_instance(element_type->base_type,
- element_type->vector_elements, 1);
- array_len *= element_type->matrix_columns;
- }
- const glsl_type *array_type = glsl_type::get_array_instance(vec_type,
- array_len);
-
- return array_type->std140_size(false);
- }
-
- /* (4) If the member is an array of scalars or vectors, the base alignment
- * and array stride are set to match the base alignment of a single
- * array element, according to rules (1), (2), and (3), and rounded up
- * to the base alignment of a vec4. The array may have padding at the
- * end; the base offset of the member following the array is rounded up
- * to the next multiple of the base alignment.
- *
- * (10) If the member is an array of <S> structures, the <S> elements of
- * the array are laid out in order, according to rule (9).
- */
- if (this->is_array()) {
- if (this->without_array()->is_record()) {
- return this->arrays_of_arrays_size() *
- this->without_array()->std140_size(row_major);
- } else {
- unsigned element_base_align =
- this->without_array()->std140_base_alignment(row_major);
- return this->arrays_of_arrays_size() * MAX2(element_base_align, 16);
- }
- }
-
- /* (9) If the member is a structure, the base alignment of the
- * structure is <N>, where <N> is the largest base alignment
- * value of any of its members, and rounded up to the base
- * alignment of a vec4. The individual members of this
- * sub-structure are then assigned offsets by applying this set
- * of rules recursively, where the base offset of the first
- * member of the sub-structure is equal to the aligned offset
- * of the structure. The structure may have padding at the end;
- * the base offset of the member following the sub-structure is
- * rounded up to the next multiple of the base alignment of the
- * structure.
- */
- if (this->is_record() || this->is_interface()) {
- unsigned size = 0;
- unsigned max_align = 0;
-
- for (unsigned i = 0; i < this->length; i++) {
- bool field_row_major = row_major;
- const enum glsl_matrix_layout matrix_layout =
- glsl_matrix_layout(this->fields.structure[i].matrix_layout);
- if (matrix_layout == GLSL_MATRIX_LAYOUT_ROW_MAJOR) {
- field_row_major = true;
- } else if (matrix_layout == GLSL_MATRIX_LAYOUT_COLUMN_MAJOR) {
- field_row_major = false;
- }
-
- const struct glsl_type *field_type = this->fields.structure[i].type;
- unsigned align = field_type->std140_base_alignment(field_row_major);
-
- /* Ignore unsized arrays when calculating size */
- if (field_type->is_unsized_array())
- continue;
-
- size = glsl_align(size, align);
- size += field_type->std140_size(field_row_major);
-
- max_align = MAX2(align, max_align);
-
- if (field_type->is_record() && (i + 1 < this->length))
- size = glsl_align(size, 16);
- }
- size = glsl_align(size, MAX2(max_align, 16));
- return size;
- }
-
- assert(!"not reached");
- return -1;
-}
-
-unsigned
-glsl_type::std430_base_alignment(bool row_major) const
-{
-
- unsigned N = is_double() ? 8 : 4;
-
- /* (1) If the member is a scalar consuming <N> basic machine units, the
- * base alignment is <N>.
- *
- * (2) If the member is a two- or four-component vector with components
- * consuming <N> basic machine units, the base alignment is 2<N> or
- * 4<N>, respectively.
- *
- * (3) If the member is a three-component vector with components consuming
- * <N> basic machine units, the base alignment is 4<N>.
- */
- if (this->is_scalar() || this->is_vector()) {
- switch (this->vector_elements) {
- case 1:
- return N;
- case 2:
- return 2 * N;
- case 3:
- case 4:
- return 4 * N;
- }
- }
-
- /* OpenGL 4.30 spec, section 7.6.2.2 "Standard Uniform Block Layout":
- *
- * "When using the std430 storage layout, shader storage blocks will be
- * laid out in buffer storage identically to uniform and shader storage
- * blocks using the std140 layout, except that the base alignment and
- * stride of arrays of scalars and vectors in rule 4 and of structures
- * in rule 9 are not rounded up a multiple of the base alignment of a vec4.
- */
-
- /* (1) If the member is a scalar consuming <N> basic machine units, the
- * base alignment is <N>.
- *
- * (2) If the member is a two- or four-component vector with components
- * consuming <N> basic machine units, the base alignment is 2<N> or
- * 4<N>, respectively.
- *
- * (3) If the member is a three-component vector with components consuming
- * <N> basic machine units, the base alignment is 4<N>.
- */
- if (this->is_array())
- return this->fields.array->std430_base_alignment(row_major);
-
- /* (5) If the member is a column-major matrix with <C> columns and
- * <R> rows, the matrix is stored identically to an array of
- * <C> column vectors with <R> components each, according to
- * rule (4).
- *
- * (7) If the member is a row-major matrix with <C> columns and <R>
- * rows, the matrix is stored identically to an array of <R>
- * row vectors with <C> components each, according to rule (4).
- */
- if (this->is_matrix()) {
- const struct glsl_type *vec_type, *array_type;
- int c = this->matrix_columns;
- int r = this->vector_elements;
-
- if (row_major) {
- vec_type = get_instance(base_type, c, 1);
- array_type = glsl_type::get_array_instance(vec_type, r);
- } else {
- vec_type = get_instance(base_type, r, 1);
- array_type = glsl_type::get_array_instance(vec_type, c);
- }
-
- return array_type->std430_base_alignment(false);
- }
-
- /* (9) If the member is a structure, the base alignment of the
- * structure is <N>, where <N> is the largest base alignment
- * value of any of its members, and rounded up to the base
- * alignment of a vec4. The individual members of this
- * sub-structure are then assigned offsets by applying this set
- * of rules recursively, where the base offset of the first
- * member of the sub-structure is equal to the aligned offset
- * of the structure. The structure may have padding at the end;
- * the base offset of the member following the sub-structure is
- * rounded up to the next multiple of the base alignment of the
- * structure.
- */
- if (this->is_record()) {
- unsigned base_alignment = 0;
- for (unsigned i = 0; i < this->length; i++) {
- bool field_row_major = row_major;
- const enum glsl_matrix_layout matrix_layout =
- glsl_matrix_layout(this->fields.structure[i].matrix_layout);
- if (matrix_layout == GLSL_MATRIX_LAYOUT_ROW_MAJOR) {
- field_row_major = true;
- } else if (matrix_layout == GLSL_MATRIX_LAYOUT_COLUMN_MAJOR) {
- field_row_major = false;
- }
-
- const struct glsl_type *field_type = this->fields.structure[i].type;
- base_alignment = MAX2(base_alignment,
- field_type->std430_base_alignment(field_row_major));
- }
- assert(base_alignment > 0);
- return base_alignment;
- }
- assert(!"not reached");
- return -1;
-}
-
-unsigned
-glsl_type::std430_array_stride(bool row_major) const
-{
- unsigned N = is_double() ? 8 : 4;
-
- /* Notice that the array stride of a vec3 is not 3 * N but 4 * N.
- * See OpenGL 4.30 spec, section 7.6.2.2 "Standard Uniform Block Layout"
- *
- * (3) If the member is a three-component vector with components consuming
- * <N> basic machine units, the base alignment is 4<N>.
- */
- if (this->is_vector() && this->vector_elements == 3)
- return 4 * N;
-
- /* By default use std430_size(row_major) */
- return this->std430_size(row_major);
-}
-
-unsigned
-glsl_type::std430_size(bool row_major) const
-{
- unsigned N = is_double() ? 8 : 4;
-
- /* OpenGL 4.30 spec, section 7.6.2.2 "Standard Uniform Block Layout":
- *
- * "When using the std430 storage layout, shader storage blocks will be
- * laid out in buffer storage identically to uniform and shader storage
- * blocks using the std140 layout, except that the base alignment and
- * stride of arrays of scalars and vectors in rule 4 and of structures
- * in rule 9 are not rounded up a multiple of the base alignment of a vec4.
- */
- if (this->is_scalar() || this->is_vector())
- return this->vector_elements * N;
-
- if (this->without_array()->is_matrix()) {
- const struct glsl_type *element_type;
- const struct glsl_type *vec_type;
- unsigned int array_len;
-
- if (this->is_array()) {
- element_type = this->without_array();
- array_len = this->arrays_of_arrays_size();
- } else {
- element_type = this;
- array_len = 1;
- }
-
- if (row_major) {
- vec_type = get_instance(element_type->base_type,
- element_type->matrix_columns, 1);
-
- array_len *= element_type->vector_elements;
- } else {
- vec_type = get_instance(element_type->base_type,
- element_type->vector_elements, 1);
- array_len *= element_type->matrix_columns;
- }
- const glsl_type *array_type = glsl_type::get_array_instance(vec_type,
- array_len);
-
- return array_type->std430_size(false);
- }
-
- if (this->is_array()) {
- if (this->without_array()->is_record())
- return this->arrays_of_arrays_size() *
- this->without_array()->std430_size(row_major);
- else
- return this->arrays_of_arrays_size() *
- this->without_array()->std430_base_alignment(row_major);
- }
-
- if (this->is_record() || this->is_interface()) {
- unsigned size = 0;
- unsigned max_align = 0;
-
- for (unsigned i = 0; i < this->length; i++) {
- bool field_row_major = row_major;
- const enum glsl_matrix_layout matrix_layout =
- glsl_matrix_layout(this->fields.structure[i].matrix_layout);
- if (matrix_layout == GLSL_MATRIX_LAYOUT_ROW_MAJOR) {
- field_row_major = true;
- } else if (matrix_layout == GLSL_MATRIX_LAYOUT_COLUMN_MAJOR) {
- field_row_major = false;
- }
-
- const struct glsl_type *field_type = this->fields.structure[i].type;
- unsigned align = field_type->std430_base_alignment(field_row_major);
- size = glsl_align(size, align);
- size += field_type->std430_size(field_row_major);
-
- max_align = MAX2(align, max_align);
- }
- size = glsl_align(size, max_align);
- return size;
- }
-
- assert(!"not reached");
- return -1;
-}
-
-unsigned
-glsl_type::count_attribute_slots(bool vertex_input_slots) const
-{
- /* From page 31 (page 37 of the PDF) of the GLSL 1.50 spec:
- *
- * "A scalar input counts the same amount against this limit as a vec4,
- * so applications may want to consider packing groups of four
- * unrelated float inputs together into a vector to better utilize the
- * capabilities of the underlying hardware. A matrix input will use up
- * multiple locations. The number of locations used will equal the
- * number of columns in the matrix."
- *
- * The spec does not explicitly say how arrays are counted. However, it
- * should be safe to assume the total number of slots consumed by an array
- * is the number of entries in the array multiplied by the number of slots
- * consumed by a single element of the array.
- *
- * The spec says nothing about how structs are counted, because vertex
- * attributes are not allowed to be (or contain) structs. However, Mesa
- * allows varying structs, the number of varying slots taken up by a
- * varying struct is simply equal to the sum of the number of slots taken
- * up by each element.
- *
- * Doubles are counted different depending on whether they are vertex
- * inputs or everything else. Vertex inputs from ARB_vertex_attrib_64bit
- * take one location no matter what size they are, otherwise dvec3/4
- * take two locations.
- */
- switch (this->base_type) {
- case GLSL_TYPE_UINT:
- case GLSL_TYPE_INT:
- case GLSL_TYPE_FLOAT:
- case GLSL_TYPE_BOOL:
- return this->matrix_columns;
- case GLSL_TYPE_DOUBLE:
- if (this->vector_elements > 2 && !vertex_input_slots)
- return this->matrix_columns * 2;
- else
- return this->matrix_columns;
- case GLSL_TYPE_STRUCT:
- case GLSL_TYPE_INTERFACE: {
- unsigned size = 0;
-
- for (unsigned i = 0; i < this->length; i++)
- size += this->fields.structure[i].type->count_attribute_slots(vertex_input_slots);
-
- return size;
- }
-
- case GLSL_TYPE_ARRAY:
- return this->length * this->fields.array->count_attribute_slots(vertex_input_slots);
-
- case GLSL_TYPE_FUNCTION:
- case GLSL_TYPE_SAMPLER:
- case GLSL_TYPE_IMAGE:
- case GLSL_TYPE_ATOMIC_UINT:
- case GLSL_TYPE_VOID:
- case GLSL_TYPE_SUBROUTINE:
- case GLSL_TYPE_ERROR:
- break;
- }
-
- assert(!"Unexpected type in count_attribute_slots()");
-
- return 0;
-}
-
-int
-glsl_type::coordinate_components() const
-{
- int size;
-
- switch (sampler_dimensionality) {
- case GLSL_SAMPLER_DIM_1D:
- case GLSL_SAMPLER_DIM_BUF:
- size = 1;
- break;
- case GLSL_SAMPLER_DIM_2D:
- case GLSL_SAMPLER_DIM_RECT:
- case GLSL_SAMPLER_DIM_MS:
- case GLSL_SAMPLER_DIM_EXTERNAL:
- size = 2;
- break;
- case GLSL_SAMPLER_DIM_3D:
- case GLSL_SAMPLER_DIM_CUBE:
- size = 3;
- break;
- default:
- assert(!"Should not get here.");
- size = 1;
- break;
- }
-
- /* Array textures need an additional component for the array index, except
- * for cubemap array images that behave like a 2D array of interleaved
- * cubemap faces.
- */
- if (sampler_array &&
- !(base_type == GLSL_TYPE_IMAGE &&
- sampler_dimensionality == GLSL_SAMPLER_DIM_CUBE))
- size += 1;
-
- return size;
-}
-
-/**
- * Declarations of type flyweights (glsl_type::_foo_type) and
- * convenience pointers (glsl_type::foo_type).
- * @{
- */
-#define DECL_TYPE(NAME, ...) \
- const glsl_type glsl_type::_##NAME##_type = glsl_type(__VA_ARGS__, #NAME); \
- const glsl_type *const glsl_type::NAME##_type = &glsl_type::_##NAME##_type;
-
-#define STRUCT_TYPE(NAME)
-
-#include "builtin_type_macros.h"
-/** @} */
diff --git a/src/glsl/nir/glsl_types.h b/src/glsl/nir/glsl_types.h
deleted file mode 100644
index ff8dcc7a5f6..00000000000
--- a/src/glsl/nir/glsl_types.h
+++ /dev/null
@@ -1,913 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright © 2009 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-#pragma once
-#ifndef GLSL_TYPES_H
-#define GLSL_TYPES_H
-
-#include <string.h>
-#include <assert.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct _mesa_glsl_parse_state;
-struct glsl_symbol_table;
-
-extern void
-_mesa_glsl_initialize_types(struct _mesa_glsl_parse_state *state);
-
-extern void
-_mesa_glsl_release_types(void);
-
-#ifdef __cplusplus
-}
-#endif
-
-enum glsl_base_type {
- GLSL_TYPE_UINT = 0,
- GLSL_TYPE_INT,
- GLSL_TYPE_FLOAT,
- GLSL_TYPE_DOUBLE,
- GLSL_TYPE_BOOL,
- GLSL_TYPE_SAMPLER,
- GLSL_TYPE_IMAGE,
- GLSL_TYPE_ATOMIC_UINT,
- GLSL_TYPE_STRUCT,
- GLSL_TYPE_FUNCTION,
- GLSL_TYPE_INTERFACE,
- GLSL_TYPE_ARRAY,
- GLSL_TYPE_VOID,
- GLSL_TYPE_SUBROUTINE,
- GLSL_TYPE_ERROR
-};
-
-enum glsl_sampler_dim {
- GLSL_SAMPLER_DIM_1D = 0,
- GLSL_SAMPLER_DIM_2D,
- GLSL_SAMPLER_DIM_3D,
- GLSL_SAMPLER_DIM_CUBE,
- GLSL_SAMPLER_DIM_RECT,
- GLSL_SAMPLER_DIM_BUF,
- GLSL_SAMPLER_DIM_EXTERNAL,
- GLSL_SAMPLER_DIM_MS
-};
-
-enum glsl_interface_packing {
- GLSL_INTERFACE_PACKING_STD140,
- GLSL_INTERFACE_PACKING_SHARED,
- GLSL_INTERFACE_PACKING_PACKED,
- GLSL_INTERFACE_PACKING_STD430
-};
-
-enum glsl_matrix_layout {
- /**
- * The layout of the matrix is inherited from the object containing the
- * matrix (the top level structure or the uniform block).
- */
- GLSL_MATRIX_LAYOUT_INHERITED,
-
- /**
- * Explicit column-major layout
- *
- * If a uniform block doesn't have an explicit layout set, it will default
- * to this layout.
- */
- GLSL_MATRIX_LAYOUT_COLUMN_MAJOR,
-
- /**
- * Row-major layout
- */
- GLSL_MATRIX_LAYOUT_ROW_MAJOR
-};
-
-enum {
- GLSL_PRECISION_NONE = 0,
- GLSL_PRECISION_HIGH,
- GLSL_PRECISION_MEDIUM,
- GLSL_PRECISION_LOW
-};
-
-#ifdef __cplusplus
-#include "GL/gl.h"
-#include "util/ralloc.h"
-#include "main/mtypes.h" /* for gl_texture_index, C++'s enum rules are broken */
-
-struct glsl_type {
- GLenum gl_type;
- glsl_base_type base_type;
-
- unsigned sampler_dimensionality:3; /**< \see glsl_sampler_dim */
- unsigned sampler_shadow:1;
- unsigned sampler_array:1;
- unsigned sampler_type:2; /**< Type of data returned using this
- * sampler or image. Only \c
- * GLSL_TYPE_FLOAT, \c GLSL_TYPE_INT,
- * and \c GLSL_TYPE_UINT are valid.
- */
- unsigned interface_packing:2;
-
- /* Callers of this ralloc-based new need not call delete. It's
- * easier to just ralloc_free 'mem_ctx' (or any of its ancestors). */
- static void* operator new(size_t size)
- {
- mtx_lock(&glsl_type::mutex);
-
- /* mem_ctx should have been created by the static members */
- assert(glsl_type::mem_ctx != NULL);
-
- void *type;
-
- type = ralloc_size(glsl_type::mem_ctx, size);
- assert(type != NULL);
-
- mtx_unlock(&glsl_type::mutex);
-
- return type;
- }
-
- /* If the user *does* call delete, that's OK, we will just
- * ralloc_free in that case. */
- static void operator delete(void *type)
- {
- mtx_lock(&glsl_type::mutex);
- ralloc_free(type);
- mtx_unlock(&glsl_type::mutex);
- }
-
- /**
- * \name Vector and matrix element counts
- *
- * For scalars, each of these values will be 1. For non-numeric types
- * these will be 0.
- */
- /*@{*/
- uint8_t vector_elements; /**< 1, 2, 3, or 4 vector elements. */
- uint8_t matrix_columns; /**< 1, 2, 3, or 4 matrix columns. */
- /*@}*/
-
- /**
- * For \c GLSL_TYPE_ARRAY, this is the length of the array. For
- * \c GLSL_TYPE_STRUCT or \c GLSL_TYPE_INTERFACE, it is the number of
- * elements in the structure and the number of values pointed to by
- * \c fields.structure (below).
- */
- unsigned length;
-
- /**
- * Name of the data type
- *
- * Will never be \c NULL.
- */
- const char *name;
-
- /**
- * Subtype of composite data types.
- */
- union {
- const struct glsl_type *array; /**< Type of array elements. */
- struct glsl_function_param *parameters; /**< Parameters to function. */
- struct glsl_struct_field *structure; /**< List of struct fields. */
- } fields;
-
- /**
- * \name Pointers to various public type singletons
- */
- /*@{*/
-#undef DECL_TYPE
-#define DECL_TYPE(NAME, ...) \
- static const glsl_type *const NAME##_type;
-#undef STRUCT_TYPE
-#define STRUCT_TYPE(NAME) \
- static const glsl_type *const struct_##NAME##_type;
-#include "builtin_type_macros.h"
- /*@}*/
-
- /**
- * Convenience accessors for vector types (shorter than get_instance()).
- * @{
- */
- static const glsl_type *vec(unsigned components);
- static const glsl_type *dvec(unsigned components);
- static const glsl_type *ivec(unsigned components);
- static const glsl_type *uvec(unsigned components);
- static const glsl_type *bvec(unsigned components);
- /**@}*/
-
- /**
- * For numeric and boolean derived types returns the basic scalar type
- *
- * If the type is a numeric or boolean scalar, vector, or matrix type,
- * this function gets the scalar type of the individual components. For
- * all other types, including arrays of numeric or boolean types, the
- * error type is returned.
- */
- const glsl_type *get_base_type() const;
-
- /**
- * Get the basic scalar type which this type aggregates.
- *
- * If the type is a numeric or boolean scalar, vector, or matrix, or an
- * array of any of those, this function gets the scalar type of the
- * individual components. For structs and arrays of structs, this function
- * returns the struct type. For samplers and arrays of samplers, this
- * function returns the sampler type.
- */
- const glsl_type *get_scalar_type() const;
-
- /**
- * Get the instance of a built-in scalar, vector, or matrix type
- */
- static const glsl_type *get_instance(unsigned base_type, unsigned rows,
- unsigned columns);
-
- /**
- * Get the instance of a sampler type
- */
- static const glsl_type *get_sampler_instance(enum glsl_sampler_dim dim,
- bool shadow,
- bool array,
- glsl_base_type type);
-
- static const glsl_type *get_image_instance(enum glsl_sampler_dim dim,
- bool array, glsl_base_type type);
-
- /**
- * Get the instance of an array type
- */
- static const glsl_type *get_array_instance(const glsl_type *base,
- unsigned elements);
-
- /**
- * Get the instance of a record type
- */
- static const glsl_type *get_record_instance(const glsl_struct_field *fields,
- unsigned num_fields,
- const char *name);
-
- /**
- * Get the instance of an interface block type
- */
- static const glsl_type *get_interface_instance(const glsl_struct_field *fields,
- unsigned num_fields,
- enum glsl_interface_packing packing,
- const char *block_name);
-
- /**
- * Get the instance of an subroutine type
- */
- static const glsl_type *get_subroutine_instance(const char *subroutine_name);
-
- /**
- * Get the instance of a function type
- */
- static const glsl_type *get_function_instance(const struct glsl_type *return_type,
- const glsl_function_param *parameters,
- unsigned num_params);
-
- /**
- * Get the type resulting from a multiplication of \p type_a * \p type_b
- */
- static const glsl_type *get_mul_type(const glsl_type *type_a,
- const glsl_type *type_b);
-
- /**
- * Query the total number of scalars that make up a scalar, vector or matrix
- */
- unsigned components() const
- {
- return vector_elements * matrix_columns;
- }
-
- /**
- * Calculate the number of components slots required to hold this type
- *
- * This is used to determine how many uniform or varying locations a type
- * might occupy.
- */
- unsigned component_slots() const;
-
- /**
- * Calculate offset between the base location of the struct in
- * uniform storage and a struct member.
- * For the initial call, length is the index of the member to find the
- * offset for.
- */
- unsigned record_location_offset(unsigned length) const;
-
- /**
- * Calculate the number of unique values from glGetUniformLocation for the
- * elements of the type.
- *
- * This is used to allocate slots in the UniformRemapTable, the amount of
- * locations may not match with actual used storage space by the driver.
- */
- unsigned uniform_locations() const;
-
- /**
- * Calculate the number of attribute slots required to hold this type
- *
- * This implements the language rules of GLSL 1.50 for counting the number
- * of slots used by a vertex attribute. It also determines the number of
- * varying slots the type will use up in the absence of varying packing
- * (and thus, it can be used to measure the number of varying slots used by
- * the varyings that are generated by lower_packed_varyings).
- *
- * For vertex shader attributes - doubles only take one slot.
- * For inter-shader varyings - dvec3/dvec4 take two slots.
- */
- unsigned count_attribute_slots(bool vertex_input_slots) const;
-
- /**
- * Alignment in bytes of the start of this type in a std140 uniform
- * block.
- */
- unsigned std140_base_alignment(bool row_major) const;
-
- /** Size in bytes of this type in a std140 uniform block.
- *
- * Note that this is not GL_UNIFORM_SIZE (which is the number of
- * elements in the array)
- */
- unsigned std140_size(bool row_major) const;
-
- /**
- * Alignment in bytes of the start of this type in a std430 shader
- * storage block.
- */
- unsigned std430_base_alignment(bool row_major) const;
-
- /**
- * Calculate array stride in bytes of this type in a std430 shader storage
- * block.
- */
- unsigned std430_array_stride(bool row_major) const;
-
- /**
- * Size in bytes of this type in a std430 shader storage block.
- *
- * Note that this is not GL_BUFFER_SIZE
- */
- unsigned std430_size(bool row_major) const;
-
- /**
- * \brief Can this type be implicitly converted to another?
- *
- * \return True if the types are identical or if this type can be converted
- * to \c desired according to Section 4.1.10 of the GLSL spec.
- *
- * \verbatim
- * From page 25 (31 of the pdf) of the GLSL 1.50 spec, Section 4.1.10
- * Implicit Conversions:
- *
- * In some situations, an expression and its type will be implicitly
- * converted to a different type. The following table shows all allowed
- * implicit conversions:
- *
- * Type of expression | Can be implicitly converted to
- * --------------------------------------------------
- * int float
- * uint
- *
- * ivec2 vec2
- * uvec2
- *
- * ivec3 vec3
- * uvec3
- *
- * ivec4 vec4
- * uvec4
- *
- * There are no implicit array or structure conversions. For example,
- * an array of int cannot be implicitly converted to an array of float.
- * There are no implicit conversions between signed and unsigned
- * integers.
- * \endverbatim
- */
- bool can_implicitly_convert_to(const glsl_type *desired,
- _mesa_glsl_parse_state *state) const;
-
- /**
- * Query whether or not a type is a scalar (non-vector and non-matrix).
- */
- bool is_scalar() const
- {
- return (vector_elements == 1)
- && (base_type >= GLSL_TYPE_UINT)
- && (base_type <= GLSL_TYPE_BOOL);
- }
-
- /**
- * Query whether or not a type is a vector
- */
- bool is_vector() const
- {
- return (vector_elements > 1)
- && (matrix_columns == 1)
- && (base_type >= GLSL_TYPE_UINT)
- && (base_type <= GLSL_TYPE_BOOL);
- }
-
- /**
- * Query whether or not a type is a matrix
- */
- bool is_matrix() const
- {
- /* GLSL only has float matrices. */
- return (matrix_columns > 1) && (base_type == GLSL_TYPE_FLOAT || base_type == GLSL_TYPE_DOUBLE);
- }
-
- /**
- * Query whether or not a type is a non-array numeric type
- */
- bool is_numeric() const
- {
- return (base_type >= GLSL_TYPE_UINT) && (base_type <= GLSL_TYPE_DOUBLE);
- }
-
- /**
- * Query whether or not a type is an integral type
- */
- bool is_integer() const
- {
- return (base_type == GLSL_TYPE_UINT) || (base_type == GLSL_TYPE_INT);
- }
-
- /**
- * Query whether or not type is an integral type, or for struct and array
- * types, contains an integral type.
- */
- bool contains_integer() const;
-
- /**
- * Query whether or not type is a double type, or for struct and array
- * types, contains a double type.
- */
- bool contains_double() const;
-
- /**
- * Query whether or not a type is a float type
- */
- bool is_float() const
- {
- return base_type == GLSL_TYPE_FLOAT;
- }
-
- /**
- * Query whether or not a type is a double type
- */
- bool is_double() const
- {
- return base_type == GLSL_TYPE_DOUBLE;
- }
-
- /**
- * Query whether a double takes two slots.
- */
- bool is_dual_slot_double() const
- {
- return base_type == GLSL_TYPE_DOUBLE && vector_elements > 2;
- }
-
- /**
- * Query whether or not a type is a non-array boolean type
- */
- bool is_boolean() const
- {
- return base_type == GLSL_TYPE_BOOL;
- }
-
- /**
- * Query whether or not a type is a sampler
- */
- bool is_sampler() const
- {
- return base_type == GLSL_TYPE_SAMPLER;
- }
-
- /**
- * Query whether or not type is a sampler, or for struct and array
- * types, contains a sampler.
- */
- bool contains_sampler() const;
-
- /**
- * Get the Mesa texture target index for a sampler type.
- */
- gl_texture_index sampler_index() const;
-
- /**
- * Query whether or not type is an image, or for struct and array
- * types, contains an image.
- */
- bool contains_image() const;
-
- /**
- * Query whether or not a type is an image
- */
- bool is_image() const
- {
- return base_type == GLSL_TYPE_IMAGE;
- }
-
- /**
- * Query whether or not a type is an array
- */
- bool is_array() const
- {
- return base_type == GLSL_TYPE_ARRAY;
- }
-
- bool is_array_of_arrays() const
- {
- return is_array() && fields.array->is_array();
- }
-
- /**
- * Query whether or not a type is a record
- */
- bool is_record() const
- {
- return base_type == GLSL_TYPE_STRUCT;
- }
-
- /**
- * Query whether or not a type is an interface
- */
- bool is_interface() const
- {
- return base_type == GLSL_TYPE_INTERFACE;
- }
-
- /**
- * Query whether or not a type is the void type singleton.
- */
- bool is_void() const
- {
- return base_type == GLSL_TYPE_VOID;
- }
-
- /**
- * Query whether or not a type is the error type singleton.
- */
- bool is_error() const
- {
- return base_type == GLSL_TYPE_ERROR;
- }
-
- /**
- * Query if a type is unnamed/anonymous (named by the parser)
- */
-
- bool is_subroutine() const
- {
- return base_type == GLSL_TYPE_SUBROUTINE;
- }
- bool contains_subroutine() const;
-
- bool is_anonymous() const
- {
- return !strncmp(name, "#anon", 5);
- }
-
- /**
- * Get the type stripped of any arrays
- *
- * \return
- * Pointer to the type of elements of the first non-array type for array
- * types, or pointer to itself for non-array types.
- */
- const glsl_type *without_array() const
- {
- const glsl_type *t = this;
-
- while (t->is_array())
- t = t->fields.array;
-
- return t;
- }
-
- /**
- * Return the total number of elements in an array including the elements
- * in arrays of arrays.
- */
- unsigned arrays_of_arrays_size() const
- {
- if (!is_array())
- return 0;
-
- unsigned size = length;
- const glsl_type *base_type = fields.array;
-
- while (base_type->is_array()) {
- size = size * base_type->length;
- base_type = base_type->fields.array;
- }
- return size;
- }
-
- /**
- * Return the amount of atomic counter storage required for a type.
- */
- unsigned atomic_size() const
- {
- if (base_type == GLSL_TYPE_ATOMIC_UINT)
- return ATOMIC_COUNTER_SIZE;
- else if (is_array())
- return length * fields.array->atomic_size();
- else
- return 0;
- }
-
- /**
- * Return whether a type contains any atomic counters.
- */
- bool contains_atomic() const
- {
- return atomic_size() > 0;
- }
-
- /**
- * Return whether a type contains any opaque types.
- */
- bool contains_opaque() const;
-
- /**
- * Query the full type of a matrix row
- *
- * \return
- * If the type is not a matrix, \c glsl_type::error_type is returned.
- * Otherwise a type matching the rows of the matrix is returned.
- */
- const glsl_type *row_type() const
- {
- return is_matrix()
- ? get_instance(base_type, matrix_columns, 1)
- : error_type;
- }
-
- /**
- * Query the full type of a matrix column
- *
- * \return
- * If the type is not a matrix, \c glsl_type::error_type is returned.
- * Otherwise a type matching the columns of the matrix is returned.
- */
- const glsl_type *column_type() const
- {
- return is_matrix()
- ? get_instance(base_type, vector_elements, 1)
- : error_type;
- }
-
- /**
- * Get the type of a structure field
- *
- * \return
- * Pointer to the type of the named field. If the type is not a structure
- * or the named field does not exist, \c glsl_type::error_type is returned.
- */
- const glsl_type *field_type(const char *name) const;
-
- /**
- * Get the location of a field within a record type
- */
- int field_index(const char *name) const;
-
- /**
- * Query the number of elements in an array type
- *
- * \return
- * The number of elements in the array for array types or -1 for non-array
- * types. If the number of elements in the array has not yet been declared,
- * zero is returned.
- */
- int array_size() const
- {
- return is_array() ? length : -1;
- }
-
- /**
- * Query whether the array size for all dimensions has been declared.
- */
- bool is_unsized_array() const
- {
- return is_array() && length == 0;
- }
-
- /**
- * Return the number of coordinate components needed for this
- * sampler or image type.
- *
- * This is based purely on the sampler's dimensionality. For example, this
- * returns 1 for sampler1D, and 3 for sampler2DArray.
- *
- * Note that this is often different than actual coordinate type used in
- * a texturing built-in function, since those pack additional values (such
- * as the shadow comparitor or projector) into the coordinate type.
- */
- int coordinate_components() const;
-
- /**
- * Compare a record type against another record type.
- *
- * This is useful for matching record types declared across shader stages.
- */
- bool record_compare(const glsl_type *b) const;
-
-private:
-
- static mtx_t mutex;
-
- /**
- * ralloc context for all glsl_type allocations
- *
- * Set on the first call to \c glsl_type::new.
- */
- static void *mem_ctx;
-
- void init_ralloc_type_ctx(void);
-
- /** Constructor for vector and matrix types */
- glsl_type(GLenum gl_type,
- glsl_base_type base_type, unsigned vector_elements,
- unsigned matrix_columns, const char *name);
-
- /** Constructor for sampler or image types */
- glsl_type(GLenum gl_type, glsl_base_type base_type,
- enum glsl_sampler_dim dim, bool shadow, bool array,
- unsigned type, const char *name);
-
- /** Constructor for record types */
- glsl_type(const glsl_struct_field *fields, unsigned num_fields,
- const char *name);
-
- /** Constructor for interface types */
- glsl_type(const glsl_struct_field *fields, unsigned num_fields,
- enum glsl_interface_packing packing, const char *name);
-
- /** Constructor for interface types */
- glsl_type(const glsl_type *return_type,
- const glsl_function_param *params, unsigned num_params);
-
- /** Constructor for array types */
- glsl_type(const glsl_type *array, unsigned length);
-
- /** Constructor for subroutine types */
- glsl_type(const char *name);
-
- /** Hash table containing the known array types. */
- static struct hash_table *array_types;
-
- /** Hash table containing the known record types. */
- static struct hash_table *record_types;
-
- /** Hash table containing the known interface types. */
- static struct hash_table *interface_types;
-
- /** Hash table containing the known subroutine types. */
- static struct hash_table *subroutine_types;
-
- /** Hash table containing the known function types. */
- static struct hash_table *function_types;
-
- static bool record_key_compare(const void *a, const void *b);
- static unsigned record_key_hash(const void *key);
-
- /**
- * \name Built-in type flyweights
- */
- /*@{*/
-#undef DECL_TYPE
-#define DECL_TYPE(NAME, ...) static const glsl_type _##NAME##_type;
-#undef STRUCT_TYPE
-#define STRUCT_TYPE(NAME) static const glsl_type _struct_##NAME##_type;
-#include "builtin_type_macros.h"
- /*@}*/
-
- /**
- * \name Friend functions.
- *
- * These functions are friends because they must have C linkage and the
- * need to call various private methods or access various private static
- * data.
- */
- /*@{*/
- friend void _mesa_glsl_initialize_types(struct _mesa_glsl_parse_state *);
- friend void _mesa_glsl_release_types(void);
- /*@}*/
-};
-
-#undef DECL_TYPE
-#undef STRUCT_TYPE
-#endif /* __cplusplus */
-
-struct glsl_struct_field {
- const struct glsl_type *type;
- const char *name;
-
- /**
- * For interface blocks, gl_varying_slot corresponding to the input/output
- * if this is a built-in input/output (i.e. a member of the built-in
- * gl_PerVertex interface block); -1 otherwise.
- *
- * Ignored for structs.
- */
- int location;
-
- /**
- * For interface blocks, the interpolation mode (as in
- * ir_variable::interpolation). 0 otherwise.
- */
- unsigned interpolation:2;
-
- /**
- * For interface blocks, 1 if this variable uses centroid interpolation (as
- * in ir_variable::centroid). 0 otherwise.
- */
- unsigned centroid:1;
-
- /**
- * For interface blocks, 1 if this variable uses sample interpolation (as
- * in ir_variable::sample). 0 otherwise.
- */
- unsigned sample:1;
-
- /**
- * Layout of the matrix. Uses glsl_matrix_layout values.
- */
- unsigned matrix_layout:2;
-
- /**
- * For interface blocks, 1 if this variable is a per-patch input or output
- * (as in ir_variable::patch). 0 otherwise.
- */
- unsigned patch:1;
-
- /**
- * Precision qualifier
- */
- unsigned precision:2;
-
- /**
- * Image qualifiers, applicable to buffer variables defined in shader
- * storage buffer objects (SSBOs)
- */
- unsigned image_read_only:1;
- unsigned image_write_only:1;
- unsigned image_coherent:1;
- unsigned image_volatile:1;
- unsigned image_restrict:1;
-
-#ifdef __cplusplus
- glsl_struct_field(const struct glsl_type *_type, const char *_name)
- : type(_type), name(_name), location(-1), interpolation(0), centroid(0),
- sample(0), matrix_layout(GLSL_MATRIX_LAYOUT_INHERITED), patch(0),
- precision(GLSL_PRECISION_NONE)
- {
- /* empty */
- }
-
- glsl_struct_field()
- {
- /* empty */
- }
-#endif
-};
-
-struct glsl_function_param {
- const struct glsl_type *type;
-
- bool in;
- bool out;
-};
-
-static inline unsigned int
-glsl_align(unsigned int a, unsigned int align)
-{
- return (a + align - 1) / align * align;
-}
-
-#endif /* GLSL_TYPES_H */
diff --git a/src/glsl/nir/nir.c b/src/glsl/nir/nir.c
deleted file mode 100644
index 42a53f6f3db..00000000000
--- a/src/glsl/nir/nir.c
+++ /dev/null
@@ -1,1753 +0,0 @@
-/*
- * Copyright © 2014 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- *
- * Authors:
- * Connor Abbott ([email protected])
- *
- */
-
-#include "nir.h"
-#include "nir_control_flow_private.h"
-#include <assert.h>
-
-nir_shader *
-nir_shader_create(void *mem_ctx,
- gl_shader_stage stage,
- const nir_shader_compiler_options *options)
-{
- nir_shader *shader = ralloc(mem_ctx, nir_shader);
-
- exec_list_make_empty(&shader->uniforms);
- exec_list_make_empty(&shader->inputs);
- exec_list_make_empty(&shader->outputs);
- exec_list_make_empty(&shader->shared);
-
- shader->options = options;
- memset(&shader->info, 0, sizeof(shader->info));
-
- exec_list_make_empty(&shader->functions);
- exec_list_make_empty(&shader->registers);
- exec_list_make_empty(&shader->globals);
- exec_list_make_empty(&shader->system_values);
- shader->reg_alloc = 0;
-
- shader->num_inputs = 0;
- shader->num_outputs = 0;
- shader->num_uniforms = 0;
- shader->num_shared = 0;
-
- shader->stage = stage;
-
- return shader;
-}
-
-static nir_register *
-reg_create(void *mem_ctx, struct exec_list *list)
-{
- nir_register *reg = ralloc(mem_ctx, nir_register);
-
- list_inithead(&reg->uses);
- list_inithead(&reg->defs);
- list_inithead(&reg->if_uses);
-
- reg->num_components = 0;
- reg->num_array_elems = 0;
- reg->is_packed = false;
- reg->name = NULL;
-
- exec_list_push_tail(list, &reg->node);
-
- return reg;
-}
-
-nir_register *
-nir_global_reg_create(nir_shader *shader)
-{
- nir_register *reg = reg_create(shader, &shader->registers);
- reg->index = shader->reg_alloc++;
- reg->is_global = true;
-
- return reg;
-}
-
-nir_register *
-nir_local_reg_create(nir_function_impl *impl)
-{
- nir_register *reg = reg_create(ralloc_parent(impl), &impl->registers);
- reg->index = impl->reg_alloc++;
- reg->is_global = false;
-
- return reg;
-}
-
-void
-nir_reg_remove(nir_register *reg)
-{
- exec_node_remove(&reg->node);
-}
-
-void
-nir_shader_add_variable(nir_shader *shader, nir_variable *var)
-{
- switch (var->data.mode) {
- case nir_var_all:
- assert(!"invalid mode");
- break;
-
- case nir_var_local:
- assert(!"nir_shader_add_variable cannot be used for local variables");
- break;
-
- case nir_var_global:
- exec_list_push_tail(&shader->globals, &var->node);
- break;
-
- case nir_var_shader_in:
- exec_list_push_tail(&shader->inputs, &var->node);
- break;
-
- case nir_var_shader_out:
- exec_list_push_tail(&shader->outputs, &var->node);
- break;
-
- case nir_var_uniform:
- case nir_var_shader_storage:
- exec_list_push_tail(&shader->uniforms, &var->node);
- break;
-
- case nir_var_shared:
- assert(shader->stage == MESA_SHADER_COMPUTE);
- exec_list_push_tail(&shader->shared, &var->node);
- break;
-
- case nir_var_system_value:
- exec_list_push_tail(&shader->system_values, &var->node);
- break;
- }
-}
-
-nir_variable *
-nir_variable_create(nir_shader *shader, nir_variable_mode mode,
- const struct glsl_type *type, const char *name)
-{
- nir_variable *var = rzalloc(shader, nir_variable);
- var->name = ralloc_strdup(var, name);
- var->type = type;
- var->data.mode = mode;
-
- if ((mode == nir_var_shader_in && shader->stage != MESA_SHADER_VERTEX) ||
- (mode == nir_var_shader_out && shader->stage != MESA_SHADER_FRAGMENT))
- var->data.interpolation = INTERP_QUALIFIER_SMOOTH;
-
- if (mode == nir_var_shader_in || mode == nir_var_uniform)
- var->data.read_only = true;
-
- nir_shader_add_variable(shader, var);
-
- return var;
-}
-
-nir_variable *
-nir_local_variable_create(nir_function_impl *impl,
- const struct glsl_type *type, const char *name)
-{
- nir_variable *var = rzalloc(impl->function->shader, nir_variable);
- var->name = ralloc_strdup(var, name);
- var->type = type;
- var->data.mode = nir_var_local;
-
- nir_function_impl_add_variable(impl, var);
-
- return var;
-}
-
-nir_function *
-nir_function_create(nir_shader *shader, const char *name)
-{
- nir_function *func = ralloc(shader, nir_function);
-
- exec_list_push_tail(&shader->functions, &func->node);
-
- func->name = ralloc_strdup(func, name);
- func->shader = shader;
- func->num_params = 0;
- func->params = NULL;
- func->return_type = glsl_void_type();
- func->impl = NULL;
-
- return func;
-}
-
-void nir_src_copy(nir_src *dest, const nir_src *src, void *mem_ctx)
-{
- dest->is_ssa = src->is_ssa;
- if (src->is_ssa) {
- dest->ssa = src->ssa;
- } else {
- dest->reg.base_offset = src->reg.base_offset;
- dest->reg.reg = src->reg.reg;
- if (src->reg.indirect) {
- dest->reg.indirect = ralloc(mem_ctx, nir_src);
- nir_src_copy(dest->reg.indirect, src->reg.indirect, mem_ctx);
- } else {
- dest->reg.indirect = NULL;
- }
- }
-}
-
-void nir_dest_copy(nir_dest *dest, const nir_dest *src, nir_instr *instr)
-{
- /* Copying an SSA definition makes no sense whatsoever. */
- assert(!src->is_ssa);
-
- dest->is_ssa = false;
-
- dest->reg.base_offset = src->reg.base_offset;
- dest->reg.reg = src->reg.reg;
- if (src->reg.indirect) {
- dest->reg.indirect = ralloc(instr, nir_src);
- nir_src_copy(dest->reg.indirect, src->reg.indirect, instr);
- } else {
- dest->reg.indirect = NULL;
- }
-}
-
-void
-nir_alu_src_copy(nir_alu_src *dest, const nir_alu_src *src,
- nir_alu_instr *instr)
-{
- nir_src_copy(&dest->src, &src->src, &instr->instr);
- dest->abs = src->abs;
- dest->negate = src->negate;
- for (unsigned i = 0; i < 4; i++)
- dest->swizzle[i] = src->swizzle[i];
-}
-
-void
-nir_alu_dest_copy(nir_alu_dest *dest, const nir_alu_dest *src,
- nir_alu_instr *instr)
-{
- nir_dest_copy(&dest->dest, &src->dest, &instr->instr);
- dest->write_mask = src->write_mask;
- dest->saturate = src->saturate;
-}
-
-
-static void
-cf_init(nir_cf_node *node, nir_cf_node_type type)
-{
- exec_node_init(&node->node);
- node->parent = NULL;
- node->type = type;
-}
-
-nir_function_impl *
-nir_function_impl_create_bare(nir_shader *shader)
-{
- nir_function_impl *impl = ralloc(shader, nir_function_impl);
-
- impl->function = NULL;
-
- cf_init(&impl->cf_node, nir_cf_node_function);
-
- exec_list_make_empty(&impl->body);
- exec_list_make_empty(&impl->registers);
- exec_list_make_empty(&impl->locals);
- impl->num_params = 0;
- impl->params = NULL;
- impl->return_var = NULL;
- impl->reg_alloc = 0;
- impl->ssa_alloc = 0;
- impl->valid_metadata = nir_metadata_none;
-
- /* create start & end blocks */
- nir_block *start_block = nir_block_create(shader);
- nir_block *end_block = nir_block_create(shader);
- start_block->cf_node.parent = &impl->cf_node;
- end_block->cf_node.parent = &impl->cf_node;
- impl->end_block = end_block;
-
- exec_list_push_tail(&impl->body, &start_block->cf_node.node);
-
- start_block->successors[0] = end_block;
- _mesa_set_add(end_block->predecessors, start_block);
- return impl;
-}
-
-nir_function_impl *
-nir_function_impl_create(nir_function *function)
-{
- assert(function->impl == NULL);
-
- nir_function_impl *impl = nir_function_impl_create_bare(function->shader);
-
- function->impl = impl;
- impl->function = function;
-
- impl->num_params = function->num_params;
- impl->params = ralloc_array(function->shader,
- nir_variable *, impl->num_params);
-
- return impl;
-}
-
-nir_block *
-nir_block_create(nir_shader *shader)
-{
- nir_block *block = ralloc(shader, nir_block);
-
- cf_init(&block->cf_node, nir_cf_node_block);
-
- block->successors[0] = block->successors[1] = NULL;
- block->predecessors = _mesa_set_create(block, _mesa_hash_pointer,
- _mesa_key_pointer_equal);
- block->imm_dom = NULL;
- /* XXX maybe it would be worth it to defer allocation? This
- * way it doesn't get allocated for shader ref's that never run
- * nir_calc_dominance? For example, state-tracker creates an
- * initial IR, clones that, runs appropriate lowering pass, passes
- * to driver which does common lowering/opt, and then stores ref
- * which is later used to do state specific lowering and futher
- * opt. Do any of the references not need dominance metadata?
- */
- block->dom_frontier = _mesa_set_create(block, _mesa_hash_pointer,
- _mesa_key_pointer_equal);
-
- exec_list_make_empty(&block->instr_list);
-
- return block;
-}
-
-static inline void
-src_init(nir_src *src)
-{
- src->is_ssa = false;
- src->reg.reg = NULL;
- src->reg.indirect = NULL;
- src->reg.base_offset = 0;
-}
-
-nir_if *
-nir_if_create(nir_shader *shader)
-{
- nir_if *if_stmt = ralloc(shader, nir_if);
-
- cf_init(&if_stmt->cf_node, nir_cf_node_if);
- src_init(&if_stmt->condition);
-
- nir_block *then = nir_block_create(shader);
- exec_list_make_empty(&if_stmt->then_list);
- exec_list_push_tail(&if_stmt->then_list, &then->cf_node.node);
- then->cf_node.parent = &if_stmt->cf_node;
-
- nir_block *else_stmt = nir_block_create(shader);
- exec_list_make_empty(&if_stmt->else_list);
- exec_list_push_tail(&if_stmt->else_list, &else_stmt->cf_node.node);
- else_stmt->cf_node.parent = &if_stmt->cf_node;
-
- return if_stmt;
-}
-
-nir_loop *
-nir_loop_create(nir_shader *shader)
-{
- nir_loop *loop = ralloc(shader, nir_loop);
-
- cf_init(&loop->cf_node, nir_cf_node_loop);
-
- nir_block *body = nir_block_create(shader);
- exec_list_make_empty(&loop->body);
- exec_list_push_tail(&loop->body, &body->cf_node.node);
- body->cf_node.parent = &loop->cf_node;
-
- body->successors[0] = body;
- _mesa_set_add(body->predecessors, body);
-
- return loop;
-}
-
-static void
-instr_init(nir_instr *instr, nir_instr_type type)
-{
- instr->type = type;
- instr->block = NULL;
- exec_node_init(&instr->node);
-}
-
-static void
-dest_init(nir_dest *dest)
-{
- dest->is_ssa = false;
- dest->reg.reg = NULL;
- dest->reg.indirect = NULL;
- dest->reg.base_offset = 0;
-}
-
-static void
-alu_dest_init(nir_alu_dest *dest)
-{
- dest_init(&dest->dest);
- dest->saturate = false;
- dest->write_mask = 0xf;
-}
-
-static void
-alu_src_init(nir_alu_src *src)
-{
- src_init(&src->src);
- src->abs = src->negate = false;
- src->swizzle[0] = 0;
- src->swizzle[1] = 1;
- src->swizzle[2] = 2;
- src->swizzle[3] = 3;
-}
-
-nir_alu_instr *
-nir_alu_instr_create(nir_shader *shader, nir_op op)
-{
- unsigned num_srcs = nir_op_infos[op].num_inputs;
- nir_alu_instr *instr =
- ralloc_size(shader,
- sizeof(nir_alu_instr) + num_srcs * sizeof(nir_alu_src));
-
- instr_init(&instr->instr, nir_instr_type_alu);
- instr->op = op;
- alu_dest_init(&instr->dest);
- for (unsigned i = 0; i < num_srcs; i++)
- alu_src_init(&instr->src[i]);
-
- return instr;
-}
-
-nir_jump_instr *
-nir_jump_instr_create(nir_shader *shader, nir_jump_type type)
-{
- nir_jump_instr *instr = ralloc(shader, nir_jump_instr);
- instr_init(&instr->instr, nir_instr_type_jump);
- instr->type = type;
- return instr;
-}
-
-nir_load_const_instr *
-nir_load_const_instr_create(nir_shader *shader, unsigned num_components)
-{
- nir_load_const_instr *instr = ralloc(shader, nir_load_const_instr);
- instr_init(&instr->instr, nir_instr_type_load_const);
-
- nir_ssa_def_init(&instr->instr, &instr->def, num_components, NULL);
-
- return instr;
-}
-
-nir_intrinsic_instr *
-nir_intrinsic_instr_create(nir_shader *shader, nir_intrinsic_op op)
-{
- unsigned num_srcs = nir_intrinsic_infos[op].num_srcs;
- nir_intrinsic_instr *instr =
- ralloc_size(shader,
- sizeof(nir_intrinsic_instr) + num_srcs * sizeof(nir_src));
-
- instr_init(&instr->instr, nir_instr_type_intrinsic);
- instr->intrinsic = op;
-
- if (nir_intrinsic_infos[op].has_dest)
- dest_init(&instr->dest);
-
- for (unsigned i = 0; i < num_srcs; i++)
- src_init(&instr->src[i]);
-
- return instr;
-}
-
-nir_call_instr *
-nir_call_instr_create(nir_shader *shader, nir_function *callee)
-{
- nir_call_instr *instr = ralloc(shader, nir_call_instr);
- instr_init(&instr->instr, nir_instr_type_call);
-
- instr->callee = callee;
- instr->num_params = callee->num_params;
- instr->params = ralloc_array(instr, nir_deref_var *, instr->num_params);
- instr->return_deref = NULL;
-
- return instr;
-}
-
-nir_tex_instr *
-nir_tex_instr_create(nir_shader *shader, unsigned num_srcs)
-{
- nir_tex_instr *instr = rzalloc(shader, nir_tex_instr);
- instr_init(&instr->instr, nir_instr_type_tex);
-
- dest_init(&instr->dest);
-
- instr->num_srcs = num_srcs;
- instr->src = ralloc_array(instr, nir_tex_src, num_srcs);
- for (unsigned i = 0; i < num_srcs; i++)
- src_init(&instr->src[i].src);
-
- instr->texture_index = 0;
- instr->texture_array_size = 0;
- instr->texture = NULL;
- instr->sampler_index = 0;
- instr->sampler = NULL;
-
- return instr;
-}
-
-nir_phi_instr *
-nir_phi_instr_create(nir_shader *shader)
-{
- nir_phi_instr *instr = ralloc(shader, nir_phi_instr);
- instr_init(&instr->instr, nir_instr_type_phi);
-
- dest_init(&instr->dest);
- exec_list_make_empty(&instr->srcs);
- return instr;
-}
-
-nir_parallel_copy_instr *
-nir_parallel_copy_instr_create(nir_shader *shader)
-{
- nir_parallel_copy_instr *instr = ralloc(shader, nir_parallel_copy_instr);
- instr_init(&instr->instr, nir_instr_type_parallel_copy);
-
- exec_list_make_empty(&instr->entries);
-
- return instr;
-}
-
-nir_ssa_undef_instr *
-nir_ssa_undef_instr_create(nir_shader *shader, unsigned num_components)
-{
- nir_ssa_undef_instr *instr = ralloc(shader, nir_ssa_undef_instr);
- instr_init(&instr->instr, nir_instr_type_ssa_undef);
-
- nir_ssa_def_init(&instr->instr, &instr->def, num_components, NULL);
-
- return instr;
-}
-
-nir_deref_var *
-nir_deref_var_create(void *mem_ctx, nir_variable *var)
-{
- nir_deref_var *deref = ralloc(mem_ctx, nir_deref_var);
- deref->deref.deref_type = nir_deref_type_var;
- deref->deref.child = NULL;
- deref->deref.type = var->type;
- deref->var = var;
- return deref;
-}
-
-nir_deref_array *
-nir_deref_array_create(void *mem_ctx)
-{
- nir_deref_array *deref = ralloc(mem_ctx, nir_deref_array);
- deref->deref.deref_type = nir_deref_type_array;
- deref->deref.child = NULL;
- deref->deref_array_type = nir_deref_array_type_direct;
- src_init(&deref->indirect);
- deref->base_offset = 0;
- return deref;
-}
-
-nir_deref_struct *
-nir_deref_struct_create(void *mem_ctx, unsigned field_index)
-{
- nir_deref_struct *deref = ralloc(mem_ctx, nir_deref_struct);
- deref->deref.deref_type = nir_deref_type_struct;
- deref->deref.child = NULL;
- deref->index = field_index;
- return deref;
-}
-
-static nir_deref_var *
-copy_deref_var(void *mem_ctx, nir_deref_var *deref)
-{
- nir_deref_var *ret = nir_deref_var_create(mem_ctx, deref->var);
- ret->deref.type = deref->deref.type;
- if (deref->deref.child)
- ret->deref.child = nir_copy_deref(ret, deref->deref.child);
- return ret;
-}
-
-static nir_deref_array *
-copy_deref_array(void *mem_ctx, nir_deref_array *deref)
-{
- nir_deref_array *ret = nir_deref_array_create(mem_ctx);
- ret->base_offset = deref->base_offset;
- ret->deref_array_type = deref->deref_array_type;
- if (deref->deref_array_type == nir_deref_array_type_indirect) {
- nir_src_copy(&ret->indirect, &deref->indirect, mem_ctx);
- }
- ret->deref.type = deref->deref.type;
- if (deref->deref.child)
- ret->deref.child = nir_copy_deref(ret, deref->deref.child);
- return ret;
-}
-
-static nir_deref_struct *
-copy_deref_struct(void *mem_ctx, nir_deref_struct *deref)
-{
- nir_deref_struct *ret = nir_deref_struct_create(mem_ctx, deref->index);
- ret->deref.type = deref->deref.type;
- if (deref->deref.child)
- ret->deref.child = nir_copy_deref(ret, deref->deref.child);
- return ret;
-}
-
-nir_deref *
-nir_copy_deref(void *mem_ctx, nir_deref *deref)
-{
- switch (deref->deref_type) {
- case nir_deref_type_var:
- return &copy_deref_var(mem_ctx, nir_deref_as_var(deref))->deref;
- case nir_deref_type_array:
- return &copy_deref_array(mem_ctx, nir_deref_as_array(deref))->deref;
- case nir_deref_type_struct:
- return &copy_deref_struct(mem_ctx, nir_deref_as_struct(deref))->deref;
- default:
- unreachable("Invalid dereference type");
- }
-
- return NULL;
-}
-
-/* Returns a load_const instruction that represents the constant
- * initializer for the given deref chain. The caller is responsible for
- * ensuring that there actually is a constant initializer.
- */
-nir_load_const_instr *
-nir_deref_get_const_initializer_load(nir_shader *shader, nir_deref_var *deref)
-{
- nir_constant *constant = deref->var->constant_initializer;
- assert(constant);
-
- const nir_deref *tail = &deref->deref;
- unsigned matrix_offset = 0;
- while (tail->child) {
- switch (tail->child->deref_type) {
- case nir_deref_type_array: {
- nir_deref_array *arr = nir_deref_as_array(tail->child);
- assert(arr->deref_array_type == nir_deref_array_type_direct);
- if (glsl_type_is_matrix(tail->type)) {
- assert(arr->deref.child == NULL);
- matrix_offset = arr->base_offset;
- } else {
- constant = constant->elements[arr->base_offset];
- }
- break;
- }
-
- case nir_deref_type_struct: {
- constant = constant->elements[nir_deref_as_struct(tail->child)->index];
- break;
- }
-
- default:
- unreachable("Invalid deref child type");
- }
-
- tail = tail->child;
- }
-
- nir_load_const_instr *load =
- nir_load_const_instr_create(shader, glsl_get_vector_elements(tail->type));
-
- matrix_offset *= load->def.num_components;
- for (unsigned i = 0; i < load->def.num_components; i++) {
- switch (glsl_get_base_type(tail->type)) {
- case GLSL_TYPE_FLOAT:
- case GLSL_TYPE_INT:
- case GLSL_TYPE_UINT:
- load->value.u[i] = constant->value.u[matrix_offset + i];
- break;
- case GLSL_TYPE_BOOL:
- load->value.u[i] = constant->value.b[matrix_offset + i] ?
- NIR_TRUE : NIR_FALSE;
- break;
- default:
- unreachable("Invalid immediate type");
- }
- }
-
- return load;
-}
-
-nir_function_impl *
-nir_cf_node_get_function(nir_cf_node *node)
-{
- while (node->type != nir_cf_node_function) {
- node = node->parent;
- }
-
- return nir_cf_node_as_function(node);
-}
-
-/* Reduces a cursor by trying to convert everything to after and trying to
- * go up to block granularity when possible.
- */
-static nir_cursor
-reduce_cursor(nir_cursor cursor)
-{
- switch (cursor.option) {
- case nir_cursor_before_block:
- if (exec_list_is_empty(&cursor.block->instr_list)) {
- /* Empty block. After is as good as before. */
- cursor.option = nir_cursor_after_block;
- } else {
- /* Try to switch to after the previous block if there is one.
- * (This isn't likely, but it can happen.)
- */
- nir_cf_node *prev_node = nir_cf_node_prev(&cursor.block->cf_node);
- if (prev_node && prev_node->type == nir_cf_node_block) {
- cursor.block = nir_cf_node_as_block(prev_node);
- cursor.option = nir_cursor_after_block;
- }
- }
- return cursor;
-
- case nir_cursor_after_block:
- return cursor;
-
- case nir_cursor_before_instr: {
- nir_instr *prev_instr = nir_instr_prev(cursor.instr);
- if (prev_instr) {
- /* Before this instruction is after the previous */
- cursor.instr = prev_instr;
- cursor.option = nir_cursor_after_instr;
- } else {
- /* No previous instruction. Switch to before block */
- cursor.block = cursor.instr->block;
- cursor.option = nir_cursor_before_block;
- }
- return reduce_cursor(cursor);
- }
-
- case nir_cursor_after_instr:
- if (nir_instr_next(cursor.instr) == NULL) {
- /* This is the last instruction, switch to after block */
- cursor.option = nir_cursor_after_block;
- cursor.block = cursor.instr->block;
- }
- return cursor;
-
- default:
- unreachable("Inavlid cursor option");
- }
-}
-
-bool
-nir_cursors_equal(nir_cursor a, nir_cursor b)
-{
- /* Reduced cursors should be unique */
- a = reduce_cursor(a);
- b = reduce_cursor(b);
-
- return a.block == b.block && a.option == b.option;
-}
-
-static bool
-add_use_cb(nir_src *src, void *state)
-{
- nir_instr *instr = state;
-
- src->parent_instr = instr;
- list_addtail(&src->use_link,
- src->is_ssa ? &src->ssa->uses : &src->reg.reg->uses);
-
- return true;
-}
-
-static bool
-add_ssa_def_cb(nir_ssa_def *def, void *state)
-{
- nir_instr *instr = state;
-
- if (instr->block && def->index == UINT_MAX) {
- nir_function_impl *impl =
- nir_cf_node_get_function(&instr->block->cf_node);
-
- def->index = impl->ssa_alloc++;
- }
-
- return true;
-}
-
-static bool
-add_reg_def_cb(nir_dest *dest, void *state)
-{
- nir_instr *instr = state;
-
- if (!dest->is_ssa) {
- dest->reg.parent_instr = instr;
- list_addtail(&dest->reg.def_link, &dest->reg.reg->defs);
- }
-
- return true;
-}
-
-static void
-add_defs_uses(nir_instr *instr)
-{
- nir_foreach_src(instr, add_use_cb, instr);
- nir_foreach_dest(instr, add_reg_def_cb, instr);
- nir_foreach_ssa_def(instr, add_ssa_def_cb, instr);
-}
-
-void
-nir_instr_insert(nir_cursor cursor, nir_instr *instr)
-{
- switch (cursor.option) {
- case nir_cursor_before_block:
- /* Only allow inserting jumps into empty blocks. */
- if (instr->type == nir_instr_type_jump)
- assert(exec_list_is_empty(&cursor.block->instr_list));
-
- instr->block = cursor.block;
- add_defs_uses(instr);
- exec_list_push_head(&cursor.block->instr_list, &instr->node);
- break;
- case nir_cursor_after_block: {
- /* Inserting instructions after a jump is illegal. */
- nir_instr *last = nir_block_last_instr(cursor.block);
- assert(last == NULL || last->type != nir_instr_type_jump);
- (void) last;
-
- instr->block = cursor.block;
- add_defs_uses(instr);
- exec_list_push_tail(&cursor.block->instr_list, &instr->node);
- break;
- }
- case nir_cursor_before_instr:
- assert(instr->type != nir_instr_type_jump);
- instr->block = cursor.instr->block;
- add_defs_uses(instr);
- exec_node_insert_node_before(&cursor.instr->node, &instr->node);
- break;
- case nir_cursor_after_instr:
- /* Inserting instructions after a jump is illegal. */
- assert(cursor.instr->type != nir_instr_type_jump);
-
- /* Only allow inserting jumps at the end of the block. */
- if (instr->type == nir_instr_type_jump)
- assert(cursor.instr == nir_block_last_instr(cursor.instr->block));
-
- instr->block = cursor.instr->block;
- add_defs_uses(instr);
- exec_node_insert_after(&cursor.instr->node, &instr->node);
- break;
- }
-
- if (instr->type == nir_instr_type_jump)
- nir_handle_add_jump(instr->block);
-}
-
-static bool
-src_is_valid(const nir_src *src)
-{
- return src->is_ssa ? (src->ssa != NULL) : (src->reg.reg != NULL);
-}
-
-static bool
-remove_use_cb(nir_src *src, void *state)
-{
- if (src_is_valid(src))
- list_del(&src->use_link);
-
- return true;
-}
-
-static bool
-remove_def_cb(nir_dest *dest, void *state)
-{
- if (!dest->is_ssa)
- list_del(&dest->reg.def_link);
-
- return true;
-}
-
-static void
-remove_defs_uses(nir_instr *instr)
-{
- nir_foreach_dest(instr, remove_def_cb, instr);
- nir_foreach_src(instr, remove_use_cb, instr);
-}
-
-void nir_instr_remove(nir_instr *instr)
-{
- remove_defs_uses(instr);
- exec_node_remove(&instr->node);
-
- if (instr->type == nir_instr_type_jump) {
- nir_jump_instr *jump_instr = nir_instr_as_jump(instr);
- nir_handle_remove_jump(instr->block, jump_instr->type);
- }
-}
-
-/*@}*/
-
-void
-nir_index_local_regs(nir_function_impl *impl)
-{
- unsigned index = 0;
- foreach_list_typed(nir_register, reg, node, &impl->registers) {
- reg->index = index++;
- }
- impl->reg_alloc = index;
-}
-
-void
-nir_index_global_regs(nir_shader *shader)
-{
- unsigned index = 0;
- foreach_list_typed(nir_register, reg, node, &shader->registers) {
- reg->index = index++;
- }
- shader->reg_alloc = index;
-}
-
-static bool
-visit_alu_dest(nir_alu_instr *instr, nir_foreach_dest_cb cb, void *state)
-{
- return cb(&instr->dest.dest, state);
-}
-
-static bool
-visit_intrinsic_dest(nir_intrinsic_instr *instr, nir_foreach_dest_cb cb,
- void *state)
-{
- if (nir_intrinsic_infos[instr->intrinsic].has_dest)
- return cb(&instr->dest, state);
-
- return true;
-}
-
-static bool
-visit_texture_dest(nir_tex_instr *instr, nir_foreach_dest_cb cb,
- void *state)
-{
- return cb(&instr->dest, state);
-}
-
-static bool
-visit_phi_dest(nir_phi_instr *instr, nir_foreach_dest_cb cb, void *state)
-{
- return cb(&instr->dest, state);
-}
-
-static bool
-visit_parallel_copy_dest(nir_parallel_copy_instr *instr,
- nir_foreach_dest_cb cb, void *state)
-{
- nir_foreach_parallel_copy_entry(instr, entry) {
- if (!cb(&entry->dest, state))
- return false;
- }
-
- return true;
-}
-
-bool
-nir_foreach_dest(nir_instr *instr, nir_foreach_dest_cb cb, void *state)
-{
- switch (instr->type) {
- case nir_instr_type_alu:
- return visit_alu_dest(nir_instr_as_alu(instr), cb, state);
- case nir_instr_type_intrinsic:
- return visit_intrinsic_dest(nir_instr_as_intrinsic(instr), cb, state);
- case nir_instr_type_tex:
- return visit_texture_dest(nir_instr_as_tex(instr), cb, state);
- case nir_instr_type_phi:
- return visit_phi_dest(nir_instr_as_phi(instr), cb, state);
- case nir_instr_type_parallel_copy:
- return visit_parallel_copy_dest(nir_instr_as_parallel_copy(instr),
- cb, state);
-
- case nir_instr_type_load_const:
- case nir_instr_type_ssa_undef:
- case nir_instr_type_call:
- case nir_instr_type_jump:
- break;
-
- default:
- unreachable("Invalid instruction type");
- break;
- }
-
- return true;
-}
-
-struct foreach_ssa_def_state {
- nir_foreach_ssa_def_cb cb;
- void *client_state;
-};
-
-static inline bool
-nir_ssa_def_visitor(nir_dest *dest, void *void_state)
-{
- struct foreach_ssa_def_state *state = void_state;
-
- if (dest->is_ssa)
- return state->cb(&dest->ssa, state->client_state);
- else
- return true;
-}
-
-bool
-nir_foreach_ssa_def(nir_instr *instr, nir_foreach_ssa_def_cb cb, void *state)
-{
- switch (instr->type) {
- case nir_instr_type_alu:
- case nir_instr_type_tex:
- case nir_instr_type_intrinsic:
- case nir_instr_type_phi:
- case nir_instr_type_parallel_copy: {
- struct foreach_ssa_def_state foreach_state = {cb, state};
- return nir_foreach_dest(instr, nir_ssa_def_visitor, &foreach_state);
- }
-
- case nir_instr_type_load_const:
- return cb(&nir_instr_as_load_const(instr)->def, state);
- case nir_instr_type_ssa_undef:
- return cb(&nir_instr_as_ssa_undef(instr)->def, state);
- case nir_instr_type_call:
- case nir_instr_type_jump:
- return true;
- default:
- unreachable("Invalid instruction type");
- }
-}
-
-static bool
-visit_src(nir_src *src, nir_foreach_src_cb cb, void *state)
-{
- if (!cb(src, state))
- return false;
- if (!src->is_ssa && src->reg.indirect)
- return cb(src->reg.indirect, state);
- return true;
-}
-
-static bool
-visit_deref_array_src(nir_deref_array *deref, nir_foreach_src_cb cb,
- void *state)
-{
- if (deref->deref_array_type == nir_deref_array_type_indirect)
- return visit_src(&deref->indirect, cb, state);
- return true;
-}
-
-static bool
-visit_deref_src(nir_deref_var *deref, nir_foreach_src_cb cb, void *state)
-{
- nir_deref *cur = &deref->deref;
- while (cur != NULL) {
- if (cur->deref_type == nir_deref_type_array)
- if (!visit_deref_array_src(nir_deref_as_array(cur), cb, state))
- return false;
-
- cur = cur->child;
- }
-
- return true;
-}
-
-static bool
-visit_alu_src(nir_alu_instr *instr, nir_foreach_src_cb cb, void *state)
-{
- for (unsigned i = 0; i < nir_op_infos[instr->op].num_inputs; i++)
- if (!visit_src(&instr->src[i].src, cb, state))
- return false;
-
- return true;
-}
-
-static bool
-visit_tex_src(nir_tex_instr *instr, nir_foreach_src_cb cb, void *state)
-{
- for (unsigned i = 0; i < instr->num_srcs; i++)
- if (!visit_src(&instr->src[i].src, cb, state))
- return false;
-
- if (instr->texture != NULL)
- if (!visit_deref_src(instr->texture, cb, state))
- return false;
-
- if (instr->sampler != NULL)
- if (!visit_deref_src(instr->sampler, cb, state))
- return false;
-
- return true;
-}
-
-static bool
-visit_intrinsic_src(nir_intrinsic_instr *instr, nir_foreach_src_cb cb,
- void *state)
-{
- unsigned num_srcs = nir_intrinsic_infos[instr->intrinsic].num_srcs;
- for (unsigned i = 0; i < num_srcs; i++)
- if (!visit_src(&instr->src[i], cb, state))
- return false;
-
- unsigned num_vars =
- nir_intrinsic_infos[instr->intrinsic].num_variables;
- for (unsigned i = 0; i < num_vars; i++)
- if (!visit_deref_src(instr->variables[i], cb, state))
- return false;
-
- return true;
-}
-
-static bool
-visit_call_src(nir_call_instr *instr, nir_foreach_src_cb cb, void *state)
-{
- return true;
-}
-
-static bool
-visit_load_const_src(nir_load_const_instr *instr, nir_foreach_src_cb cb,
- void *state)
-{
- return true;
-}
-
-static bool
-visit_phi_src(nir_phi_instr *instr, nir_foreach_src_cb cb, void *state)
-{
- nir_foreach_phi_src(instr, src) {
- if (!visit_src(&src->src, cb, state))
- return false;
- }
-
- return true;
-}
-
-static bool
-visit_parallel_copy_src(nir_parallel_copy_instr *instr,
- nir_foreach_src_cb cb, void *state)
-{
- nir_foreach_parallel_copy_entry(instr, entry) {
- if (!visit_src(&entry->src, cb, state))
- return false;
- }
-
- return true;
-}
-
-typedef struct {
- void *state;
- nir_foreach_src_cb cb;
-} visit_dest_indirect_state;
-
-static bool
-visit_dest_indirect(nir_dest *dest, void *_state)
-{
- visit_dest_indirect_state *state = (visit_dest_indirect_state *) _state;
-
- if (!dest->is_ssa && dest->reg.indirect)
- return state->cb(dest->reg.indirect, state->state);
-
- return true;
-}
-
-bool
-nir_foreach_src(nir_instr *instr, nir_foreach_src_cb cb, void *state)
-{
- switch (instr->type) {
- case nir_instr_type_alu:
- if (!visit_alu_src(nir_instr_as_alu(instr), cb, state))
- return false;
- break;
- case nir_instr_type_intrinsic:
- if (!visit_intrinsic_src(nir_instr_as_intrinsic(instr), cb, state))
- return false;
- break;
- case nir_instr_type_tex:
- if (!visit_tex_src(nir_instr_as_tex(instr), cb, state))
- return false;
- break;
- case nir_instr_type_call:
- if (!visit_call_src(nir_instr_as_call(instr), cb, state))
- return false;
- break;
- case nir_instr_type_load_const:
- if (!visit_load_const_src(nir_instr_as_load_const(instr), cb, state))
- return false;
- break;
- case nir_instr_type_phi:
- if (!visit_phi_src(nir_instr_as_phi(instr), cb, state))
- return false;
- break;
- case nir_instr_type_parallel_copy:
- if (!visit_parallel_copy_src(nir_instr_as_parallel_copy(instr),
- cb, state))
- return false;
- break;
- case nir_instr_type_jump:
- case nir_instr_type_ssa_undef:
- return true;
-
- default:
- unreachable("Invalid instruction type");
- break;
- }
-
- visit_dest_indirect_state dest_state;
- dest_state.state = state;
- dest_state.cb = cb;
- return nir_foreach_dest(instr, visit_dest_indirect, &dest_state);
-}
-
-nir_const_value *
-nir_src_as_const_value(nir_src src)
-{
- if (!src.is_ssa)
- return NULL;
-
- if (src.ssa->parent_instr->type != nir_instr_type_load_const)
- return NULL;
-
- nir_load_const_instr *load = nir_instr_as_load_const(src.ssa->parent_instr);
-
- return &load->value;
-}
-
-/**
- * Returns true if the source is known to be dynamically uniform. Otherwise it
- * returns false which means it may or may not be dynamically uniform but it
- * can't be determined.
- */
-bool
-nir_src_is_dynamically_uniform(nir_src src)
-{
- if (!src.is_ssa)
- return false;
-
- /* Constants are trivially dynamically uniform */
- if (src.ssa->parent_instr->type == nir_instr_type_load_const)
- return true;
-
- /* As are uniform variables */
- if (src.ssa->parent_instr->type == nir_instr_type_intrinsic) {
- nir_intrinsic_instr *intr = nir_instr_as_intrinsic(src.ssa->parent_instr);
-
- if (intr->intrinsic == nir_intrinsic_load_uniform)
- return true;
- }
-
- /* XXX: this could have many more tests, such as when a sampler function is
- * called with dynamically uniform arguments.
- */
- return false;
-}
-
-static void
-src_remove_all_uses(nir_src *src)
-{
- for (; src; src = src->is_ssa ? NULL : src->reg.indirect) {
- if (!src_is_valid(src))
- continue;
-
- list_del(&src->use_link);
- }
-}
-
-static void
-src_add_all_uses(nir_src *src, nir_instr *parent_instr, nir_if *parent_if)
-{
- for (; src; src = src->is_ssa ? NULL : src->reg.indirect) {
- if (!src_is_valid(src))
- continue;
-
- if (parent_instr) {
- src->parent_instr = parent_instr;
- if (src->is_ssa)
- list_addtail(&src->use_link, &src->ssa->uses);
- else
- list_addtail(&src->use_link, &src->reg.reg->uses);
- } else {
- assert(parent_if);
- src->parent_if = parent_if;
- if (src->is_ssa)
- list_addtail(&src->use_link, &src->ssa->if_uses);
- else
- list_addtail(&src->use_link, &src->reg.reg->if_uses);
- }
- }
-}
-
-void
-nir_instr_rewrite_src(nir_instr *instr, nir_src *src, nir_src new_src)
-{
- assert(!src_is_valid(src) || src->parent_instr == instr);
-
- src_remove_all_uses(src);
- *src = new_src;
- src_add_all_uses(src, instr, NULL);
-}
-
-void
-nir_instr_move_src(nir_instr *dest_instr, nir_src *dest, nir_src *src)
-{
- assert(!src_is_valid(dest) || dest->parent_instr == dest_instr);
-
- src_remove_all_uses(dest);
- src_remove_all_uses(src);
- *dest = *src;
- *src = NIR_SRC_INIT;
- src_add_all_uses(dest, dest_instr, NULL);
-}
-
-void
-nir_if_rewrite_condition(nir_if *if_stmt, nir_src new_src)
-{
- nir_src *src = &if_stmt->condition;
- assert(!src_is_valid(src) || src->parent_if == if_stmt);
-
- src_remove_all_uses(src);
- *src = new_src;
- src_add_all_uses(src, NULL, if_stmt);
-}
-
-void
-nir_instr_rewrite_dest(nir_instr *instr, nir_dest *dest, nir_dest new_dest)
-{
- if (dest->is_ssa) {
- /* We can only overwrite an SSA destination if it has no uses. */
- assert(list_empty(&dest->ssa.uses) && list_empty(&dest->ssa.if_uses));
- } else {
- list_del(&dest->reg.def_link);
- if (dest->reg.indirect)
- src_remove_all_uses(dest->reg.indirect);
- }
-
- /* We can't re-write with an SSA def */
- assert(!new_dest.is_ssa);
-
- nir_dest_copy(dest, &new_dest, instr);
-
- dest->reg.parent_instr = instr;
- list_addtail(&dest->reg.def_link, &new_dest.reg.reg->defs);
-
- if (dest->reg.indirect)
- src_add_all_uses(dest->reg.indirect, instr, NULL);
-}
-
-void
-nir_ssa_def_init(nir_instr *instr, nir_ssa_def *def,
- unsigned num_components, const char *name)
-{
- def->name = name;
- def->parent_instr = instr;
- list_inithead(&def->uses);
- list_inithead(&def->if_uses);
- def->num_components = num_components;
-
- if (instr->block) {
- nir_function_impl *impl =
- nir_cf_node_get_function(&instr->block->cf_node);
-
- def->index = impl->ssa_alloc++;
- } else {
- def->index = UINT_MAX;
- }
-}
-
-void
-nir_ssa_dest_init(nir_instr *instr, nir_dest *dest,
- unsigned num_components, const char *name)
-{
- dest->is_ssa = true;
- nir_ssa_def_init(instr, &dest->ssa, num_components, name);
-}
-
-void
-nir_ssa_def_rewrite_uses(nir_ssa_def *def, nir_src new_src)
-{
- assert(!new_src.is_ssa || def != new_src.ssa);
-
- nir_foreach_use_safe(def, use_src)
- nir_instr_rewrite_src(use_src->parent_instr, use_src, new_src);
-
- nir_foreach_if_use_safe(def, use_src)
- nir_if_rewrite_condition(use_src->parent_if, new_src);
-}
-
-static bool
-is_instr_between(nir_instr *start, nir_instr *end, nir_instr *between)
-{
- assert(start->block == end->block);
-
- if (between->block != start->block)
- return false;
-
- /* Search backwards looking for "between" */
- while (start != end) {
- if (between == end)
- return true;
-
- end = nir_instr_prev(end);
- assert(end);
- }
-
- return false;
-}
-
-/* Replaces all uses of the given SSA def with the given source but only if
- * the use comes after the after_me instruction. This can be useful if you
- * are emitting code to fix up the result of some instruction: you can freely
- * use the result in that code and then call rewrite_uses_after and pass the
- * last fixup instruction as after_me and it will replace all of the uses you
- * want without touching the fixup code.
- *
- * This function assumes that after_me is in the same block as
- * def->parent_instr and that after_me comes after def->parent_instr.
- */
-void
-nir_ssa_def_rewrite_uses_after(nir_ssa_def *def, nir_src new_src,
- nir_instr *after_me)
-{
- assert(!new_src.is_ssa || def != new_src.ssa);
-
- nir_foreach_use_safe(def, use_src) {
- assert(use_src->parent_instr != def->parent_instr);
- /* Since def already dominates all of its uses, the only way a use can
- * not be dominated by after_me is if it is between def and after_me in
- * the instruction list.
- */
- if (!is_instr_between(def->parent_instr, after_me, use_src->parent_instr))
- nir_instr_rewrite_src(use_src->parent_instr, use_src, new_src);
- }
-
- nir_foreach_if_use_safe(def, use_src)
- nir_if_rewrite_condition(use_src->parent_if, new_src);
-}
-
-static bool foreach_cf_node(nir_cf_node *node, nir_foreach_block_cb cb,
- bool reverse, void *state);
-
-static inline bool
-foreach_if(nir_if *if_stmt, nir_foreach_block_cb cb, bool reverse, void *state)
-{
- if (reverse) {
- foreach_list_typed_reverse_safe(nir_cf_node, node, node,
- &if_stmt->else_list) {
- if (!foreach_cf_node(node, cb, reverse, state))
- return false;
- }
-
- foreach_list_typed_reverse_safe(nir_cf_node, node, node,
- &if_stmt->then_list) {
- if (!foreach_cf_node(node, cb, reverse, state))
- return false;
- }
- } else {
- foreach_list_typed_safe(nir_cf_node, node, node, &if_stmt->then_list) {
- if (!foreach_cf_node(node, cb, reverse, state))
- return false;
- }
-
- foreach_list_typed_safe(nir_cf_node, node, node, &if_stmt->else_list) {
- if (!foreach_cf_node(node, cb, reverse, state))
- return false;
- }
- }
-
- return true;
-}
-
-static inline bool
-foreach_loop(nir_loop *loop, nir_foreach_block_cb cb, bool reverse, void *state)
-{
- if (reverse) {
- foreach_list_typed_reverse_safe(nir_cf_node, node, node, &loop->body) {
- if (!foreach_cf_node(node, cb, reverse, state))
- return false;
- }
- } else {
- foreach_list_typed_safe(nir_cf_node, node, node, &loop->body) {
- if (!foreach_cf_node(node, cb, reverse, state))
- return false;
- }
- }
-
- return true;
-}
-
-static bool
-foreach_cf_node(nir_cf_node *node, nir_foreach_block_cb cb,
- bool reverse, void *state)
-{
- switch (node->type) {
- case nir_cf_node_block:
- return cb(nir_cf_node_as_block(node), state);
- case nir_cf_node_if:
- return foreach_if(nir_cf_node_as_if(node), cb, reverse, state);
- case nir_cf_node_loop:
- return foreach_loop(nir_cf_node_as_loop(node), cb, reverse, state);
- break;
-
- default:
- unreachable("Invalid CFG node type");
- break;
- }
-
- return false;
-}
-
-bool
-nir_foreach_block_in_cf_node(nir_cf_node *node, nir_foreach_block_cb cb,
- void *state)
-{
- return foreach_cf_node(node, cb, false, state);
-}
-
-bool
-nir_foreach_block(nir_function_impl *impl, nir_foreach_block_cb cb, void *state)
-{
- foreach_list_typed_safe(nir_cf_node, node, node, &impl->body) {
- if (!foreach_cf_node(node, cb, false, state))
- return false;
- }
-
- return cb(impl->end_block, state);
-}
-
-bool
-nir_foreach_block_reverse(nir_function_impl *impl, nir_foreach_block_cb cb,
- void *state)
-{
- if (!cb(impl->end_block, state))
- return false;
-
- foreach_list_typed_reverse_safe(nir_cf_node, node, node, &impl->body) {
- if (!foreach_cf_node(node, cb, true, state))
- return false;
- }
-
- return true;
-}
-
-nir_if *
-nir_block_get_following_if(nir_block *block)
-{
- if (exec_node_is_tail_sentinel(&block->cf_node.node))
- return NULL;
-
- if (nir_cf_node_is_last(&block->cf_node))
- return NULL;
-
- nir_cf_node *next_node = nir_cf_node_next(&block->cf_node);
-
- if (next_node->type != nir_cf_node_if)
- return NULL;
-
- return nir_cf_node_as_if(next_node);
-}
-
-nir_loop *
-nir_block_get_following_loop(nir_block *block)
-{
- if (exec_node_is_tail_sentinel(&block->cf_node.node))
- return NULL;
-
- if (nir_cf_node_is_last(&block->cf_node))
- return NULL;
-
- nir_cf_node *next_node = nir_cf_node_next(&block->cf_node);
-
- if (next_node->type != nir_cf_node_loop)
- return NULL;
-
- return nir_cf_node_as_loop(next_node);
-}
-static bool
-index_block(nir_block *block, void *state)
-{
- unsigned *index = state;
- block->index = (*index)++;
- return true;
-}
-
-void
-nir_index_blocks(nir_function_impl *impl)
-{
- unsigned index = 0;
-
- if (impl->valid_metadata & nir_metadata_block_index)
- return;
-
- nir_foreach_block(impl, index_block, &index);
-
- impl->num_blocks = index;
-}
-
-static bool
-index_ssa_def_cb(nir_ssa_def *def, void *state)
-{
- unsigned *index = (unsigned *) state;
- def->index = (*index)++;
-
- return true;
-}
-
-static bool
-index_ssa_block(nir_block *block, void *state)
-{
- nir_foreach_instr(block, instr)
- nir_foreach_ssa_def(instr, index_ssa_def_cb, state);
-
- return true;
-}
-
-/**
- * The indices are applied top-to-bottom which has the very nice property
- * that, if A dominates B, then A->index <= B->index.
- */
-void
-nir_index_ssa_defs(nir_function_impl *impl)
-{
- unsigned index = 0;
- nir_foreach_block(impl, index_ssa_block, &index);
- impl->ssa_alloc = index;
-}
-
-static bool
-index_instrs_block(nir_block *block, void *state)
-{
- unsigned *index = state;
- nir_foreach_instr(block, instr)
- instr->index = (*index)++;
-
- return true;
-}
-
-/**
- * The indices are applied top-to-bottom which has the very nice property
- * that, if A dominates B, then A->index <= B->index.
- */
-unsigned
-nir_index_instrs(nir_function_impl *impl)
-{
- unsigned index = 0;
- nir_foreach_block(impl, index_instrs_block, &index);
- return index;
-}
-
-nir_intrinsic_op
-nir_intrinsic_from_system_value(gl_system_value val)
-{
- switch (val) {
- case SYSTEM_VALUE_VERTEX_ID:
- return nir_intrinsic_load_vertex_id;
- case SYSTEM_VALUE_INSTANCE_ID:
- return nir_intrinsic_load_instance_id;
- case SYSTEM_VALUE_DRAW_ID:
- return nir_intrinsic_load_draw_id;
- case SYSTEM_VALUE_BASE_INSTANCE:
- return nir_intrinsic_load_base_instance;
- case SYSTEM_VALUE_VERTEX_ID_ZERO_BASE:
- return nir_intrinsic_load_vertex_id_zero_base;
- case SYSTEM_VALUE_BASE_VERTEX:
- return nir_intrinsic_load_base_vertex;
- case SYSTEM_VALUE_INVOCATION_ID:
- return nir_intrinsic_load_invocation_id;
- case SYSTEM_VALUE_FRONT_FACE:
- return nir_intrinsic_load_front_face;
- case SYSTEM_VALUE_SAMPLE_ID:
- return nir_intrinsic_load_sample_id;
- case SYSTEM_VALUE_SAMPLE_POS:
- return nir_intrinsic_load_sample_pos;
- case SYSTEM_VALUE_SAMPLE_MASK_IN:
- return nir_intrinsic_load_sample_mask_in;
- case SYSTEM_VALUE_LOCAL_INVOCATION_ID:
- return nir_intrinsic_load_local_invocation_id;
- case SYSTEM_VALUE_WORK_GROUP_ID:
- return nir_intrinsic_load_work_group_id;
- case SYSTEM_VALUE_NUM_WORK_GROUPS:
- return nir_intrinsic_load_num_work_groups;
- case SYSTEM_VALUE_PRIMITIVE_ID:
- return nir_intrinsic_load_primitive_id;
- case SYSTEM_VALUE_TESS_COORD:
- return nir_intrinsic_load_tess_coord;
- case SYSTEM_VALUE_TESS_LEVEL_OUTER:
- return nir_intrinsic_load_tess_level_outer;
- case SYSTEM_VALUE_TESS_LEVEL_INNER:
- return nir_intrinsic_load_tess_level_inner;
- case SYSTEM_VALUE_VERTICES_IN:
- return nir_intrinsic_load_patch_vertices_in;
- case SYSTEM_VALUE_HELPER_INVOCATION:
- return nir_intrinsic_load_helper_invocation;
- default:
- unreachable("system value does not directly correspond to intrinsic");
- }
-}
-
-gl_system_value
-nir_system_value_from_intrinsic(nir_intrinsic_op intrin)
-{
- switch (intrin) {
- case nir_intrinsic_load_vertex_id:
- return SYSTEM_VALUE_VERTEX_ID;
- case nir_intrinsic_load_instance_id:
- return SYSTEM_VALUE_INSTANCE_ID;
- case nir_intrinsic_load_draw_id:
- return SYSTEM_VALUE_DRAW_ID;
- case nir_intrinsic_load_base_instance:
- return SYSTEM_VALUE_BASE_INSTANCE;
- case nir_intrinsic_load_vertex_id_zero_base:
- return SYSTEM_VALUE_VERTEX_ID_ZERO_BASE;
- case nir_intrinsic_load_base_vertex:
- return SYSTEM_VALUE_BASE_VERTEX;
- case nir_intrinsic_load_invocation_id:
- return SYSTEM_VALUE_INVOCATION_ID;
- case nir_intrinsic_load_front_face:
- return SYSTEM_VALUE_FRONT_FACE;
- case nir_intrinsic_load_sample_id:
- return SYSTEM_VALUE_SAMPLE_ID;
- case nir_intrinsic_load_sample_pos:
- return SYSTEM_VALUE_SAMPLE_POS;
- case nir_intrinsic_load_sample_mask_in:
- return SYSTEM_VALUE_SAMPLE_MASK_IN;
- case nir_intrinsic_load_local_invocation_id:
- return SYSTEM_VALUE_LOCAL_INVOCATION_ID;
- case nir_intrinsic_load_num_work_groups:
- return SYSTEM_VALUE_NUM_WORK_GROUPS;
- case nir_intrinsic_load_work_group_id:
- return SYSTEM_VALUE_WORK_GROUP_ID;
- case nir_intrinsic_load_primitive_id:
- return SYSTEM_VALUE_PRIMITIVE_ID;
- case nir_intrinsic_load_tess_coord:
- return SYSTEM_VALUE_TESS_COORD;
- case nir_intrinsic_load_tess_level_outer:
- return SYSTEM_VALUE_TESS_LEVEL_OUTER;
- case nir_intrinsic_load_tess_level_inner:
- return SYSTEM_VALUE_TESS_LEVEL_INNER;
- case nir_intrinsic_load_patch_vertices_in:
- return SYSTEM_VALUE_VERTICES_IN;
- case nir_intrinsic_load_helper_invocation:
- return SYSTEM_VALUE_HELPER_INVOCATION;
- default:
- unreachable("intrinsic doesn't produce a system value");
- }
-}
diff --git a/src/glsl/nir/nir.h b/src/glsl/nir/nir.h
deleted file mode 100644
index ec6595b091d..00000000000
--- a/src/glsl/nir/nir.h
+++ /dev/null
@@ -1,2239 +0,0 @@
-/*
- * Copyright © 2014 Connor Abbott
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- *
- * Authors:
- * Connor Abbott ([email protected])
- *
- */
-
-#pragma once
-
-#include "util/hash_table.h"
-#include "../list.h"
-#include "GL/gl.h" /* GLenum */
-#include "util/list.h"
-#include "util/ralloc.h"
-#include "util/set.h"
-#include "util/bitset.h"
-#include "nir_types.h"
-#include "shader_enums.h"
-#include <stdio.h>
-
-#include "nir_opcodes.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct gl_program;
-struct gl_shader_program;
-
-#define NIR_FALSE 0u
-#define NIR_TRUE (~0u)
-
-/** Defines a cast function
- *
- * This macro defines a cast function from in_type to out_type where
- * out_type is some structure type that contains a field of type out_type.
- *
- * Note that you have to be a bit careful as the generated cast function
- * destroys constness.
- */
-#define NIR_DEFINE_CAST(name, in_type, out_type, field) \
-static inline out_type * \
-name(const in_type *parent) \
-{ \
- return exec_node_data(out_type, parent, field); \
-}
-
-struct nir_function;
-struct nir_shader;
-struct nir_instr;
-
-
-/**
- * Description of built-in state associated with a uniform
- *
- * \sa nir_variable::state_slots
- */
-typedef struct {
- int tokens[5];
- int swizzle;
-} nir_state_slot;
-
-typedef enum {
- nir_var_all = -1,
- nir_var_shader_in,
- nir_var_shader_out,
- nir_var_global,
- nir_var_local,
- nir_var_uniform,
- nir_var_shader_storage,
- nir_var_shared,
- nir_var_system_value
-} nir_variable_mode;
-
-/**
- * Data stored in an nir_constant
- */
-union nir_constant_data {
- unsigned u[16];
- int i[16];
- float f[16];
- bool b[16];
-};
-
-typedef struct nir_constant {
- /**
- * Value of the constant.
- *
- * The field used to back the values supplied by the constant is determined
- * by the type associated with the \c nir_variable. Constants may be
- * scalars, vectors, or matrices.
- */
- union nir_constant_data value;
-
- /* we could get this from the var->type but makes clone *much* easier to
- * not have to care about the type.
- */
- unsigned num_elements;
-
- /* Array elements / Structure Fields */
- struct nir_constant **elements;
-} nir_constant;
-
-/**
- * \brief Layout qualifiers for gl_FragDepth.
- *
- * The AMD/ARB_conservative_depth extensions allow gl_FragDepth to be redeclared
- * with a layout qualifier.
- */
-typedef enum {
- nir_depth_layout_none, /**< No depth layout is specified. */
- nir_depth_layout_any,
- nir_depth_layout_greater,
- nir_depth_layout_less,
- nir_depth_layout_unchanged
-} nir_depth_layout;
-
-/**
- * Either a uniform, global variable, shader input, or shader output. Based on
- * ir_variable - it should be easy to translate between the two.
- */
-
-typedef struct nir_variable {
- struct exec_node node;
-
- /**
- * Declared type of the variable
- */
- const struct glsl_type *type;
-
- /**
- * Declared name of the variable
- */
- char *name;
-
- struct nir_variable_data {
-
- /**
- * Is the variable read-only?
- *
- * This is set for variables declared as \c const, shader inputs,
- * and uniforms.
- */
- unsigned read_only:1;
- unsigned centroid:1;
- unsigned sample:1;
- unsigned patch:1;
- unsigned invariant:1;
-
- /**
- * Storage class of the variable.
- *
- * \sa nir_variable_mode
- */
- nir_variable_mode mode:4;
-
- /**
- * Interpolation mode for shader inputs / outputs
- *
- * \sa glsl_interp_qualifier
- */
- unsigned interpolation:2;
-
- /**
- * \name ARB_fragment_coord_conventions
- * @{
- */
- unsigned origin_upper_left:1;
- unsigned pixel_center_integer:1;
- /*@}*/
-
- /**
- * Was the location explicitly set in the shader?
- *
- * If the location is explicitly set in the shader, it \b cannot be changed
- * by the linker or by the API (e.g., calls to \c glBindAttribLocation have
- * no effect).
- */
- unsigned explicit_location:1;
- unsigned explicit_index:1;
-
- /**
- * Was an initial binding explicitly set in the shader?
- *
- * If so, constant_initializer contains an integer nir_constant
- * representing the initial binding point.
- */
- unsigned explicit_binding:1;
-
- /**
- * Does this variable have an initializer?
- *
- * This is used by the linker to cross-validiate initializers of global
- * variables.
- */
- unsigned has_initializer:1;
-
- /**
- * If non-zero, then this variable may be packed along with other variables
- * into a single varying slot, so this offset should be applied when
- * accessing components. For example, an offset of 1 means that the x
- * component of this variable is actually stored in component y of the
- * location specified by \c location.
- */
- unsigned location_frac:2;
-
- /**
- * Non-zero if this variable was created by lowering a named interface
- * block which was not an array.
- *
- * Note that this variable and \c from_named_ifc_block_array will never
- * both be non-zero.
- */
- unsigned from_named_ifc_block_nonarray:1;
-
- /**
- * Non-zero if this variable was created by lowering a named interface
- * block which was an array.
- *
- * Note that this variable and \c from_named_ifc_block_nonarray will never
- * both be non-zero.
- */
- unsigned from_named_ifc_block_array:1;
-
- /**
- * \brief Layout qualifier for gl_FragDepth.
- *
- * This is not equal to \c ir_depth_layout_none if and only if this
- * variable is \c gl_FragDepth and a layout qualifier is specified.
- */
- nir_depth_layout depth_layout;
-
- /**
- * Storage location of the base of this variable
- *
- * The precise meaning of this field depends on the nature of the variable.
- *
- * - Vertex shader input: one of the values from \c gl_vert_attrib.
- * - Vertex shader output: one of the values from \c gl_varying_slot.
- * - Geometry shader input: one of the values from \c gl_varying_slot.
- * - Geometry shader output: one of the values from \c gl_varying_slot.
- * - Fragment shader input: one of the values from \c gl_varying_slot.
- * - Fragment shader output: one of the values from \c gl_frag_result.
- * - Uniforms: Per-stage uniform slot number for default uniform block.
- * - Uniforms: Index within the uniform block definition for UBO members.
- * - Non-UBO Uniforms: uniform slot number.
- * - Other: This field is not currently used.
- *
- * If the variable is a uniform, shader input, or shader output, and the
- * slot has not been assigned, the value will be -1.
- */
- int location;
-
- /**
- * The actual location of the variable in the IR. Only valid for inputs
- * and outputs.
- */
- unsigned int driver_location;
-
- /**
- * output index for dual source blending.
- */
- int index;
-
- /**
- * Descriptor set binding for sampler or UBO.
- */
- int descriptor_set;
-
- /**
- * Initial binding point for a sampler or UBO.
- *
- * For array types, this represents the binding point for the first element.
- */
- int binding;
-
- /**
- * Location an atomic counter is stored at.
- */
- unsigned offset;
-
- /**
- * ARB_shader_image_load_store qualifiers.
- */
- struct {
- bool read_only; /**< "readonly" qualifier. */
- bool write_only; /**< "writeonly" qualifier. */
- bool coherent;
- bool _volatile;
- bool restrict_flag;
-
- /** Image internal format if specified explicitly, otherwise GL_NONE. */
- GLenum format;
- } image;
-
- /**
- * Highest element accessed with a constant expression array index
- *
- * Not used for non-array variables.
- */
- unsigned max_array_access;
-
- } data;
-
- /**
- * Built-in state that backs this uniform
- *
- * Once set at variable creation, \c state_slots must remain invariant.
- * This is because, ideally, this array would be shared by all clones of
- * this variable in the IR tree. In other words, we'd really like for it
- * to be a fly-weight.
- *
- * If the variable is not a uniform, \c num_state_slots will be zero and
- * \c state_slots will be \c NULL.
- */
- /*@{*/
- unsigned num_state_slots; /**< Number of state slots used */
- nir_state_slot *state_slots; /**< State descriptors. */
- /*@}*/
-
- /**
- * Constant expression assigned in the initializer of the variable
- */
- nir_constant *constant_initializer;
-
- /**
- * For variables that are in an interface block or are an instance of an
- * interface block, this is the \c GLSL_TYPE_INTERFACE type for that block.
- *
- * \sa ir_variable::location
- */
- const struct glsl_type *interface_type;
-} nir_variable;
-
-#define nir_foreach_variable(var, var_list) \
- foreach_list_typed(nir_variable, var, node, var_list)
-
-/**
- * Returns the bits in the inputs_read, outputs_written, or
- * system_values_read bitfield corresponding to this variable.
- */
-static inline uint64_t
-nir_variable_get_io_mask(nir_variable *var, gl_shader_stage stage)
-{
- assert(var->data.mode == nir_var_shader_in ||
- var->data.mode == nir_var_shader_out ||
- var->data.mode == nir_var_system_value);
- assert(var->data.location >= 0);
-
- const struct glsl_type *var_type = var->type;
- if (stage == MESA_SHADER_GEOMETRY && var->data.mode == nir_var_shader_in) {
- /* Most geometry shader inputs are per-vertex arrays */
- if (var->data.location >= VARYING_SLOT_VAR0)
- assert(glsl_type_is_array(var_type));
-
- if (glsl_type_is_array(var_type))
- var_type = glsl_get_array_element(var_type);
- }
-
- bool is_vertex_input = (var->data.mode == nir_var_shader_in &&
- stage == MESA_SHADER_VERTEX);
- unsigned slots = glsl_count_attribute_slots(var_type, is_vertex_input);
- return ((1ull << slots) - 1) << var->data.location;
-}
-
-typedef struct nir_register {
- struct exec_node node;
-
- unsigned num_components; /** < number of vector components */
- unsigned num_array_elems; /** < size of array (0 for no array) */
-
- /** generic register index. */
- unsigned index;
-
- /** only for debug purposes, can be NULL */
- const char *name;
-
- /** whether this register is local (per-function) or global (per-shader) */
- bool is_global;
-
- /**
- * If this flag is set to true, then accessing channels >= num_components
- * is well-defined, and simply spills over to the next array element. This
- * is useful for backends that can do per-component accessing, in
- * particular scalar backends. By setting this flag and making
- * num_components equal to 1, structures can be packed tightly into
- * registers and then registers can be accessed per-component to get to
- * each structure member, even if it crosses vec4 boundaries.
- */
- bool is_packed;
-
- /** set of nir_src's where this register is used (read from) */
- struct list_head uses;
-
- /** set of nir_dest's where this register is defined (written to) */
- struct list_head defs;
-
- /** set of nir_if's where this register is used as a condition */
- struct list_head if_uses;
-} nir_register;
-
-typedef enum {
- nir_instr_type_alu,
- nir_instr_type_call,
- nir_instr_type_tex,
- nir_instr_type_intrinsic,
- nir_instr_type_load_const,
- nir_instr_type_jump,
- nir_instr_type_ssa_undef,
- nir_instr_type_phi,
- nir_instr_type_parallel_copy,
-} nir_instr_type;
-
-typedef struct nir_instr {
- struct exec_node node;
- nir_instr_type type;
- struct nir_block *block;
-
- /** generic instruction index. */
- unsigned index;
-
- /* A temporary for optimization and analysis passes to use for storing
- * flags. For instance, DCE uses this to store the "dead/live" info.
- */
- uint8_t pass_flags;
-} nir_instr;
-
-static inline nir_instr *
-nir_instr_next(nir_instr *instr)
-{
- struct exec_node *next = exec_node_get_next(&instr->node);
- if (exec_node_is_tail_sentinel(next))
- return NULL;
- else
- return exec_node_data(nir_instr, next, node);
-}
-
-static inline nir_instr *
-nir_instr_prev(nir_instr *instr)
-{
- struct exec_node *prev = exec_node_get_prev(&instr->node);
- if (exec_node_is_head_sentinel(prev))
- return NULL;
- else
- return exec_node_data(nir_instr, prev, node);
-}
-
-static inline bool
-nir_instr_is_first(nir_instr *instr)
-{
- return exec_node_is_head_sentinel(exec_node_get_prev(&instr->node));
-}
-
-static inline bool
-nir_instr_is_last(nir_instr *instr)
-{
- return exec_node_is_tail_sentinel(exec_node_get_next(&instr->node));
-}
-
-typedef struct nir_ssa_def {
- /** for debugging only, can be NULL */
- const char* name;
-
- /** generic SSA definition index. */
- unsigned index;
-
- /** Index into the live_in and live_out bitfields */
- unsigned live_index;
-
- nir_instr *parent_instr;
-
- /** set of nir_instr's where this register is used (read from) */
- struct list_head uses;
-
- /** set of nir_if's where this register is used as a condition */
- struct list_head if_uses;
-
- uint8_t num_components;
-} nir_ssa_def;
-
-struct nir_src;
-
-typedef struct {
- nir_register *reg;
- struct nir_src *indirect; /** < NULL for no indirect offset */
- unsigned base_offset;
-
- /* TODO use-def chain goes here */
-} nir_reg_src;
-
-typedef struct {
- nir_instr *parent_instr;
- struct list_head def_link;
-
- nir_register *reg;
- struct nir_src *indirect; /** < NULL for no indirect offset */
- unsigned base_offset;
-
- /* TODO def-use chain goes here */
-} nir_reg_dest;
-
-struct nir_if;
-
-typedef struct nir_src {
- union {
- nir_instr *parent_instr;
- struct nir_if *parent_if;
- };
-
- struct list_head use_link;
-
- union {
- nir_reg_src reg;
- nir_ssa_def *ssa;
- };
-
- bool is_ssa;
-} nir_src;
-
-#ifdef __cplusplus
-# define NIR_SRC_INIT nir_src()
-#else
-# define NIR_SRC_INIT (nir_src) { { NULL } }
-#endif
-
-#define nir_foreach_use(reg_or_ssa_def, src) \
- list_for_each_entry(nir_src, src, &(reg_or_ssa_def)->uses, use_link)
-
-#define nir_foreach_use_safe(reg_or_ssa_def, src) \
- list_for_each_entry_safe(nir_src, src, &(reg_or_ssa_def)->uses, use_link)
-
-#define nir_foreach_if_use(reg_or_ssa_def, src) \
- list_for_each_entry(nir_src, src, &(reg_or_ssa_def)->if_uses, use_link)
-
-#define nir_foreach_if_use_safe(reg_or_ssa_def, src) \
- list_for_each_entry_safe(nir_src, src, &(reg_or_ssa_def)->if_uses, use_link)
-
-typedef struct {
- union {
- nir_reg_dest reg;
- nir_ssa_def ssa;
- };
-
- bool is_ssa;
-} nir_dest;
-
-#ifdef __cplusplus
-# define NIR_DEST_INIT nir_dest()
-#else
-# define NIR_DEST_INIT (nir_dest) { { { NULL } } }
-#endif
-
-#define nir_foreach_def(reg, dest) \
- list_for_each_entry(nir_dest, dest, &(reg)->defs, reg.def_link)
-
-#define nir_foreach_def_safe(reg, dest) \
- list_for_each_entry_safe(nir_dest, dest, &(reg)->defs, reg.def_link)
-
-static inline nir_src
-nir_src_for_ssa(nir_ssa_def *def)
-{
- nir_src src = NIR_SRC_INIT;
-
- src.is_ssa = true;
- src.ssa = def;
-
- return src;
-}
-
-static inline nir_src
-nir_src_for_reg(nir_register *reg)
-{
- nir_src src = NIR_SRC_INIT;
-
- src.is_ssa = false;
- src.reg.reg = reg;
- src.reg.indirect = NULL;
- src.reg.base_offset = 0;
-
- return src;
-}
-
-static inline nir_dest
-nir_dest_for_reg(nir_register *reg)
-{
- nir_dest dest = NIR_DEST_INIT;
-
- dest.reg.reg = reg;
-
- return dest;
-}
-
-void nir_src_copy(nir_src *dest, const nir_src *src, void *instr_or_if);
-void nir_dest_copy(nir_dest *dest, const nir_dest *src, nir_instr *instr);
-
-typedef struct {
- nir_src src;
-
- /**
- * \name input modifiers
- */
- /*@{*/
- /**
- * For inputs interpreted as floating point, flips the sign bit. For
- * inputs interpreted as integers, performs the two's complement negation.
- */
- bool negate;
-
- /**
- * Clears the sign bit for floating point values, and computes the integer
- * absolute value for integers. Note that the negate modifier acts after
- * the absolute value modifier, therefore if both are set then all inputs
- * will become negative.
- */
- bool abs;
- /*@}*/
-
- /**
- * For each input component, says which component of the register it is
- * chosen from. Note that which elements of the swizzle are used and which
- * are ignored are based on the write mask for most opcodes - for example,
- * a statement like "foo.xzw = bar.zyx" would have a writemask of 1101b and
- * a swizzle of {2, x, 1, 0} where x means "don't care."
- */
- uint8_t swizzle[4];
-} nir_alu_src;
-
-typedef struct {
- nir_dest dest;
-
- /**
- * \name saturate output modifier
- *
- * Only valid for opcodes that output floating-point numbers. Clamps the
- * output to between 0.0 and 1.0 inclusive.
- */
-
- bool saturate;
-
- unsigned write_mask : 4; /* ignored if dest.is_ssa is true */
-} nir_alu_dest;
-
-typedef enum {
- nir_type_invalid = 0, /* Not a valid type */
- nir_type_float,
- nir_type_int,
- nir_type_uint,
- nir_type_bool
-} nir_alu_type;
-
-typedef enum {
- NIR_OP_IS_COMMUTATIVE = (1 << 0),
- NIR_OP_IS_ASSOCIATIVE = (1 << 1),
-} nir_op_algebraic_property;
-
-typedef struct {
- const char *name;
-
- unsigned num_inputs;
-
- /**
- * The number of components in the output
- *
- * If non-zero, this is the size of the output and input sizes are
- * explicitly given; swizzle and writemask are still in effect, but if
- * the output component is masked out, then the input component may
- * still be in use.
- *
- * If zero, the opcode acts in the standard, per-component manner; the
- * operation is performed on each component (except the ones that are
- * masked out) with the input being taken from the input swizzle for
- * that component.
- *
- * The size of some of the inputs may be given (i.e. non-zero) even
- * though output_size is zero; in that case, the inputs with a zero
- * size act per-component, while the inputs with non-zero size don't.
- */
- unsigned output_size;
-
- /**
- * The type of vector that the instruction outputs. Note that the
- * staurate modifier is only allowed on outputs with the float type.
- */
-
- nir_alu_type output_type;
-
- /**
- * The number of components in each input
- */
- unsigned input_sizes[4];
-
- /**
- * The type of vector that each input takes. Note that negate and
- * absolute value are only allowed on inputs with int or float type and
- * behave differently on the two.
- */
- nir_alu_type input_types[4];
-
- nir_op_algebraic_property algebraic_properties;
-} nir_op_info;
-
-extern const nir_op_info nir_op_infos[nir_num_opcodes];
-
-typedef struct nir_alu_instr {
- nir_instr instr;
- nir_op op;
- nir_alu_dest dest;
- nir_alu_src src[];
-} nir_alu_instr;
-
-void nir_alu_src_copy(nir_alu_src *dest, const nir_alu_src *src,
- nir_alu_instr *instr);
-void nir_alu_dest_copy(nir_alu_dest *dest, const nir_alu_dest *src,
- nir_alu_instr *instr);
-
-/* is this source channel used? */
-static inline bool
-nir_alu_instr_channel_used(nir_alu_instr *instr, unsigned src, unsigned channel)
-{
- if (nir_op_infos[instr->op].input_sizes[src] > 0)
- return channel < nir_op_infos[instr->op].input_sizes[src];
-
- return (instr->dest.write_mask >> channel) & 1;
-}
-
-/*
- * For instructions whose destinations are SSA, get the number of channels
- * used for a source
- */
-static inline unsigned
-nir_ssa_alu_instr_src_components(const nir_alu_instr *instr, unsigned src)
-{
- assert(instr->dest.dest.is_ssa);
-
- if (nir_op_infos[instr->op].input_sizes[src] > 0)
- return nir_op_infos[instr->op].input_sizes[src];
-
- return instr->dest.dest.ssa.num_components;
-}
-
-typedef enum {
- nir_deref_type_var,
- nir_deref_type_array,
- nir_deref_type_struct
-} nir_deref_type;
-
-typedef struct nir_deref {
- nir_deref_type deref_type;
- struct nir_deref *child;
- const struct glsl_type *type;
-} nir_deref;
-
-typedef struct {
- nir_deref deref;
-
- nir_variable *var;
-} nir_deref_var;
-
-/* This enum describes how the array is referenced. If the deref is
- * direct then the base_offset is used. If the deref is indirect then then
- * offset is given by base_offset + indirect. If the deref is a wildcard
- * then the deref refers to all of the elements of the array at the same
- * time. Wildcard dereferences are only ever allowed in copy_var
- * intrinsics and the source and destination derefs must have matching
- * wildcards.
- */
-typedef enum {
- nir_deref_array_type_direct,
- nir_deref_array_type_indirect,
- nir_deref_array_type_wildcard,
-} nir_deref_array_type;
-
-typedef struct {
- nir_deref deref;
-
- nir_deref_array_type deref_array_type;
- unsigned base_offset;
- nir_src indirect;
-} nir_deref_array;
-
-typedef struct {
- nir_deref deref;
-
- unsigned index;
-} nir_deref_struct;
-
-NIR_DEFINE_CAST(nir_deref_as_var, nir_deref, nir_deref_var, deref)
-NIR_DEFINE_CAST(nir_deref_as_array, nir_deref, nir_deref_array, deref)
-NIR_DEFINE_CAST(nir_deref_as_struct, nir_deref, nir_deref_struct, deref)
-
-/* Returns the last deref in the chain. */
-static inline nir_deref *
-nir_deref_tail(nir_deref *deref)
-{
- while (deref->child)
- deref = deref->child;
- return deref;
-}
-
-typedef struct {
- nir_instr instr;
-
- unsigned num_params;
- nir_deref_var **params;
- nir_deref_var *return_deref;
-
- struct nir_function *callee;
-} nir_call_instr;
-
-#define INTRINSIC(name, num_srcs, src_components, has_dest, dest_components, \
- num_variables, num_indices, flags) \
- nir_intrinsic_##name,
-
-#define LAST_INTRINSIC(name) nir_last_intrinsic = nir_intrinsic_##name,
-
-typedef enum {
-#include "nir_intrinsics.h"
- nir_num_intrinsics = nir_last_intrinsic + 1
-} nir_intrinsic_op;
-
-#undef INTRINSIC
-#undef LAST_INTRINSIC
-
-/** Represents an intrinsic
- *
- * An intrinsic is an instruction type for handling things that are
- * more-or-less regular operations but don't just consume and produce SSA
- * values like ALU operations do. Intrinsics are not for things that have
- * special semantic meaning such as phi nodes and parallel copies.
- * Examples of intrinsics include variable load/store operations, system
- * value loads, and the like. Even though texturing more-or-less falls
- * under this category, texturing is its own instruction type because
- * trying to represent texturing with intrinsics would lead to a
- * combinatorial explosion of intrinsic opcodes.
- *
- * By having a single instruction type for handling a lot of different
- * cases, optimization passes can look for intrinsics and, for the most
- * part, completely ignore them. Each intrinsic type also has a few
- * possible flags that govern whether or not they can be reordered or
- * eliminated. That way passes like dead code elimination can still work
- * on intrisics without understanding the meaning of each.
- *
- * Each intrinsic has some number of constant indices, some number of
- * variables, and some number of sources. What these sources, variables,
- * and indices mean depends on the intrinsic and is documented with the
- * intrinsic declaration in nir_intrinsics.h. Intrinsics and texture
- * instructions are the only types of instruction that can operate on
- * variables.
- */
-typedef struct {
- nir_instr instr;
-
- nir_intrinsic_op intrinsic;
-
- nir_dest dest;
-
- /** number of components if this is a vectorized intrinsic
- *
- * Similarly to ALU operations, some intrinsics are vectorized.
- * An intrinsic is vectorized if nir_intrinsic_infos.dest_components == 0.
- * For vectorized intrinsics, the num_components field specifies the
- * number of destination components and the number of source components
- * for all sources with nir_intrinsic_infos.src_components[i] == 0.
- */
- uint8_t num_components;
-
- int const_index[3];
-
- nir_deref_var *variables[2];
-
- nir_src src[];
-} nir_intrinsic_instr;
-
-/**
- * \name NIR intrinsics semantic flags
- *
- * information about what the compiler can do with the intrinsics.
- *
- * \sa nir_intrinsic_info::flags
- */
-typedef enum {
- /**
- * whether the intrinsic can be safely eliminated if none of its output
- * value is not being used.
- */
- NIR_INTRINSIC_CAN_ELIMINATE = (1 << 0),
-
- /**
- * Whether the intrinsic can be reordered with respect to any other
- * intrinsic, i.e. whether the only reordering dependencies of the
- * intrinsic are due to the register reads/writes.
- */
- NIR_INTRINSIC_CAN_REORDER = (1 << 1),
-} nir_intrinsic_semantic_flag;
-
-#define NIR_INTRINSIC_MAX_INPUTS 4
-
-typedef struct {
- const char *name;
-
- unsigned num_srcs; /** < number of register/SSA inputs */
-
- /** number of components of each input register
- *
- * If this value is 0, the number of components is given by the
- * num_components field of nir_intrinsic_instr.
- */
- unsigned src_components[NIR_INTRINSIC_MAX_INPUTS];
-
- bool has_dest;
-
- /** number of components of the output register
- *
- * If this value is 0, the number of components is given by the
- * num_components field of nir_intrinsic_instr.
- */
- unsigned dest_components;
-
- /** the number of inputs/outputs that are variables */
- unsigned num_variables;
-
- /** the number of constant indices used by the intrinsic */
- unsigned num_indices;
-
- /** semantic flags for calls to this intrinsic */
- nir_intrinsic_semantic_flag flags;
-} nir_intrinsic_info;
-
-extern const nir_intrinsic_info nir_intrinsic_infos[nir_num_intrinsics];
-
-/**
- * \group texture information
- *
- * This gives semantic information about textures which is useful to the
- * frontend, the backend, and lowering passes, but not the optimizer.
- */
-
-typedef enum {
- nir_tex_src_coord,
- nir_tex_src_projector,
- nir_tex_src_comparitor, /* shadow comparitor */
- nir_tex_src_offset,
- nir_tex_src_bias,
- nir_tex_src_lod,
- nir_tex_src_ms_index, /* MSAA sample index */
- nir_tex_src_ddx,
- nir_tex_src_ddy,
- nir_tex_src_texture_offset, /* < dynamically uniform indirect offset */
- nir_tex_src_sampler_offset, /* < dynamically uniform indirect offset */
- nir_num_tex_src_types
-} nir_tex_src_type;
-
-typedef struct {
- nir_src src;
- nir_tex_src_type src_type;
-} nir_tex_src;
-
-typedef enum {
- nir_texop_tex, /**< Regular texture look-up */
- nir_texop_txb, /**< Texture look-up with LOD bias */
- nir_texop_txl, /**< Texture look-up with explicit LOD */
- nir_texop_txd, /**< Texture look-up with partial derivatvies */
- nir_texop_txf, /**< Texel fetch with explicit LOD */
- nir_texop_txf_ms, /**< Multisample texture fetch */
- nir_texop_txs, /**< Texture size */
- nir_texop_lod, /**< Texture lod query */
- nir_texop_tg4, /**< Texture gather */
- nir_texop_query_levels, /**< Texture levels query */
- nir_texop_texture_samples, /**< Texture samples query */
- nir_texop_samples_identical, /**< Query whether all samples are definitely
- * identical.
- */
-} nir_texop;
-
-typedef struct {
- nir_instr instr;
-
- enum glsl_sampler_dim sampler_dim;
- nir_alu_type dest_type;
-
- nir_texop op;
- nir_dest dest;
- nir_tex_src *src;
- unsigned num_srcs, coord_components;
- bool is_array, is_shadow;
-
- /**
- * If is_shadow is true, whether this is the old-style shadow that outputs 4
- * components or the new-style shadow that outputs 1 component.
- */
- bool is_new_style_shadow;
-
- /* constant offset - must be 0 if the offset source is used */
- int const_offset[4];
-
- /* gather component selector */
- unsigned component : 2;
-
- /** The texture index
- *
- * If this texture instruction has a nir_tex_src_texture_offset source,
- * then the texture index is given by texture_index + texture_offset.
- */
- unsigned texture_index;
-
- /** The size of the texture array or 0 if it's not an array */
- unsigned texture_array_size;
-
- /** The texture deref
- *
- * If both this and `sampler` are both NULL, use texture_index instead.
- * If `texture` is NULL, but `sampler` is non-NULL, then the texture is
- * implied from the sampler.
- */
- nir_deref_var *texture;
-
- /** The sampler index
- *
- * If this texture instruction has a nir_tex_src_sampler_offset source,
- * then the sampler index is given by sampler_index + sampler_offset.
- */
- unsigned sampler_index;
-
- /** The sampler deref
- *
- * If this is null, use sampler_index instead.
- */
- nir_deref_var *sampler;
-} nir_tex_instr;
-
-static inline unsigned
-nir_tex_instr_dest_size(nir_tex_instr *instr)
-{
- switch (instr->op) {
- case nir_texop_txs: {
- unsigned ret;
- switch (instr->sampler_dim) {
- case GLSL_SAMPLER_DIM_1D:
- case GLSL_SAMPLER_DIM_BUF:
- ret = 1;
- break;
- case GLSL_SAMPLER_DIM_2D:
- case GLSL_SAMPLER_DIM_CUBE:
- case GLSL_SAMPLER_DIM_MS:
- case GLSL_SAMPLER_DIM_RECT:
- case GLSL_SAMPLER_DIM_EXTERNAL:
- ret = 2;
- break;
- case GLSL_SAMPLER_DIM_3D:
- ret = 3;
- break;
- default:
- unreachable("not reached");
- }
- if (instr->is_array)
- ret++;
- return ret;
- }
-
- case nir_texop_lod:
- return 2;
-
- case nir_texop_texture_samples:
- case nir_texop_query_levels:
- case nir_texop_samples_identical:
- return 1;
-
- default:
- if (instr->is_shadow && instr->is_new_style_shadow)
- return 1;
-
- return 4;
- }
-}
-
-/* Returns true if this texture operation queries something about the texture
- * rather than actually sampling it.
- */
-static inline bool
-nir_tex_instr_is_query(nir_tex_instr *instr)
-{
- switch (instr->op) {
- case nir_texop_txs:
- case nir_texop_lod:
- case nir_texop_texture_samples:
- case nir_texop_query_levels:
- return true;
- case nir_texop_tex:
- case nir_texop_txb:
- case nir_texop_txl:
- case nir_texop_txd:
- case nir_texop_txf:
- case nir_texop_txf_ms:
- case nir_texop_tg4:
- return false;
- default:
- unreachable("Invalid texture opcode");
- }
-}
-
-static inline unsigned
-nir_tex_instr_src_size(nir_tex_instr *instr, unsigned src)
-{
- if (instr->src[src].src_type == nir_tex_src_coord)
- return instr->coord_components;
-
-
- if (instr->src[src].src_type == nir_tex_src_offset ||
- instr->src[src].src_type == nir_tex_src_ddx ||
- instr->src[src].src_type == nir_tex_src_ddy) {
- if (instr->is_array)
- return instr->coord_components - 1;
- else
- return instr->coord_components;
- }
-
- return 1;
-}
-
-static inline int
-nir_tex_instr_src_index(nir_tex_instr *instr, nir_tex_src_type type)
-{
- for (unsigned i = 0; i < instr->num_srcs; i++)
- if (instr->src[i].src_type == type)
- return (int) i;
-
- return -1;
-}
-
-typedef struct {
- union {
- float f[4];
- int32_t i[4];
- uint32_t u[4];
- };
-} nir_const_value;
-
-typedef struct {
- nir_instr instr;
-
- nir_const_value value;
-
- nir_ssa_def def;
-} nir_load_const_instr;
-
-typedef enum {
- nir_jump_return,
- nir_jump_break,
- nir_jump_continue,
-} nir_jump_type;
-
-typedef struct {
- nir_instr instr;
- nir_jump_type type;
-} nir_jump_instr;
-
-/* creates a new SSA variable in an undefined state */
-
-typedef struct {
- nir_instr instr;
- nir_ssa_def def;
-} nir_ssa_undef_instr;
-
-typedef struct {
- struct exec_node node;
-
- /* The predecessor block corresponding to this source */
- struct nir_block *pred;
-
- nir_src src;
-} nir_phi_src;
-
-#define nir_foreach_phi_src(phi, entry) \
- foreach_list_typed(nir_phi_src, entry, node, &(phi)->srcs)
-#define nir_foreach_phi_src_safe(phi, entry) \
- foreach_list_typed_safe(nir_phi_src, entry, node, &(phi)->srcs)
-
-typedef struct {
- nir_instr instr;
-
- struct exec_list srcs; /** < list of nir_phi_src */
-
- nir_dest dest;
-} nir_phi_instr;
-
-typedef struct {
- struct exec_node node;
- nir_src src;
- nir_dest dest;
-} nir_parallel_copy_entry;
-
-#define nir_foreach_parallel_copy_entry(pcopy, entry) \
- foreach_list_typed(nir_parallel_copy_entry, entry, node, &(pcopy)->entries)
-
-typedef struct {
- nir_instr instr;
-
- /* A list of nir_parallel_copy_entry's. The sources of all of the
- * entries are copied to the corresponding destinations "in parallel".
- * In other words, if we have two entries: a -> b and b -> a, the values
- * get swapped.
- */
- struct exec_list entries;
-} nir_parallel_copy_instr;
-
-NIR_DEFINE_CAST(nir_instr_as_alu, nir_instr, nir_alu_instr, instr)
-NIR_DEFINE_CAST(nir_instr_as_call, nir_instr, nir_call_instr, instr)
-NIR_DEFINE_CAST(nir_instr_as_jump, nir_instr, nir_jump_instr, instr)
-NIR_DEFINE_CAST(nir_instr_as_tex, nir_instr, nir_tex_instr, instr)
-NIR_DEFINE_CAST(nir_instr_as_intrinsic, nir_instr, nir_intrinsic_instr, instr)
-NIR_DEFINE_CAST(nir_instr_as_load_const, nir_instr, nir_load_const_instr, instr)
-NIR_DEFINE_CAST(nir_instr_as_ssa_undef, nir_instr, nir_ssa_undef_instr, instr)
-NIR_DEFINE_CAST(nir_instr_as_phi, nir_instr, nir_phi_instr, instr)
-NIR_DEFINE_CAST(nir_instr_as_parallel_copy, nir_instr,
- nir_parallel_copy_instr, instr)
-
-/*
- * Control flow
- *
- * Control flow consists of a tree of control flow nodes, which include
- * if-statements and loops. The leaves of the tree are basic blocks, lists of
- * instructions that always run start-to-finish. Each basic block also keeps
- * track of its successors (blocks which may run immediately after the current
- * block) and predecessors (blocks which could have run immediately before the
- * current block). Each function also has a start block and an end block which
- * all return statements point to (which is always empty). Together, all the
- * blocks with their predecessors and successors make up the control flow
- * graph (CFG) of the function. There are helpers that modify the tree of
- * control flow nodes while modifying the CFG appropriately; these should be
- * used instead of modifying the tree directly.
- */
-
-typedef enum {
- nir_cf_node_block,
- nir_cf_node_if,
- nir_cf_node_loop,
- nir_cf_node_function
-} nir_cf_node_type;
-
-typedef struct nir_cf_node {
- struct exec_node node;
- nir_cf_node_type type;
- struct nir_cf_node *parent;
-} nir_cf_node;
-
-typedef struct nir_block {
- nir_cf_node cf_node;
-
- struct exec_list instr_list; /** < list of nir_instr */
-
- /** generic block index; generated by nir_index_blocks */
- unsigned index;
-
- /*
- * Each block can only have up to 2 successors, so we put them in a simple
- * array - no need for anything more complicated.
- */
- struct nir_block *successors[2];
-
- /* Set of nir_block predecessors in the CFG */
- struct set *predecessors;
-
- /*
- * this node's immediate dominator in the dominance tree - set to NULL for
- * the start block.
- */
- struct nir_block *imm_dom;
-
- /* This node's children in the dominance tree */
- unsigned num_dom_children;
- struct nir_block **dom_children;
-
- /* Set of nir_block's on the dominance frontier of this block */
- struct set *dom_frontier;
-
- /*
- * These two indices have the property that dom_{pre,post}_index for each
- * child of this block in the dominance tree will always be between
- * dom_pre_index and dom_post_index for this block, which makes testing if
- * a given block is dominated by another block an O(1) operation.
- */
- unsigned dom_pre_index, dom_post_index;
-
- /* live in and out for this block; used for liveness analysis */
- BITSET_WORD *live_in;
- BITSET_WORD *live_out;
-} nir_block;
-
-static inline nir_instr *
-nir_block_first_instr(nir_block *block)
-{
- struct exec_node *head = exec_list_get_head(&block->instr_list);
- return exec_node_data(nir_instr, head, node);
-}
-
-static inline nir_instr *
-nir_block_last_instr(nir_block *block)
-{
- struct exec_node *tail = exec_list_get_tail(&block->instr_list);
- return exec_node_data(nir_instr, tail, node);
-}
-
-#define nir_foreach_instr(block, instr) \
- foreach_list_typed(nir_instr, instr, node, &(block)->instr_list)
-#define nir_foreach_instr_reverse(block, instr) \
- foreach_list_typed_reverse(nir_instr, instr, node, &(block)->instr_list)
-#define nir_foreach_instr_safe(block, instr) \
- foreach_list_typed_safe(nir_instr, instr, node, &(block)->instr_list)
-#define nir_foreach_instr_reverse_safe(block, instr) \
- foreach_list_typed_reverse_safe(nir_instr, instr, node, &(block)->instr_list)
-
-typedef struct nir_if {
- nir_cf_node cf_node;
- nir_src condition;
-
- struct exec_list then_list; /** < list of nir_cf_node */
- struct exec_list else_list; /** < list of nir_cf_node */
-} nir_if;
-
-static inline nir_cf_node *
-nir_if_first_then_node(nir_if *if_stmt)
-{
- struct exec_node *head = exec_list_get_head(&if_stmt->then_list);
- return exec_node_data(nir_cf_node, head, node);
-}
-
-static inline nir_cf_node *
-nir_if_last_then_node(nir_if *if_stmt)
-{
- struct exec_node *tail = exec_list_get_tail(&if_stmt->then_list);
- return exec_node_data(nir_cf_node, tail, node);
-}
-
-static inline nir_cf_node *
-nir_if_first_else_node(nir_if *if_stmt)
-{
- struct exec_node *head = exec_list_get_head(&if_stmt->else_list);
- return exec_node_data(nir_cf_node, head, node);
-}
-
-static inline nir_cf_node *
-nir_if_last_else_node(nir_if *if_stmt)
-{
- struct exec_node *tail = exec_list_get_tail(&if_stmt->else_list);
- return exec_node_data(nir_cf_node, tail, node);
-}
-
-typedef struct {
- nir_cf_node cf_node;
-
- struct exec_list body; /** < list of nir_cf_node */
-} nir_loop;
-
-static inline nir_cf_node *
-nir_loop_first_cf_node(nir_loop *loop)
-{
- return exec_node_data(nir_cf_node, exec_list_get_head(&loop->body), node);
-}
-
-static inline nir_cf_node *
-nir_loop_last_cf_node(nir_loop *loop)
-{
- return exec_node_data(nir_cf_node, exec_list_get_tail(&loop->body), node);
-}
-
-/**
- * Various bits of metadata that can may be created or required by
- * optimization and analysis passes
- */
-typedef enum {
- nir_metadata_none = 0x0,
- nir_metadata_block_index = 0x1,
- nir_metadata_dominance = 0x2,
- nir_metadata_live_ssa_defs = 0x4,
- nir_metadata_not_properly_reset = 0x8,
-} nir_metadata;
-
-typedef struct {
- nir_cf_node cf_node;
-
- /** pointer to the function of which this is an implementation */
- struct nir_function *function;
-
- struct exec_list body; /** < list of nir_cf_node */
-
- nir_block *end_block;
-
- /** list for all local variables in the function */
- struct exec_list locals;
-
- /** array of variables used as parameters */
- unsigned num_params;
- nir_variable **params;
-
- /** variable used to hold the result of the function */
- nir_variable *return_var;
-
- /** list of local registers in the function */
- struct exec_list registers;
-
- /** next available local register index */
- unsigned reg_alloc;
-
- /** next available SSA value index */
- unsigned ssa_alloc;
-
- /* total number of basic blocks, only valid when block_index_dirty = false */
- unsigned num_blocks;
-
- nir_metadata valid_metadata;
-} nir_function_impl;
-
-static inline nir_block *
-nir_start_block(nir_function_impl *impl)
-{
- return (nir_block *) exec_list_get_head(&impl->body);
-}
-
-static inline nir_cf_node *
-nir_cf_node_next(nir_cf_node *node)
-{
- struct exec_node *next = exec_node_get_next(&node->node);
- if (exec_node_is_tail_sentinel(next))
- return NULL;
- else
- return exec_node_data(nir_cf_node, next, node);
-}
-
-static inline nir_cf_node *
-nir_cf_node_prev(nir_cf_node *node)
-{
- struct exec_node *prev = exec_node_get_prev(&node->node);
- if (exec_node_is_head_sentinel(prev))
- return NULL;
- else
- return exec_node_data(nir_cf_node, prev, node);
-}
-
-static inline bool
-nir_cf_node_is_first(const nir_cf_node *node)
-{
- return exec_node_is_head_sentinel(node->node.prev);
-}
-
-static inline bool
-nir_cf_node_is_last(const nir_cf_node *node)
-{
- return exec_node_is_tail_sentinel(node->node.next);
-}
-
-NIR_DEFINE_CAST(nir_cf_node_as_block, nir_cf_node, nir_block, cf_node)
-NIR_DEFINE_CAST(nir_cf_node_as_if, nir_cf_node, nir_if, cf_node)
-NIR_DEFINE_CAST(nir_cf_node_as_loop, nir_cf_node, nir_loop, cf_node)
-NIR_DEFINE_CAST(nir_cf_node_as_function, nir_cf_node, nir_function_impl, cf_node)
-
-typedef enum {
- nir_parameter_in,
- nir_parameter_out,
- nir_parameter_inout,
-} nir_parameter_type;
-
-typedef struct {
- nir_parameter_type param_type;
- const struct glsl_type *type;
-} nir_parameter;
-
-typedef struct nir_function {
- struct exec_node node;
-
- const char *name;
- struct nir_shader *shader;
-
- unsigned num_params;
- nir_parameter *params;
- const struct glsl_type *return_type;
-
- /** The implementation of this function.
- *
- * If the function is only declared and not implemented, this is NULL.
- */
- nir_function_impl *impl;
-} nir_function;
-
-typedef struct nir_shader_compiler_options {
- bool lower_fdiv;
- bool lower_ffma;
- bool lower_flrp;
- bool lower_fpow;
- bool lower_fsat;
- bool lower_fsqrt;
- bool lower_fmod;
- bool lower_bitfield_extract;
- bool lower_bitfield_insert;
- bool lower_uadd_carry;
- bool lower_usub_borrow;
- /** lowers fneg and ineg to fsub and isub. */
- bool lower_negate;
- /** lowers fsub and isub to fadd+fneg and iadd+ineg. */
- bool lower_sub;
-
- /* lower {slt,sge,seq,sne} to {flt,fge,feq,fne} + b2f: */
- bool lower_scmp;
-
- /* Does the native fdot instruction replicate its result for four
- * components? If so, then opt_algebraic_late will turn all fdotN
- * instructions into fdot_replicatedN instructions.
- */
- bool fdot_replicates;
-
- /** lowers ffract to fsub+ffloor: */
- bool lower_ffract;
-
- bool lower_pack_half_2x16;
- bool lower_pack_unorm_2x16;
- bool lower_pack_snorm_2x16;
- bool lower_pack_unorm_4x8;
- bool lower_pack_snorm_4x8;
- bool lower_unpack_half_2x16;
- bool lower_unpack_unorm_2x16;
- bool lower_unpack_snorm_2x16;
- bool lower_unpack_unorm_4x8;
- bool lower_unpack_snorm_4x8;
-
- bool lower_extract_byte;
- bool lower_extract_word;
-
- /**
- * Does the driver support real 32-bit integers? (Otherwise, integers
- * are simulated by floats.)
- */
- bool native_integers;
-
- /* Indicates that the driver only has zero-based vertex id */
- bool vertex_id_zero_based;
-} nir_shader_compiler_options;
-
-typedef struct nir_shader_info {
- const char *name;
-
- /* Descriptive name provided by the client; may be NULL */
- const char *label;
-
- /* Number of textures used by this shader */
- unsigned num_textures;
- /* Number of uniform buffers used by this shader */
- unsigned num_ubos;
- /* Number of atomic buffers used by this shader */
- unsigned num_abos;
- /* Number of shader storage buffers used by this shader */
- unsigned num_ssbos;
- /* Number of images used by this shader */
- unsigned num_images;
-
- /* Which inputs are actually read */
- uint64_t inputs_read;
- /* Which outputs are actually written */
- uint64_t outputs_written;
- /* Which system values are actually read */
- uint64_t system_values_read;
-
- /* Which patch inputs are actually read */
- uint32_t patch_inputs_read;
- /* Which patch outputs are actually written */
- uint32_t patch_outputs_written;
-
- /* Whether or not this shader ever uses textureGather() */
- bool uses_texture_gather;
-
- /* Whether or not this shader uses the gl_ClipDistance output */
- bool uses_clip_distance_out;
-
- /* Whether or not separate shader objects were used */
- bool separate_shader;
-
- /** Was this shader linked with any transform feedback varyings? */
- bool has_transform_feedback_varyings;
-
- union {
- struct {
- /** The number of vertices recieves per input primitive */
- unsigned vertices_in;
-
- /** The output primitive type (GL enum value) */
- unsigned output_primitive;
-
- /** The maximum number of vertices the geometry shader might write. */
- unsigned vertices_out;
-
- /** 1 .. MAX_GEOMETRY_SHADER_INVOCATIONS */
- unsigned invocations;
-
- /** Whether or not this shader uses EndPrimitive */
- bool uses_end_primitive;
-
- /** Whether or not this shader uses non-zero streams */
- bool uses_streams;
- } gs;
-
- struct {
- bool uses_discard;
-
- /**
- * Whether early fragment tests are enabled as defined by
- * ARB_shader_image_load_store.
- */
- bool early_fragment_tests;
-
- /** gl_FragDepth layout for ARB_conservative_depth. */
- enum gl_frag_depth_layout depth_layout;
- } fs;
-
- struct {
- unsigned local_size[3];
- } cs;
-
- struct {
- /** The number of vertices in the TCS output patch. */
- unsigned vertices_out;
- } tcs;
- };
-} nir_shader_info;
-
-typedef struct nir_shader {
- /** list of uniforms (nir_variable) */
- struct exec_list uniforms;
-
- /** list of inputs (nir_variable) */
- struct exec_list inputs;
-
- /** list of outputs (nir_variable) */
- struct exec_list outputs;
-
- /** list of shared compute variables (nir_variable) */
- struct exec_list shared;
-
- /** Set of driver-specific options for the shader.
- *
- * The memory for the options is expected to be kept in a single static
- * copy by the driver.
- */
- const struct nir_shader_compiler_options *options;
-
- /** Various bits of compile-time information about a given shader */
- struct nir_shader_info info;
-
- /** list of global variables in the shader (nir_variable) */
- struct exec_list globals;
-
- /** list of system value variables in the shader (nir_variable) */
- struct exec_list system_values;
-
- struct exec_list functions; /** < list of nir_function */
-
- /** list of global register in the shader */
- struct exec_list registers;
-
- /** next available global register index */
- unsigned reg_alloc;
-
- /**
- * the highest index a load_input_*, load_uniform_*, etc. intrinsic can
- * access plus one
- */
- unsigned num_inputs, num_uniforms, num_outputs, num_shared;
-
- /** The shader stage, such as MESA_SHADER_VERTEX. */
- gl_shader_stage stage;
-} nir_shader;
-
-#define nir_foreach_function(shader, func) \
- foreach_list_typed(nir_function, func, node, &(shader)->functions)
-
-nir_shader *nir_shader_create(void *mem_ctx,
- gl_shader_stage stage,
- const nir_shader_compiler_options *options);
-
-/** creates a register, including assigning it an index and adding it to the list */
-nir_register *nir_global_reg_create(nir_shader *shader);
-
-nir_register *nir_local_reg_create(nir_function_impl *impl);
-
-void nir_reg_remove(nir_register *reg);
-
-/** Adds a variable to the appropreate list in nir_shader */
-void nir_shader_add_variable(nir_shader *shader, nir_variable *var);
-
-static inline void
-nir_function_impl_add_variable(nir_function_impl *impl, nir_variable *var)
-{
- assert(var->data.mode == nir_var_local);
- exec_list_push_tail(&impl->locals, &var->node);
-}
-
-/** creates a variable, sets a few defaults, and adds it to the list */
-nir_variable *nir_variable_create(nir_shader *shader,
- nir_variable_mode mode,
- const struct glsl_type *type,
- const char *name);
-/** creates a local variable and adds it to the list */
-nir_variable *nir_local_variable_create(nir_function_impl *impl,
- const struct glsl_type *type,
- const char *name);
-
-/** creates a function and adds it to the shader's list of functions */
-nir_function *nir_function_create(nir_shader *shader, const char *name);
-
-nir_function_impl *nir_function_impl_create(nir_function *func);
-/** creates a function_impl that isn't tied to any particular function */
-nir_function_impl *nir_function_impl_create_bare(nir_shader *shader);
-
-nir_block *nir_block_create(nir_shader *shader);
-nir_if *nir_if_create(nir_shader *shader);
-nir_loop *nir_loop_create(nir_shader *shader);
-
-nir_function_impl *nir_cf_node_get_function(nir_cf_node *node);
-
-/** requests that the given pieces of metadata be generated */
-void nir_metadata_require(nir_function_impl *impl, nir_metadata required);
-/** dirties all but the preserved metadata */
-void nir_metadata_preserve(nir_function_impl *impl, nir_metadata preserved);
-
-/** creates an instruction with default swizzle/writemask/etc. with NULL registers */
-nir_alu_instr *nir_alu_instr_create(nir_shader *shader, nir_op op);
-
-nir_jump_instr *nir_jump_instr_create(nir_shader *shader, nir_jump_type type);
-
-nir_load_const_instr *nir_load_const_instr_create(nir_shader *shader,
- unsigned num_components);
-
-nir_intrinsic_instr *nir_intrinsic_instr_create(nir_shader *shader,
- nir_intrinsic_op op);
-
-nir_call_instr *nir_call_instr_create(nir_shader *shader,
- nir_function *callee);
-
-nir_tex_instr *nir_tex_instr_create(nir_shader *shader, unsigned num_srcs);
-
-nir_phi_instr *nir_phi_instr_create(nir_shader *shader);
-
-nir_parallel_copy_instr *nir_parallel_copy_instr_create(nir_shader *shader);
-
-nir_ssa_undef_instr *nir_ssa_undef_instr_create(nir_shader *shader,
- unsigned num_components);
-
-nir_deref_var *nir_deref_var_create(void *mem_ctx, nir_variable *var);
-nir_deref_array *nir_deref_array_create(void *mem_ctx);
-nir_deref_struct *nir_deref_struct_create(void *mem_ctx, unsigned field_index);
-
-nir_deref *nir_copy_deref(void *mem_ctx, nir_deref *deref);
-
-nir_load_const_instr *
-nir_deref_get_const_initializer_load(nir_shader *shader, nir_deref_var *deref);
-
-/**
- * NIR Cursors and Instruction Insertion API
- * @{
- *
- * A tiny struct representing a point to insert/extract instructions or
- * control flow nodes. Helps reduce the combinatorial explosion of possible
- * points to insert/extract.
- *
- * \sa nir_control_flow.h
- */
-typedef enum {
- nir_cursor_before_block,
- nir_cursor_after_block,
- nir_cursor_before_instr,
- nir_cursor_after_instr,
-} nir_cursor_option;
-
-typedef struct {
- nir_cursor_option option;
- union {
- nir_block *block;
- nir_instr *instr;
- };
-} nir_cursor;
-
-static inline nir_block *
-nir_cursor_current_block(nir_cursor cursor)
-{
- if (cursor.option == nir_cursor_before_instr ||
- cursor.option == nir_cursor_after_instr) {
- return cursor.instr->block;
- } else {
- return cursor.block;
- }
-}
-
-bool nir_cursors_equal(nir_cursor a, nir_cursor b);
-
-static inline nir_cursor
-nir_before_block(nir_block *block)
-{
- nir_cursor cursor;
- cursor.option = nir_cursor_before_block;
- cursor.block = block;
- return cursor;
-}
-
-static inline nir_cursor
-nir_after_block(nir_block *block)
-{
- nir_cursor cursor;
- cursor.option = nir_cursor_after_block;
- cursor.block = block;
- return cursor;
-}
-
-static inline nir_cursor
-nir_before_instr(nir_instr *instr)
-{
- nir_cursor cursor;
- cursor.option = nir_cursor_before_instr;
- cursor.instr = instr;
- return cursor;
-}
-
-static inline nir_cursor
-nir_after_instr(nir_instr *instr)
-{
- nir_cursor cursor;
- cursor.option = nir_cursor_after_instr;
- cursor.instr = instr;
- return cursor;
-}
-
-static inline nir_cursor
-nir_after_block_before_jump(nir_block *block)
-{
- nir_instr *last_instr = nir_block_last_instr(block);
- if (last_instr && last_instr->type == nir_instr_type_jump) {
- return nir_before_instr(last_instr);
- } else {
- return nir_after_block(block);
- }
-}
-
-static inline nir_cursor
-nir_before_cf_node(nir_cf_node *node)
-{
- if (node->type == nir_cf_node_block)
- return nir_before_block(nir_cf_node_as_block(node));
-
- return nir_after_block(nir_cf_node_as_block(nir_cf_node_prev(node)));
-}
-
-static inline nir_cursor
-nir_after_cf_node(nir_cf_node *node)
-{
- if (node->type == nir_cf_node_block)
- return nir_after_block(nir_cf_node_as_block(node));
-
- return nir_before_block(nir_cf_node_as_block(nir_cf_node_next(node)));
-}
-
-static inline nir_cursor
-nir_after_cf_node_and_phis(nir_cf_node *node)
-{
- if (node->type == nir_cf_node_block)
- return nir_after_block(nir_cf_node_as_block(node));
-
- nir_block *block = nir_cf_node_as_block(nir_cf_node_next(node));
- assert(block->cf_node.type == nir_cf_node_block);
-
- nir_foreach_instr(block, instr) {
- if (instr->type != nir_instr_type_phi)
- return nir_before_instr(instr);
- }
- return nir_after_block(block);
-}
-
-static inline nir_cursor
-nir_before_cf_list(struct exec_list *cf_list)
-{
- nir_cf_node *first_node = exec_node_data(nir_cf_node,
- exec_list_get_head(cf_list), node);
- return nir_before_cf_node(first_node);
-}
-
-static inline nir_cursor
-nir_after_cf_list(struct exec_list *cf_list)
-{
- nir_cf_node *last_node = exec_node_data(nir_cf_node,
- exec_list_get_tail(cf_list), node);
- return nir_after_cf_node(last_node);
-}
-
-/**
- * Insert a NIR instruction at the given cursor.
- *
- * Note: This does not update the cursor.
- */
-void nir_instr_insert(nir_cursor cursor, nir_instr *instr);
-
-static inline void
-nir_instr_insert_before(nir_instr *instr, nir_instr *before)
-{
- nir_instr_insert(nir_before_instr(instr), before);
-}
-
-static inline void
-nir_instr_insert_after(nir_instr *instr, nir_instr *after)
-{
- nir_instr_insert(nir_after_instr(instr), after);
-}
-
-static inline void
-nir_instr_insert_before_block(nir_block *block, nir_instr *before)
-{
- nir_instr_insert(nir_before_block(block), before);
-}
-
-static inline void
-nir_instr_insert_after_block(nir_block *block, nir_instr *after)
-{
- nir_instr_insert(nir_after_block(block), after);
-}
-
-static inline void
-nir_instr_insert_before_cf(nir_cf_node *node, nir_instr *before)
-{
- nir_instr_insert(nir_before_cf_node(node), before);
-}
-
-static inline void
-nir_instr_insert_after_cf(nir_cf_node *node, nir_instr *after)
-{
- nir_instr_insert(nir_after_cf_node(node), after);
-}
-
-static inline void
-nir_instr_insert_before_cf_list(struct exec_list *list, nir_instr *before)
-{
- nir_instr_insert(nir_before_cf_list(list), before);
-}
-
-static inline void
-nir_instr_insert_after_cf_list(struct exec_list *list, nir_instr *after)
-{
- nir_instr_insert(nir_after_cf_list(list), after);
-}
-
-void nir_instr_remove(nir_instr *instr);
-
-/** @} */
-
-typedef bool (*nir_foreach_ssa_def_cb)(nir_ssa_def *def, void *state);
-typedef bool (*nir_foreach_dest_cb)(nir_dest *dest, void *state);
-typedef bool (*nir_foreach_src_cb)(nir_src *src, void *state);
-bool nir_foreach_ssa_def(nir_instr *instr, nir_foreach_ssa_def_cb cb,
- void *state);
-bool nir_foreach_dest(nir_instr *instr, nir_foreach_dest_cb cb, void *state);
-bool nir_foreach_src(nir_instr *instr, nir_foreach_src_cb cb, void *state);
-
-nir_const_value *nir_src_as_const_value(nir_src src);
-bool nir_src_is_dynamically_uniform(nir_src src);
-bool nir_srcs_equal(nir_src src1, nir_src src2);
-void nir_instr_rewrite_src(nir_instr *instr, nir_src *src, nir_src new_src);
-void nir_instr_move_src(nir_instr *dest_instr, nir_src *dest, nir_src *src);
-void nir_if_rewrite_condition(nir_if *if_stmt, nir_src new_src);
-void nir_instr_rewrite_dest(nir_instr *instr, nir_dest *dest,
- nir_dest new_dest);
-
-void nir_ssa_dest_init(nir_instr *instr, nir_dest *dest,
- unsigned num_components, const char *name);
-void nir_ssa_def_init(nir_instr *instr, nir_ssa_def *def,
- unsigned num_components, const char *name);
-void nir_ssa_def_rewrite_uses(nir_ssa_def *def, nir_src new_src);
-void nir_ssa_def_rewrite_uses_after(nir_ssa_def *def, nir_src new_src,
- nir_instr *after_me);
-
-/* visits basic blocks in source-code order */
-typedef bool (*nir_foreach_block_cb)(nir_block *block, void *state);
-bool nir_foreach_block(nir_function_impl *impl, nir_foreach_block_cb cb,
- void *state);
-bool nir_foreach_block_reverse(nir_function_impl *impl, nir_foreach_block_cb cb,
- void *state);
-bool nir_foreach_block_in_cf_node(nir_cf_node *node, nir_foreach_block_cb cb,
- void *state);
-
-/* If the following CF node is an if, this function returns that if.
- * Otherwise, it returns NULL.
- */
-nir_if *nir_block_get_following_if(nir_block *block);
-
-nir_loop *nir_block_get_following_loop(nir_block *block);
-
-void nir_index_local_regs(nir_function_impl *impl);
-void nir_index_global_regs(nir_shader *shader);
-void nir_index_ssa_defs(nir_function_impl *impl);
-unsigned nir_index_instrs(nir_function_impl *impl);
-
-void nir_index_blocks(nir_function_impl *impl);
-
-void nir_print_shader(nir_shader *shader, FILE *fp);
-void nir_print_instr(const nir_instr *instr, FILE *fp);
-
-nir_shader *nir_shader_clone(void *mem_ctx, const nir_shader *s);
-nir_function_impl *nir_function_impl_clone(const nir_function_impl *impl);
-nir_constant *nir_constant_clone(const nir_constant *c, nir_variable *var);
-
-#ifdef DEBUG
-void nir_validate_shader(nir_shader *shader);
-void nir_metadata_set_validation_flag(nir_shader *shader);
-void nir_metadata_check_validation_flag(nir_shader *shader);
-
-#include "util/debug.h"
-static inline bool
-should_clone_nir(void)
-{
- static int should_clone = -1;
- if (should_clone < 0)
- should_clone = env_var_as_boolean("NIR_TEST_CLONE", false);
-
- return should_clone;
-}
-#else
-static inline void nir_validate_shader(nir_shader *shader) { (void) shader; }
-static inline void nir_metadata_set_validation_flag(nir_shader *shader) { (void) shader; }
-static inline void nir_metadata_check_validation_flag(nir_shader *shader) { (void) shader; }
-static inline bool should_clone_nir(void) { return false; }
-#endif /* DEBUG */
-
-#define _PASS(nir, do_pass) do { \
- do_pass \
- nir_validate_shader(nir); \
- if (should_clone_nir()) { \
- nir_shader *clone = nir_shader_clone(ralloc_parent(nir), nir); \
- ralloc_free(nir); \
- nir = clone; \
- } \
-} while (0)
-
-#define NIR_PASS(progress, nir, pass, ...) _PASS(nir, \
- nir_metadata_set_validation_flag(nir); \
- if (pass(nir, ##__VA_ARGS__)) { \
- progress = true; \
- nir_metadata_check_validation_flag(nir); \
- } \
-)
-
-#define NIR_PASS_V(nir, pass, ...) _PASS(nir, \
- pass(nir, ##__VA_ARGS__); \
-)
-
-void nir_calc_dominance_impl(nir_function_impl *impl);
-void nir_calc_dominance(nir_shader *shader);
-
-nir_block *nir_dominance_lca(nir_block *b1, nir_block *b2);
-bool nir_block_dominates(nir_block *parent, nir_block *child);
-
-void nir_dump_dom_tree_impl(nir_function_impl *impl, FILE *fp);
-void nir_dump_dom_tree(nir_shader *shader, FILE *fp);
-
-void nir_dump_dom_frontier_impl(nir_function_impl *impl, FILE *fp);
-void nir_dump_dom_frontier(nir_shader *shader, FILE *fp);
-
-void nir_dump_cfg_impl(nir_function_impl *impl, FILE *fp);
-void nir_dump_cfg(nir_shader *shader, FILE *fp);
-
-int nir_gs_count_vertices(const nir_shader *shader);
-
-bool nir_split_var_copies(nir_shader *shader);
-
-bool nir_lower_returns_impl(nir_function_impl *impl);
-bool nir_lower_returns(nir_shader *shader);
-
-bool nir_inline_functions(nir_shader *shader);
-
-void nir_lower_var_copy_instr(nir_intrinsic_instr *copy, void *mem_ctx);
-void nir_lower_var_copies(nir_shader *shader);
-
-bool nir_lower_global_vars_to_local(nir_shader *shader);
-
-bool nir_lower_indirect_derefs(nir_shader *shader, uint32_t mode_mask);
-
-bool nir_lower_locals_to_regs(nir_shader *shader);
-
-void nir_lower_outputs_to_temporaries(nir_shader *shader,
- nir_function *entrypoint);
-
-void nir_shader_gather_info(nir_shader *shader, nir_function_impl *entrypoint);
-
-void nir_assign_var_locations(struct exec_list *var_list,
- unsigned *size,
- int (*type_size)(const struct glsl_type *));
-
-void nir_lower_io(nir_shader *shader,
- nir_variable_mode mode,
- int (*type_size)(const struct glsl_type *));
-nir_src *nir_get_io_offset_src(nir_intrinsic_instr *instr);
-nir_src *nir_get_io_vertex_index_src(nir_intrinsic_instr *instr);
-
-void nir_lower_vars_to_ssa(nir_shader *shader);
-
-bool nir_remove_dead_variables(nir_shader *shader, nir_variable_mode mode);
-
-void nir_move_vec_src_uses_to_dest(nir_shader *shader);
-bool nir_lower_vec_to_movs(nir_shader *shader);
-void nir_lower_alu_to_scalar(nir_shader *shader);
-void nir_lower_load_const_to_scalar(nir_shader *shader);
-
-void nir_lower_phis_to_scalar(nir_shader *shader);
-
-void nir_lower_samplers(nir_shader *shader,
- const struct gl_shader_program *shader_program);
-
-bool nir_lower_system_values(nir_shader *shader);
-
-typedef struct nir_lower_tex_options {
- /**
- * bitmask of (1 << GLSL_SAMPLER_DIM_x) to control for which
- * sampler types a texture projector is lowered.
- */
- unsigned lower_txp;
-
- /**
- * If true, lower rect textures to 2D, using txs to fetch the
- * texture dimensions and dividing the texture coords by the
- * texture dims to normalize.
- */
- bool lower_rect;
-
- /**
- * To emulate certain texture wrap modes, this can be used
- * to saturate the specified tex coord to [0.0, 1.0]. The
- * bits are according to sampler #, ie. if, for example:
- *
- * (conf->saturate_s & (1 << n))
- *
- * is true, then the s coord for sampler n is saturated.
- *
- * Note that clamping must happen *after* projector lowering
- * so any projected texture sample instruction with a clamped
- * coordinate gets automatically lowered, regardless of the
- * 'lower_txp' setting.
- */
- unsigned saturate_s;
- unsigned saturate_t;
- unsigned saturate_r;
-
- /* Bitmask of samplers that need swizzling.
- *
- * If (swizzle_result & (1 << sampler_index)), then the swizzle in
- * swizzles[sampler_index] is applied to the result of the texturing
- * operation.
- */
- unsigned swizzle_result;
-
- /* A swizzle for each sampler. Values 0-3 represent x, y, z, or w swizzles
- * while 4 and 5 represent 0 and 1 respectively.
- */
- uint8_t swizzles[32][4];
-} nir_lower_tex_options;
-
-bool nir_lower_tex(nir_shader *shader,
- const nir_lower_tex_options *options);
-
-void nir_lower_idiv(nir_shader *shader);
-
-void nir_lower_clip_vs(nir_shader *shader, unsigned ucp_enables);
-void nir_lower_clip_fs(nir_shader *shader, unsigned ucp_enables);
-
-void nir_lower_two_sided_color(nir_shader *shader);
-
-void nir_lower_atomics(nir_shader *shader,
- const struct gl_shader_program *shader_program);
-void nir_lower_to_source_mods(nir_shader *shader);
-
-bool nir_lower_gs_intrinsics(nir_shader *shader);
-
-bool nir_normalize_cubemap_coords(nir_shader *shader);
-
-void nir_live_ssa_defs_impl(nir_function_impl *impl);
-bool nir_ssa_defs_interfere(nir_ssa_def *a, nir_ssa_def *b);
-
-void nir_convert_to_ssa_impl(nir_function_impl *impl);
-void nir_convert_to_ssa(nir_shader *shader);
-
-bool nir_repair_ssa_impl(nir_function_impl *impl);
-bool nir_repair_ssa(nir_shader *shader);
-
-/* If phi_webs_only is true, only convert SSA values involved in phi nodes to
- * registers. If false, convert all values (even those not involved in a phi
- * node) to registers.
- */
-void nir_convert_from_ssa(nir_shader *shader, bool phi_webs_only);
-
-bool nir_opt_algebraic(nir_shader *shader);
-bool nir_opt_algebraic_late(nir_shader *shader);
-bool nir_opt_constant_folding(nir_shader *shader);
-
-bool nir_opt_global_to_local(nir_shader *shader);
-
-bool nir_copy_prop(nir_shader *shader);
-
-bool nir_opt_cse(nir_shader *shader);
-
-bool nir_opt_dce(nir_shader *shader);
-
-bool nir_opt_dead_cf(nir_shader *shader);
-
-void nir_opt_gcm(nir_shader *shader);
-
-bool nir_opt_peephole_select(nir_shader *shader);
-
-bool nir_opt_remove_phis(nir_shader *shader);
-
-bool nir_opt_undef(nir_shader *shader);
-
-void nir_sweep(nir_shader *shader);
-
-nir_intrinsic_op nir_intrinsic_from_system_value(gl_system_value val);
-gl_system_value nir_system_value_from_intrinsic(nir_intrinsic_op intrin);
-
-#ifdef __cplusplus
-} /* extern "C" */
-#endif
diff --git a/src/glsl/nir/nir_algebraic.py b/src/glsl/nir/nir_algebraic.py
deleted file mode 100644
index 14c0e822ad8..00000000000
--- a/src/glsl/nir/nir_algebraic.py
+++ /dev/null
@@ -1,305 +0,0 @@
-#! /usr/bin/env python
-#
-# Copyright (C) 2014 Intel Corporation
-#
-# Permission is hereby granted, free of charge, to any person obtaining a
-# copy of this software and associated documentation files (the "Software"),
-# to deal in the Software without restriction, including without limitation
-# the rights to use, copy, modify, merge, publish, distribute, sublicense,
-# and/or sell copies of the Software, and to permit persons to whom the
-# Software is furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice (including the next
-# paragraph) shall be included in all copies or substantial portions of the
-# Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-# IN THE SOFTWARE.
-#
-# Authors:
-# Jason Ekstrand ([email protected])
-
-import itertools
-import struct
-import sys
-import mako.template
-import re
-
-# Represents a set of variables, each with a unique id
-class VarSet(object):
- def __init__(self):
- self.names = {}
- self.ids = itertools.count()
- self.immutable = False;
-
- def __getitem__(self, name):
- if name not in self.names:
- assert not self.immutable, "Unknown replacement variable: " + name
- self.names[name] = self.ids.next()
-
- return self.names[name]
-
- def lock(self):
- self.immutable = True
-
-class Value(object):
- @staticmethod
- def create(val, name_base, varset):
- if isinstance(val, tuple):
- return Expression(val, name_base, varset)
- elif isinstance(val, Expression):
- return val
- elif isinstance(val, (str, unicode)):
- return Variable(val, name_base, varset)
- elif isinstance(val, (bool, int, long, float)):
- return Constant(val, name_base)
-
- __template = mako.template.Template("""
-static const ${val.c_type} ${val.name} = {
- { ${val.type_enum} },
-% if isinstance(val, Constant):
- { ${hex(val)} /* ${val.value} */ },
-% elif isinstance(val, Variable):
- ${val.index}, /* ${val.var_name} */
- ${'true' if val.is_constant else 'false'},
- nir_type_${ val.required_type or 'invalid' },
-% elif isinstance(val, Expression):
- nir_op_${val.opcode},
- { ${', '.join(src.c_ptr for src in val.sources)} },
-% endif
-};""")
-
- def __init__(self, name, type_str):
- self.name = name
- self.type_str = type_str
-
- @property
- def type_enum(self):
- return "nir_search_value_" + self.type_str
-
- @property
- def c_type(self):
- return "nir_search_" + self.type_str
-
- @property
- def c_ptr(self):
- return "&{0}.value".format(self.name)
-
- def render(self):
- return self.__template.render(val=self,
- Constant=Constant,
- Variable=Variable,
- Expression=Expression)
-
-class Constant(Value):
- def __init__(self, val, name):
- Value.__init__(self, name, "constant")
- self.value = val
-
- def __hex__(self):
- # Even if it's an integer, we still need to unpack as an unsigned
- # int. This is because, without C99, we can only assign to the first
- # element of a union in an initializer.
- if isinstance(self.value, (bool)):
- return 'NIR_TRUE' if self.value else 'NIR_FALSE'
- if isinstance(self.value, (int, long)):
- return hex(struct.unpack('I', struct.pack('i' if self.value < 0 else 'I', self.value))[0])
- elif isinstance(self.value, float):
- return hex(struct.unpack('I', struct.pack('f', self.value))[0])
- else:
- assert False
-
-_var_name_re = re.compile(r"(?P<const>#)?(?P<name>\w+)(?:@(?P<type>\w+))?")
-
-class Variable(Value):
- def __init__(self, val, name, varset):
- Value.__init__(self, name, "variable")
-
- m = _var_name_re.match(val)
- assert m and m.group('name') is not None
-
- self.var_name = m.group('name')
- self.is_constant = m.group('const') is not None
- self.required_type = m.group('type')
-
- if self.required_type is not None:
- assert self.required_type in ('float', 'bool', 'int', 'unsigned')
-
- self.index = varset[self.var_name]
-
-class Expression(Value):
- def __init__(self, expr, name_base, varset):
- Value.__init__(self, name_base, "expression")
- assert isinstance(expr, tuple)
-
- self.opcode = expr[0]
- self.sources = [ Value.create(src, "{0}_{1}".format(name_base, i), varset)
- for (i, src) in enumerate(expr[1:]) ]
-
- def render(self):
- srcs = "\n".join(src.render() for src in self.sources)
- return srcs + super(Expression, self).render()
-
-_optimization_ids = itertools.count()
-
-condition_list = ['true']
-
-class SearchAndReplace(object):
- def __init__(self, transform):
- self.id = _optimization_ids.next()
-
- search = transform[0]
- replace = transform[1]
- if len(transform) > 2:
- self.condition = transform[2]
- else:
- self.condition = 'true'
-
- if self.condition not in condition_list:
- condition_list.append(self.condition)
- self.condition_index = condition_list.index(self.condition)
-
- varset = VarSet()
- if isinstance(search, Expression):
- self.search = search
- else:
- self.search = Expression(search, "search{0}".format(self.id), varset)
-
- varset.lock()
-
- if isinstance(replace, Value):
- self.replace = replace
- else:
- self.replace = Value.create(replace, "replace{0}".format(self.id), varset)
-
-_algebraic_pass_template = mako.template.Template("""
-#include "nir.h"
-#include "nir_search.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;
-};
-
-struct opt_state {
- void *mem_ctx;
- bool progress;
- const bool *condition_flags;
-};
-
-#endif
-
-% for (opcode, xform_list) in xform_dict.iteritems():
-% for xform in xform_list:
- ${xform.search.render()}
- ${xform.replace.render()}
-% endfor
-
-static const struct transform ${pass_name}_${opcode}_xforms[] = {
-% for xform in xform_list:
- { &${xform.search.name}, ${xform.replace.c_ptr}, ${xform.condition_index} },
-% endfor
-};
-% endfor
-
-static bool
-${pass_name}_block(nir_block *block, void *void_state)
-{
- struct opt_state *state = void_state;
-
- nir_foreach_instr_safe(block, instr) {
- 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) {
- % for opcode in xform_dict.keys():
- case nir_op_${opcode}:
- for (unsigned i = 0; i < ARRAY_SIZE(${pass_name}_${opcode}_xforms); i++) {
- const struct transform *xform = &${pass_name}_${opcode}_xforms[i];
- if (state->condition_flags[xform->condition_offset] &&
- nir_replace_instr(alu, xform->search, xform->replace,
- state->mem_ctx)) {
- state->progress = true;
- break;
- }
- }
- break;
- % endfor
- default:
- break;
- }
- }
-
- return true;
-}
-
-static bool
-${pass_name}_impl(nir_function_impl *impl, const bool *condition_flags)
-{
- struct opt_state state;
-
- state.mem_ctx = ralloc_parent(impl);
- state.progress = false;
- state.condition_flags = condition_flags;
-
- nir_foreach_block(impl, ${pass_name}_block, &state);
-
- if (state.progress)
- nir_metadata_preserve(impl, nir_metadata_block_index |
- nir_metadata_dominance);
-
- return state.progress;
-}
-
-
-bool
-${pass_name}(nir_shader *shader)
-{
- bool progress = false;
- bool condition_flags[${len(condition_list)}];
- const nir_shader_compiler_options *options = shader->options;
-
- % for index, condition in enumerate(condition_list):
- condition_flags[${index}] = ${condition};
- % endfor
-
- nir_foreach_function(shader, function) {
- if (function->impl)
- progress |= ${pass_name}_impl(function->impl, condition_flags);
- }
-
- return progress;
-}
-""")
-
-class AlgebraicPass(object):
- def __init__(self, pass_name, transforms):
- self.xform_dict = {}
- self.pass_name = pass_name
-
- for xform in transforms:
- if not isinstance(xform, SearchAndReplace):
- xform = SearchAndReplace(xform)
-
- if xform.search.opcode not in self.xform_dict:
- self.xform_dict[xform.search.opcode] = []
-
- self.xform_dict[xform.search.opcode].append(xform)
-
- def render(self):
- return _algebraic_pass_template.render(pass_name=self.pass_name,
- xform_dict=self.xform_dict,
- condition_list=condition_list)
diff --git a/src/glsl/nir/nir_array.h b/src/glsl/nir/nir_array.h
deleted file mode 100644
index 1db4e8cea36..00000000000
--- a/src/glsl/nir/nir_array.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright © 2015 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- *
- * Authors:
- * Jason Ekstrand ([email protected])
- *
- */
-
-#pragma once
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef struct {
- void *mem_ctx;
- size_t size;
- size_t alloc;
- void *data;
-} nir_array;
-
-static inline void
-nir_array_init(nir_array *arr, void *mem_ctx)
-{
- arr->mem_ctx = mem_ctx;
- arr->size = 0;
- arr->alloc = 0;
- arr->data = NULL;
-}
-
-static inline void
-nir_array_fini(nir_array *arr)
-{
- if (arr->mem_ctx)
- ralloc_free(arr->data);
- else
- free(arr->data);
-}
-
-#define NIR_ARRAY_INITIAL_SIZE 64
-
-/* Increments the size of the array by the given ammount and returns a
- * pointer to the beginning of the newly added space.
- */
-static inline void *
-nir_array_grow(nir_array *arr, size_t additional)
-{
- size_t new_size = arr->size + additional;
- if (new_size > arr->alloc) {
- if (arr->alloc == 0)
- arr->alloc = NIR_ARRAY_INITIAL_SIZE;
-
- while (new_size > arr->alloc)
- arr->alloc *= 2;
-
- if (arr->mem_ctx)
- arr->data = reralloc_size(arr->mem_ctx, arr->data, arr->alloc);
- else
- arr->data = realloc(arr->data, arr->alloc);
- }
-
- void *ptr = (void *)((char *)arr->data + arr->size);
- arr->size = new_size;
-
- return ptr;
-}
-
-#define nir_array_add(arr, type, elem) \
- *(type *)nir_array_grow(arr, sizeof(type)) = (elem)
-
-#define nir_array_foreach(arr, type, elem) \
- for (type *elem = (type *)(arr)->data; \
- elem < (type *)((char *)(arr)->data + (arr)->size); elem++)
-
-#ifdef __cplusplus
-} /* extern "C" */
-#endif
diff --git a/src/glsl/nir/nir_builder.h b/src/glsl/nir/nir_builder.h
deleted file mode 100644
index 1c7c78acae8..00000000000
--- a/src/glsl/nir/nir_builder.h
+++ /dev/null
@@ -1,441 +0,0 @@
-/*
- * Copyright © 2014-2015 Broadcom
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#ifndef NIR_BUILDER_H
-#define NIR_BUILDER_H
-
-#include "nir_control_flow.h"
-
-struct exec_list;
-
-typedef struct nir_builder {
- nir_cursor cursor;
-
- nir_shader *shader;
- nir_function_impl *impl;
-} nir_builder;
-
-static inline void
-nir_builder_init(nir_builder *build, nir_function_impl *impl)
-{
- memset(build, 0, sizeof(*build));
- build->impl = impl;
- build->shader = impl->function->shader;
-}
-
-static inline void
-nir_builder_init_simple_shader(nir_builder *build, void *mem_ctx,
- gl_shader_stage stage,
- const nir_shader_compiler_options *options)
-{
- build->shader = nir_shader_create(mem_ctx, stage, options);
- nir_function *func = nir_function_create(build->shader, "main");
- build->impl = nir_function_impl_create(func);
- build->cursor = nir_after_cf_list(&build->impl->body);
-}
-
-static inline void
-nir_builder_instr_insert(nir_builder *build, nir_instr *instr)
-{
- nir_instr_insert(build->cursor, instr);
-
- /* Move the cursor forward. */
- build->cursor = nir_after_instr(instr);
-}
-
-static inline void
-nir_builder_cf_insert(nir_builder *build, nir_cf_node *cf)
-{
- nir_cf_node_insert(build->cursor, cf);
-}
-
-static inline nir_ssa_def *
-nir_ssa_undef(nir_builder *build, unsigned num_components)
-{
- nir_ssa_undef_instr *undef =
- nir_ssa_undef_instr_create(build->shader, num_components);
- if (!undef)
- return NULL;
-
- nir_instr_insert(nir_before_block(nir_start_block(build->impl)),
- &undef->instr);
-
- return &undef->def;
-}
-
-static inline nir_ssa_def *
-nir_build_imm(nir_builder *build, unsigned num_components, nir_const_value value)
-{
- nir_load_const_instr *load_const =
- nir_load_const_instr_create(build->shader, num_components);
- if (!load_const)
- return NULL;
-
- load_const->value = value;
-
- nir_builder_instr_insert(build, &load_const->instr);
-
- return &load_const->def;
-}
-
-static inline nir_ssa_def *
-nir_imm_float(nir_builder *build, float x)
-{
- nir_const_value v;
-
- memset(&v, 0, sizeof(v));
- v.f[0] = x;
-
- return nir_build_imm(build, 1, v);
-}
-
-static inline nir_ssa_def *
-nir_imm_vec4(nir_builder *build, float x, float y, float z, float w)
-{
- nir_const_value v;
-
- memset(&v, 0, sizeof(v));
- v.f[0] = x;
- v.f[1] = y;
- v.f[2] = z;
- v.f[3] = w;
-
- return nir_build_imm(build, 4, v);
-}
-
-static inline nir_ssa_def *
-nir_imm_int(nir_builder *build, int x)
-{
- nir_const_value v;
-
- memset(&v, 0, sizeof(v));
- v.i[0] = x;
-
- return nir_build_imm(build, 1, v);
-}
-
-static inline nir_ssa_def *
-nir_imm_ivec4(nir_builder *build, int x, int y, int z, int w)
-{
- nir_const_value v;
-
- memset(&v, 0, sizeof(v));
- v.i[0] = x;
- v.i[1] = y;
- v.i[2] = z;
- v.i[3] = w;
-
- return nir_build_imm(build, 4, v);
-}
-
-static inline nir_ssa_def *
-nir_build_alu(nir_builder *build, nir_op op, nir_ssa_def *src0,
- nir_ssa_def *src1, nir_ssa_def *src2, nir_ssa_def *src3)
-{
- const nir_op_info *op_info = &nir_op_infos[op];
- nir_alu_instr *instr = nir_alu_instr_create(build->shader, op);
- if (!instr)
- return NULL;
-
- instr->src[0].src = nir_src_for_ssa(src0);
- if (src1)
- instr->src[1].src = nir_src_for_ssa(src1);
- if (src2)
- instr->src[2].src = nir_src_for_ssa(src2);
- if (src3)
- instr->src[3].src = nir_src_for_ssa(src3);
-
- /* Guess the number of components the destination temporary should have
- * based on our input sizes, if it's not fixed for the op.
- */
- unsigned num_components = op_info->output_size;
- if (num_components == 0) {
- for (unsigned i = 0; i < op_info->num_inputs; i++) {
- if (op_info->input_sizes[i] == 0)
- num_components = MAX2(num_components,
- instr->src[i].src.ssa->num_components);
- }
- }
- assert(num_components != 0);
-
- /* Make sure we don't swizzle from outside of our source vector (like if a
- * scalar value was passed into a multiply with a vector).
- */
- for (unsigned i = 0; i < op_info->num_inputs; i++) {
- for (unsigned j = instr->src[i].src.ssa->num_components; j < 4; j++) {
- instr->src[i].swizzle[j] = instr->src[i].src.ssa->num_components - 1;
- }
- }
-
- nir_ssa_dest_init(&instr->instr, &instr->dest.dest, num_components, NULL);
- instr->dest.write_mask = (1 << num_components) - 1;
-
- nir_builder_instr_insert(build, &instr->instr);
-
- return &instr->dest.dest.ssa;
-}
-
-#define ALU1(op) \
-static inline nir_ssa_def * \
-nir_##op(nir_builder *build, nir_ssa_def *src0) \
-{ \
- return nir_build_alu(build, nir_op_##op, src0, NULL, NULL, NULL); \
-}
-
-#define ALU2(op) \
-static inline nir_ssa_def * \
-nir_##op(nir_builder *build, nir_ssa_def *src0, nir_ssa_def *src1) \
-{ \
- return nir_build_alu(build, nir_op_##op, src0, src1, NULL, NULL); \
-}
-
-#define ALU3(op) \
-static inline nir_ssa_def * \
-nir_##op(nir_builder *build, nir_ssa_def *src0, \
- nir_ssa_def *src1, nir_ssa_def *src2) \
-{ \
- return nir_build_alu(build, nir_op_##op, src0, src1, src2, NULL); \
-}
-
-#define ALU4(op) \
-static inline nir_ssa_def * \
-nir_##op(nir_builder *build, nir_ssa_def *src0, \
- nir_ssa_def *src1, nir_ssa_def *src2, nir_ssa_def *src3) \
-{ \
- return nir_build_alu(build, nir_op_##op, src0, src1, src2, src3); \
-}
-
-#include "nir_builder_opcodes.h"
-
-static inline nir_ssa_def *
-nir_vec(nir_builder *build, nir_ssa_def **comp, unsigned num_components)
-{
- switch (num_components) {
- case 4:
- return nir_vec4(build, comp[0], comp[1], comp[2], comp[3]);
- case 3:
- return nir_vec3(build, comp[0], comp[1], comp[2]);
- case 2:
- return nir_vec2(build, comp[0], comp[1]);
- case 1:
- return comp[0];
- default:
- unreachable("bad component count");
- return NULL;
- }
-}
-
-/**
- * Similar to nir_fmov, but takes a nir_alu_src instead of a nir_ssa_def.
- */
-static inline nir_ssa_def *
-nir_fmov_alu(nir_builder *build, nir_alu_src src, unsigned num_components)
-{
- nir_alu_instr *mov = nir_alu_instr_create(build->shader, nir_op_fmov);
- nir_ssa_dest_init(&mov->instr, &mov->dest.dest, num_components, NULL);
- mov->dest.write_mask = (1 << num_components) - 1;
- mov->src[0] = src;
- nir_builder_instr_insert(build, &mov->instr);
-
- return &mov->dest.dest.ssa;
-}
-
-static inline nir_ssa_def *
-nir_imov_alu(nir_builder *build, nir_alu_src src, unsigned num_components)
-{
- nir_alu_instr *mov = nir_alu_instr_create(build->shader, nir_op_imov);
- nir_ssa_dest_init(&mov->instr, &mov->dest.dest, num_components, NULL);
- mov->dest.write_mask = (1 << num_components) - 1;
- mov->src[0] = src;
- nir_builder_instr_insert(build, &mov->instr);
-
- return &mov->dest.dest.ssa;
-}
-
-/**
- * Construct an fmov or imov that reswizzles the source's components.
- */
-static inline nir_ssa_def *
-nir_swizzle(nir_builder *build, nir_ssa_def *src, unsigned swiz[4],
- unsigned num_components, bool use_fmov)
-{
- nir_alu_src alu_src = { NIR_SRC_INIT };
- alu_src.src = nir_src_for_ssa(src);
- for (unsigned i = 0; i < num_components; i++)
- alu_src.swizzle[i] = swiz[i];
-
- return use_fmov ? nir_fmov_alu(build, alu_src, num_components) :
- nir_imov_alu(build, alu_src, num_components);
-}
-
-/* Selects the right fdot given the number of components in each source. */
-static inline nir_ssa_def *
-nir_fdot(nir_builder *build, nir_ssa_def *src0, nir_ssa_def *src1)
-{
- assert(src0->num_components == src1->num_components);
- switch (src0->num_components) {
- case 1: return nir_fmul(build, src0, src1);
- case 2: return nir_fdot2(build, src0, src1);
- case 3: return nir_fdot3(build, src0, src1);
- case 4: return nir_fdot4(build, src0, src1);
- default:
- unreachable("bad component size");
- }
-
- return NULL;
-}
-
-static inline nir_ssa_def *
-nir_channel(nir_builder *b, nir_ssa_def *def, unsigned c)
-{
- unsigned swizzle[4] = {c, c, c, c};
- return nir_swizzle(b, def, swizzle, 1, false);
-}
-
-/**
- * Turns a nir_src into a nir_ssa_def * so it can be passed to
- * nir_build_alu()-based builder calls.
- *
- * See nir_ssa_for_alu_src() for alu instructions.
- */
-static inline nir_ssa_def *
-nir_ssa_for_src(nir_builder *build, nir_src src, int num_components)
-{
- if (src.is_ssa && src.ssa->num_components == num_components)
- return src.ssa;
-
- nir_alu_src alu = { NIR_SRC_INIT };
- alu.src = src;
- for (int j = 0; j < 4; j++)
- alu.swizzle[j] = j;
-
- return nir_imov_alu(build, alu, num_components);
-}
-
-/**
- * Similar to nir_ssa_for_src(), but for alu src's, respecting the
- * nir_alu_src's swizzle.
- */
-static inline nir_ssa_def *
-nir_ssa_for_alu_src(nir_builder *build, nir_alu_instr *instr, unsigned srcn)
-{
- static uint8_t trivial_swizzle[4] = { 0, 1, 2, 3 };
- nir_alu_src *src = &instr->src[srcn];
- unsigned num_components = nir_ssa_alu_instr_src_components(instr, srcn);
-
- if (src->src.is_ssa && (src->src.ssa->num_components == num_components) &&
- !src->abs && !src->negate &&
- (memcmp(src->swizzle, trivial_swizzle, num_components) == 0))
- return src->src.ssa;
-
- return nir_imov_alu(build, *src, num_components);
-}
-
-static inline nir_ssa_def *
-nir_load_var(nir_builder *build, nir_variable *var)
-{
- const unsigned num_components = glsl_get_vector_elements(var->type);
-
- nir_intrinsic_instr *load =
- nir_intrinsic_instr_create(build->shader, nir_intrinsic_load_var);
- load->num_components = num_components;
- load->variables[0] = nir_deref_var_create(load, var);
- nir_ssa_dest_init(&load->instr, &load->dest, num_components, NULL);
- nir_builder_instr_insert(build, &load->instr);
- return &load->dest.ssa;
-}
-
-static inline void
-nir_store_var(nir_builder *build, nir_variable *var, nir_ssa_def *value,
- unsigned writemask)
-{
- const unsigned num_components = glsl_get_vector_elements(var->type);
-
- nir_intrinsic_instr *store =
- nir_intrinsic_instr_create(build->shader, nir_intrinsic_store_var);
- store->num_components = num_components;
- store->const_index[0] = writemask;
- store->variables[0] = nir_deref_var_create(store, var);
- store->src[0] = nir_src_for_ssa(value);
- nir_builder_instr_insert(build, &store->instr);
-}
-
-static inline void
-nir_store_deref_var(nir_builder *build, nir_deref_var *deref,
- nir_ssa_def *value, unsigned writemask)
-{
- const unsigned num_components =
- glsl_get_vector_elements(nir_deref_tail(&deref->deref)->type);
-
- nir_intrinsic_instr *store =
- nir_intrinsic_instr_create(build->shader, nir_intrinsic_store_var);
- store->num_components = num_components;
- store->const_index[0] = writemask & ((1 << num_components) - 1);
- store->variables[0] = nir_deref_as_var(nir_copy_deref(store, &deref->deref));
- store->src[0] = nir_src_for_ssa(value);
- nir_builder_instr_insert(build, &store->instr);
-}
-
-static inline void
-nir_copy_deref_var(nir_builder *build, nir_deref_var *dest, nir_deref_var *src)
-{
- assert(nir_deref_tail(&dest->deref)->type ==
- nir_deref_tail(&src->deref)->type);
-
- nir_intrinsic_instr *copy =
- nir_intrinsic_instr_create(build->shader, nir_intrinsic_copy_var);
- copy->variables[0] = nir_deref_as_var(nir_copy_deref(copy, &dest->deref));
- copy->variables[1] = nir_deref_as_var(nir_copy_deref(copy, &src->deref));
- nir_builder_instr_insert(build, &copy->instr);
-}
-
-static inline void
-nir_copy_var(nir_builder *build, nir_variable *dest, nir_variable *src)
-{
- nir_intrinsic_instr *copy =
- nir_intrinsic_instr_create(build->shader, nir_intrinsic_copy_var);
- copy->variables[0] = nir_deref_var_create(copy, dest);
- copy->variables[1] = nir_deref_var_create(copy, src);
- nir_builder_instr_insert(build, &copy->instr);
-}
-
-static inline nir_ssa_def *
-nir_load_system_value(nir_builder *build, nir_intrinsic_op op, int index)
-{
- nir_intrinsic_instr *load = nir_intrinsic_instr_create(build->shader, op);
- load->num_components = nir_intrinsic_infos[op].dest_components;
- load->const_index[0] = index;
- nir_ssa_dest_init(&load->instr, &load->dest,
- nir_intrinsic_infos[op].dest_components, NULL);
- nir_builder_instr_insert(build, &load->instr);
- return &load->dest.ssa;
-}
-
-static inline void
-nir_jump(nir_builder *build, nir_jump_type jump_type)
-{
- nir_jump_instr *jump = nir_jump_instr_create(build->shader, jump_type);
- nir_builder_instr_insert(build, &jump->instr);
-}
-
-#endif /* NIR_BUILDER_H */
diff --git a/src/glsl/nir/nir_builder_opcodes_h.py b/src/glsl/nir/nir_builder_opcodes_h.py
deleted file mode 100644
index e27206ea8fc..00000000000
--- a/src/glsl/nir/nir_builder_opcodes_h.py
+++ /dev/null
@@ -1,38 +0,0 @@
-#! /usr/bin/env python
-
-template = """\
-/* Copyright (C) 2015 Broadcom
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#ifndef _NIR_BUILDER_OPCODES_
-#define _NIR_BUILDER_OPCODES_
-
-% for name, opcode in sorted(opcodes.iteritems()):
-ALU${opcode.num_inputs}(${name});
-% endfor
-
-#endif /* _NIR_BUILDER_OPCODES_ */"""
-
-from nir_opcodes import opcodes
-from mako.template import Template
-
-print Template(template).render(opcodes=opcodes)
diff --git a/src/glsl/nir/nir_clone.c b/src/glsl/nir/nir_clone.c
deleted file mode 100644
index bc6df56b753..00000000000
--- a/src/glsl/nir/nir_clone.c
+++ /dev/null
@@ -1,711 +0,0 @@
-/*
- * Copyright © 2015 Red Hat
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include "nir.h"
-#include "nir_control_flow_private.h"
-
-/* Secret Decoder Ring:
- * clone_foo():
- * Allocate and clone a foo.
- * __clone_foo():
- * Clone body of foo (ie. parent class, embedded struct, etc)
- */
-
-typedef struct {
- /* True if we are cloning an entire shader. */
- bool global_clone;
-
- /* maps orig ptr -> cloned ptr: */
- struct hash_table *remap_table;
-
- /* List of phi sources. */
- struct list_head phi_srcs;
-
- /* new shader object, used as memctx for just about everything else: */
- nir_shader *ns;
-} clone_state;
-
-static void
-init_clone_state(clone_state *state, bool global)
-{
- state->global_clone = global;
- state->remap_table = _mesa_hash_table_create(NULL, _mesa_hash_pointer,
- _mesa_key_pointer_equal);
- list_inithead(&state->phi_srcs);
-}
-
-static void
-free_clone_state(clone_state *state)
-{
- _mesa_hash_table_destroy(state->remap_table, NULL);
-}
-
-static inline void *
-_lookup_ptr(clone_state *state, const void *ptr, bool global)
-{
- struct hash_entry *entry;
-
- if (!ptr)
- return NULL;
-
- if (!state->global_clone && global)
- return (void *)ptr;
-
- entry = _mesa_hash_table_search(state->remap_table, ptr);
- assert(entry && "Failed to find pointer!");
- if (!entry)
- return NULL;
-
- return entry->data;
-}
-
-static void
-add_remap(clone_state *state, void *nptr, const void *ptr)
-{
- _mesa_hash_table_insert(state->remap_table, ptr, nptr);
-}
-
-static void *
-remap_local(clone_state *state, const void *ptr)
-{
- return _lookup_ptr(state, ptr, false);
-}
-
-static void *
-remap_global(clone_state *state, const void *ptr)
-{
- return _lookup_ptr(state, ptr, true);
-}
-
-static nir_register *
-remap_reg(clone_state *state, const nir_register *reg)
-{
- return _lookup_ptr(state, reg, reg->is_global);
-}
-
-static nir_variable *
-remap_var(clone_state *state, const nir_variable *var)
-{
- return _lookup_ptr(state, var, var->data.mode != nir_var_local);
-}
-
-nir_constant *
-nir_constant_clone(const nir_constant *c, nir_variable *nvar)
-{
- nir_constant *nc = ralloc(nvar, nir_constant);
-
- nc->value = c->value;
- nc->num_elements = c->num_elements;
- nc->elements = ralloc_array(nvar, nir_constant *, c->num_elements);
- for (unsigned i = 0; i < c->num_elements; i++) {
- nc->elements[i] = nir_constant_clone(c->elements[i], nvar);
- }
-
- return nc;
-}
-
-/* NOTE: for cloning nir_variable's, bypass nir_variable_create to avoid
- * having to deal with locals and globals separately:
- */
-static nir_variable *
-clone_variable(clone_state *state, const nir_variable *var)
-{
- nir_variable *nvar = rzalloc(state->ns, nir_variable);
- add_remap(state, nvar, var);
-
- nvar->type = var->type;
- nvar->name = ralloc_strdup(nvar, var->name);
- nvar->data = var->data;
- nvar->num_state_slots = var->num_state_slots;
- nvar->state_slots = ralloc_array(nvar, nir_state_slot, var->num_state_slots);
- memcpy(nvar->state_slots, var->state_slots,
- var->num_state_slots * sizeof(nir_state_slot));
- if (var->constant_initializer) {
- nvar->constant_initializer =
- nir_constant_clone(var->constant_initializer, nvar);
- }
- nvar->interface_type = var->interface_type;
-
- return nvar;
-}
-
-/* clone list of nir_variable: */
-static void
-clone_var_list(clone_state *state, struct exec_list *dst,
- const struct exec_list *list)
-{
- exec_list_make_empty(dst);
- foreach_list_typed(nir_variable, var, node, list) {
- nir_variable *nvar = clone_variable(state, var);
- exec_list_push_tail(dst, &nvar->node);
- }
-}
-
-/* NOTE: for cloning nir_register's, bypass nir_global/local_reg_create()
- * to avoid having to deal with locals and globals separately:
- */
-static nir_register *
-clone_register(clone_state *state, const nir_register *reg)
-{
- nir_register *nreg = rzalloc(state->ns, nir_register);
- add_remap(state, nreg, reg);
-
- nreg->num_components = reg->num_components;
- nreg->num_array_elems = reg->num_array_elems;
- nreg->index = reg->index;
- nreg->name = ralloc_strdup(nreg, reg->name);
- nreg->is_global = reg->is_global;
- nreg->is_packed = reg->is_packed;
-
- /* reconstructing uses/defs/if_uses handled by nir_instr_insert() */
- list_inithead(&nreg->uses);
- list_inithead(&nreg->defs);
- list_inithead(&nreg->if_uses);
-
- return nreg;
-}
-
-/* clone list of nir_register: */
-static void
-clone_reg_list(clone_state *state, struct exec_list *dst,
- const struct exec_list *list)
-{
- exec_list_make_empty(dst);
- foreach_list_typed(nir_register, reg, node, list) {
- nir_register *nreg = clone_register(state, reg);
- exec_list_push_tail(dst, &nreg->node);
- }
-}
-
-static void
-__clone_src(clone_state *state, void *ninstr_or_if,
- nir_src *nsrc, const nir_src *src)
-{
- nsrc->is_ssa = src->is_ssa;
- if (src->is_ssa) {
- nsrc->ssa = remap_local(state, src->ssa);
- } else {
- nsrc->reg.reg = remap_reg(state, src->reg.reg);
- if (src->reg.indirect) {
- nsrc->reg.indirect = ralloc(ninstr_or_if, nir_src);
- __clone_src(state, ninstr_or_if, nsrc->reg.indirect, src->reg.indirect);
- }
- nsrc->reg.base_offset = src->reg.base_offset;
- }
-}
-
-static void
-__clone_dst(clone_state *state, nir_instr *ninstr,
- nir_dest *ndst, const nir_dest *dst)
-{
- ndst->is_ssa = dst->is_ssa;
- if (dst->is_ssa) {
- nir_ssa_dest_init(ninstr, ndst, dst->ssa.num_components, dst->ssa.name);
- add_remap(state, &ndst->ssa, &dst->ssa);
- } else {
- ndst->reg.reg = remap_reg(state, dst->reg.reg);
- if (dst->reg.indirect) {
- ndst->reg.indirect = ralloc(ninstr, nir_src);
- __clone_src(state, ninstr, ndst->reg.indirect, dst->reg.indirect);
- }
- ndst->reg.base_offset = dst->reg.base_offset;
- }
-}
-
-static nir_deref *clone_deref(clone_state *state, const nir_deref *deref,
- nir_instr *ninstr, nir_deref *parent);
-
-static nir_deref_var *
-clone_deref_var(clone_state *state, const nir_deref_var *dvar,
- nir_instr *ninstr)
-{
- nir_variable *nvar = remap_var(state, dvar->var);
- nir_deref_var *ndvar = nir_deref_var_create(ninstr, nvar);
-
- if (dvar->deref.child)
- ndvar->deref.child = clone_deref(state, dvar->deref.child,
- ninstr, &ndvar->deref);
-
- return ndvar;
-}
-
-static nir_deref_array *
-clone_deref_array(clone_state *state, const nir_deref_array *darr,
- nir_instr *ninstr, nir_deref *parent)
-{
- nir_deref_array *ndarr = nir_deref_array_create(parent);
-
- ndarr->deref.type = darr->deref.type;
- if (darr->deref.child)
- ndarr->deref.child = clone_deref(state, darr->deref.child,
- ninstr, &ndarr->deref);
-
- ndarr->deref_array_type = darr->deref_array_type;
- ndarr->base_offset = darr->base_offset;
- if (ndarr->deref_array_type == nir_deref_array_type_indirect)
- __clone_src(state, ninstr, &ndarr->indirect, &darr->indirect);
-
- return ndarr;
-}
-
-static nir_deref_struct *
-clone_deref_struct(clone_state *state, const nir_deref_struct *dstr,
- nir_instr *ninstr, nir_deref *parent)
-{
- nir_deref_struct *ndstr = nir_deref_struct_create(parent, dstr->index);
-
- ndstr->deref.type = dstr->deref.type;
- if (dstr->deref.child)
- ndstr->deref.child = clone_deref(state, dstr->deref.child,
- ninstr, &ndstr->deref);
-
- return ndstr;
-}
-
-static nir_deref *
-clone_deref(clone_state *state, const nir_deref *dref,
- nir_instr *ninstr, nir_deref *parent)
-{
- switch (dref->deref_type) {
- case nir_deref_type_array:
- return &clone_deref_array(state, nir_deref_as_array(dref),
- ninstr, parent)->deref;
- case nir_deref_type_struct:
- return &clone_deref_struct(state, nir_deref_as_struct(dref),
- ninstr, parent)->deref;
- default:
- unreachable("bad deref type");
- return NULL;
- }
-}
-
-static nir_alu_instr *
-clone_alu(clone_state *state, const nir_alu_instr *alu)
-{
- nir_alu_instr *nalu = nir_alu_instr_create(state->ns, alu->op);
-
- __clone_dst(state, &nalu->instr, &nalu->dest.dest, &alu->dest.dest);
- nalu->dest.saturate = alu->dest.saturate;
- nalu->dest.write_mask = alu->dest.write_mask;
-
- for (unsigned i = 0; i < nir_op_infos[alu->op].num_inputs; i++) {
- __clone_src(state, &nalu->instr, &nalu->src[i].src, &alu->src[i].src);
- nalu->src[i].negate = alu->src[i].negate;
- nalu->src[i].abs = alu->src[i].abs;
- memcpy(nalu->src[i].swizzle, alu->src[i].swizzle,
- sizeof(nalu->src[i].swizzle));
- }
-
- return nalu;
-}
-
-static nir_intrinsic_instr *
-clone_intrinsic(clone_state *state, const nir_intrinsic_instr *itr)
-{
- nir_intrinsic_instr *nitr =
- nir_intrinsic_instr_create(state->ns, itr->intrinsic);
-
- unsigned num_variables = nir_intrinsic_infos[itr->intrinsic].num_variables;
- unsigned num_srcs = nir_intrinsic_infos[itr->intrinsic].num_srcs;
-
- if (nir_intrinsic_infos[itr->intrinsic].has_dest)
- __clone_dst(state, &nitr->instr, &nitr->dest, &itr->dest);
-
- nitr->num_components = itr->num_components;
- memcpy(nitr->const_index, itr->const_index, sizeof(nitr->const_index));
-
- for (unsigned i = 0; i < num_variables; i++) {
- nitr->variables[i] = clone_deref_var(state, itr->variables[i],
- &nitr->instr);
- }
-
- for (unsigned i = 0; i < num_srcs; i++)
- __clone_src(state, &nitr->instr, &nitr->src[i], &itr->src[i]);
-
- return nitr;
-}
-
-static nir_load_const_instr *
-clone_load_const(clone_state *state, const nir_load_const_instr *lc)
-{
- nir_load_const_instr *nlc =
- nir_load_const_instr_create(state->ns, lc->def.num_components);
-
- memcpy(&nlc->value, &lc->value, sizeof(nlc->value));
-
- add_remap(state, &nlc->def, &lc->def);
-
- return nlc;
-}
-
-static nir_ssa_undef_instr *
-clone_ssa_undef(clone_state *state, const nir_ssa_undef_instr *sa)
-{
- nir_ssa_undef_instr *nsa =
- nir_ssa_undef_instr_create(state->ns, sa->def.num_components);
-
- add_remap(state, &nsa->def, &sa->def);
-
- return nsa;
-}
-
-static nir_tex_instr *
-clone_tex(clone_state *state, const nir_tex_instr *tex)
-{
- nir_tex_instr *ntex = nir_tex_instr_create(state->ns, tex->num_srcs);
-
- ntex->sampler_dim = tex->sampler_dim;
- ntex->dest_type = tex->dest_type;
- ntex->op = tex->op;
- __clone_dst(state, &ntex->instr, &ntex->dest, &tex->dest);
- for (unsigned i = 0; i < ntex->num_srcs; i++) {
- ntex->src[i].src_type = tex->src[i].src_type;
- __clone_src(state, &ntex->instr, &ntex->src[i].src, &tex->src[i].src);
- }
- ntex->coord_components = tex->coord_components;
- ntex->is_array = tex->is_array;
- ntex->is_shadow = tex->is_shadow;
- ntex->is_new_style_shadow = tex->is_new_style_shadow;
- memcpy(ntex->const_offset, tex->const_offset, sizeof(ntex->const_offset));
- ntex->component = tex->component;
- ntex->texture_index = tex->texture_index;
- ntex->texture_array_size = tex->texture_array_size;
- if (tex->texture)
- ntex->texture = clone_deref_var(state, tex->texture, &ntex->instr);
- ntex->sampler_index = tex->sampler_index;
- if (tex->sampler)
- ntex->sampler = clone_deref_var(state, tex->sampler, &ntex->instr);
-
- return ntex;
-}
-
-static nir_phi_instr *
-clone_phi(clone_state *state, const nir_phi_instr *phi, nir_block *nblk)
-{
- nir_phi_instr *nphi = nir_phi_instr_create(state->ns);
-
- __clone_dst(state, &nphi->instr, &nphi->dest, &phi->dest);
-
- /* Cloning a phi node is a bit different from other instructions. The
- * sources of phi instructions are the only time where we can use an SSA
- * def before it is defined. In order to handle this, we just copy over
- * the sources from the old phi instruction directly and then fix them up
- * in a second pass once all the instrutions in the function have been
- * properly cloned.
- *
- * In order to ensure that the copied sources (which are the same as the
- * old phi instruction's sources for now) don't get inserted into the old
- * shader's use-def lists, we have to add the phi instruction *before* we
- * set up its sources.
- */
- nir_instr_insert_after_block(nblk, &nphi->instr);
-
- foreach_list_typed(nir_phi_src, src, node, &phi->srcs) {
- nir_phi_src *nsrc = ralloc(nphi, nir_phi_src);
-
- /* Just copy the old source for now. */
- memcpy(nsrc, src, sizeof(*src));
-
- /* Since we're not letting nir_insert_instr handle use/def stuff for us,
- * we have to set the parent_instr manually. It doesn't really matter
- * when we do it, so we might as well do it here.
- */
- nsrc->src.parent_instr = &nphi->instr;
-
- /* Stash it in the list of phi sources. We'll walk this list and fix up
- * sources at the very end of clone_function_impl.
- */
- list_add(&nsrc->src.use_link, &state->phi_srcs);
-
- exec_list_push_tail(&nphi->srcs, &nsrc->node);
- }
-
- return nphi;
-}
-
-static nir_jump_instr *
-clone_jump(clone_state *state, const nir_jump_instr *jmp)
-{
- nir_jump_instr *njmp = nir_jump_instr_create(state->ns, jmp->type);
-
- return njmp;
-}
-
-static nir_call_instr *
-clone_call(clone_state *state, const nir_call_instr *call)
-{
- nir_function *ncallee = remap_global(state, call->callee);
- nir_call_instr *ncall = nir_call_instr_create(state->ns, ncallee);
-
- for (unsigned i = 0; i < ncall->num_params; i++)
- ncall->params[i] = clone_deref_var(state, call->params[i], &ncall->instr);
-
- ncall->return_deref = clone_deref_var(state, call->return_deref,
- &ncall->instr);
-
- return ncall;
-}
-
-static nir_instr *
-clone_instr(clone_state *state, const nir_instr *instr)
-{
- switch (instr->type) {
- case nir_instr_type_alu:
- return &clone_alu(state, nir_instr_as_alu(instr))->instr;
- case nir_instr_type_intrinsic:
- return &clone_intrinsic(state, nir_instr_as_intrinsic(instr))->instr;
- case nir_instr_type_load_const:
- return &clone_load_const(state, nir_instr_as_load_const(instr))->instr;
- case nir_instr_type_ssa_undef:
- return &clone_ssa_undef(state, nir_instr_as_ssa_undef(instr))->instr;
- case nir_instr_type_tex:
- return &clone_tex(state, nir_instr_as_tex(instr))->instr;
- case nir_instr_type_phi:
- unreachable("Cannot clone phis with clone_instr");
- case nir_instr_type_jump:
- return &clone_jump(state, nir_instr_as_jump(instr))->instr;
- case nir_instr_type_call:
- return &clone_call(state, nir_instr_as_call(instr))->instr;
- case nir_instr_type_parallel_copy:
- unreachable("Cannot clone parallel copies");
- default:
- unreachable("bad instr type");
- return NULL;
- }
-}
-
-static nir_block *
-clone_block(clone_state *state, struct exec_list *cf_list, const nir_block *blk)
-{
- /* Don't actually create a new block. Just use the one from the tail of
- * the list. NIR guarantees that the tail of the list is a block and that
- * no two blocks are side-by-side in the IR; It should be empty.
- */
- nir_block *nblk =
- exec_node_data(nir_block, exec_list_get_tail(cf_list), cf_node.node);
- assert(nblk->cf_node.type == nir_cf_node_block);
- assert(exec_list_is_empty(&nblk->instr_list));
-
- /* We need this for phi sources */
- add_remap(state, nblk, blk);
-
- nir_foreach_instr(blk, instr) {
- if (instr->type == nir_instr_type_phi) {
- /* Phi instructions are a bit of a special case when cloning because
- * we don't want inserting the instruction to automatically handle
- * use/defs for us. Instead, we need to wait until all the
- * blocks/instructions are in so that we can set their sources up.
- */
- clone_phi(state, nir_instr_as_phi(instr), nblk);
- } else {
- nir_instr *ninstr = clone_instr(state, instr);
- nir_instr_insert_after_block(nblk, ninstr);
- }
- }
-
- return nblk;
-}
-
-static void
-clone_cf_list(clone_state *state, struct exec_list *dst,
- const struct exec_list *list);
-
-static nir_if *
-clone_if(clone_state *state, struct exec_list *cf_list, const nir_if *i)
-{
- nir_if *ni = nir_if_create(state->ns);
-
- __clone_src(state, ni, &ni->condition, &i->condition);
-
- nir_cf_node_insert_end(cf_list, &ni->cf_node);
-
- clone_cf_list(state, &ni->then_list, &i->then_list);
- clone_cf_list(state, &ni->else_list, &i->else_list);
-
- return ni;
-}
-
-static nir_loop *
-clone_loop(clone_state *state, struct exec_list *cf_list, const nir_loop *loop)
-{
- nir_loop *nloop = nir_loop_create(state->ns);
-
- nir_cf_node_insert_end(cf_list, &nloop->cf_node);
-
- clone_cf_list(state, &nloop->body, &loop->body);
-
- return nloop;
-}
-
-/* clone list of nir_cf_node: */
-static void
-clone_cf_list(clone_state *state, struct exec_list *dst,
- const struct exec_list *list)
-{
- foreach_list_typed(nir_cf_node, cf, node, list) {
- switch (cf->type) {
- case nir_cf_node_block:
- clone_block(state, dst, nir_cf_node_as_block(cf));
- break;
- case nir_cf_node_if:
- clone_if(state, dst, nir_cf_node_as_if(cf));
- break;
- case nir_cf_node_loop:
- clone_loop(state, dst, nir_cf_node_as_loop(cf));
- break;
- default:
- unreachable("bad cf type");
- }
- }
-}
-
-static nir_function_impl *
-clone_function_impl(clone_state *state, const nir_function_impl *fi)
-{
- nir_function_impl *nfi = nir_function_impl_create_bare(state->ns);
-
- clone_var_list(state, &nfi->locals, &fi->locals);
- clone_reg_list(state, &nfi->registers, &fi->registers);
- nfi->reg_alloc = fi->reg_alloc;
-
- nfi->num_params = fi->num_params;
- nfi->params = ralloc_array(state->ns, nir_variable *, fi->num_params);
- for (unsigned i = 0; i < fi->num_params; i++) {
- nfi->params[i] = remap_local(state, fi->params[i]);
- }
- nfi->return_var = remap_local(state, fi->return_var);
-
- assert(list_empty(&state->phi_srcs));
-
- clone_cf_list(state, &nfi->body, &fi->body);
-
- /* After we've cloned almost everything, we have to walk the list of phi
- * sources and fix them up. Thanks to loops, the block and SSA value for a
- * phi source may not be defined when we first encounter it. Instead, we
- * add it to the phi_srcs list and we fix it up here.
- */
- list_for_each_entry_safe(nir_phi_src, src, &state->phi_srcs, src.use_link) {
- src->pred = remap_local(state, src->pred);
- assert(src->src.is_ssa);
- src->src.ssa = remap_local(state, src->src.ssa);
-
- /* Remove from this list and place in the uses of the SSA def */
- list_del(&src->src.use_link);
- list_addtail(&src->src.use_link, &src->src.ssa->uses);
- }
- assert(list_empty(&state->phi_srcs));
-
- /* All metadata is invalidated in the cloning process */
- nfi->valid_metadata = 0;
-
- return nfi;
-}
-
-nir_function_impl *
-nir_function_impl_clone(const nir_function_impl *fi)
-{
- clone_state state;
- init_clone_state(&state, false);
-
- /* We use the same shader */
- state.ns = fi->function->shader;
-
- nir_function_impl *nfi = clone_function_impl(&state, fi);
-
- free_clone_state(&state);
-
- return nfi;
-}
-
-static nir_function *
-clone_function(clone_state *state, const nir_function *fxn, nir_shader *ns)
-{
- assert(ns == state->ns);
- nir_function *nfxn = nir_function_create(ns, fxn->name);
-
- /* Needed for call instructions */
- add_remap(state, nfxn, fxn);
-
- nfxn->num_params = fxn->num_params;
- nfxn->params = ralloc_array(state->ns, nir_parameter, fxn->num_params);
- memcpy(nfxn->params, fxn->params, sizeof(nir_parameter) * fxn->num_params);
-
- nfxn->return_type = fxn->return_type;
-
- /* At first glance, it looks like we should clone the function_impl here.
- * However, call instructions need to be able to reference at least the
- * function and those will get processed as we clone the function_impl's.
- * We stop here and do function_impls as a second pass.
- */
-
- return nfxn;
-}
-
-nir_shader *
-nir_shader_clone(void *mem_ctx, const nir_shader *s)
-{
- clone_state state;
- init_clone_state(&state, true);
-
- nir_shader *ns = nir_shader_create(mem_ctx, s->stage, s->options);
- state.ns = ns;
-
- clone_var_list(&state, &ns->uniforms, &s->uniforms);
- clone_var_list(&state, &ns->inputs, &s->inputs);
- clone_var_list(&state, &ns->outputs, &s->outputs);
- clone_var_list(&state, &ns->shared, &s->shared);
- clone_var_list(&state, &ns->globals, &s->globals);
- clone_var_list(&state, &ns->system_values, &s->system_values);
-
- /* Go through and clone functions */
- foreach_list_typed(nir_function, fxn, node, &s->functions)
- clone_function(&state, fxn, ns);
-
- /* Only after all functions are cloned can we clone the actual function
- * implementations. This is because nir_call_instr's need to reference the
- * functions of other functions and we don't know what order the functions
- * will have in the list.
- */
- nir_foreach_function(s, fxn) {
- nir_function *nfxn = remap_global(&state, fxn);
- nfxn->impl = clone_function_impl(&state, fxn->impl);
- nfxn->impl->function = nfxn;
- }
-
- clone_reg_list(&state, &ns->registers, &s->registers);
- ns->reg_alloc = s->reg_alloc;
-
- ns->info = s->info;
- ns->info.name = ralloc_strdup(ns, ns->info.name);
- if (ns->info.label)
- ns->info.label = ralloc_strdup(ns, ns->info.label);
-
- ns->num_inputs = s->num_inputs;
- ns->num_uniforms = s->num_uniforms;
- ns->num_outputs = s->num_outputs;
- ns->num_shared = s->num_shared;
-
- free_clone_state(&state);
-
- return ns;
-}
diff --git a/src/glsl/nir/nir_constant_expressions.h b/src/glsl/nir/nir_constant_expressions.h
deleted file mode 100644
index 97997f2e514..00000000000
--- a/src/glsl/nir/nir_constant_expressions.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright © 2014 Connor Abbott
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- *
- * Authors:
- * Connor Abbott ([email protected])
- *
- */
-
-#include "nir.h"
-
-nir_const_value nir_eval_const_opcode(nir_op op, unsigned num_components,
- nir_const_value *src);
diff --git a/src/glsl/nir/nir_constant_expressions.py b/src/glsl/nir/nir_constant_expressions.py
deleted file mode 100644
index 32784f6398d..00000000000
--- a/src/glsl/nir/nir_constant_expressions.py
+++ /dev/null
@@ -1,336 +0,0 @@
-#! /usr/bin/python2
-template = """\
-/*
- * Copyright (C) 2014 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- *
- * Authors:
- * Jason Ekstrand ([email protected])
- */
-
-#include <math.h>
-#include "main/core.h"
-#include "util/rounding.h" /* for _mesa_roundeven */
-#include "util/half_float.h"
-#include "nir_constant_expressions.h"
-
-/**
- * Evaluate one component of packSnorm4x8.
- */
-static uint8_t
-pack_snorm_1x8(float x)
-{
- /* From section 8.4 of the GLSL 4.30 spec:
- *
- * packSnorm4x8
- * ------------
- * The conversion for component c of v to fixed point is done as
- * follows:
- *
- * packSnorm4x8: round(clamp(c, -1, +1) * 127.0)
- *
- * We must first cast the float to an int, because casting a negative
- * float to a uint is undefined.
- */
- return (uint8_t) (int)
- _mesa_roundevenf(CLAMP(x, -1.0f, +1.0f) * 127.0f);
-}
-
-/**
- * Evaluate one component of packSnorm2x16.
- */
-static uint16_t
-pack_snorm_1x16(float x)
-{
- /* From section 8.4 of the GLSL ES 3.00 spec:
- *
- * packSnorm2x16
- * -------------
- * The conversion for component c of v to fixed point is done as
- * follows:
- *
- * packSnorm2x16: round(clamp(c, -1, +1) * 32767.0)
- *
- * We must first cast the float to an int, because casting a negative
- * float to a uint is undefined.
- */
- return (uint16_t) (int)
- _mesa_roundevenf(CLAMP(x, -1.0f, +1.0f) * 32767.0f);
-}
-
-/**
- * Evaluate one component of unpackSnorm4x8.
- */
-static float
-unpack_snorm_1x8(uint8_t u)
-{
- /* From section 8.4 of the GLSL 4.30 spec:
- *
- * unpackSnorm4x8
- * --------------
- * The conversion for unpacked fixed-point value f to floating point is
- * done as follows:
- *
- * unpackSnorm4x8: clamp(f / 127.0, -1, +1)
- */
- return CLAMP((int8_t) u / 127.0f, -1.0f, +1.0f);
-}
-
-/**
- * Evaluate one component of unpackSnorm2x16.
- */
-static float
-unpack_snorm_1x16(uint16_t u)
-{
- /* From section 8.4 of the GLSL ES 3.00 spec:
- *
- * unpackSnorm2x16
- * ---------------
- * The conversion for unpacked fixed-point value f to floating point is
- * done as follows:
- *
- * unpackSnorm2x16: clamp(f / 32767.0, -1, +1)
- */
- return CLAMP((int16_t) u / 32767.0f, -1.0f, +1.0f);
-}
-
-/**
- * Evaluate one component packUnorm4x8.
- */
-static uint8_t
-pack_unorm_1x8(float x)
-{
- /* From section 8.4 of the GLSL 4.30 spec:
- *
- * packUnorm4x8
- * ------------
- * The conversion for component c of v to fixed point is done as
- * follows:
- *
- * packUnorm4x8: round(clamp(c, 0, +1) * 255.0)
- */
- return (uint8_t) (int)
- _mesa_roundevenf(CLAMP(x, 0.0f, 1.0f) * 255.0f);
-}
-
-/**
- * Evaluate one component packUnorm2x16.
- */
-static uint16_t
-pack_unorm_1x16(float x)
-{
- /* From section 8.4 of the GLSL ES 3.00 spec:
- *
- * packUnorm2x16
- * -------------
- * The conversion for component c of v to fixed point is done as
- * follows:
- *
- * packUnorm2x16: round(clamp(c, 0, +1) * 65535.0)
- */
- return (uint16_t) (int)
- _mesa_roundevenf(CLAMP(x, 0.0f, 1.0f) * 65535.0f);
-}
-
-/**
- * Evaluate one component of unpackUnorm4x8.
- */
-static float
-unpack_unorm_1x8(uint8_t u)
-{
- /* From section 8.4 of the GLSL 4.30 spec:
- *
- * unpackUnorm4x8
- * --------------
- * The conversion for unpacked fixed-point value f to floating point is
- * done as follows:
- *
- * unpackUnorm4x8: f / 255.0
- */
- return (float) u / 255.0f;
-}
-
-/**
- * Evaluate one component of unpackUnorm2x16.
- */
-static float
-unpack_unorm_1x16(uint16_t u)
-{
- /* From section 8.4 of the GLSL ES 3.00 spec:
- *
- * unpackUnorm2x16
- * ---------------
- * The conversion for unpacked fixed-point value f to floating point is
- * done as follows:
- *
- * unpackUnorm2x16: f / 65535.0
- */
- return (float) u / 65535.0f;
-}
-
-/**
- * Evaluate one component of packHalf2x16.
- */
-static uint16_t
-pack_half_1x16(float x)
-{
- return _mesa_float_to_half(x);
-}
-
-/**
- * Evaluate one component of unpackHalf2x16.
- */
-static float
-unpack_half_1x16(uint16_t u)
-{
- return _mesa_half_to_float(u);
-}
-
-/* Some typed vector structures to make things like src0.y work */
-% for type in ["float", "int", "uint", "bool"]:
-struct ${type}_vec {
- ${type} x;
- ${type} y;
- ${type} z;
- ${type} w;
-};
-% endfor
-
-% for name, op in sorted(opcodes.iteritems()):
-static nir_const_value
-evaluate_${name}(unsigned num_components, nir_const_value *_src)
-{
- nir_const_value _dst_val = { { {0, 0, 0, 0} } };
-
- ## For each non-per-component input, create a variable srcN that
- ## contains x, y, z, and w elements which are filled in with the
- ## appropriately-typed values.
- % for j in range(op.num_inputs):
- % if op.input_sizes[j] == 0:
- <% continue %>
- % elif "src" + str(j) not in op.const_expr:
- ## Avoid unused variable warnings
- <% continue %>
- %endif
-
- struct ${op.input_types[j]}_vec src${j} = {
- % for k in range(op.input_sizes[j]):
- % if op.input_types[j] == "bool":
- _src[${j}].u[${k}] != 0,
- % else:
- _src[${j}].${op.input_types[j][:1]}[${k}],
- % endif
- % endfor
- };
- % endfor
-
- % if op.output_size == 0:
- ## For per-component instructions, we need to iterate over the
- ## components and apply the constant expression one component
- ## at a time.
- for (unsigned _i = 0; _i < num_components; _i++) {
- ## For each per-component input, create a variable srcN that
- ## contains the value of the current (_i'th) component.
- % for j in range(op.num_inputs):
- % if op.input_sizes[j] != 0:
- <% continue %>
- % elif "src" + str(j) not in op.const_expr:
- ## Avoid unused variable warnings
- <% continue %>
- % elif op.input_types[j] == "bool":
- bool src${j} = _src[${j}].u[_i] != 0;
- % else:
- ${op.input_types[j]} src${j} = _src[${j}].${op.input_types[j][:1]}[_i];
- % endif
- % endfor
-
- ## Create an appropriately-typed variable dst and assign the
- ## result of the const_expr to it. If const_expr already contains
- ## writes to dst, just include const_expr directly.
- % if "dst" in op.const_expr:
- ${op.output_type} dst;
- ${op.const_expr}
- % else:
- ${op.output_type} dst = ${op.const_expr};
- % endif
-
- ## Store the current component of the actual destination to the
- ## value of dst.
- % if op.output_type == "bool":
- ## Sanitize the C value to a proper NIR bool
- _dst_val.u[_i] = dst ? NIR_TRUE : NIR_FALSE;
- % else:
- _dst_val.${op.output_type[:1]}[_i] = dst;
- % endif
- }
- % else:
- ## In the non-per-component case, create a struct dst with
- ## appropriately-typed elements x, y, z, and w and assign the result
- ## of the const_expr to all components of dst, or include the
- ## const_expr directly if it writes to dst already.
- struct ${op.output_type}_vec dst;
-
- % if "dst" in op.const_expr:
- ${op.const_expr}
- % else:
- ## Splat the value to all components. This way expressions which
- ## write the same value to all components don't need to explicitly
- ## write to dest. One such example is fnoise which has a
- ## const_expr of 0.0f.
- dst.x = dst.y = dst.z = dst.w = ${op.const_expr};
- % endif
-
- ## For each component in the destination, copy the value of dst to
- ## the actual destination.
- % for k in range(op.output_size):
- % if op.output_type == "bool":
- ## Sanitize the C value to a proper NIR bool
- _dst_val.u[${k}] = dst.${"xyzw"[k]} ? NIR_TRUE : NIR_FALSE;
- % else:
- _dst_val.${op.output_type[:1]}[${k}] = dst.${"xyzw"[k]};
- % endif
- % endfor
- % endif
-
- return _dst_val;
-}
-% endfor
-
-nir_const_value
-nir_eval_const_opcode(nir_op op, unsigned num_components,
- nir_const_value *src)
-{
- switch (op) {
-% for name in sorted(opcodes.iterkeys()):
- case nir_op_${name}: {
- return evaluate_${name}(num_components, src);
- break;
- }
-% endfor
- default:
- unreachable("shouldn't get here");
- }
-}"""
-
-from nir_opcodes import opcodes
-from mako.template import Template
-
-print Template(template).render(opcodes=opcodes)
diff --git a/src/glsl/nir/nir_control_flow.c b/src/glsl/nir/nir_control_flow.c
deleted file mode 100644
index 33b06d0cc84..00000000000
--- a/src/glsl/nir/nir_control_flow.c
+++ /dev/null
@@ -1,820 +0,0 @@
-/*
- * Copyright © 2014 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- *
- * Authors:
- * Connor Abbott ([email protected])
- *
- */
-
-#include "nir_control_flow_private.h"
-
-/**
- * \name Control flow modification
- *
- * These functions modify the control flow tree while keeping the control flow
- * graph up-to-date. The invariants respected are:
- * 1. Each then statement, else statement, or loop body must have at least one
- * control flow node.
- * 2. Each if-statement and loop must have one basic block before it and one
- * after.
- * 3. Two basic blocks cannot be directly next to each other.
- * 4. If a basic block has a jump instruction, there must be only one and it
- * must be at the end of the block.
- * 5. The CFG must always be connected - this means that we must insert a fake
- * CFG edge for loops with no break statement.
- *
- * The purpose of the second one is so that we have places to insert code during
- * GCM, as well as eliminating the possibility of critical edges.
- */
-/*@{*/
-
-static bool
-block_ends_in_jump(nir_block *block)
-{
- return !exec_list_is_empty(&block->instr_list) &&
- nir_block_last_instr(block)->type == nir_instr_type_jump;
-}
-
-static inline void
-block_add_pred(nir_block *block, nir_block *pred)
-{
- _mesa_set_add(block->predecessors, pred);
-}
-
-static inline void
-block_remove_pred(nir_block *block, nir_block *pred)
-{
- struct set_entry *entry = _mesa_set_search(block->predecessors, pred);
-
- assert(entry);
-
- _mesa_set_remove(block->predecessors, entry);
-}
-
-static void
-link_blocks(nir_block *pred, nir_block *succ1, nir_block *succ2)
-{
- pred->successors[0] = succ1;
- if (succ1 != NULL)
- block_add_pred(succ1, pred);
-
- pred->successors[1] = succ2;
- if (succ2 != NULL)
- block_add_pred(succ2, pred);
-}
-
-static void
-unlink_blocks(nir_block *pred, nir_block *succ)
-{
- if (pred->successors[0] == succ) {
- pred->successors[0] = pred->successors[1];
- pred->successors[1] = NULL;
- } else {
- assert(pred->successors[1] == succ);
- pred->successors[1] = NULL;
- }
-
- block_remove_pred(succ, pred);
-}
-
-static void
-unlink_block_successors(nir_block *block)
-{
- if (block->successors[1] != NULL)
- unlink_blocks(block, block->successors[1]);
- if (block->successors[0] != NULL)
- unlink_blocks(block, block->successors[0]);
-}
-
-static void
-link_non_block_to_block(nir_cf_node *node, nir_block *block)
-{
- if (node->type == nir_cf_node_if) {
- /*
- * We're trying to link an if to a block after it; this just means linking
- * the last block of the then and else branches.
- */
-
- nir_if *if_stmt = nir_cf_node_as_if(node);
-
- nir_cf_node *last_then = nir_if_last_then_node(if_stmt);
- assert(last_then->type == nir_cf_node_block);
- nir_block *last_then_block = nir_cf_node_as_block(last_then);
-
- nir_cf_node *last_else = nir_if_last_else_node(if_stmt);
- assert(last_else->type == nir_cf_node_block);
- nir_block *last_else_block = nir_cf_node_as_block(last_else);
-
- if (!block_ends_in_jump(last_then_block)) {
- unlink_block_successors(last_then_block);
- link_blocks(last_then_block, block, NULL);
- }
-
- if (!block_ends_in_jump(last_else_block)) {
- unlink_block_successors(last_else_block);
- link_blocks(last_else_block, block, NULL);
- }
- } else {
- assert(node->type == nir_cf_node_loop);
-
- /*
- * We can only get to this codepath if we're inserting a new loop, or
- * at least a loop with no break statements; we can't insert break
- * statements into a loop when we haven't inserted it into the CFG
- * because we wouldn't know which block comes after the loop
- * and therefore, which block should be the successor of the block with
- * the break). Therefore, we need to insert a fake edge (see invariant
- * #5).
- */
-
- nir_loop *loop = nir_cf_node_as_loop(node);
-
- nir_cf_node *last = nir_loop_last_cf_node(loop);
- assert(last->type == nir_cf_node_block);
- nir_block *last_block = nir_cf_node_as_block(last);
-
- last_block->successors[1] = block;
- block_add_pred(block, last_block);
- }
-}
-
-static void
-link_block_to_non_block(nir_block *block, nir_cf_node *node)
-{
- if (node->type == nir_cf_node_if) {
- /*
- * We're trying to link a block to an if after it; this just means linking
- * the block to the first block of the then and else branches.
- */
-
- nir_if *if_stmt = nir_cf_node_as_if(node);
-
- nir_cf_node *first_then = nir_if_first_then_node(if_stmt);
- assert(first_then->type == nir_cf_node_block);
- nir_block *first_then_block = nir_cf_node_as_block(first_then);
-
- nir_cf_node *first_else = nir_if_first_else_node(if_stmt);
- assert(first_else->type == nir_cf_node_block);
- nir_block *first_else_block = nir_cf_node_as_block(first_else);
-
- unlink_block_successors(block);
- link_blocks(block, first_then_block, first_else_block);
- } else {
- /*
- * For similar reasons as the corresponding case in
- * link_non_block_to_block(), don't worry about if the loop header has
- * any predecessors that need to be unlinked.
- */
-
- assert(node->type == nir_cf_node_loop);
-
- nir_loop *loop = nir_cf_node_as_loop(node);
-
- nir_cf_node *loop_header = nir_loop_first_cf_node(loop);
- assert(loop_header->type == nir_cf_node_block);
- nir_block *loop_header_block = nir_cf_node_as_block(loop_header);
-
- unlink_block_successors(block);
- link_blocks(block, loop_header_block, NULL);
- }
-
-}
-
-/**
- * Replace a block's successor with a different one.
- */
-static void
-replace_successor(nir_block *block, nir_block *old_succ, nir_block *new_succ)
-{
- if (block->successors[0] == old_succ) {
- block->successors[0] = new_succ;
- } else {
- assert(block->successors[1] == old_succ);
- block->successors[1] = new_succ;
- }
-
- block_remove_pred(old_succ, block);
- block_add_pred(new_succ, block);
-}
-
-/**
- * Takes a basic block and inserts a new empty basic block before it, making its
- * predecessors point to the new block. This essentially splits the block into
- * an empty header and a body so that another non-block CF node can be inserted
- * between the two. Note that this does *not* link the two basic blocks, so
- * some kind of cleanup *must* be performed after this call.
- */
-
-static nir_block *
-split_block_beginning(nir_block *block)
-{
- nir_block *new_block = nir_block_create(ralloc_parent(block));
- new_block->cf_node.parent = block->cf_node.parent;
- exec_node_insert_node_before(&block->cf_node.node, &new_block->cf_node.node);
-
- struct set_entry *entry;
- set_foreach(block->predecessors, entry) {
- nir_block *pred = (nir_block *) entry->key;
- replace_successor(pred, block, new_block);
- }
-
- /* Any phi nodes must stay part of the new block, or else their
- * sourcse will be messed up. This will reverse the order of the phi's, but
- * order shouldn't matter.
- */
- nir_foreach_instr_safe(block, instr) {
- if (instr->type != nir_instr_type_phi)
- break;
-
- exec_node_remove(&instr->node);
- instr->block = new_block;
- exec_list_push_head(&new_block->instr_list, &instr->node);
- }
-
- return new_block;
-}
-
-static void
-rewrite_phi_preds(nir_block *block, nir_block *old_pred, nir_block *new_pred)
-{
- nir_foreach_instr_safe(block, instr) {
- if (instr->type != nir_instr_type_phi)
- break;
-
- nir_phi_instr *phi = nir_instr_as_phi(instr);
- nir_foreach_phi_src(phi, src) {
- if (src->pred == old_pred) {
- src->pred = new_pred;
- break;
- }
- }
- }
-}
-
-static void
-insert_phi_undef(nir_block *block, nir_block *pred)
-{
- nir_function_impl *impl = nir_cf_node_get_function(&block->cf_node);
- nir_foreach_instr(block, instr) {
- if (instr->type != nir_instr_type_phi)
- break;
-
- nir_phi_instr *phi = nir_instr_as_phi(instr);
- nir_ssa_undef_instr *undef =
- nir_ssa_undef_instr_create(ralloc_parent(phi),
- phi->dest.ssa.num_components);
- nir_instr_insert_before_cf_list(&impl->body, &undef->instr);
- nir_phi_src *src = ralloc(phi, nir_phi_src);
- src->pred = pred;
- src->src.parent_instr = &phi->instr;
- src->src.is_ssa = true;
- src->src.ssa = &undef->def;
-
- list_addtail(&src->src.use_link, &undef->def.uses);
-
- exec_list_push_tail(&phi->srcs, &src->node);
- }
-}
-
-/**
- * Moves the successors of source to the successors of dest, leaving both
- * successors of source NULL.
- */
-
-static void
-move_successors(nir_block *source, nir_block *dest)
-{
- nir_block *succ1 = source->successors[0];
- nir_block *succ2 = source->successors[1];
-
- if (succ1) {
- unlink_blocks(source, succ1);
- rewrite_phi_preds(succ1, source, dest);
- }
-
- if (succ2) {
- unlink_blocks(source, succ2);
- rewrite_phi_preds(succ2, source, dest);
- }
-
- unlink_block_successors(dest);
- link_blocks(dest, succ1, succ2);
-}
-
-/* Given a basic block with no successors that has been inserted into the
- * control flow tree, gives it the successors it would normally have assuming
- * it doesn't end in a jump instruction. Also inserts phi sources with undefs
- * if necessary.
- */
-static void
-block_add_normal_succs(nir_block *block)
-{
- if (exec_node_is_tail_sentinel(block->cf_node.node.next)) {
- nir_cf_node *parent = block->cf_node.parent;
- if (parent->type == nir_cf_node_if) {
- nir_cf_node *next = nir_cf_node_next(parent);
- assert(next->type == nir_cf_node_block);
- nir_block *next_block = nir_cf_node_as_block(next);
-
- link_blocks(block, next_block, NULL);
- } else if (parent->type == nir_cf_node_loop) {
- nir_loop *loop = nir_cf_node_as_loop(parent);
-
- nir_cf_node *head = nir_loop_first_cf_node(loop);
- assert(head->type == nir_cf_node_block);
- nir_block *head_block = nir_cf_node_as_block(head);
-
- link_blocks(block, head_block, NULL);
- insert_phi_undef(head_block, block);
- } else {
- assert(parent->type == nir_cf_node_function);
- nir_function_impl *impl = nir_cf_node_as_function(parent);
- link_blocks(block, impl->end_block, NULL);
- }
- } else {
- nir_cf_node *next = nir_cf_node_next(&block->cf_node);
- if (next->type == nir_cf_node_if) {
- nir_if *next_if = nir_cf_node_as_if(next);
-
- nir_cf_node *first_then = nir_if_first_then_node(next_if);
- assert(first_then->type == nir_cf_node_block);
- nir_block *first_then_block = nir_cf_node_as_block(first_then);
-
- nir_cf_node *first_else = nir_if_first_else_node(next_if);
- assert(first_else->type == nir_cf_node_block);
- nir_block *first_else_block = nir_cf_node_as_block(first_else);
-
- link_blocks(block, first_then_block, first_else_block);
- } else {
- assert(next->type == nir_cf_node_loop);
- nir_loop *next_loop = nir_cf_node_as_loop(next);
-
- nir_cf_node *first = nir_loop_first_cf_node(next_loop);
- assert(first->type == nir_cf_node_block);
- nir_block *first_block = nir_cf_node_as_block(first);
-
- link_blocks(block, first_block, NULL);
- insert_phi_undef(first_block, block);
- }
- }
-}
-
-static nir_block *
-split_block_end(nir_block *block)
-{
- nir_block *new_block = nir_block_create(ralloc_parent(block));
- new_block->cf_node.parent = block->cf_node.parent;
- exec_node_insert_after(&block->cf_node.node, &new_block->cf_node.node);
-
- if (block_ends_in_jump(block)) {
- /* Figure out what successor block would've had if it didn't have a jump
- * instruction, and make new_block have that successor.
- */
- block_add_normal_succs(new_block);
- } else {
- move_successors(block, new_block);
- }
-
- return new_block;
-}
-
-static nir_block *
-split_block_before_instr(nir_instr *instr)
-{
- assert(instr->type != nir_instr_type_phi);
- nir_block *new_block = split_block_beginning(instr->block);
-
- nir_foreach_instr_safe(instr->block, cur_instr) {
- if (cur_instr == instr)
- break;
-
- exec_node_remove(&cur_instr->node);
- cur_instr->block = new_block;
- exec_list_push_tail(&new_block->instr_list, &cur_instr->node);
- }
-
- return new_block;
-}
-
-/* Splits a basic block at the point specified by the cursor. The "before" and
- * "after" arguments are filled out with the blocks resulting from the split
- * if non-NULL. Note that the "beginning" of the block is actually interpreted
- * as before the first non-phi instruction, and it's illegal to split a block
- * before a phi instruction.
- */
-
-static void
-split_block_cursor(nir_cursor cursor,
- nir_block **_before, nir_block **_after)
-{
- nir_block *before, *after;
- switch (cursor.option) {
- case nir_cursor_before_block:
- after = cursor.block;
- before = split_block_beginning(cursor.block);
- break;
-
- case nir_cursor_after_block:
- before = cursor.block;
- after = split_block_end(cursor.block);
- break;
-
- case nir_cursor_before_instr:
- after = cursor.instr->block;
- before = split_block_before_instr(cursor.instr);
- break;
-
- case nir_cursor_after_instr:
- /* We lower this to split_block_before_instr() so that we can keep the
- * after-a-jump-instr case contained to split_block_end().
- */
- if (nir_instr_is_last(cursor.instr)) {
- before = cursor.instr->block;
- after = split_block_end(cursor.instr->block);
- } else {
- after = cursor.instr->block;
- before = split_block_before_instr(nir_instr_next(cursor.instr));
- }
- break;
-
- default:
- unreachable("not reached");
- }
-
- if (_before)
- *_before = before;
- if (_after)
- *_after = after;
-}
-
-/**
- * Inserts a non-basic block between two basic blocks and links them together.
- */
-
-static void
-insert_non_block(nir_block *before, nir_cf_node *node, nir_block *after)
-{
- node->parent = before->cf_node.parent;
- exec_node_insert_after(&before->cf_node.node, &node->node);
- link_block_to_non_block(before, node);
- link_non_block_to_block(node, after);
-}
-
-/* walk up the control flow tree to find the innermost enclosed loop */
-static nir_loop *
-nearest_loop(nir_cf_node *node)
-{
- while (node->type != nir_cf_node_loop) {
- node = node->parent;
- }
-
- return nir_cf_node_as_loop(node);
-}
-
-/*
- * update the CFG after a jump instruction has been added to the end of a block
- */
-
-void
-nir_handle_add_jump(nir_block *block)
-{
- nir_instr *instr = nir_block_last_instr(block);
- nir_jump_instr *jump_instr = nir_instr_as_jump(instr);
-
- unlink_block_successors(block);
-
- nir_function_impl *impl = nir_cf_node_get_function(&block->cf_node);
- nir_metadata_preserve(impl, nir_metadata_none);
-
- if (jump_instr->type == nir_jump_break ||
- jump_instr->type == nir_jump_continue) {
- nir_loop *loop = nearest_loop(&block->cf_node);
-
- if (jump_instr->type == nir_jump_continue) {
- nir_cf_node *first_node = nir_loop_first_cf_node(loop);
- assert(first_node->type == nir_cf_node_block);
- nir_block *first_block = nir_cf_node_as_block(first_node);
- link_blocks(block, first_block, NULL);
- } else {
- nir_cf_node *after = nir_cf_node_next(&loop->cf_node);
- assert(after->type == nir_cf_node_block);
- nir_block *after_block = nir_cf_node_as_block(after);
- link_blocks(block, after_block, NULL);
-
- /* If we inserted a fake link, remove it */
- nir_cf_node *last = nir_loop_last_cf_node(loop);
- assert(last->type == nir_cf_node_block);
- nir_block *last_block = nir_cf_node_as_block(last);
- if (last_block->successors[1] != NULL)
- unlink_blocks(last_block, after_block);
- }
- } else {
- assert(jump_instr->type == nir_jump_return);
- link_blocks(block, impl->end_block, NULL);
- }
-}
-
-static void
-remove_phi_src(nir_block *block, nir_block *pred)
-{
- nir_foreach_instr(block, instr) {
- if (instr->type != nir_instr_type_phi)
- break;
-
- nir_phi_instr *phi = nir_instr_as_phi(instr);
- nir_foreach_phi_src_safe(phi, src) {
- if (src->pred == pred) {
- list_del(&src->src.use_link);
- exec_node_remove(&src->node);
- }
- }
- }
-}
-
-/* Removes the successor of a block with a jump, and inserts a fake edge for
- * infinite loops. Note that the jump to be eliminated may be free-floating.
- */
-
-static void
-unlink_jump(nir_block *block, nir_jump_type type, bool add_normal_successors)
-{
- nir_block *next = block->successors[0];
-
- if (block->successors[0])
- remove_phi_src(block->successors[0], block);
- if (block->successors[1])
- remove_phi_src(block->successors[1], block);
-
- unlink_block_successors(block);
- if (add_normal_successors)
- block_add_normal_succs(block);
-
- /* If we've just removed a break, and the block we were jumping to (after
- * the loop) now has zero predecessors, we've created a new infinite loop.
- *
- * NIR doesn't allow blocks (other than the start block) to have zero
- * predecessors. In particular, dominance assumes all blocks are reachable.
- * So, we insert a "fake link" by making successors[1] point after the loop.
- *
- * Note that we have to do this after unlinking/recreating the block's
- * successors. If we removed a "break" at the end of the loop, then
- * block == last_block, so block->successors[0] would already be "next",
- * and adding a fake link would create two identical successors. Doing
- * this afterward works, as we'll have changed block->successors[0] to
- * be the top of the loop.
- */
- if (type == nir_jump_break && next->predecessors->entries == 0) {
- nir_loop *loop =
- nir_cf_node_as_loop(nir_cf_node_prev(&next->cf_node));
-
- /* insert fake link */
- nir_cf_node *last = nir_loop_last_cf_node(loop);
- assert(last->type == nir_cf_node_block);
- nir_block *last_block = nir_cf_node_as_block(last);
-
- last_block->successors[1] = next;
- block_add_pred(next, last_block);
- }
-}
-
-void
-nir_handle_remove_jump(nir_block *block, nir_jump_type type)
-{
- unlink_jump(block, type, true);
-
- nir_function_impl *impl = nir_cf_node_get_function(&block->cf_node);
- nir_metadata_preserve(impl, nir_metadata_none);
-}
-
-static void
-update_if_uses(nir_cf_node *node)
-{
- if (node->type != nir_cf_node_if)
- return;
-
- nir_if *if_stmt = nir_cf_node_as_if(node);
-
- if_stmt->condition.parent_if = if_stmt;
- if (if_stmt->condition.is_ssa) {
- list_addtail(&if_stmt->condition.use_link,
- &if_stmt->condition.ssa->if_uses);
- } else {
- list_addtail(&if_stmt->condition.use_link,
- &if_stmt->condition.reg.reg->if_uses);
- }
-}
-
-/**
- * Stitch two basic blocks together into one. The aggregate must have the same
- * predecessors as the first and the same successors as the second.
- */
-
-static void
-stitch_blocks(nir_block *before, nir_block *after)
-{
- /*
- * We move after into before, so we have to deal with up to 2 successors vs.
- * possibly a large number of predecessors.
- *
- * TODO: special case when before is empty and after isn't?
- */
-
- if (block_ends_in_jump(before)) {
- assert(exec_list_is_empty(&after->instr_list));
- if (after->successors[0])
- remove_phi_src(after->successors[0], after);
- if (after->successors[1])
- remove_phi_src(after->successors[1], after);
- unlink_block_successors(after);
- exec_node_remove(&after->cf_node.node);
- } else {
- move_successors(after, before);
-
- foreach_list_typed(nir_instr, instr, node, &after->instr_list) {
- instr->block = before;
- }
-
- exec_list_append(&before->instr_list, &after->instr_list);
- exec_node_remove(&after->cf_node.node);
- }
-}
-
-void
-nir_cf_node_insert(nir_cursor cursor, nir_cf_node *node)
-{
- nir_block *before, *after;
-
- split_block_cursor(cursor, &before, &after);
-
- if (node->type == nir_cf_node_block) {
- nir_block *block = nir_cf_node_as_block(node);
- exec_node_insert_after(&before->cf_node.node, &block->cf_node.node);
- block->cf_node.parent = before->cf_node.parent;
- /* stitch_blocks() assumes that any block that ends with a jump has
- * already been setup with the correct successors, so we need to set
- * up jumps here as the block is being inserted.
- */
- if (block_ends_in_jump(block))
- nir_handle_add_jump(block);
-
- stitch_blocks(block, after);
- stitch_blocks(before, block);
- } else {
- update_if_uses(node);
- insert_non_block(before, node, after);
- }
-}
-
-static bool
-replace_ssa_def_uses(nir_ssa_def *def, void *void_impl)
-{
- nir_function_impl *impl = void_impl;
- void *mem_ctx = ralloc_parent(impl);
-
- nir_ssa_undef_instr *undef =
- nir_ssa_undef_instr_create(mem_ctx, def->num_components);
- nir_instr_insert_before_cf_list(&impl->body, &undef->instr);
- nir_ssa_def_rewrite_uses(def, nir_src_for_ssa(&undef->def));
- return true;
-}
-
-static void
-cleanup_cf_node(nir_cf_node *node, nir_function_impl *impl)
-{
- switch (node->type) {
- case nir_cf_node_block: {
- nir_block *block = nir_cf_node_as_block(node);
- /* We need to walk the instructions and clean up defs/uses */
- nir_foreach_instr_safe(block, instr) {
- if (instr->type == nir_instr_type_jump) {
- nir_jump_type jump_type = nir_instr_as_jump(instr)->type;
- unlink_jump(block, jump_type, false);
- } else {
- nir_foreach_ssa_def(instr, replace_ssa_def_uses, impl);
- nir_instr_remove(instr);
- }
- }
- break;
- }
-
- case nir_cf_node_if: {
- nir_if *if_stmt = nir_cf_node_as_if(node);
- foreach_list_typed(nir_cf_node, child, node, &if_stmt->then_list)
- cleanup_cf_node(child, impl);
- foreach_list_typed(nir_cf_node, child, node, &if_stmt->else_list)
- cleanup_cf_node(child, impl);
-
- list_del(&if_stmt->condition.use_link);
- break;
- }
-
- case nir_cf_node_loop: {
- nir_loop *loop = nir_cf_node_as_loop(node);
- foreach_list_typed(nir_cf_node, child, node, &loop->body)
- cleanup_cf_node(child, impl);
- break;
- }
- case nir_cf_node_function: {
- nir_function_impl *impl = nir_cf_node_as_function(node);
- foreach_list_typed(nir_cf_node, child, node, &impl->body)
- cleanup_cf_node(child, impl);
- break;
- }
- default:
- unreachable("Invalid CF node type");
- }
-}
-
-void
-nir_cf_extract(nir_cf_list *extracted, nir_cursor begin, nir_cursor end)
-{
- nir_block *block_begin, *block_end, *block_before, *block_after;
-
- if (nir_cursors_equal(begin, end)) {
- exec_list_make_empty(&extracted->list);
- extracted->impl = NULL; /* we shouldn't need this */
- return;
- }
-
- /* In the case where begin points to an instruction in some basic block and
- * end points to the end of the same basic block, we rely on the fact that
- * splitting on an instruction moves earlier instructions into a new basic
- * block. If the later instructions were moved instead, then the end cursor
- * would be pointing to the same place that begin used to point to, which
- * is obviously not what we want.
- */
- split_block_cursor(begin, &block_before, &block_begin);
- split_block_cursor(end, &block_end, &block_after);
-
- extracted->impl = nir_cf_node_get_function(&block_begin->cf_node);
- exec_list_make_empty(&extracted->list);
-
- /* Dominance and other block-related information is toast. */
- nir_metadata_preserve(extracted->impl, nir_metadata_none);
-
- nir_cf_node *cf_node = &block_begin->cf_node;
- nir_cf_node *cf_node_end = &block_end->cf_node;
- while (true) {
- nir_cf_node *next = nir_cf_node_next(cf_node);
-
- exec_node_remove(&cf_node->node);
- cf_node->parent = NULL;
- exec_list_push_tail(&extracted->list, &cf_node->node);
-
- if (cf_node == cf_node_end)
- break;
-
- cf_node = next;
- }
-
- stitch_blocks(block_before, block_after);
-}
-
-void
-nir_cf_reinsert(nir_cf_list *cf_list, nir_cursor cursor)
-{
- nir_block *before, *after;
-
- if (exec_list_is_empty(&cf_list->list))
- return;
-
- split_block_cursor(cursor, &before, &after);
-
- foreach_list_typed_safe(nir_cf_node, node, node, &cf_list->list) {
- exec_node_remove(&node->node);
- node->parent = before->cf_node.parent;
- exec_node_insert_node_before(&after->cf_node.node, &node->node);
- }
-
- stitch_blocks(before,
- nir_cf_node_as_block(nir_cf_node_next(&before->cf_node)));
- stitch_blocks(nir_cf_node_as_block(nir_cf_node_prev(&after->cf_node)),
- after);
-}
-
-void
-nir_cf_delete(nir_cf_list *cf_list)
-{
- foreach_list_typed(nir_cf_node, node, node, &cf_list->list) {
- cleanup_cf_node(node, cf_list->impl);
- }
-}
diff --git a/src/glsl/nir/nir_control_flow.h b/src/glsl/nir/nir_control_flow.h
deleted file mode 100644
index b71382fc597..00000000000
--- a/src/glsl/nir/nir_control_flow.h
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * Copyright © 2014 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- *
- * Authors:
- * Connor Abbott ([email protected])
- *
- */
-
-#include "nir.h"
-
-#pragma once
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/** NIR Control Flow Modification
- *
- * This file contains various API's that make modifying control flow in NIR,
- * while maintaining the invariants checked by the validator, much easier.
- * There are two parts to this:
- *
- * 1. Inserting control flow (if's and loops) in various places, for creating
- * IR either from scratch or as part of some lowering pass.
- * 2. Taking existing pieces of the IR and either moving them around or
- * deleting them.
- */
-
-/** Control flow insertion. */
-
-/** puts a control flow node where the cursor is */
-void nir_cf_node_insert(nir_cursor cursor, nir_cf_node *node);
-
-/** puts a control flow node immediately after another control flow node */
-static inline void
-nir_cf_node_insert_after(nir_cf_node *node, nir_cf_node *after)
-{
- nir_cf_node_insert(nir_after_cf_node(node), after);
-}
-
-/** puts a control flow node immediately before another control flow node */
-static inline void
-nir_cf_node_insert_before(nir_cf_node *node, nir_cf_node *before)
-{
- nir_cf_node_insert(nir_before_cf_node(node), before);
-}
-
-/** puts a control flow node at the beginning of a list from an if, loop, or function */
-static inline void
-nir_cf_node_insert_begin(struct exec_list *list, nir_cf_node *node)
-{
- nir_cf_node_insert(nir_before_cf_list(list), node);
-}
-
-/** puts a control flow node at the end of a list from an if, loop, or function */
-static inline void
-nir_cf_node_insert_end(struct exec_list *list, nir_cf_node *node)
-{
- nir_cf_node_insert(nir_after_cf_list(list), node);
-}
-
-
-/** Control flow motion.
- *
- * These functions let you take a part of a control flow list (basically
- * equivalent to a series of statement in GLSL) and "extract" it from the IR,
- * so that it's a free-floating piece of IR that can be either re-inserted
- * somewhere else or deleted entirely. A few notes on using it:
- *
- * 1. Phi nodes are considered attached to the piece of control flow that
- * their sources come from. There are three places where phi nodes can
- * occur, which are the three places where a block can have multiple
- * predecessors:
- *
- * 1) After an if statement, if neither branch ends in a jump.
- * 2) After a loop, if there are multiple break's.
- * 3) At the beginning of a loop.
- *
- * For #1, the phi node is considered to be part of the if, and for #2 and
- * #3 the phi node is considered to be part of the loop. This allows us to
- * keep phi's intact, but it means that phi nodes cannot be separated from
- * the control flow they come from. For example, extracting an if without
- * extracting all the phi nodes after it is not allowed, and neither is
- * extracting only some of the phi nodes at the beginning of a block. It
- * also means that extracting from the beginning of a basic block actually
- * means extracting from the first non-phi instruction, since there's no
- * situation where extracting phi nodes without extracting what comes
- * before them makes any sense.
- *
- * 2. Phi node sources are guaranteed to remain valid, meaning that they still
- * correspond one-to-one with the predecessors of the basic block they're
- * part of. In addition, the original sources will be preserved unless they
- * correspond to a break or continue that was deleted. However, no attempt
- * is made to ensure that SSA form is maintained. In particular, it is
- * *not* guaranteed that definitions of SSA values will dominate all their
- * uses after all is said and done. Either the caller must ensure that this
- * is the case, or it must insert extra phi nodes to restore SSA.
- *
- * 3. It is invalid to move a piece of IR with a break/continue outside of the
- * loop it references. Doing this will result in invalid
- * successors/predecessors and phi node sources.
- *
- * 4. It is invalid to move a piece of IR from one function implementation to
- * another.
- *
- * 5. Extracting a control flow list will leave lots of dangling references to
- * and from other pieces of the IR. It also leaves things in a not 100%
- * consistent state. This means that some things (e.g. inserting
- * instructions) might not work reliably on the extracted control flow. It
- * also means that extracting control flow without re-inserting it or
- * deleting it is a Bad Thing (tm).
- */
-
-typedef struct {
- struct exec_list list;
- nir_function_impl *impl; /* for cleaning up if the list is deleted */
-} nir_cf_list;
-
-void nir_cf_extract(nir_cf_list *extracted, nir_cursor begin, nir_cursor end);
-
-void nir_cf_reinsert(nir_cf_list *cf_list, nir_cursor cursor);
-
-void nir_cf_delete(nir_cf_list *cf_list);
-
-static inline void
-nir_cf_list_extract(nir_cf_list *extracted, struct exec_list *cf_list)
-{
- nir_cf_extract(extracted, nir_before_cf_list(cf_list),
- nir_after_cf_list(cf_list));
-}
-
-/** removes a control flow node, doing any cleanup necessary */
-static inline void
-nir_cf_node_remove(nir_cf_node *node)
-{
- nir_cf_list list;
- nir_cf_extract(&list, nir_before_cf_node(node), nir_after_cf_node(node));
- nir_cf_delete(&list);
-}
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/src/glsl/nir/nir_control_flow_private.h b/src/glsl/nir/nir_control_flow_private.h
deleted file mode 100644
index f32b57a8cef..00000000000
--- a/src/glsl/nir/nir_control_flow_private.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright © 2014 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- *
- * Authors:
- * Connor Abbott ([email protected])
- *
- */
-
-#include "nir_control_flow.h"
-
-#pragma once
-
-/* Internal control-flow modification functions used when inserting/removing
- * instructions.
- */
-
-void nir_handle_add_jump(nir_block *block);
-void nir_handle_remove_jump(nir_block *block, nir_jump_type type);
diff --git a/src/glsl/nir/nir_dominance.c b/src/glsl/nir/nir_dominance.c
deleted file mode 100644
index d95f3968074..00000000000
--- a/src/glsl/nir/nir_dominance.c
+++ /dev/null
@@ -1,354 +0,0 @@
-/*
- * Copyright © 2014 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- *
- * Authors:
- * Connor Abbott ([email protected])
- *
- */
-
-#include "nir.h"
-
-/*
- * Implements the algorithms for computing the dominance tree and the
- * dominance frontier from "A Simple, Fast Dominance Algorithm" by Cooper,
- * Harvey, and Kennedy.
- */
-
-typedef struct {
- nir_function_impl *impl;
- bool progress;
-} dom_state;
-
-static bool
-init_block_cb(nir_block *block, void *_state)
-{
- dom_state *state = (dom_state *) _state;
- if (block == nir_start_block(state->impl))
- block->imm_dom = block;
- else
- block->imm_dom = NULL;
- block->num_dom_children = 0;
-
- struct set_entry *entry;
- set_foreach(block->dom_frontier, entry) {
- _mesa_set_remove(block->dom_frontier, entry);
- }
-
- return true;
-}
-
-static nir_block *
-intersect(nir_block *b1, nir_block *b2)
-{
- while (b1 != b2) {
- /*
- * Note, the comparisons here are the opposite of what the paper says
- * because we index blocks from beginning -> end (i.e. reverse
- * post-order) instead of post-order like they assume.
- */
- while (b1->index > b2->index)
- b1 = b1->imm_dom;
- while (b2->index > b1->index)
- b2 = b2->imm_dom;
- }
-
- return b1;
-}
-
-static bool
-calc_dominance_cb(nir_block *block, void *_state)
-{
- dom_state *state = (dom_state *) _state;
- if (block == nir_start_block(state->impl))
- return true;
-
- nir_block *new_idom = NULL;
- struct set_entry *entry;
- set_foreach(block->predecessors, entry) {
- nir_block *pred = (nir_block *) entry->key;
-
- if (pred->imm_dom) {
- if (new_idom)
- new_idom = intersect(pred, new_idom);
- else
- new_idom = pred;
- }
- }
-
- if (block->imm_dom != new_idom) {
- block->imm_dom = new_idom;
- state->progress = true;
- }
-
- return true;
-}
-
-static bool
-calc_dom_frontier_cb(nir_block *block, void *state)
-{
- (void) state;
-
- if (block->predecessors->entries > 1) {
- struct set_entry *entry;
- set_foreach(block->predecessors, entry) {
- nir_block *runner = (nir_block *) entry->key;
-
- /* Skip unreachable predecessors */
- if (runner->imm_dom == NULL)
- continue;
-
- while (runner != block->imm_dom) {
- _mesa_set_add(runner->dom_frontier, block);
- runner = runner->imm_dom;
- }
- }
- }
-
- return true;
-}
-
-/*
- * Compute each node's children in the dominance tree from the immediate
- * dominator information. We do this in three stages:
- *
- * 1. Calculate the number of children each node has
- * 2. Allocate arrays, setting the number of children to 0 again
- * 3. For each node, add itself to its parent's list of children, using
- * num_dom_children as an index - at the end of this step, num_dom_children
- * for each node will be the same as it was at the end of step #1.
- */
-
-static bool
-block_count_children(nir_block *block, void *state)
-{
- (void) state;
-
- if (block->imm_dom)
- block->imm_dom->num_dom_children++;
-
- return true;
-}
-
-static bool
-block_alloc_children(nir_block *block, void *state)
-{
- void *mem_ctx = state;
-
- block->dom_children = ralloc_array(mem_ctx, nir_block *,
- block->num_dom_children);
- block->num_dom_children = 0;
-
- return true;
-}
-
-static bool
-block_add_child(nir_block *block, void *state)
-{
- (void) state;
-
- if (block->imm_dom)
- block->imm_dom->dom_children[block->imm_dom->num_dom_children++] = block;
-
- return true;
-}
-
-static void
-calc_dom_children(nir_function_impl* impl)
-{
- void *mem_ctx = ralloc_parent(impl);
-
- nir_foreach_block(impl, block_count_children, NULL);
- nir_foreach_block(impl, block_alloc_children, mem_ctx);
- nir_foreach_block(impl, block_add_child, NULL);
-}
-
-static void
-calc_dfs_indicies(nir_block *block, unsigned *index)
-{
- block->dom_pre_index = (*index)++;
-
- for (unsigned i = 0; i < block->num_dom_children; i++)
- calc_dfs_indicies(block->dom_children[i], index);
-
- block->dom_post_index = (*index)++;
-}
-
-void
-nir_calc_dominance_impl(nir_function_impl *impl)
-{
- if (impl->valid_metadata & nir_metadata_dominance)
- return;
-
- nir_metadata_require(impl, nir_metadata_block_index);
-
- dom_state state;
- state.impl = impl;
- state.progress = true;
-
- nir_foreach_block(impl, init_block_cb, &state);
-
- while (state.progress) {
- state.progress = false;
- nir_foreach_block(impl, calc_dominance_cb, &state);
- }
-
- nir_foreach_block(impl, calc_dom_frontier_cb, &state);
-
- nir_block *start_block = nir_start_block(impl);
- start_block->imm_dom = NULL;
-
- calc_dom_children(impl);
-
- unsigned dfs_index = 0;
- calc_dfs_indicies(start_block, &dfs_index);
-}
-
-void
-nir_calc_dominance(nir_shader *shader)
-{
- nir_foreach_function(shader, function) {
- if (function->impl)
- nir_calc_dominance_impl(function->impl);
- }
-}
-
-/**
- * Computes the least common anscestor of two blocks. If one of the blocks
- * is null, the other block is returned.
- */
-nir_block *
-nir_dominance_lca(nir_block *b1, nir_block *b2)
-{
- if (b1 == NULL)
- return b2;
-
- if (b2 == NULL)
- return b1;
-
- assert(nir_cf_node_get_function(&b1->cf_node) ==
- nir_cf_node_get_function(&b2->cf_node));
-
- assert(nir_cf_node_get_function(&b1->cf_node)->valid_metadata &
- nir_metadata_dominance);
-
- return intersect(b1, b2);
-}
-
-/**
- * Returns true if parent dominates child
- */
-bool
-nir_block_dominates(nir_block *parent, nir_block *child)
-{
- assert(nir_cf_node_get_function(&parent->cf_node) ==
- nir_cf_node_get_function(&child->cf_node));
-
- assert(nir_cf_node_get_function(&parent->cf_node)->valid_metadata &
- nir_metadata_dominance);
-
- return child->dom_pre_index >= parent->dom_pre_index &&
- child->dom_post_index <= parent->dom_post_index;
-}
-
-static bool
-dump_block_dom(nir_block *block, void *state)
-{
- FILE *fp = state;
- if (block->imm_dom)
- fprintf(fp, "\t%u -> %u\n", block->imm_dom->index, block->index);
- return true;
-}
-
-void
-nir_dump_dom_tree_impl(nir_function_impl *impl, FILE *fp)
-{
- fprintf(fp, "digraph doms_%s {\n", impl->function->name);
- nir_foreach_block(impl, dump_block_dom, fp);
- fprintf(fp, "}\n\n");
-}
-
-void
-nir_dump_dom_tree(nir_shader *shader, FILE *fp)
-{
- nir_foreach_function(shader, function) {
- if (function->impl)
- nir_dump_dom_tree_impl(function->impl, fp);
- }
-}
-
-static bool
-dump_block_dom_frontier(nir_block *block, void *state)
-{
- FILE *fp = state;
-
- fprintf(fp, "DF(%u) = {", block->index);
- struct set_entry *entry;
- set_foreach(block->dom_frontier, entry) {
- nir_block *df = (nir_block *) entry->key;
- fprintf(fp, "%u, ", df->index);
- }
- fprintf(fp, "}\n");
- return true;
-}
-
-void
-nir_dump_dom_frontier_impl(nir_function_impl *impl, FILE *fp)
-{
- nir_foreach_block(impl, dump_block_dom_frontier, fp);
-}
-
-void
-nir_dump_dom_frontier(nir_shader *shader, FILE *fp)
-{
- nir_foreach_function(shader, function) {
- if (function->impl)
- nir_dump_dom_frontier_impl(function->impl, fp);
- }
-}
-
-static bool
-dump_block_succs(nir_block *block, void *state)
-{
- FILE *fp = state;
- if (block->successors[0])
- fprintf(fp, "\t%u -> %u\n", block->index, block->successors[0]->index);
- if (block->successors[1])
- fprintf(fp, "\t%u -> %u\n", block->index, block->successors[1]->index);
- return true;
-}
-
-void
-nir_dump_cfg_impl(nir_function_impl *impl, FILE *fp)
-{
- fprintf(fp, "digraph cfg_%s {\n", impl->function->name);
- nir_foreach_block(impl, dump_block_succs, fp);
- fprintf(fp, "}\n\n");
-}
-
-void
-nir_dump_cfg(nir_shader *shader, FILE *fp)
-{
- nir_foreach_function(shader, function) {
- if (function->impl)
- nir_dump_cfg_impl(function->impl, fp);
- }
-}
diff --git a/src/glsl/nir/nir_from_ssa.c b/src/glsl/nir/nir_from_ssa.c
deleted file mode 100644
index 8bc9f24e406..00000000000
--- a/src/glsl/nir/nir_from_ssa.c
+++ /dev/null
@@ -1,805 +0,0 @@
-/*
- * Copyright © 2014 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- *
- * Authors:
- * Jason Ekstrand ([email protected])
- *
- */
-
-#include "nir.h"
-#include "nir_vla.h"
-
-/*
- * This file implements an out-of-SSA pass as described in "Revisiting
- * Out-of-SSA Translation for Correctness, Code Quality, and Efficiency" by
- * Boissinot et. al.
- */
-
-struct from_ssa_state {
- void *mem_ctx;
- void *dead_ctx;
- bool phi_webs_only;
- struct hash_table *merge_node_table;
- nir_instr *instr;
- nir_function_impl *impl;
-};
-
-/* Returns true if a dominates b */
-static bool
-ssa_def_dominates(nir_ssa_def *a, nir_ssa_def *b)
-{
- if (a->live_index == 0) {
- /* SSA undefs always dominate */
- return true;
- } else if (b->live_index < a->live_index) {
- return false;
- } else if (a->parent_instr->block == b->parent_instr->block) {
- return a->live_index <= b->live_index;
- } else {
- return nir_block_dominates(a->parent_instr->block,
- b->parent_instr->block);
- }
-}
-
-
-/* The following data structure, which I have named merge_set is a way of
- * representing a set registers of non-interfering registers. This is
- * based on the concept of a "dominence forest" presented in "Fast Copy
- * Coalescing and Live-Range Identification" by Budimlic et. al. but the
- * implementation concept is taken from "Revisiting Out-of-SSA Translation
- * for Correctness, Code Quality, and Efficiency" by Boissinot et. al..
- *
- * Each SSA definition is associated with a merge_node and the association
- * is represented by a combination of a hash table and the "def" parameter
- * in the merge_node structure. The merge_set stores a linked list of
- * merge_node's in dominence order of the ssa definitions. (Since the
- * liveness analysis pass indexes the SSA values in dominence order for us,
- * this is an easy thing to keep up.) It is assumed that no pair of the
- * nodes in a given set interfere. Merging two sets or checking for
- * interference can be done in a single linear-time merge-sort walk of the
- * two lists of nodes.
- */
-struct merge_set;
-
-typedef struct {
- struct exec_node node;
- struct merge_set *set;
- nir_ssa_def *def;
-} merge_node;
-
-typedef struct merge_set {
- struct exec_list nodes;
- unsigned size;
- nir_register *reg;
-} merge_set;
-
-#if 0
-static void
-merge_set_dump(merge_set *set, FILE *fp)
-{
- nir_ssa_def *dom[set->size];
- int dom_idx = -1;
-
- foreach_list_typed(merge_node, node, node, &set->nodes) {
- while (dom_idx >= 0 && !ssa_def_dominates(dom[dom_idx], node->def))
- dom_idx--;
-
- for (int i = 0; i <= dom_idx; i++)
- fprintf(fp, " ");
-
- if (node->def->name)
- fprintf(fp, "ssa_%d /* %s */\n", node->def->index, node->def->name);
- else
- fprintf(fp, "ssa_%d\n", node->def->index);
-
- dom[++dom_idx] = node->def;
- }
-}
-#endif
-
-static merge_node *
-get_merge_node(nir_ssa_def *def, struct from_ssa_state *state)
-{
- struct hash_entry *entry =
- _mesa_hash_table_search(state->merge_node_table, def);
- if (entry)
- return entry->data;
-
- merge_set *set = ralloc(state->dead_ctx, merge_set);
- exec_list_make_empty(&set->nodes);
- set->size = 1;
- set->reg = NULL;
-
- merge_node *node = ralloc(state->dead_ctx, merge_node);
- node->set = set;
- node->def = def;
- exec_list_push_head(&set->nodes, &node->node);
-
- _mesa_hash_table_insert(state->merge_node_table, def, node);
-
- return node;
-}
-
-static bool
-merge_nodes_interfere(merge_node *a, merge_node *b)
-{
- return nir_ssa_defs_interfere(a->def, b->def);
-}
-
-/* Merges b into a */
-static merge_set *
-merge_merge_sets(merge_set *a, merge_set *b)
-{
- struct exec_node *an = exec_list_get_head(&a->nodes);
- struct exec_node *bn = exec_list_get_head(&b->nodes);
- while (!exec_node_is_tail_sentinel(bn)) {
- merge_node *a_node = exec_node_data(merge_node, an, node);
- merge_node *b_node = exec_node_data(merge_node, bn, node);
-
- if (exec_node_is_tail_sentinel(an) ||
- a_node->def->live_index > b_node->def->live_index) {
- struct exec_node *next = bn->next;
- exec_node_remove(bn);
- exec_node_insert_node_before(an, bn);
- exec_node_data(merge_node, bn, node)->set = a;
- bn = next;
- } else {
- an = an->next;
- }
- }
-
- a->size += b->size;
- b->size = 0;
-
- return a;
-}
-
-/* Checks for any interference between two merge sets
- *
- * This is an implementation of Algorithm 2 in "Revisiting Out-of-SSA
- * Translation for Correctness, Code Quality, and Efficiency" by
- * Boissinot et. al.
- */
-static bool
-merge_sets_interfere(merge_set *a, merge_set *b)
-{
- NIR_VLA(merge_node *, dom, a->size + b->size);
- int dom_idx = -1;
-
- struct exec_node *an = exec_list_get_head(&a->nodes);
- struct exec_node *bn = exec_list_get_head(&b->nodes);
- while (!exec_node_is_tail_sentinel(an) ||
- !exec_node_is_tail_sentinel(bn)) {
-
- merge_node *current;
- if (exec_node_is_tail_sentinel(an)) {
- current = exec_node_data(merge_node, bn, node);
- bn = bn->next;
- } else if (exec_node_is_tail_sentinel(bn)) {
- current = exec_node_data(merge_node, an, node);
- an = an->next;
- } else {
- merge_node *a_node = exec_node_data(merge_node, an, node);
- merge_node *b_node = exec_node_data(merge_node, bn, node);
-
- if (a_node->def->live_index <= b_node->def->live_index) {
- current = a_node;
- an = an->next;
- } else {
- current = b_node;
- bn = bn->next;
- }
- }
-
- while (dom_idx >= 0 &&
- !ssa_def_dominates(dom[dom_idx]->def, current->def))
- dom_idx--;
-
- if (dom_idx >= 0 && merge_nodes_interfere(current, dom[dom_idx]))
- return true;
-
- dom[++dom_idx] = current;
- }
-
- return false;
-}
-
-static bool
-add_parallel_copy_to_end_of_block(nir_block *block, void *void_state)
-{
- struct from_ssa_state *state = void_state;
-
- bool need_end_copy = false;
- if (block->successors[0]) {
- nir_instr *instr = nir_block_first_instr(block->successors[0]);
- if (instr && instr->type == nir_instr_type_phi)
- need_end_copy = true;
- }
-
- if (block->successors[1]) {
- nir_instr *instr = nir_block_first_instr(block->successors[1]);
- if (instr && instr->type == nir_instr_type_phi)
- need_end_copy = true;
- }
-
- if (need_end_copy) {
- /* If one of our successors has at least one phi node, we need to
- * create a parallel copy at the end of the block but before the jump
- * (if there is one).
- */
- nir_parallel_copy_instr *pcopy =
- nir_parallel_copy_instr_create(state->dead_ctx);
-
- nir_instr_insert(nir_after_block_before_jump(block), &pcopy->instr);
- }
-
- return true;
-}
-
-static nir_parallel_copy_instr *
-get_parallel_copy_at_end_of_block(nir_block *block)
-{
- nir_instr *last_instr = nir_block_last_instr(block);
- if (last_instr == NULL)
- return NULL;
-
- /* The last instruction may be a jump in which case the parallel copy is
- * right before it.
- */
- if (last_instr->type == nir_instr_type_jump)
- last_instr = nir_instr_prev(last_instr);
-
- if (last_instr && last_instr->type == nir_instr_type_parallel_copy)
- return nir_instr_as_parallel_copy(last_instr);
- else
- return NULL;
-}
-
-/** Isolate phi nodes with parallel copies
- *
- * In order to solve the dependency problems with the sources and
- * destinations of phi nodes, we first isolate them by adding parallel
- * copies to the beginnings and ends of basic blocks. For every block with
- * phi nodes, we add a parallel copy immediately following the last phi
- * node that copies the destinations of all of the phi nodes to new SSA
- * values. We also add a parallel copy to the end of every block that has
- * a successor with phi nodes that, for each phi node in each successor,
- * copies the corresponding sorce of the phi node and adjust the phi to
- * used the destination of the parallel copy.
- *
- * In SSA form, each value has exactly one definition. What this does is
- * ensure that each value used in a phi also has exactly one use. The
- * destinations of phis are only used by the parallel copy immediately
- * following the phi nodes and. Thanks to the parallel copy at the end of
- * the predecessor block, the sources of phi nodes are are the only use of
- * that value. This allows us to immediately assign all the sources and
- * destinations of any given phi node to the same register without worrying
- * about interference at all. We do coalescing to get rid of the parallel
- * copies where possible.
- *
- * Before this pass can be run, we have to iterate over the blocks with
- * add_parallel_copy_to_end_of_block to ensure that the parallel copies at
- * the ends of blocks exist. We can create the ones at the beginnings as
- * we go, but the ones at the ends of blocks need to be created ahead of
- * time because of potential back-edges in the CFG.
- */
-static bool
-isolate_phi_nodes_block(nir_block *block, void *void_state)
-{
- struct from_ssa_state *state = void_state;
-
- nir_instr *last_phi_instr = NULL;
- nir_foreach_instr(block, instr) {
- /* Phi nodes only ever come at the start of a block */
- if (instr->type != nir_instr_type_phi)
- break;
-
- last_phi_instr = instr;
- }
-
- /* If we don't have any phi's, then there's nothing for us to do. */
- if (last_phi_instr == NULL)
- return true;
-
- /* If we have phi nodes, we need to create a parallel copy at the
- * start of this block but after the phi nodes.
- */
- nir_parallel_copy_instr *block_pcopy =
- nir_parallel_copy_instr_create(state->dead_ctx);
- nir_instr_insert_after(last_phi_instr, &block_pcopy->instr);
-
- nir_foreach_instr(block, instr) {
- /* Phi nodes only ever come at the start of a block */
- if (instr->type != nir_instr_type_phi)
- break;
-
- nir_phi_instr *phi = nir_instr_as_phi(instr);
- assert(phi->dest.is_ssa);
- nir_foreach_phi_src(phi, src) {
- nir_parallel_copy_instr *pcopy =
- get_parallel_copy_at_end_of_block(src->pred);
- assert(pcopy);
-
- nir_parallel_copy_entry *entry = rzalloc(state->dead_ctx,
- nir_parallel_copy_entry);
- nir_ssa_dest_init(&pcopy->instr, &entry->dest,
- phi->dest.ssa.num_components, src->src.ssa->name);
- exec_list_push_tail(&pcopy->entries, &entry->node);
-
- assert(src->src.is_ssa);
- nir_instr_rewrite_src(&pcopy->instr, &entry->src, src->src);
-
- nir_instr_rewrite_src(&phi->instr, &src->src,
- nir_src_for_ssa(&entry->dest.ssa));
- }
-
- nir_parallel_copy_entry *entry = rzalloc(state->dead_ctx,
- nir_parallel_copy_entry);
- nir_ssa_dest_init(&block_pcopy->instr, &entry->dest,
- phi->dest.ssa.num_components, phi->dest.ssa.name);
- exec_list_push_tail(&block_pcopy->entries, &entry->node);
-
- nir_ssa_def_rewrite_uses(&phi->dest.ssa,
- nir_src_for_ssa(&entry->dest.ssa));
-
- nir_instr_rewrite_src(&block_pcopy->instr, &entry->src,
- nir_src_for_ssa(&phi->dest.ssa));
- }
-
- return true;
-}
-
-static bool
-coalesce_phi_nodes_block(nir_block *block, void *void_state)
-{
- struct from_ssa_state *state = void_state;
-
- nir_foreach_instr(block, instr) {
- /* Phi nodes only ever come at the start of a block */
- if (instr->type != nir_instr_type_phi)
- break;
-
- nir_phi_instr *phi = nir_instr_as_phi(instr);
-
- assert(phi->dest.is_ssa);
- merge_node *dest_node = get_merge_node(&phi->dest.ssa, state);
-
- nir_foreach_phi_src(phi, src) {
- assert(src->src.is_ssa);
- merge_node *src_node = get_merge_node(src->src.ssa, state);
- if (src_node->set != dest_node->set)
- merge_merge_sets(dest_node->set, src_node->set);
- }
- }
-
- return true;
-}
-
-static void
-aggressive_coalesce_parallel_copy(nir_parallel_copy_instr *pcopy,
- struct from_ssa_state *state)
-{
- nir_foreach_parallel_copy_entry(pcopy, entry) {
- if (!entry->src.is_ssa)
- continue;
-
- /* Since load_const instructions are SSA only, we can't replace their
- * destinations with registers and, therefore, can't coalesce them.
- */
- if (entry->src.ssa->parent_instr->type == nir_instr_type_load_const)
- continue;
-
- /* Don't try and coalesce these */
- if (entry->dest.ssa.num_components != entry->src.ssa->num_components)
- continue;
-
- merge_node *src_node = get_merge_node(entry->src.ssa, state);
- merge_node *dest_node = get_merge_node(&entry->dest.ssa, state);
-
- if (src_node->set == dest_node->set)
- continue;
-
- if (!merge_sets_interfere(src_node->set, dest_node->set))
- merge_merge_sets(src_node->set, dest_node->set);
- }
-}
-
-static bool
-aggressive_coalesce_block(nir_block *block, void *void_state)
-{
- struct from_ssa_state *state = void_state;
-
- nir_parallel_copy_instr *start_pcopy = NULL;
- nir_foreach_instr(block, instr) {
- /* Phi nodes only ever come at the start of a block */
- if (instr->type != nir_instr_type_phi) {
- if (instr->type != nir_instr_type_parallel_copy)
- break; /* The parallel copy must be right after the phis */
-
- start_pcopy = nir_instr_as_parallel_copy(instr);
-
- aggressive_coalesce_parallel_copy(start_pcopy, state);
-
- break;
- }
- }
-
- nir_parallel_copy_instr *end_pcopy =
- get_parallel_copy_at_end_of_block(block);
-
- if (end_pcopy && end_pcopy != start_pcopy)
- aggressive_coalesce_parallel_copy(end_pcopy, state);
-
- return true;
-}
-
-static bool
-rewrite_ssa_def(nir_ssa_def *def, void *void_state)
-{
- struct from_ssa_state *state = void_state;
- nir_register *reg;
-
- struct hash_entry *entry =
- _mesa_hash_table_search(state->merge_node_table, def);
- if (entry) {
- /* In this case, we're part of a phi web. Use the web's register. */
- merge_node *node = (merge_node *)entry->data;
-
- /* If it doesn't have a register yet, create one. Note that all of
- * the things in the merge set should be the same so it doesn't
- * matter which node's definition we use.
- */
- if (node->set->reg == NULL) {
- node->set->reg = nir_local_reg_create(state->impl);
- node->set->reg->name = def->name;
- node->set->reg->num_components = def->num_components;
- node->set->reg->num_array_elems = 0;
- }
-
- reg = node->set->reg;
- } else {
- if (state->phi_webs_only)
- return true;
-
- /* We leave load_const SSA values alone. They act as immediates to
- * the backend. If it got coalesced into a phi, that's ok.
- */
- if (def->parent_instr->type == nir_instr_type_load_const)
- return true;
-
- reg = nir_local_reg_create(state->impl);
- reg->name = def->name;
- reg->num_components = def->num_components;
- reg->num_array_elems = 0;
- }
-
- nir_ssa_def_rewrite_uses(def, nir_src_for_reg(reg));
- assert(list_empty(&def->uses) && list_empty(&def->if_uses));
-
- if (def->parent_instr->type == nir_instr_type_ssa_undef) {
- /* If it's an ssa_undef instruction, remove it since we know we just got
- * rid of all its uses.
- */
- nir_instr *parent_instr = def->parent_instr;
- nir_instr_remove(parent_instr);
- ralloc_steal(state->dead_ctx, parent_instr);
- return true;
- }
-
- assert(def->parent_instr->type != nir_instr_type_load_const);
-
- /* At this point we know a priori that this SSA def is part of a
- * nir_dest. We can use exec_node_data to get the dest pointer.
- */
- nir_dest *dest = exec_node_data(nir_dest, def, ssa);
-
- nir_instr_rewrite_dest(state->instr, dest, nir_dest_for_reg(reg));
-
- return true;
-}
-
-/* Resolves ssa definitions to registers. While we're at it, we also
- * remove phi nodes.
- */
-static bool
-resolve_registers_block(nir_block *block, void *void_state)
-{
- struct from_ssa_state *state = void_state;
-
- nir_foreach_instr_safe(block, instr) {
- state->instr = instr;
- nir_foreach_ssa_def(instr, rewrite_ssa_def, state);
-
- if (instr->type == nir_instr_type_phi) {
- nir_instr_remove(instr);
- ralloc_steal(state->dead_ctx, instr);
- }
- }
- state->instr = NULL;
-
- return true;
-}
-
-static void
-emit_copy(nir_parallel_copy_instr *pcopy, nir_src src, nir_src dest_src,
- void *mem_ctx)
-{
- assert(!dest_src.is_ssa &&
- dest_src.reg.indirect == NULL &&
- dest_src.reg.base_offset == 0);
-
- if (src.is_ssa)
- assert(src.ssa->num_components >= dest_src.reg.reg->num_components);
- else
- assert(src.reg.reg->num_components >= dest_src.reg.reg->num_components);
-
- nir_alu_instr *mov = nir_alu_instr_create(mem_ctx, nir_op_imov);
- nir_src_copy(&mov->src[0].src, &src, mov);
- mov->dest.dest = nir_dest_for_reg(dest_src.reg.reg);
- mov->dest.write_mask = (1 << dest_src.reg.reg->num_components) - 1;
-
- nir_instr_insert_before(&pcopy->instr, &mov->instr);
-}
-
-/* Resolves a single parallel copy operation into a sequence of mov's
- *
- * This is based on Algorithm 1 from "Revisiting Out-of-SSA Translation for
- * Correctness, Code Quality, and Efficiency" by Boissinot et. al..
- * However, I never got the algorithm to work as written, so this version
- * is slightly modified.
- *
- * The algorithm works by playing this little shell game with the values.
- * We start by recording where every source value is and which source value
- * each destination value should receive. We then grab any copy whose
- * destination is "empty", i.e. not used as a source, and do the following:
- * - Find where its source value currently lives
- * - Emit the move instruction
- * - Set the location of the source value to the destination
- * - Mark the location containing the source value
- * - Mark the destination as no longer needing to be copied
- *
- * When we run out of "empty" destinations, we have a cycle and so we
- * create a temporary register, copy to that register, and mark the value
- * we copied as living in that temporary. Now, the cycle is broken, so we
- * can continue with the above steps.
- */
-static void
-resolve_parallel_copy(nir_parallel_copy_instr *pcopy,
- struct from_ssa_state *state)
-{
- unsigned num_copies = 0;
- nir_foreach_parallel_copy_entry(pcopy, entry) {
- /* Sources may be SSA */
- if (!entry->src.is_ssa && entry->src.reg.reg == entry->dest.reg.reg)
- continue;
-
- num_copies++;
- }
-
- if (num_copies == 0) {
- /* Hooray, we don't need any copies! */
- nir_instr_remove(&pcopy->instr);
- return;
- }
-
- /* The register/source corresponding to the given index */
- NIR_VLA_ZERO(nir_src, values, num_copies * 2);
-
- /* The current location of a given piece of data. We will use -1 for "null" */
- NIR_VLA_FILL(int, loc, num_copies * 2, -1);
-
- /* The piece of data that the given piece of data is to be copied from. We will use -1 for "null" */
- NIR_VLA_FILL(int, pred, num_copies * 2, -1);
-
- /* The destinations we have yet to properly fill */
- NIR_VLA(int, to_do, num_copies * 2);
- int to_do_idx = -1;
-
- /* Now we set everything up:
- * - All values get assigned a temporary index
- * - Current locations are set from sources
- * - Predicessors are recorded from sources and destinations
- */
- int num_vals = 0;
- nir_foreach_parallel_copy_entry(pcopy, entry) {
- /* Sources may be SSA */
- if (!entry->src.is_ssa && entry->src.reg.reg == entry->dest.reg.reg)
- continue;
-
- int src_idx = -1;
- for (int i = 0; i < num_vals; ++i) {
- if (nir_srcs_equal(values[i], entry->src))
- src_idx = i;
- }
- if (src_idx < 0) {
- src_idx = num_vals++;
- values[src_idx] = entry->src;
- }
-
- nir_src dest_src = nir_src_for_reg(entry->dest.reg.reg);
-
- int dest_idx = -1;
- for (int i = 0; i < num_vals; ++i) {
- if (nir_srcs_equal(values[i], dest_src)) {
- /* Each destination of a parallel copy instruction should be
- * unique. A destination may get used as a source, so we still
- * have to walk the list. However, the predecessor should not,
- * at this point, be set yet, so we should have -1 here.
- */
- assert(pred[i] == -1);
- dest_idx = i;
- }
- }
- if (dest_idx < 0) {
- dest_idx = num_vals++;
- values[dest_idx] = dest_src;
- }
-
- loc[src_idx] = src_idx;
- pred[dest_idx] = src_idx;
-
- to_do[++to_do_idx] = dest_idx;
- }
-
- /* Currently empty destinations we can go ahead and fill */
- NIR_VLA(int, ready, num_copies * 2);
- int ready_idx = -1;
-
- /* Mark the ones that are ready for copying. We know an index is a
- * destination if it has a predecessor and it's ready for copying if
- * it's not marked as containing data.
- */
- for (int i = 0; i < num_vals; i++) {
- if (pred[i] != -1 && loc[i] == -1)
- ready[++ready_idx] = i;
- }
-
- while (to_do_idx >= 0) {
- while (ready_idx >= 0) {
- int b = ready[ready_idx--];
- int a = pred[b];
- emit_copy(pcopy, values[loc[a]], values[b], state->mem_ctx);
-
- /* If any other copies want a they can find it at b */
- loc[a] = b;
-
- /* b has been filled, mark it as not needing to be copied */
- pred[b] = -1;
-
- /* If a needs to be filled, it's ready for copying now */
- if (pred[a] != -1)
- ready[++ready_idx] = a;
- }
- int b = to_do[to_do_idx--];
- if (pred[b] == -1)
- continue;
-
- /* If we got here, then we don't have any more trivial copies that we
- * can do. We have to break a cycle, so we create a new temporary
- * register for that purpose. Normally, if going out of SSA after
- * register allocation, you would want to avoid creating temporary
- * registers. However, we are going out of SSA before register
- * allocation, so we would rather not create extra register
- * dependencies for the backend to deal with. If it wants, the
- * backend can coalesce the (possibly multiple) temporaries.
- */
- assert(num_vals < num_copies * 2);
- nir_register *reg = nir_local_reg_create(state->impl);
- reg->name = "copy_temp";
- reg->num_array_elems = 0;
- if (values[b].is_ssa)
- reg->num_components = values[b].ssa->num_components;
- else
- reg->num_components = values[b].reg.reg->num_components;
- values[num_vals].is_ssa = false;
- values[num_vals].reg.reg = reg;
-
- emit_copy(pcopy, values[b], values[num_vals], state->mem_ctx);
- loc[b] = num_vals;
- ready[++ready_idx] = b;
- num_vals++;
- }
-
- nir_instr_remove(&pcopy->instr);
-}
-
-/* Resolves the parallel copies in a block. Each block can have at most
- * two: One at the beginning, right after all the phi noces, and one at
- * the end (or right before the final jump if it exists).
- */
-static bool
-resolve_parallel_copies_block(nir_block *block, void *void_state)
-{
- struct from_ssa_state *state = void_state;
-
- /* At this point, we have removed all of the phi nodes. If a parallel
- * copy existed right after the phi nodes in this block, it is now the
- * first instruction.
- */
- nir_instr *first_instr = nir_block_first_instr(block);
- if (first_instr == NULL)
- return true; /* Empty, nothing to do. */
-
- if (first_instr->type == nir_instr_type_parallel_copy) {
- nir_parallel_copy_instr *pcopy = nir_instr_as_parallel_copy(first_instr);
-
- resolve_parallel_copy(pcopy, state);
- }
-
- /* It's possible that the above code already cleaned up the end parallel
- * copy. However, doing so removed it form the instructions list so we
- * won't find it here. Therefore, it's safe to go ahead and just look
- * for one and clean it up if it exists.
- */
- nir_parallel_copy_instr *end_pcopy =
- get_parallel_copy_at_end_of_block(block);
- if (end_pcopy)
- resolve_parallel_copy(end_pcopy, state);
-
- return true;
-}
-
-static void
-nir_convert_from_ssa_impl(nir_function_impl *impl, bool phi_webs_only)
-{
- struct from_ssa_state state;
-
- state.mem_ctx = ralloc_parent(impl);
- state.dead_ctx = ralloc_context(NULL);
- state.impl = impl;
- state.phi_webs_only = phi_webs_only;
- state.merge_node_table = _mesa_hash_table_create(NULL, _mesa_hash_pointer,
- _mesa_key_pointer_equal);
-
- nir_foreach_block(impl, add_parallel_copy_to_end_of_block, &state);
- nir_foreach_block(impl, isolate_phi_nodes_block, &state);
-
- /* Mark metadata as dirty before we ask for liveness analysis */
- nir_metadata_preserve(impl, nir_metadata_block_index |
- nir_metadata_dominance);
-
- nir_metadata_require(impl, nir_metadata_live_ssa_defs |
- nir_metadata_dominance);
-
- nir_foreach_block(impl, coalesce_phi_nodes_block, &state);
- nir_foreach_block(impl, aggressive_coalesce_block, &state);
-
- nir_foreach_block(impl, resolve_registers_block, &state);
-
- nir_foreach_block(impl, resolve_parallel_copies_block, &state);
-
- nir_metadata_preserve(impl, nir_metadata_block_index |
- nir_metadata_dominance);
-
- /* Clean up dead instructions and the hash tables */
- _mesa_hash_table_destroy(state.merge_node_table, NULL);
- ralloc_free(state.dead_ctx);
-}
-
-void
-nir_convert_from_ssa(nir_shader *shader, bool phi_webs_only)
-{
- nir_foreach_function(shader, function) {
- if (function->impl)
- nir_convert_from_ssa_impl(function->impl, phi_webs_only);
- }
-}
diff --git a/src/glsl/nir/nir_gather_info.c b/src/glsl/nir/nir_gather_info.c
deleted file mode 100644
index b84915c2d2b..00000000000
--- a/src/glsl/nir/nir_gather_info.c
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Copyright © 2015 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include "nir.h"
-
-static void
-gather_intrinsic_info(nir_intrinsic_instr *instr, nir_shader *shader)
-{
- switch (instr->intrinsic) {
- case nir_intrinsic_discard:
- assert(shader->stage == MESA_SHADER_FRAGMENT);
- shader->info.fs.uses_discard = true;
- break;
-
- case nir_intrinsic_load_front_face:
- case nir_intrinsic_load_vertex_id:
- case nir_intrinsic_load_vertex_id_zero_base:
- case nir_intrinsic_load_base_vertex:
- case nir_intrinsic_load_instance_id:
- case nir_intrinsic_load_sample_id:
- case nir_intrinsic_load_sample_pos:
- case nir_intrinsic_load_sample_mask_in:
- case nir_intrinsic_load_primitive_id:
- case nir_intrinsic_load_invocation_id:
- case nir_intrinsic_load_local_invocation_id:
- case nir_intrinsic_load_work_group_id:
- case nir_intrinsic_load_num_work_groups:
- shader->info.system_values_read |=
- (1 << nir_system_value_from_intrinsic(instr->intrinsic));
- break;
-
- case nir_intrinsic_end_primitive:
- case nir_intrinsic_end_primitive_with_counter:
- assert(shader->stage == MESA_SHADER_GEOMETRY);
- shader->info.gs.uses_end_primitive = 1;
- break;
-
- default:
- break;
- }
-}
-
-static void
-gather_tex_info(nir_tex_instr *instr, nir_shader *shader)
-{
- if (instr->op == nir_texop_tg4)
- shader->info.uses_texture_gather = true;
-}
-
-static bool
-gather_info_block(nir_block *block, void *shader)
-{
- nir_foreach_instr(block, instr) {
- switch (instr->type) {
- case nir_instr_type_intrinsic:
- gather_intrinsic_info(nir_instr_as_intrinsic(instr), shader);
- break;
- case nir_instr_type_tex:
- gather_tex_info(nir_instr_as_tex(instr), shader);
- break;
- case nir_instr_type_call:
- assert(!"nir_shader_gather_info only works if functions are inlined");
- break;
- default:
- break;
- }
- }
-
- return true;
-}
-
-void
-nir_shader_gather_info(nir_shader *shader, nir_function_impl *entrypoint)
-{
- shader->info.inputs_read = 0;
- foreach_list_typed(nir_variable, var, node, &shader->inputs)
- shader->info.inputs_read |= nir_variable_get_io_mask(var, shader->stage);
-
- /* TODO: Some day we may need to add stream support to NIR */
- shader->info.outputs_written = 0;
- foreach_list_typed(nir_variable, var, node, &shader->outputs)
- shader->info.outputs_written |= nir_variable_get_io_mask(var, shader->stage);
-
- shader->info.system_values_read = 0;
- foreach_list_typed(nir_variable, var, node, &shader->system_values)
- shader->info.system_values_read |= nir_variable_get_io_mask(var, shader->stage);
-
- nir_foreach_block(entrypoint, gather_info_block, shader);
-}
diff --git a/src/glsl/nir/nir_gs_count_vertices.c b/src/glsl/nir/nir_gs_count_vertices.c
deleted file mode 100644
index db15d160ee7..00000000000
--- a/src/glsl/nir/nir_gs_count_vertices.c
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright © 2015 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include "nir.h"
-#include "nir_builder.h"
-
-static nir_intrinsic_instr *
-as_intrinsic(nir_instr *instr, nir_intrinsic_op op)
-{
- if (instr->type != nir_instr_type_intrinsic)
- return NULL;
-
- nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
- if (intrin->intrinsic != op)
- return NULL;
-
- return intrin;
-}
-
-static nir_intrinsic_instr *
-as_set_vertex_count(nir_instr *instr)
-{
- return as_intrinsic(instr, nir_intrinsic_set_vertex_count);
-}
-
-/**
- * If a geometry shader emits a constant number of vertices, return the
- * number of vertices. Otherwise, return -1 (unknown).
- *
- * This only works if you've used nir_lower_gs_intrinsics() to do vertex
- * counting at the NIR level.
- */
-int
-nir_gs_count_vertices(const nir_shader *shader)
-{
- int count = -1;
-
- nir_foreach_function(shader, function) {
- if (!function->impl)
- continue;
-
- /* set_vertex_count intrinsics only appear in predecessors of the
- * end block. So we don't need to walk all of them.
- */
- struct set_entry *entry;
- set_foreach(function->impl->end_block->predecessors, entry) {
- nir_block *block = (nir_block *) entry->key;
-
- nir_foreach_instr_reverse(block, instr) {
- nir_intrinsic_instr *intrin = as_set_vertex_count(instr);
- if (!intrin)
- continue;
-
- nir_const_value *val = nir_src_as_const_value(intrin->src[0]);
- /* We've found a non-constant value. Bail. */
- if (!val)
- return -1;
-
- if (count == -1)
- count = val->i[0];
-
- /* We've found contradictory set_vertex_count intrinsics.
- * This can happen if there are early-returns in main() and
- * different paths emit different numbers of vertices.
- */
- if (count != val->i[0])
- return -1;
- }
- }
- }
-
- return count;
-}
diff --git a/src/glsl/nir/nir_inline_functions.c b/src/glsl/nir/nir_inline_functions.c
deleted file mode 100644
index 3cf83279053..00000000000
--- a/src/glsl/nir/nir_inline_functions.c
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * Copyright © 2015 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include "nir.h"
-#include "nir_builder.h"
-#include "nir_control_flow.h"
-
-struct inline_functions_state {
- struct set *inlined;
- nir_builder builder;
- bool progress;
-};
-
-static bool inline_function_impl(nir_function_impl *impl, struct set *inlined);
-
-static bool
-inline_functions_block(nir_block *block, void *void_state)
-{
- struct inline_functions_state *state = void_state;
-
- nir_builder *b = &state->builder;
-
- /* This is tricky. We're iterating over instructions in a block but, as
- * we go, the block and its instruction list are being split into
- * pieces. However, this *should* be safe since foreach_safe always
- * stashes the next thing in the iteration. That next thing will
- * properly get moved to the next block when it gets split, and we
- * continue iterating there.
- */
- nir_foreach_instr_safe(block, instr) {
- if (instr->type != nir_instr_type_call)
- continue;
-
- state->progress = true;
-
- nir_call_instr *call = nir_instr_as_call(instr);
- assert(call->callee->impl);
-
- inline_function_impl(call->callee->impl, state->inlined);
-
- nir_function_impl *callee_copy =
- nir_function_impl_clone(call->callee->impl);
-
- exec_list_append(&b->impl->locals, &callee_copy->locals);
- exec_list_append(&b->impl->registers, &callee_copy->registers);
-
- b->cursor = nir_before_instr(&call->instr);
-
- /* Add copies of all in parameters */
- assert(call->num_params == callee_copy->num_params);
- for (unsigned i = 0; i < callee_copy->num_params; i++) {
- /* Only in or inout parameters */
- if (call->callee->params[i].param_type == nir_parameter_out)
- continue;
-
- nir_copy_deref_var(b, nir_deref_var_create(b->shader,
- callee_copy->params[i]),
- call->params[i]);
- }
-
- /* Pluck the body out of the function and place it here */
- nir_cf_list body;
- nir_cf_list_extract(&body, &callee_copy->body);
- nir_cf_reinsert(&body, b->cursor);
-
- b->cursor = nir_before_instr(&call->instr);
-
- /* Add copies of all out parameters and the return */
- assert(call->num_params == callee_copy->num_params);
- for (unsigned i = 0; i < callee_copy->num_params; i++) {
- /* Only out or inout parameters */
- if (call->callee->params[i].param_type == nir_parameter_in)
- continue;
-
- nir_copy_deref_var(b, call->params[i],
- nir_deref_var_create(b->shader,
- callee_copy->params[i]));
- }
- if (!glsl_type_is_void(call->callee->return_type)) {
- nir_copy_deref_var(b, call->return_deref,
- nir_deref_var_create(b->shader,
- callee_copy->return_var));
- }
-
- nir_instr_remove(&call->instr);
- }
-
- return true;
-}
-
-static bool
-inline_function_impl(nir_function_impl *impl, struct set *inlined)
-{
- if (_mesa_set_search(inlined, impl))
- return false; /* Already inlined */
-
- struct inline_functions_state state;
-
- state.inlined = inlined;
- state.progress = false;
- nir_builder_init(&state.builder, impl);
-
- nir_foreach_block(impl, inline_functions_block, &state);
-
- if (state.progress) {
- /* SSA and register indices are completely messed up now */
- nir_index_ssa_defs(impl);
- nir_index_local_regs(impl);
-
- nir_metadata_preserve(impl, nir_metadata_none);
- }
-
- _mesa_set_add(inlined, impl);
-
- return state.progress;
-}
-
-bool
-nir_inline_functions(nir_shader *shader)
-{
- struct set *inlined = _mesa_set_create(NULL, _mesa_hash_pointer,
- _mesa_key_pointer_equal);
- bool progress = false;
-
- nir_foreach_function(shader, function) {
- if (function->impl)
- progress = inline_function_impl(function->impl, inlined) || progress;
- }
-
- _mesa_set_destroy(inlined, NULL);
-
- return progress;
-}
diff --git a/src/glsl/nir/nir_instr_set.c b/src/glsl/nir/nir_instr_set.c
deleted file mode 100644
index eb021326097..00000000000
--- a/src/glsl/nir/nir_instr_set.c
+++ /dev/null
@@ -1,522 +0,0 @@
-/*
- * Copyright © 2014 Connor Abbott
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include "nir_instr_set.h"
-#include "nir_vla.h"
-
-#define HASH(hash, data) _mesa_fnv32_1a_accumulate((hash), (data))
-
-static uint32_t
-hash_src(uint32_t hash, const nir_src *src)
-{
- assert(src->is_ssa);
- hash = HASH(hash, src->ssa);
- return hash;
-}
-
-static uint32_t
-hash_alu_src(uint32_t hash, const nir_alu_src *src, unsigned num_components)
-{
- hash = HASH(hash, src->abs);
- hash = HASH(hash, src->negate);
-
- for (unsigned i = 0; i < num_components; i++)
- hash = HASH(hash, src->swizzle[i]);
-
- hash = hash_src(hash, &src->src);
- return hash;
-}
-
-static uint32_t
-hash_alu(uint32_t hash, const nir_alu_instr *instr)
-{
- hash = HASH(hash, instr->op);
- hash = HASH(hash, instr->dest.dest.ssa.num_components);
-
- if (nir_op_infos[instr->op].algebraic_properties & NIR_OP_IS_COMMUTATIVE) {
- assert(nir_op_infos[instr->op].num_inputs == 2);
- uint32_t hash0 = hash_alu_src(hash, &instr->src[0],
- nir_ssa_alu_instr_src_components(instr, 0));
- uint32_t hash1 = hash_alu_src(hash, &instr->src[1],
- nir_ssa_alu_instr_src_components(instr, 1));
- /* For commutative operations, we need some commutative way of
- * combining the hashes. One option would be to XOR them but that
- * means that anything with two identical sources will hash to 0 and
- * that's common enough we probably don't want the guaranteed
- * collision. Either addition or multiplication will also work.
- */
- hash = hash0 * hash1;
- } else {
- for (unsigned i = 0; i < nir_op_infos[instr->op].num_inputs; i++) {
- hash = hash_alu_src(hash, &instr->src[i],
- nir_ssa_alu_instr_src_components(instr, i));
- }
- }
-
- return hash;
-}
-
-static uint32_t
-hash_load_const(uint32_t hash, const nir_load_const_instr *instr)
-{
- hash = HASH(hash, instr->def.num_components);
-
- hash = _mesa_fnv32_1a_accumulate_block(hash, instr->value.f,
- instr->def.num_components
- * sizeof(instr->value.f[0]));
-
- return hash;
-}
-
-static int
-cmp_phi_src(const void *data1, const void *data2)
-{
- nir_phi_src *src1 = *(nir_phi_src **)data1;
- nir_phi_src *src2 = *(nir_phi_src **)data2;
- return src1->pred - src2->pred;
-}
-
-static uint32_t
-hash_phi(uint32_t hash, const nir_phi_instr *instr)
-{
- hash = HASH(hash, instr->instr.block);
-
- /* sort sources by predecessor, since the order shouldn't matter */
- unsigned num_preds = instr->instr.block->predecessors->entries;
- NIR_VLA(nir_phi_src *, srcs, num_preds);
- unsigned i = 0;
- nir_foreach_phi_src(instr, src) {
- srcs[i++] = src;
- }
-
- qsort(srcs, num_preds, sizeof(nir_phi_src *), cmp_phi_src);
-
- for (i = 0; i < num_preds; i++) {
- hash = hash_src(hash, &srcs[i]->src);
- hash = HASH(hash, srcs[i]->pred);
- }
-
- return hash;
-}
-
-static uint32_t
-hash_intrinsic(uint32_t hash, const nir_intrinsic_instr *instr)
-{
- const nir_intrinsic_info *info = &nir_intrinsic_infos[instr->intrinsic];
- hash = HASH(hash, instr->intrinsic);
-
- if (info->has_dest)
- hash = HASH(hash, instr->dest.ssa.num_components);
-
- assert(info->num_variables == 0);
-
- hash = _mesa_fnv32_1a_accumulate_block(hash, instr->const_index,
- info->num_indices
- * sizeof(instr->const_index[0]));
- return hash;
-}
-
-static uint32_t
-hash_tex(uint32_t hash, const nir_tex_instr *instr)
-{
- hash = HASH(hash, instr->op);
- hash = HASH(hash, instr->num_srcs);
-
- for (unsigned i = 0; i < instr->num_srcs; i++) {
- hash = HASH(hash, instr->src[i].src_type);
- hash = hash_src(hash, &instr->src[i].src);
- }
-
- hash = HASH(hash, instr->coord_components);
- hash = HASH(hash, instr->sampler_dim);
- hash = HASH(hash, instr->is_array);
- hash = HASH(hash, instr->is_shadow);
- hash = HASH(hash, instr->is_new_style_shadow);
- hash = HASH(hash, instr->const_offset);
- unsigned component = instr->component;
- hash = HASH(hash, component);
- hash = HASH(hash, instr->texture_index);
- hash = HASH(hash, instr->texture_array_size);
- hash = HASH(hash, instr->sampler_index);
-
- assert(!instr->sampler);
-
- return hash;
-}
-
-/* Computes a hash of an instruction for use in a hash table. Note that this
- * will only work for instructions where instr_can_rewrite() returns true, and
- * it should return identical hashes for two instructions that are the same
- * according nir_instrs_equal().
- */
-
-static uint32_t
-hash_instr(const void *data)
-{
- const nir_instr *instr = data;
- uint32_t hash = _mesa_fnv32_1a_offset_bias;
-
- switch (instr->type) {
- case nir_instr_type_alu:
- hash = hash_alu(hash, nir_instr_as_alu(instr));
- break;
- case nir_instr_type_load_const:
- hash = hash_load_const(hash, nir_instr_as_load_const(instr));
- break;
- case nir_instr_type_phi:
- hash = hash_phi(hash, nir_instr_as_phi(instr));
- break;
- case nir_instr_type_intrinsic:
- hash = hash_intrinsic(hash, nir_instr_as_intrinsic(instr));
- break;
- case nir_instr_type_tex:
- hash = hash_tex(hash, nir_instr_as_tex(instr));
- break;
- default:
- unreachable("Invalid instruction type");
- }
-
- return hash;
-}
-
-bool
-nir_srcs_equal(nir_src src1, nir_src src2)
-{
- if (src1.is_ssa) {
- if (src2.is_ssa) {
- return src1.ssa == src2.ssa;
- } else {
- return false;
- }
- } else {
- if (src2.is_ssa) {
- return false;
- } else {
- if ((src1.reg.indirect == NULL) != (src2.reg.indirect == NULL))
- return false;
-
- if (src1.reg.indirect) {
- if (!nir_srcs_equal(*src1.reg.indirect, *src2.reg.indirect))
- return false;
- }
-
- return src1.reg.reg == src2.reg.reg &&
- src1.reg.base_offset == src2.reg.base_offset;
- }
- }
-}
-
-static bool
-nir_alu_srcs_equal(const nir_alu_instr *alu1, const nir_alu_instr *alu2,
- unsigned src1, unsigned src2)
-{
- if (alu1->src[src1].abs != alu2->src[src2].abs ||
- alu1->src[src1].negate != alu2->src[src2].negate)
- return false;
-
- for (unsigned i = 0; i < nir_ssa_alu_instr_src_components(alu1, src1); i++) {
- if (alu1->src[src1].swizzle[i] != alu2->src[src2].swizzle[i])
- return false;
- }
-
- return nir_srcs_equal(alu1->src[src1].src, alu2->src[src2].src);
-}
-
-/* Returns "true" if two instructions are equal. Note that this will only
- * work for the subset of instructions defined by instr_can_rewrite(). Also,
- * it should only return "true" for instructions that hash_instr() will return
- * the same hash for (ignoring collisions, of course).
- */
-
-static bool
-nir_instrs_equal(const nir_instr *instr1, const nir_instr *instr2)
-{
- if (instr1->type != instr2->type)
- return false;
-
- switch (instr1->type) {
- case nir_instr_type_alu: {
- nir_alu_instr *alu1 = nir_instr_as_alu(instr1);
- nir_alu_instr *alu2 = nir_instr_as_alu(instr2);
-
- if (alu1->op != alu2->op)
- return false;
-
- /* TODO: We can probably acutally do something more inteligent such
- * as allowing different numbers and taking a maximum or something
- * here */
- if (alu1->dest.dest.ssa.num_components != alu2->dest.dest.ssa.num_components)
- return false;
-
- if (nir_op_infos[alu1->op].algebraic_properties & NIR_OP_IS_COMMUTATIVE) {
- assert(nir_op_infos[alu1->op].num_inputs == 2);
- return (nir_alu_srcs_equal(alu1, alu2, 0, 0) &&
- nir_alu_srcs_equal(alu1, alu2, 1, 1)) ||
- (nir_alu_srcs_equal(alu1, alu2, 0, 1) &&
- nir_alu_srcs_equal(alu1, alu2, 1, 0));
- } else {
- for (unsigned i = 0; i < nir_op_infos[alu1->op].num_inputs; i++) {
- if (!nir_alu_srcs_equal(alu1, alu2, i, i))
- return false;
- }
- }
- return true;
- }
- case nir_instr_type_tex: {
- nir_tex_instr *tex1 = nir_instr_as_tex(instr1);
- nir_tex_instr *tex2 = nir_instr_as_tex(instr2);
-
- if (tex1->op != tex2->op)
- return false;
-
- if (tex1->num_srcs != tex2->num_srcs)
- return false;
- for (unsigned i = 0; i < tex1->num_srcs; i++) {
- if (tex1->src[i].src_type != tex2->src[i].src_type ||
- !nir_srcs_equal(tex1->src[i].src, tex2->src[i].src)) {
- return false;
- }
- }
-
- if (tex1->coord_components != tex2->coord_components ||
- tex1->sampler_dim != tex2->sampler_dim ||
- tex1->is_array != tex2->is_array ||
- tex1->is_shadow != tex2->is_shadow ||
- tex1->is_new_style_shadow != tex2->is_new_style_shadow ||
- memcmp(tex1->const_offset, tex2->const_offset,
- sizeof(tex1->const_offset)) != 0 ||
- tex1->component != tex2->component ||
- tex1->texture_index != tex2->texture_index ||
- tex1->texture_array_size != tex2->texture_array_size ||
- tex1->sampler_index != tex2->sampler_index) {
- return false;
- }
-
- /* Don't support un-lowered sampler derefs currently. */
- assert(!tex1->texture && !tex1->sampler &&
- !tex2->texture && !tex2->sampler);
-
- return true;
- }
- case nir_instr_type_load_const: {
- nir_load_const_instr *load1 = nir_instr_as_load_const(instr1);
- nir_load_const_instr *load2 = nir_instr_as_load_const(instr2);
-
- if (load1->def.num_components != load2->def.num_components)
- return false;
-
- return memcmp(load1->value.f, load2->value.f,
- load1->def.num_components * sizeof(*load2->value.f)) == 0;
- }
- case nir_instr_type_phi: {
- nir_phi_instr *phi1 = nir_instr_as_phi(instr1);
- nir_phi_instr *phi2 = nir_instr_as_phi(instr2);
-
- if (phi1->instr.block != phi2->instr.block)
- return false;
-
- nir_foreach_phi_src(phi1, src1) {
- nir_foreach_phi_src(phi2, src2) {
- if (src1->pred == src2->pred) {
- if (!nir_srcs_equal(src1->src, src2->src))
- return false;
-
- break;
- }
- }
- }
-
- return true;
- }
- case nir_instr_type_intrinsic: {
- nir_intrinsic_instr *intrinsic1 = nir_instr_as_intrinsic(instr1);
- nir_intrinsic_instr *intrinsic2 = nir_instr_as_intrinsic(instr2);
- const nir_intrinsic_info *info =
- &nir_intrinsic_infos[intrinsic1->intrinsic];
-
- if (intrinsic1->intrinsic != intrinsic2->intrinsic ||
- intrinsic1->num_components != intrinsic2->num_components)
- return false;
-
- if (info->has_dest && intrinsic1->dest.ssa.num_components !=
- intrinsic2->dest.ssa.num_components)
- return false;
-
- for (unsigned i = 0; i < info->num_srcs; i++) {
- if (!nir_srcs_equal(intrinsic1->src[i], intrinsic2->src[i]))
- return false;
- }
-
- assert(info->num_variables == 0);
-
- for (unsigned i = 0; i < info->num_indices; i++) {
- if (intrinsic1->const_index[i] != intrinsic2->const_index[i])
- return false;
- }
-
- return true;
- }
- case nir_instr_type_call:
- case nir_instr_type_jump:
- case nir_instr_type_ssa_undef:
- case nir_instr_type_parallel_copy:
- default:
- unreachable("Invalid instruction type");
- }
-
- return false;
-}
-
-static bool
-src_is_ssa(nir_src *src, void *data)
-{
- (void) data;
- return src->is_ssa;
-}
-
-static bool
-dest_is_ssa(nir_dest *dest, void *data)
-{
- (void) data;
- return dest->is_ssa;
-}
-
-/* This function determines if uses of an instruction can safely be rewritten
- * to use another identical instruction instead. Note that this function must
- * be kept in sync with hash_instr() and nir_instrs_equal() -- only
- * instructions that pass this test will be handed on to those functions, and
- * conversely they must handle everything that this function returns true for.
- */
-
-static bool
-instr_can_rewrite(nir_instr *instr)
-{
- /* We only handle SSA. */
- if (!nir_foreach_dest(instr, dest_is_ssa, NULL) ||
- !nir_foreach_src(instr, src_is_ssa, NULL))
- return false;
-
- switch (instr->type) {
- case nir_instr_type_alu:
- case nir_instr_type_load_const:
- case nir_instr_type_phi:
- return true;
- case nir_instr_type_tex: {
- nir_tex_instr *tex = nir_instr_as_tex(instr);
-
- /* Don't support un-lowered sampler derefs currently. */
- if (tex->texture || tex->sampler)
- return false;
-
- return true;
- }
- case nir_instr_type_intrinsic: {
- const nir_intrinsic_info *info =
- &nir_intrinsic_infos[nir_instr_as_intrinsic(instr)->intrinsic];
- return (info->flags & NIR_INTRINSIC_CAN_ELIMINATE) &&
- (info->flags & NIR_INTRINSIC_CAN_REORDER) &&
- info->num_variables == 0; /* not implemented yet */
- }
- case nir_instr_type_call:
- case nir_instr_type_jump:
- case nir_instr_type_ssa_undef:
- return false;
- case nir_instr_type_parallel_copy:
- default:
- unreachable("Invalid instruction type");
- }
-
- return false;
-}
-
-static nir_ssa_def *
-nir_instr_get_dest_ssa_def(nir_instr *instr)
-{
- switch (instr->type) {
- case nir_instr_type_alu:
- assert(nir_instr_as_alu(instr)->dest.dest.is_ssa);
- return &nir_instr_as_alu(instr)->dest.dest.ssa;
- case nir_instr_type_load_const:
- return &nir_instr_as_load_const(instr)->def;
- case nir_instr_type_phi:
- assert(nir_instr_as_phi(instr)->dest.is_ssa);
- return &nir_instr_as_phi(instr)->dest.ssa;
- case nir_instr_type_intrinsic:
- assert(nir_instr_as_intrinsic(instr)->dest.is_ssa);
- return &nir_instr_as_intrinsic(instr)->dest.ssa;
- case nir_instr_type_tex:
- assert(nir_instr_as_tex(instr)->dest.is_ssa);
- return &nir_instr_as_tex(instr)->dest.ssa;
- default:
- unreachable("We never ask for any of these");
- }
-}
-
-static bool
-cmp_func(const void *data1, const void *data2)
-{
- return nir_instrs_equal(data1, data2);
-}
-
-struct set *
-nir_instr_set_create(void *mem_ctx)
-{
- return _mesa_set_create(mem_ctx, hash_instr, cmp_func);
-}
-
-void
-nir_instr_set_destroy(struct set *instr_set)
-{
- _mesa_set_destroy(instr_set, NULL);
-}
-
-bool
-nir_instr_set_add_or_rewrite(struct set *instr_set, nir_instr *instr)
-{
- if (!instr_can_rewrite(instr))
- return false;
-
- struct set_entry *entry = _mesa_set_search(instr_set, instr);
- if (entry) {
- nir_ssa_def *def = nir_instr_get_dest_ssa_def(instr);
- nir_ssa_def *new_def =
- nir_instr_get_dest_ssa_def((nir_instr *) entry->key);
- nir_ssa_def_rewrite_uses(def, nir_src_for_ssa(new_def));
- return true;
- }
-
- _mesa_set_add(instr_set, instr);
- return false;
-}
-
-void
-nir_instr_set_remove(struct set *instr_set, nir_instr *instr)
-{
- if (!instr_can_rewrite(instr))
- return;
-
- struct set_entry *entry = _mesa_set_search(instr_set, instr);
- if (entry)
- _mesa_set_remove(instr_set, entry);
-}
-
diff --git a/src/glsl/nir/nir_instr_set.h b/src/glsl/nir/nir_instr_set.h
deleted file mode 100644
index 939e8ddbf58..00000000000
--- a/src/glsl/nir/nir_instr_set.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright © 2014 Connor Abbott
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#pragma once
-
-#include "nir.h"
-
-/**
- * This file defines functions for creating, destroying, and manipulating an
- * "instruction set," which is an abstraction for finding duplicate
- * instructions using a hash set. Note that the question of whether an
- * instruction is actually a duplicate (e.g. whether it has any side effects)
- * is handled transparently. The user can pass any instruction to
- * nir_instr_set_add_or_rewrite() and nir_instr_set_remove(), and if the
- * instruction isn't safe to rewrite or isn't supported, it's silently
- * removed.
- */
-
-/*@{*/
-
-/** Creates an instruction set, using a given ralloc mem_ctx */
-struct set *nir_instr_set_create(void *mem_ctx);
-
-/** Destroys an instruction set. */
-void nir_instr_set_destroy(struct set *instr_set);
-
-/**
- * Adds an instruction to an instruction set if it doesn't exist, or if it
- * does already exist, rewrites all uses of it to point to the other
- * already-inserted instruction. Returns 'true' if the uses of the instruction
- * were rewritten.
- */
-bool nir_instr_set_add_or_rewrite(struct set *instr_set, nir_instr *instr);
-
-/**
- * Removes an instruction from an instruction set, so that other instructions
- * won't be merged with it.
- */
-void nir_instr_set_remove(struct set *instr_set, nir_instr *instr);
-
-/*@}*/
-
diff --git a/src/glsl/nir/nir_intrinsics.c b/src/glsl/nir/nir_intrinsics.c
deleted file mode 100644
index a7c868c39af..00000000000
--- a/src/glsl/nir/nir_intrinsics.c
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright © 2014 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- *
- * Authors:
- * Connor Abbott ([email protected])
- *
- */
-
-#include "nir.h"
-
-#define OPCODE(name) nir_intrinsic_##name
-
-#define INTRINSIC(_name, _num_srcs, _src_components, _has_dest, \
- _dest_components, _num_variables, _num_indices, _flags) \
-{ \
- .name = #_name, \
- .num_srcs = _num_srcs, \
- .src_components = _src_components, \
- .has_dest = _has_dest, \
- .dest_components = _dest_components, \
- .num_variables = _num_variables, \
- .num_indices = _num_indices, \
- .flags = _flags \
-},
-
-#define LAST_INTRINSIC(name)
-
-const nir_intrinsic_info nir_intrinsic_infos[nir_num_intrinsics] = {
-#include "nir_intrinsics.h"
-}; \ No newline at end of file
diff --git a/src/glsl/nir/nir_intrinsics.h b/src/glsl/nir/nir_intrinsics.h
deleted file mode 100644
index 3e7cf735a1b..00000000000
--- a/src/glsl/nir/nir_intrinsics.h
+++ /dev/null
@@ -1,367 +0,0 @@
-/*
- * Copyright © 2014 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- *
- * Authors:
- * Connor Abbott ([email protected])
- *
- */
-
-/**
- * This header file defines all the available intrinsics in one place. It
- * expands to a list of macros of the form:
- *
- * INTRINSIC(name, num_srcs, src_components, has_dest, dest_components,
- * num_variables, num_indices, flags)
- *
- * Which should correspond one-to-one with the nir_intrinsic_info structure. It
- * is included in both ir.h to create the nir_intrinsic enum (with members of
- * the form nir_intrinsic_(name)) and and in opcodes.c to create
- * nir_intrinsic_infos, which is a const array of nir_intrinsic_info structures
- * for each intrinsic.
- */
-
-#define ARR(...) { __VA_ARGS__ }
-
-
-INTRINSIC(load_var, 0, ARR(), true, 0, 1, 0, NIR_INTRINSIC_CAN_ELIMINATE)
-INTRINSIC(store_var, 1, ARR(0), false, 0, 1, 1, 0)
-INTRINSIC(copy_var, 0, ARR(), false, 0, 2, 0, 0)
-
-/*
- * Interpolation of input. The interp_var_at* intrinsics are similar to the
- * load_var intrinsic acting an a shader input except that they interpolate
- * the input differently. The at_sample and at_offset intrinsics take an
- * aditional source that is a integer sample id or a vec2 position offset
- * respectively.
- */
-
-INTRINSIC(interp_var_at_centroid, 0, ARR(0), true, 0, 1, 0,
- NIR_INTRINSIC_CAN_ELIMINATE | NIR_INTRINSIC_CAN_REORDER)
-INTRINSIC(interp_var_at_sample, 1, ARR(1), true, 0, 1, 0,
- NIR_INTRINSIC_CAN_ELIMINATE | NIR_INTRINSIC_CAN_REORDER)
-INTRINSIC(interp_var_at_offset, 1, ARR(2), true, 0, 1, 0,
- NIR_INTRINSIC_CAN_ELIMINATE | NIR_INTRINSIC_CAN_REORDER)
-
-/*
- * Ask the driver for the size of a given buffer. It takes the buffer index
- * as source.
- */
-INTRINSIC(get_buffer_size, 1, ARR(1), true, 1, 0, 0,
- NIR_INTRINSIC_CAN_ELIMINATE | NIR_INTRINSIC_CAN_REORDER)
-
-/*
- * a barrier is an intrinsic with no inputs/outputs but which can't be moved
- * around/optimized in general
- */
-#define BARRIER(name) INTRINSIC(name, 0, ARR(), false, 0, 0, 0, 0)
-
-BARRIER(barrier)
-BARRIER(discard)
-
-/*
- * Memory barrier with semantics analogous to the memoryBarrier() GLSL
- * intrinsic.
- */
-BARRIER(memory_barrier)
-
-/*
- * Shader clock intrinsic with semantics analogous to the clock2x32ARB()
- * GLSL intrinsic.
- * The latter can be used as code motion barrier, which is currently not
- * feasible with NIR.
- */
-INTRINSIC(shader_clock, 0, ARR(), true, 1, 0, 0, NIR_INTRINSIC_CAN_ELIMINATE)
-
-/*
- * Memory barrier with semantics analogous to the compute shader
- * groupMemoryBarrier(), memoryBarrierAtomicCounter(), memoryBarrierBuffer(),
- * memoryBarrierImage() and memoryBarrierShared() GLSL intrinsics.
- */
-BARRIER(group_memory_barrier)
-BARRIER(memory_barrier_atomic_counter)
-BARRIER(memory_barrier_buffer)
-BARRIER(memory_barrier_image)
-BARRIER(memory_barrier_shared)
-
-/** A conditional discard, with a single boolean source. */
-INTRINSIC(discard_if, 1, ARR(1), false, 0, 0, 0, 0)
-
-/**
- * Basic Geometry Shader intrinsics.
- *
- * emit_vertex implements GLSL's EmitStreamVertex() built-in. It takes a single
- * index, which is the stream ID to write to.
- *
- * end_primitive implements GLSL's EndPrimitive() built-in.
- */
-INTRINSIC(emit_vertex, 0, ARR(), false, 0, 0, 1, 0)
-INTRINSIC(end_primitive, 0, ARR(), false, 0, 0, 1, 0)
-
-/**
- * Geometry Shader intrinsics with a vertex count.
- *
- * Alternatively, drivers may implement these intrinsics, and use
- * nir_lower_gs_intrinsics() to convert from the basic intrinsics.
- *
- * These maintain a count of the number of vertices emitted, as an additional
- * unsigned integer source.
- */
-INTRINSIC(emit_vertex_with_counter, 1, ARR(1), false, 0, 0, 1, 0)
-INTRINSIC(end_primitive_with_counter, 1, ARR(1), false, 0, 0, 1, 0)
-INTRINSIC(set_vertex_count, 1, ARR(1), false, 0, 0, 0, 0)
-
-/*
- * Atomic counters
- *
- * The *_var variants take an atomic_uint nir_variable, while the other,
- * lowered, variants take a constant buffer index and register offset.
- */
-
-#define ATOMIC(name, flags) \
- INTRINSIC(atomic_counter_##name##_var, 0, ARR(), true, 1, 1, 0, flags) \
- INTRINSIC(atomic_counter_##name, 1, ARR(1), true, 1, 0, 1, flags)
-
-ATOMIC(inc, 0)
-ATOMIC(dec, 0)
-ATOMIC(read, NIR_INTRINSIC_CAN_ELIMINATE)
-
-/*
- * Image load, store and atomic intrinsics.
- *
- * All image intrinsics take an image target passed as a nir_variable. Image
- * variables contain a number of memory and layout qualifiers that influence
- * the semantics of the intrinsic.
- *
- * All image intrinsics take a four-coordinate vector and a sample index as
- * first two sources, determining the location within the image that will be
- * accessed by the intrinsic. Components not applicable to the image target
- * in use are undefined. Image store takes an additional four-component
- * argument with the value to be written, and image atomic operations take
- * either one or two additional scalar arguments with the same meaning as in
- * the ARB_shader_image_load_store specification.
- */
-INTRINSIC(image_load, 2, ARR(4, 1), true, 4, 1, 0,
- NIR_INTRINSIC_CAN_ELIMINATE)
-INTRINSIC(image_store, 3, ARR(4, 1, 4), false, 0, 1, 0, 0)
-INTRINSIC(image_atomic_add, 3, ARR(4, 1, 1), true, 1, 1, 0, 0)
-INTRINSIC(image_atomic_min, 3, ARR(4, 1, 1), true, 1, 1, 0, 0)
-INTRINSIC(image_atomic_max, 3, ARR(4, 1, 1), true, 1, 1, 0, 0)
-INTRINSIC(image_atomic_and, 3, ARR(4, 1, 1), true, 1, 1, 0, 0)
-INTRINSIC(image_atomic_or, 3, ARR(4, 1, 1), true, 1, 1, 0, 0)
-INTRINSIC(image_atomic_xor, 3, ARR(4, 1, 1), true, 1, 1, 0, 0)
-INTRINSIC(image_atomic_exchange, 3, ARR(4, 1, 1), true, 1, 1, 0, 0)
-INTRINSIC(image_atomic_comp_swap, 4, ARR(4, 1, 1, 1), true, 1, 1, 0, 0)
-INTRINSIC(image_size, 0, ARR(), true, 4, 1, 0,
- NIR_INTRINSIC_CAN_ELIMINATE | NIR_INTRINSIC_CAN_REORDER)
-INTRINSIC(image_samples, 0, ARR(), true, 1, 1, 0,
- NIR_INTRINSIC_CAN_ELIMINATE | NIR_INTRINSIC_CAN_REORDER)
-
-/*
- * Vulkan descriptor set intrinsic
- *
- * The Vulkan API uses a different binding model from GL. In the Vulkan
- * API, all external resources are represented by a tripple:
- *
- * (descriptor set, binding, array index)
- *
- * where the array index is the only thing allowed to be indirect. The
- * vulkan_surface_index intrinsic takes the descriptor set and binding as
- * its first two indices and the array index as its source. The third
- * index is a nir_variable_mode in case that's useful to the backend.
- *
- * The intended usage is that the shader will call vulkan_surface_index to
- * get an index and then pass that as the buffer index ubo/ssbo calls.
- */
-INTRINSIC(vulkan_resource_index, 1, ARR(1), true, 1, 0, 3,
- NIR_INTRINSIC_CAN_ELIMINATE | NIR_INTRINSIC_CAN_REORDER)
-
-/*
- * variable atomic intrinsics
- *
- * All of these variable atomic memory operations read a value from memory,
- * compute a new value using one of the operations below, write the new value
- * to memory, and return the original value read.
- *
- * All operations take 1 source except CompSwap that takes 2. These sources
- * represent:
- *
- * 0: The data parameter to the atomic function (i.e. the value to add
- * in shared_atomic_add, etc).
- * 1: For CompSwap only: the second data parameter.
- *
- * All operations take 1 variable deref.
- */
-INTRINSIC(var_atomic_add, 1, ARR(1), true, 1, 1, 0, 0)
-INTRINSIC(var_atomic_imin, 1, ARR(1), true, 1, 1, 0, 0)
-INTRINSIC(var_atomic_umin, 1, ARR(1), true, 1, 1, 0, 0)
-INTRINSIC(var_atomic_imax, 1, ARR(1), true, 1, 1, 0, 0)
-INTRINSIC(var_atomic_umax, 1, ARR(1), true, 1, 1, 0, 0)
-INTRINSIC(var_atomic_and, 1, ARR(1), true, 1, 1, 0, 0)
-INTRINSIC(var_atomic_or, 1, ARR(1), true, 1, 1, 0, 0)
-INTRINSIC(var_atomic_xor, 1, ARR(1), true, 1, 1, 0, 0)
-INTRINSIC(var_atomic_exchange, 1, ARR(1), true, 1, 1, 0, 0)
-INTRINSIC(var_atomic_comp_swap, 2, ARR(1, 1), true, 1, 1, 0, 0)
-
-/*
- * SSBO atomic intrinsics
- *
- * All of the SSBO atomic memory operations read a value from memory,
- * compute a new value using one of the operations below, write the new
- * value to memory, and return the original value read.
- *
- * All operations take 3 sources except CompSwap that takes 4. These
- * sources represent:
- *
- * 0: The SSBO buffer index.
- * 1: The offset into the SSBO buffer of the variable that the atomic
- * operation will operate on.
- * 2: The data parameter to the atomic function (i.e. the value to add
- * in ssbo_atomic_add, etc).
- * 3: For CompSwap only: the second data parameter.
- */
-INTRINSIC(ssbo_atomic_add, 3, ARR(1, 1, 1), true, 1, 0, 0, 0)
-INTRINSIC(ssbo_atomic_imin, 3, ARR(1, 1, 1), true, 1, 0, 0, 0)
-INTRINSIC(ssbo_atomic_umin, 3, ARR(1, 1, 1), true, 1, 0, 0, 0)
-INTRINSIC(ssbo_atomic_imax, 3, ARR(1, 1, 1), true, 1, 0, 0, 0)
-INTRINSIC(ssbo_atomic_umax, 3, ARR(1, 1, 1), true, 1, 0, 0, 0)
-INTRINSIC(ssbo_atomic_and, 3, ARR(1, 1, 1), true, 1, 0, 0, 0)
-INTRINSIC(ssbo_atomic_or, 3, ARR(1, 1, 1), true, 1, 0, 0, 0)
-INTRINSIC(ssbo_atomic_xor, 3, ARR(1, 1, 1), true, 1, 0, 0, 0)
-INTRINSIC(ssbo_atomic_exchange, 3, ARR(1, 1, 1), true, 1, 0, 0, 0)
-INTRINSIC(ssbo_atomic_comp_swap, 4, ARR(1, 1, 1, 1), true, 1, 0, 0, 0)
-
-/*
- * CS shared variable atomic intrinsics
- *
- * All of the shared variable atomic memory operations read a value from
- * memory, compute a new value using one of the operations below, write the
- * new value to memory, and return the original value read.
- *
- * All operations take 2 sources except CompSwap that takes 3. These
- * sources represent:
- *
- * 0: The offset into the shared variable storage region that the atomic
- * operation will operate on.
- * 1: The data parameter to the atomic function (i.e. the value to add
- * in shared_atomic_add, etc).
- * 2: For CompSwap only: the second data parameter.
- */
-INTRINSIC(shared_atomic_add, 2, ARR(1, 1), true, 1, 0, 0, 0)
-INTRINSIC(shared_atomic_imin, 2, ARR(1, 1), true, 1, 0, 0, 0)
-INTRINSIC(shared_atomic_umin, 2, ARR(1, 1), true, 1, 0, 0, 0)
-INTRINSIC(shared_atomic_imax, 2, ARR(1, 1), true, 1, 0, 0, 0)
-INTRINSIC(shared_atomic_umax, 2, ARR(1, 1), true, 1, 0, 0, 0)
-INTRINSIC(shared_atomic_and, 2, ARR(1, 1), true, 1, 0, 0, 0)
-INTRINSIC(shared_atomic_or, 2, ARR(1, 1), true, 1, 0, 0, 0)
-INTRINSIC(shared_atomic_xor, 2, ARR(1, 1), true, 1, 0, 0, 0)
-INTRINSIC(shared_atomic_exchange, 2, ARR(1, 1), true, 1, 0, 0, 0)
-INTRINSIC(shared_atomic_comp_swap, 3, ARR(1, 1, 1), true, 1, 0, 0, 0)
-
-#define SYSTEM_VALUE(name, components, num_indices) \
- INTRINSIC(load_##name, 0, ARR(), true, components, 0, num_indices, \
- NIR_INTRINSIC_CAN_ELIMINATE | NIR_INTRINSIC_CAN_REORDER)
-
-SYSTEM_VALUE(front_face, 1, 0)
-SYSTEM_VALUE(vertex_id, 1, 0)
-SYSTEM_VALUE(vertex_id_zero_base, 1, 0)
-SYSTEM_VALUE(base_vertex, 1, 0)
-SYSTEM_VALUE(instance_id, 1, 0)
-SYSTEM_VALUE(base_instance, 1, 0)
-SYSTEM_VALUE(draw_id, 1, 0)
-SYSTEM_VALUE(sample_id, 1, 0)
-SYSTEM_VALUE(sample_pos, 2, 0)
-SYSTEM_VALUE(sample_mask_in, 1, 0)
-SYSTEM_VALUE(primitive_id, 1, 0)
-SYSTEM_VALUE(invocation_id, 1, 0)
-SYSTEM_VALUE(tess_coord, 3, 0)
-SYSTEM_VALUE(tess_level_outer, 4, 0)
-SYSTEM_VALUE(tess_level_inner, 2, 0)
-SYSTEM_VALUE(patch_vertices_in, 1, 0)
-SYSTEM_VALUE(local_invocation_id, 3, 0)
-SYSTEM_VALUE(work_group_id, 3, 0)
-SYSTEM_VALUE(user_clip_plane, 4, 1) /* const_index[0] is user_clip_plane[idx] */
-SYSTEM_VALUE(num_work_groups, 3, 0)
-SYSTEM_VALUE(helper_invocation, 1, 0)
-
-/*
- * Load operations pull data from some piece of GPU memory. All load
- * operations operate in terms of offsets into some piece of theoretical
- * memory. Loads from externally visible memory (UBO and SSBO) simply take a
- * byte offset as a source. Loads from opaque memory (uniforms, inputs, etc.)
- * take a base+offset pair where the base (const_index[0]) gives the location
- * of the start of the variable being loaded and and the offset source is a
- * offset into that variable.
- *
- * Uniform load operations have a second index that specifies the size of the
- * variable being loaded. If const_index[1] == 0, then the size is unknown.
- *
- * Some load operations such as UBO/SSBO load and per_vertex loads take an
- * additional source to specify which UBO/SSBO/vertex to load from.
- *
- * The exact address type depends on the lowering pass that generates the
- * load/store intrinsics. Typically, this is vec4 units for things such as
- * varying slots and float units for fragment shader inputs. UBO and SSBO
- * offsets are always in bytes.
- */
-
-#define LOAD(name, srcs, indices, flags) \
- INTRINSIC(load_##name, srcs, ARR(1, 1, 1, 1), true, 0, 0, indices, flags)
-
-/* src[] = { offset }. const_index[] = { base, size } */
-LOAD(uniform, 1, 2, NIR_INTRINSIC_CAN_ELIMINATE | NIR_INTRINSIC_CAN_REORDER)
-/* src[] = { buffer_index, offset }. No const_index */
-LOAD(ubo, 2, 0, NIR_INTRINSIC_CAN_ELIMINATE | NIR_INTRINSIC_CAN_REORDER)
-/* src[] = { offset }. const_index[] = { base } */
-LOAD(input, 1, 1, NIR_INTRINSIC_CAN_ELIMINATE | NIR_INTRINSIC_CAN_REORDER)
-/* src[] = { vertex, offset }. const_index[] = { base } */
-LOAD(per_vertex_input, 2, 1, NIR_INTRINSIC_CAN_ELIMINATE | NIR_INTRINSIC_CAN_REORDER)
-/* src[] = { buffer_index, offset }. No const_index */
-LOAD(ssbo, 2, 0, NIR_INTRINSIC_CAN_ELIMINATE)
-/* src[] = { offset }. const_index[] = { base } */
-LOAD(output, 1, 1, NIR_INTRINSIC_CAN_ELIMINATE)
-/* src[] = { vertex, offset }. const_index[] = { base } */
-LOAD(per_vertex_output, 2, 1, NIR_INTRINSIC_CAN_ELIMINATE)
-/* src[] = { offset }. const_index[] = { base } */
-LOAD(shared, 1, 1, NIR_INTRINSIC_CAN_ELIMINATE)
-/* src[] = { offset }. const_index[] = { base, size } */
-LOAD(push_constant, 1, 2, NIR_INTRINSIC_CAN_ELIMINATE | NIR_INTRINSIC_CAN_REORDER)
-
-/*
- * Stores work the same way as loads, except now the first source is the value
- * to store and the second (and possibly third) source specify where to store
- * the value. SSBO and shared memory stores also have a write mask as
- * const_index[0].
- */
-
-#define STORE(name, srcs, indices, flags) \
- INTRINSIC(store_##name, srcs, ARR(0, 1, 1, 1), false, 0, 0, indices, flags)
-
-/* src[] = { value, offset }. const_index[] = { base, write_mask } */
-STORE(output, 2, 2, 0)
-/* src[] = { value, vertex, offset }. const_index[] = { base, write_mask } */
-STORE(per_vertex_output, 3, 2, 0)
-/* src[] = { value, block_index, offset }. const_index[] = { write_mask } */
-STORE(ssbo, 3, 1, 0)
-/* src[] = { value, offset }. const_index[] = { base, write_mask } */
-STORE(shared, 2, 2, 0)
-
-LAST_INTRINSIC(store_shared)
diff --git a/src/glsl/nir/nir_liveness.c b/src/glsl/nir/nir_liveness.c
deleted file mode 100644
index 05f79d7bc61..00000000000
--- a/src/glsl/nir/nir_liveness.c
+++ /dev/null
@@ -1,297 +0,0 @@
-/*
- * Copyright © 2014 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- *
- * Authors:
- * Jason Ekstrand ([email protected])
- */
-
-#include "nir.h"
-#include "nir_worklist.h"
-#include "nir_vla.h"
-
-/*
- * Basic liveness analysis. This works only in SSA form.
- *
- * This liveness pass treats phi nodes as being melded to the space between
- * blocks so that the destinations of a phi are in the livein of the block
- * in which it resides and the sources are in the liveout of the
- * corresponding block. By formulating the liveness information in this
- * way, we ensure that the definition of any variable dominates its entire
- * live range. This is true because the only way that the definition of an
- * SSA value may not dominate a use is if the use is in a phi node and the
- * uses in phi no are in the live-out of the corresponding predecessor
- * block but not in the live-in of the block containing the phi node.
- */
-
-struct live_ssa_defs_state {
- unsigned num_ssa_defs;
- unsigned bitset_words;
-
- nir_block_worklist worklist;
-};
-
-static bool
-index_ssa_def(nir_ssa_def *def, void *void_state)
-{
- struct live_ssa_defs_state *state = void_state;
-
- if (def->parent_instr->type == nir_instr_type_ssa_undef)
- def->live_index = 0;
- else
- def->live_index = state->num_ssa_defs++;
-
- return true;
-}
-
-static bool
-index_ssa_definitions_block(nir_block *block, void *state)
-{
- nir_foreach_instr(block, instr)
- nir_foreach_ssa_def(instr, index_ssa_def, state);
-
- return true;
-}
-
-/* Initialize the liveness data to zero and add the given block to the
- * worklist.
- */
-static bool
-init_liveness_block(nir_block *block, void *void_state)
-{
- struct live_ssa_defs_state *state = void_state;
-
- block->live_in = reralloc(block, block->live_in, BITSET_WORD,
- state->bitset_words);
- memset(block->live_in, 0, state->bitset_words * sizeof(BITSET_WORD));
-
- block->live_out = reralloc(block, block->live_out, BITSET_WORD,
- state->bitset_words);
- memset(block->live_out, 0, state->bitset_words * sizeof(BITSET_WORD));
-
- nir_block_worklist_push_head(&state->worklist, block);
-
- return true;
-}
-
-static bool
-set_src_live(nir_src *src, void *void_live)
-{
- BITSET_WORD *live = void_live;
-
- if (!src->is_ssa)
- return true;
-
- if (src->ssa->live_index == 0)
- return true; /* undefined variables are never live */
-
- BITSET_SET(live, src->ssa->live_index);
-
- return true;
-}
-
-static bool
-set_ssa_def_dead(nir_ssa_def *def, void *void_live)
-{
- BITSET_WORD *live = void_live;
-
- BITSET_CLEAR(live, def->live_index);
-
- return true;
-}
-
-/** Propagates the live in of succ across the edge to the live out of pred
- *
- * Phi nodes exist "between" blocks and all the phi nodes at the start of a
- * block act "in parallel". When we propagate from the live_in of one
- * block to the live out of the other, we have to kill any writes from phis
- * and make live any sources.
- *
- * Returns true if updating live out of pred added anything
- */
-static bool
-propagate_across_edge(nir_block *pred, nir_block *succ,
- struct live_ssa_defs_state *state)
-{
- NIR_VLA(BITSET_WORD, live, state->bitset_words);
- memcpy(live, succ->live_in, state->bitset_words * sizeof *live);
-
- nir_foreach_instr(succ, instr) {
- if (instr->type != nir_instr_type_phi)
- break;
- nir_phi_instr *phi = nir_instr_as_phi(instr);
-
- assert(phi->dest.is_ssa);
- set_ssa_def_dead(&phi->dest.ssa, live);
- }
-
- nir_foreach_instr(succ, instr) {
- if (instr->type != nir_instr_type_phi)
- break;
- nir_phi_instr *phi = nir_instr_as_phi(instr);
-
- nir_foreach_phi_src(phi, src) {
- if (src->pred == pred) {
- set_src_live(&src->src, live);
- break;
- }
- }
- }
-
- BITSET_WORD progress = 0;
- for (unsigned i = 0; i < state->bitset_words; ++i) {
- progress |= live[i] & ~pred->live_out[i];
- pred->live_out[i] |= live[i];
- }
- return progress != 0;
-}
-
-void
-nir_live_ssa_defs_impl(nir_function_impl *impl)
-{
- struct live_ssa_defs_state state;
-
- /* We start at 1 because we reserve the index value of 0 for ssa_undef
- * instructions. Those are never live, so their liveness information
- * can be compacted into a single bit.
- */
- state.num_ssa_defs = 1;
- nir_foreach_block(impl, index_ssa_definitions_block, &state);
-
- nir_block_worklist_init(&state.worklist, impl->num_blocks, NULL);
-
- /* We now know how many unique ssa definitions we have and we can go
- * ahead and allocate live_in and live_out sets and add all of the
- * blocks to the worklist.
- */
- state.bitset_words = BITSET_WORDS(state.num_ssa_defs);
- nir_foreach_block(impl, init_liveness_block, &state);
-
- /* We're now ready to work through the worklist and update the liveness
- * sets of each of the blocks. By the time we get to this point, every
- * block in the function implementation has been pushed onto the
- * worklist in reverse order. As long as we keep the worklist
- * up-to-date as we go, everything will get covered.
- */
- while (!nir_block_worklist_is_empty(&state.worklist)) {
- /* We pop them off in the reverse order we pushed them on. This way
- * the first walk of the instructions is backwards so we only walk
- * once in the case of no control flow.
- */
- nir_block *block = nir_block_worklist_pop_head(&state.worklist);
-
- memcpy(block->live_in, block->live_out,
- state.bitset_words * sizeof(BITSET_WORD));
-
- nir_if *following_if = nir_block_get_following_if(block);
- if (following_if)
- set_src_live(&following_if->condition, block->live_in);
-
- nir_foreach_instr_reverse(block, instr) {
- /* Phi nodes are handled seperately so we want to skip them. Since
- * we are going backwards and they are at the beginning, we can just
- * break as soon as we see one.
- */
- if (instr->type == nir_instr_type_phi)
- break;
-
- nir_foreach_ssa_def(instr, set_ssa_def_dead, block->live_in);
- nir_foreach_src(instr, set_src_live, block->live_in);
- }
-
- /* Walk over all of the predecessors of the current block updating
- * their live in with the live out of this one. If anything has
- * changed, add the predecessor to the work list so that we ensure
- * that the new information is used.
- */
- struct set_entry *entry;
- set_foreach(block->predecessors, entry) {
- nir_block *pred = (nir_block *)entry->key;
- if (propagate_across_edge(pred, block, &state))
- nir_block_worklist_push_tail(&state.worklist, pred);
- }
- }
-
- nir_block_worklist_fini(&state.worklist);
-}
-
-static bool
-src_does_not_use_def(nir_src *src, void *def)
-{
- return !src->is_ssa || src->ssa != (nir_ssa_def *)def;
-}
-
-static bool
-search_for_use_after_instr(nir_instr *start, nir_ssa_def *def)
-{
- /* Only look for a use strictly after the given instruction */
- struct exec_node *node = start->node.next;
- while (!exec_node_is_tail_sentinel(node)) {
- nir_instr *instr = exec_node_data(nir_instr, node, node);
- if (!nir_foreach_src(instr, src_does_not_use_def, def))
- return true;
- node = node->next;
- }
- return false;
-}
-
-/* Returns true if def is live at instr assuming that def comes before
- * instr in a pre DFS search of the dominance tree.
- */
-static bool
-nir_ssa_def_is_live_at(nir_ssa_def *def, nir_instr *instr)
-{
- if (BITSET_TEST(instr->block->live_out, def->live_index)) {
- /* Since def dominates instr, if def is in the liveout of the block,
- * it's live at instr
- */
- return true;
- } else {
- if (BITSET_TEST(instr->block->live_in, def->live_index) ||
- def->parent_instr->block == instr->block) {
- /* In this case it is either live coming into instr's block or it
- * is defined in the same block. In this case, we simply need to
- * see if it is used after instr.
- */
- return search_for_use_after_instr(instr, def);
- } else {
- return false;
- }
- }
-}
-
-bool
-nir_ssa_defs_interfere(nir_ssa_def *a, nir_ssa_def *b)
-{
- if (a->parent_instr == b->parent_instr) {
- /* Two variables defined at the same time interfere assuming at
- * least one isn't dead.
- */
- return true;
- } else if (a->live_index == 0 || b->live_index == 0) {
- /* If either variable is an ssa_undef, then there's no interference */
- return false;
- } else if (a->live_index < b->live_index) {
- return nir_ssa_def_is_live_at(a, b->parent_instr);
- } else {
- return nir_ssa_def_is_live_at(b, a->parent_instr);
- }
-}
diff --git a/src/glsl/nir/nir_lower_alu_to_scalar.c b/src/glsl/nir/nir_lower_alu_to_scalar.c
deleted file mode 100644
index 37cb0221e0b..00000000000
--- a/src/glsl/nir/nir_lower_alu_to_scalar.c
+++ /dev/null
@@ -1,264 +0,0 @@
-/*
- * Copyright © 2014-2015 Broadcom
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include "nir.h"
-#include "nir_builder.h"
-
-/** @file nir_lower_alu_to_scalar.c
- *
- * Replaces nir_alu_instr operations with more than one channel used in the
- * arguments with individual per-channel operations.
- */
-
-static void
-nir_alu_ssa_dest_init(nir_alu_instr *instr, unsigned num_components)
-{
- nir_ssa_dest_init(&instr->instr, &instr->dest.dest, num_components, NULL);
- instr->dest.write_mask = (1 << num_components) - 1;
-}
-
-static void
-lower_reduction(nir_alu_instr *instr, nir_op chan_op, nir_op merge_op,
- nir_builder *builder)
-{
- unsigned num_components = nir_op_infos[instr->op].input_sizes[0];
-
- nir_ssa_def *last = NULL;
- for (unsigned i = 0; i < num_components; i++) {
- nir_alu_instr *chan = nir_alu_instr_create(builder->shader, chan_op);
- nir_alu_ssa_dest_init(chan, 1);
- nir_alu_src_copy(&chan->src[0], &instr->src[0], chan);
- chan->src[0].swizzle[0] = chan->src[0].swizzle[i];
- if (nir_op_infos[chan_op].num_inputs > 1) {
- assert(nir_op_infos[chan_op].num_inputs == 2);
- nir_alu_src_copy(&chan->src[1], &instr->src[1], chan);
- chan->src[1].swizzle[0] = chan->src[1].swizzle[i];
- }
-
- nir_builder_instr_insert(builder, &chan->instr);
-
- if (i == 0) {
- last = &chan->dest.dest.ssa;
- } else {
- last = nir_build_alu(builder, merge_op,
- last, &chan->dest.dest.ssa, NULL, NULL);
- }
- }
-
- assert(instr->dest.write_mask == 1);
- nir_ssa_def_rewrite_uses(&instr->dest.dest.ssa, nir_src_for_ssa(last));
- nir_instr_remove(&instr->instr);
-}
-
-static void
-lower_alu_instr_scalar(nir_alu_instr *instr, nir_builder *b)
-{
- unsigned num_src = nir_op_infos[instr->op].num_inputs;
- unsigned i, chan;
-
- assert(instr->dest.dest.is_ssa);
- assert(instr->dest.write_mask != 0);
-
- b->cursor = nir_before_instr(&instr->instr);
-
-#define LOWER_REDUCTION(name, chan, merge) \
- case name##2: \
- case name##3: \
- case name##4: \
- lower_reduction(instr, chan, merge, b); \
- return;
-
- switch (instr->op) {
- case nir_op_vec4:
- case nir_op_vec3:
- case nir_op_vec2:
- /* We don't need to scalarize these ops, they're the ones generated to
- * group up outputs into a value that can be SSAed.
- */
- return;
-
- case nir_op_pack_half_2x16:
- if (!b->shader->options->lower_pack_half_2x16)
- return;
-
- nir_ssa_def *val =
- nir_pack_half_2x16_split(b, nir_channel(b, instr->src[0].src.ssa,
- instr->src[0].swizzle[0]),
- nir_channel(b, instr->src[0].src.ssa,
- instr->src[0].swizzle[1]));
-
- nir_ssa_def_rewrite_uses(&instr->dest.dest.ssa, nir_src_for_ssa(val));
- nir_instr_remove(&instr->instr);
- return;
-
- case nir_op_unpack_unorm_4x8:
- case nir_op_unpack_snorm_4x8:
- case nir_op_unpack_unorm_2x16:
- case nir_op_unpack_snorm_2x16:
- /* There is no scalar version of these ops, unless we were to break it
- * down to bitshifts and math (which is definitely not intended).
- */
- return;
-
- case nir_op_unpack_half_2x16: {
- if (!b->shader->options->lower_unpack_half_2x16)
- return;
-
- nir_ssa_def *comps[2];
- comps[0] = nir_unpack_half_2x16_split_x(b, instr->src[0].src.ssa);
- comps[1] = nir_unpack_half_2x16_split_y(b, instr->src[0].src.ssa);
- nir_ssa_def *vec = nir_vec(b, comps, 2);
-
- nir_ssa_def_rewrite_uses(&instr->dest.dest.ssa, nir_src_for_ssa(vec));
- nir_instr_remove(&instr->instr);
- return;
- }
-
- case nir_op_pack_uvec2_to_uint: {
- assert(b->shader->options->lower_pack_snorm_2x16 ||
- b->shader->options->lower_pack_unorm_2x16);
-
- nir_ssa_def *word =
- nir_extract_uword(b, instr->src[0].src.ssa, nir_imm_int(b, 0));
- nir_ssa_def *val =
- nir_ior(b, nir_ishl(b, nir_channel(b, word, 1), nir_imm_int(b, 16)),
- nir_channel(b, word, 0));
-
- nir_ssa_def_rewrite_uses(&instr->dest.dest.ssa, nir_src_for_ssa(val));
- nir_instr_remove(&instr->instr);
- break;
- }
-
- case nir_op_pack_uvec4_to_uint: {
- assert(b->shader->options->lower_pack_snorm_4x8 ||
- b->shader->options->lower_pack_unorm_4x8);
-
- nir_ssa_def *byte =
- nir_extract_ubyte(b, instr->src[0].src.ssa, nir_imm_int(b, 0));
- nir_ssa_def *val =
- nir_ior(b, nir_ior(b, nir_ishl(b, nir_channel(b, byte, 3), nir_imm_int(b, 24)),
- nir_ishl(b, nir_channel(b, byte, 2), nir_imm_int(b, 16))),
- nir_ior(b, nir_ishl(b, nir_channel(b, byte, 1), nir_imm_int(b, 8)),
- nir_channel(b, byte, 0)));
-
- nir_ssa_def_rewrite_uses(&instr->dest.dest.ssa, nir_src_for_ssa(val));
- nir_instr_remove(&instr->instr);
- break;
- }
-
- case nir_op_fdph: {
- nir_ssa_def *sum[4];
- for (unsigned i = 0; i < 3; i++) {
- sum[i] = nir_fmul(b, nir_channel(b, instr->src[0].src.ssa,
- instr->src[0].swizzle[i]),
- nir_channel(b, instr->src[1].src.ssa,
- instr->src[1].swizzle[i]));
- }
- sum[3] = nir_channel(b, instr->src[1].src.ssa, instr->src[1].swizzle[3]);
-
- nir_ssa_def *val = nir_fadd(b, nir_fadd(b, sum[0], sum[1]),
- nir_fadd(b, sum[2], sum[3]));
-
- nir_ssa_def_rewrite_uses(&instr->dest.dest.ssa, nir_src_for_ssa(val));
- nir_instr_remove(&instr->instr);
- return;
- }
-
- LOWER_REDUCTION(nir_op_fdot, nir_op_fmul, nir_op_fadd);
- LOWER_REDUCTION(nir_op_ball_fequal, nir_op_feq, nir_op_iand);
- LOWER_REDUCTION(nir_op_ball_iequal, nir_op_ieq, nir_op_iand);
- LOWER_REDUCTION(nir_op_bany_fnequal, nir_op_fne, nir_op_ior);
- LOWER_REDUCTION(nir_op_bany_inequal, nir_op_ine, nir_op_ior);
- LOWER_REDUCTION(nir_op_fall_equal, nir_op_seq, nir_op_fand);
- LOWER_REDUCTION(nir_op_fany_nequal, nir_op_sne, nir_op_for);
-
- default:
- break;
- }
-
- if (instr->dest.dest.ssa.num_components == 1)
- return;
-
- unsigned num_components = instr->dest.dest.ssa.num_components;
- nir_ssa_def *comps[] = { NULL, NULL, NULL, NULL };
-
- for (chan = 0; chan < 4; chan++) {
- if (!(instr->dest.write_mask & (1 << chan)))
- continue;
-
- nir_alu_instr *lower = nir_alu_instr_create(b->shader, instr->op);
- for (i = 0; i < num_src; i++) {
- /* We only handle same-size-as-dest (input_sizes[] == 0) or scalar
- * args (input_sizes[] == 1).
- */
- assert(nir_op_infos[instr->op].input_sizes[i] < 2);
- unsigned src_chan = (nir_op_infos[instr->op].input_sizes[i] == 1 ?
- 0 : chan);
-
- nir_alu_src_copy(&lower->src[i], &instr->src[i], lower);
- for (int j = 0; j < 4; j++)
- lower->src[i].swizzle[j] = instr->src[i].swizzle[src_chan];
- }
-
- nir_alu_ssa_dest_init(lower, 1);
- lower->dest.saturate = instr->dest.saturate;
- comps[chan] = &lower->dest.dest.ssa;
-
- nir_builder_instr_insert(b, &lower->instr);
- }
-
- nir_ssa_def *vec = nir_vec(b, comps, num_components);
-
- nir_ssa_def_rewrite_uses(&instr->dest.dest.ssa, nir_src_for_ssa(vec));
-
- nir_instr_remove(&instr->instr);
-}
-
-static bool
-lower_alu_to_scalar_block(nir_block *block, void *builder)
-{
- nir_foreach_instr_safe(block, instr) {
- if (instr->type == nir_instr_type_alu)
- lower_alu_instr_scalar(nir_instr_as_alu(instr), builder);
- }
-
- return true;
-}
-
-static void
-nir_lower_alu_to_scalar_impl(nir_function_impl *impl)
-{
- nir_builder builder;
- nir_builder_init(&builder, impl);
-
- nir_foreach_block(impl, lower_alu_to_scalar_block, &builder);
-}
-
-void
-nir_lower_alu_to_scalar(nir_shader *shader)
-{
- nir_foreach_function(shader, function) {
- if (function->impl)
- nir_lower_alu_to_scalar_impl(function->impl);
- }
-}
diff --git a/src/glsl/nir/nir_lower_atomics.c b/src/glsl/nir/nir_lower_atomics.c
deleted file mode 100644
index a9d0ddbbd41..00000000000
--- a/src/glsl/nir/nir_lower_atomics.c
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * Copyright © 2014 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- *
- * Authors:
- * Connor Abbott ([email protected])
- *
- */
-
-#include "ir_uniform.h"
-#include "nir.h"
-#include "main/config.h"
-#include <assert.h>
-
-typedef struct {
- const struct gl_shader_program *shader_program;
- nir_shader *shader;
-} lower_atomic_state;
-
-/*
- * replace atomic counter intrinsics that use a variable with intrinsics
- * that directly store the buffer index and byte offset
- */
-
-static void
-lower_instr(nir_intrinsic_instr *instr,
- lower_atomic_state *state)
-{
- nir_intrinsic_op op;
- switch (instr->intrinsic) {
- case nir_intrinsic_atomic_counter_read_var:
- op = nir_intrinsic_atomic_counter_read;
- break;
-
- case nir_intrinsic_atomic_counter_inc_var:
- op = nir_intrinsic_atomic_counter_inc;
- break;
-
- case nir_intrinsic_atomic_counter_dec_var:
- op = nir_intrinsic_atomic_counter_dec;
- break;
-
- default:
- return;
- }
-
- if (instr->variables[0]->var->data.mode != nir_var_uniform &&
- instr->variables[0]->var->data.mode != nir_var_shader_storage &&
- instr->variables[0]->var->data.mode != nir_var_shared)
- return; /* atomics passed as function arguments can't be lowered */
-
- void *mem_ctx = ralloc_parent(instr);
- unsigned uniform_loc = instr->variables[0]->var->data.location;
-
- nir_intrinsic_instr *new_instr = nir_intrinsic_instr_create(mem_ctx, op);
- new_instr->const_index[0] =
- state->shader_program->UniformStorage[uniform_loc].opaque[state->shader->stage].index;
-
- nir_load_const_instr *offset_const = nir_load_const_instr_create(mem_ctx, 1);
- offset_const->value.u[0] = instr->variables[0]->var->data.offset;
-
- nir_instr_insert_before(&instr->instr, &offset_const->instr);
-
- nir_ssa_def *offset_def = &offset_const->def;
-
- nir_deref *tail = &instr->variables[0]->deref;
- while (tail->child != NULL) {
- assert(tail->child->deref_type == nir_deref_type_array);
- nir_deref_array *deref_array = nir_deref_as_array(tail->child);
- tail = tail->child;
-
- unsigned child_array_elements = tail->child != NULL ?
- glsl_get_aoa_size(tail->type) : 1;
-
- offset_const->value.u[0] += deref_array->base_offset *
- child_array_elements * ATOMIC_COUNTER_SIZE;
-
- if (deref_array->deref_array_type == nir_deref_array_type_indirect) {
- nir_load_const_instr *atomic_counter_size =
- nir_load_const_instr_create(mem_ctx, 1);
- atomic_counter_size->value.u[0] = child_array_elements * ATOMIC_COUNTER_SIZE;
- nir_instr_insert_before(&instr->instr, &atomic_counter_size->instr);
-
- nir_alu_instr *mul = nir_alu_instr_create(mem_ctx, nir_op_imul);
- nir_ssa_dest_init(&mul->instr, &mul->dest.dest, 1, NULL);
- mul->dest.write_mask = 0x1;
- nir_src_copy(&mul->src[0].src, &deref_array->indirect, mul);
- mul->src[1].src.is_ssa = true;
- mul->src[1].src.ssa = &atomic_counter_size->def;
- nir_instr_insert_before(&instr->instr, &mul->instr);
-
- nir_alu_instr *add = nir_alu_instr_create(mem_ctx, nir_op_iadd);
- nir_ssa_dest_init(&add->instr, &add->dest.dest, 1, NULL);
- add->dest.write_mask = 0x1;
- add->src[0].src.is_ssa = true;
- add->src[0].src.ssa = &mul->dest.dest.ssa;
- add->src[1].src.is_ssa = true;
- add->src[1].src.ssa = offset_def;
- nir_instr_insert_before(&instr->instr, &add->instr);
-
- offset_def = &add->dest.dest.ssa;
- }
- }
-
- new_instr->src[0].is_ssa = true;
- new_instr->src[0].ssa = offset_def;
-
- if (instr->dest.is_ssa) {
- nir_ssa_dest_init(&new_instr->instr, &new_instr->dest,
- instr->dest.ssa.num_components, NULL);
- nir_ssa_def_rewrite_uses(&instr->dest.ssa,
- nir_src_for_ssa(&new_instr->dest.ssa));
- } else {
- nir_dest_copy(&new_instr->dest, &instr->dest, mem_ctx);
- }
-
- nir_instr_insert_before(&instr->instr, &new_instr->instr);
- nir_instr_remove(&instr->instr);
-}
-
-static bool
-lower_block(nir_block *block, void *state)
-{
- nir_foreach_instr_safe(block, instr) {
- if (instr->type == nir_instr_type_intrinsic)
- lower_instr(nir_instr_as_intrinsic(instr),
- (lower_atomic_state *) state);
- }
-
- return true;
-}
-
-void
-nir_lower_atomics(nir_shader *shader,
- const struct gl_shader_program *shader_program)
-{
- lower_atomic_state state = {
- .shader = shader,
- .shader_program = shader_program,
- };
-
- nir_foreach_function(shader, function) {
- if (function->impl) {
- nir_foreach_block(function->impl, lower_block, (void *) &state);
- nir_metadata_preserve(function->impl, nir_metadata_block_index |
- nir_metadata_dominance);
- }
- }
-}
diff --git a/src/glsl/nir/nir_lower_clip.c b/src/glsl/nir/nir_lower_clip.c
deleted file mode 100644
index 0ca6a289396..00000000000
--- a/src/glsl/nir/nir_lower_clip.c
+++ /dev/null
@@ -1,339 +0,0 @@
-/*
- * Copyright © 2015 Red Hat
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- *
- * Authors:
- * Rob Clark <[email protected]>
- */
-
-#include "nir.h"
-#include "nir_builder.h"
-
-#define MAX_CLIP_PLANES 8
-
-/* Generates the lowering code for user-clip-planes, generating CLIPDIST
- * from UCP[n] + CLIPVERTEX or POSITION. Additionally, an optional pass
- * for fragment shaders to insert conditional kill's based on the inter-
- * polated CLIPDIST
- *
- * NOTE: should be run after nir_lower_outputs_to_temporaries() (or at
- * least in scenarios where you can count on each output written once
- * and only once).
- */
-
-
-static nir_variable *
-create_clipdist_var(nir_shader *shader, unsigned drvloc,
- bool output, gl_varying_slot slot)
-{
- nir_variable *var = rzalloc(shader, nir_variable);
-
- var->data.driver_location = drvloc;
- var->type = glsl_vec4_type();
- var->data.mode = output ? nir_var_shader_out : nir_var_shader_in;
- var->name = ralloc_asprintf(var, "clipdist_%d", drvloc);
- var->data.index = 0;
- var->data.location = slot;
-
- if (output) {
- exec_list_push_tail(&shader->outputs, &var->node);
- shader->num_outputs++; /* TODO use type_size() */
- }
- else {
- exec_list_push_tail(&shader->inputs, &var->node);
- shader->num_inputs++; /* TODO use type_size() */
- }
- return var;
-}
-
-static void
-store_clipdist_output(nir_builder *b, nir_variable *out, nir_ssa_def **val)
-{
- nir_intrinsic_instr *store;
-
- store = nir_intrinsic_instr_create(b->shader, nir_intrinsic_store_output);
- store->num_components = 4;
- store->const_index[0] = out->data.driver_location;
- store->const_index[1] = 0xf; /* wrmask */
- store->src[0].ssa = nir_vec4(b, val[0], val[1], val[2], val[3]);
- store->src[0].is_ssa = true;
- store->src[1] = nir_src_for_ssa(nir_imm_int(b, 0));
- nir_builder_instr_insert(b, &store->instr);
-}
-
-static void
-load_clipdist_input(nir_builder *b, nir_variable *in, nir_ssa_def **val)
-{
- nir_intrinsic_instr *load;
-
- load = nir_intrinsic_instr_create(b->shader, nir_intrinsic_load_input);
- load->num_components = 4;
- load->const_index[0] = in->data.driver_location;
- load->src[0] = nir_src_for_ssa(nir_imm_int(b, 0));
- nir_ssa_dest_init(&load->instr, &load->dest, 4, NULL);
- nir_builder_instr_insert(b, &load->instr);
-
- val[0] = nir_channel(b, &load->dest.ssa, 0);
- val[1] = nir_channel(b, &load->dest.ssa, 1);
- val[2] = nir_channel(b, &load->dest.ssa, 2);
- val[3] = nir_channel(b, &load->dest.ssa, 3);
-}
-
-struct find_output_state
-{
- unsigned drvloc;
- nir_ssa_def *def;
-};
-
-static bool
-find_output_in_block(nir_block *block, void *void_state)
-{
- struct find_output_state *state = void_state;
- nir_foreach_instr(block, instr) {
-
- if (instr->type == nir_instr_type_intrinsic) {
- nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
- if ((intr->intrinsic == nir_intrinsic_store_output) &&
- intr->const_index[0] == state->drvloc) {
- assert(state->def == NULL);
- assert(intr->src[0].is_ssa);
- assert(nir_src_as_const_value(intr->src[1]));
- state->def = intr->src[0].ssa;
-
-#if !defined(DEBUG)
- /* for debug builds, scan entire shader to assert
- * if output is written multiple times. For release
- * builds just assume all is well and bail when we
- * find first:
- */
- return false;
-#endif
- }
- }
- }
-
- return true;
-}
-
-/* TODO: maybe this would be a useful helper?
- * NOTE: assumes each output is written exactly once (and unconditionally)
- * so if needed nir_lower_outputs_to_temporaries()
- */
-static nir_ssa_def *
-find_output(nir_shader *shader, unsigned drvloc)
-{
- struct find_output_state state = {
- .drvloc = drvloc,
- };
-
- nir_foreach_function(shader, function) {
- if (function->impl) {
- nir_foreach_block_reverse(function->impl,
- find_output_in_block, &state);
- }
- }
-
- return state.def;
-}
-
-/*
- * VS lowering
- */
-
-static void
-lower_clip_vs(nir_function_impl *impl, unsigned ucp_enables,
- nir_ssa_def *cv, nir_variable **out)
-{
- nir_ssa_def *clipdist[MAX_CLIP_PLANES];
- nir_builder b;
-
- nir_builder_init(&b, impl);
-
- /* NIR should ensure that, even in case of loops/if-else, there
- * should be only a single predecessor block to end_block, which
- * makes the perfect place to insert the clipdist calculations.
- *
- * NOTE: in case of early return's, these would have to be lowered
- * to jumps to end_block predecessor in a previous pass. Not sure
- * if there is a good way to sanity check this, but for now the
- * users of this pass don't support sub-routines.
- */
- assert(impl->end_block->predecessors->entries == 1);
- b.cursor = nir_after_cf_list(&impl->body);
-
- for (int plane = 0; plane < MAX_CLIP_PLANES; plane++) {
- if (ucp_enables & (1 << plane)) {
- nir_ssa_def *ucp =
- nir_load_system_value(&b, nir_intrinsic_load_user_clip_plane, plane);
-
- /* calculate clipdist[plane] - dot(ucp, cv): */
- clipdist[plane] = nir_fdot4(&b, ucp, cv);
- }
- else {
- /* 0.0 == don't-clip == disabled: */
- clipdist[plane] = nir_imm_float(&b, 0.0);
- }
- }
-
- if (ucp_enables & 0x0f)
- store_clipdist_output(&b, out[0], &clipdist[0]);
- if (ucp_enables & 0xf0)
- store_clipdist_output(&b, out[1], &clipdist[4]);
-
- nir_metadata_preserve(impl, nir_metadata_dominance);
-}
-
-/* ucp_enables is bitmask of enabled ucp's. Actual ucp values are
- * passed in to shader via user_clip_plane system-values
- */
-void
-nir_lower_clip_vs(nir_shader *shader, unsigned ucp_enables)
-{
- int clipvertex = -1;
- int position = -1;
- int maxloc = -1;
- nir_ssa_def *cv;
- nir_variable *out[2] = { NULL };
-
- if (!ucp_enables)
- return;
-
- /* find clipvertex/position outputs: */
- nir_foreach_variable(var, &shader->outputs) {
- int loc = var->data.driver_location;
-
- /* keep track of last used driver-location.. we'll be
- * appending CLIP_DIST0/CLIP_DIST1 after last existing
- * output:
- */
- maxloc = MAX2(maxloc, loc);
-
- switch (var->data.location) {
- case VARYING_SLOT_POS:
- position = loc;
- break;
- case VARYING_SLOT_CLIP_VERTEX:
- clipvertex = loc;
- break;
- case VARYING_SLOT_CLIP_DIST0:
- case VARYING_SLOT_CLIP_DIST1:
- /* if shader is already writing CLIPDIST, then
- * there should be no user-clip-planes to deal
- * with.
- */
- return;
- }
- }
-
- if (clipvertex != -1)
- cv = find_output(shader, clipvertex);
- else if (position != -1)
- cv = find_output(shader, position);
- else
- return;
-
- /* insert CLIPDIST outputs: */
- if (ucp_enables & 0x0f)
- out[0] =
- create_clipdist_var(shader, ++maxloc, true, VARYING_SLOT_CLIP_DIST0);
- if (ucp_enables & 0xf0)
- out[1] =
- create_clipdist_var(shader, ++maxloc, true, VARYING_SLOT_CLIP_DIST1);
-
- nir_foreach_function(shader, function) {
- if (!strcmp(function->name, "main"))
- lower_clip_vs(function->impl, ucp_enables, cv, out);
- }
-}
-
-/*
- * FS lowering
- */
-
-static void
-lower_clip_fs(nir_function_impl *impl, unsigned ucp_enables,
- nir_variable **in)
-{
- nir_ssa_def *clipdist[MAX_CLIP_PLANES];
- nir_builder b;
-
- nir_builder_init(&b, impl);
- b.cursor = nir_before_cf_list(&impl->body);
-
- if (ucp_enables & 0x0f)
- load_clipdist_input(&b, in[0], &clipdist[0]);
- if (ucp_enables & 0xf0)
- load_clipdist_input(&b, in[1], &clipdist[4]);
-
- for (int plane = 0; plane < MAX_CLIP_PLANES; plane++) {
- if (ucp_enables & (1 << plane)) {
- nir_intrinsic_instr *discard;
- nir_ssa_def *cond;
-
- cond = nir_flt(&b, clipdist[plane], nir_imm_float(&b, 0.0));
-
- discard = nir_intrinsic_instr_create(b.shader,
- nir_intrinsic_discard_if);
- discard->src[0] = nir_src_for_ssa(cond);
- nir_builder_instr_insert(&b, &discard->instr);
- }
- }
-}
-
-/* insert conditional kill based on interpolated CLIPDIST
- */
-void
-nir_lower_clip_fs(nir_shader *shader, unsigned ucp_enables)
-{
- nir_variable *in[2];
- int maxloc = -1;
-
- if (!ucp_enables)
- return;
-
- nir_foreach_variable(var, &shader->inputs) {
- int loc = var->data.driver_location;
-
- /* keep track of last used driver-location.. we'll be
- * appending CLIP_DIST0/CLIP_DIST1 after last existing
- * input:
- */
- maxloc = MAX2(maxloc, loc);
- }
-
- /* The shader won't normally have CLIPDIST inputs, so we
- * must add our own:
- */
- /* insert CLIPDIST outputs: */
- if (ucp_enables & 0x0f)
- in[0] =
- create_clipdist_var(shader, ++maxloc, false,
- VARYING_SLOT_CLIP_DIST0);
- if (ucp_enables & 0xf0)
- in[1] =
- create_clipdist_var(shader, ++maxloc, false,
- VARYING_SLOT_CLIP_DIST1);
-
- nir_foreach_function(shader, function) {
- if (!strcmp(function->name, "main"))
- lower_clip_fs(function->impl, ucp_enables, in);
- }
-}
diff --git a/src/glsl/nir/nir_lower_global_vars_to_local.c b/src/glsl/nir/nir_lower_global_vars_to_local.c
deleted file mode 100644
index 7b4cd4ee8dc..00000000000
--- a/src/glsl/nir/nir_lower_global_vars_to_local.c
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright © 2014 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- *
- * Authors:
- * Jason Ekstrand ([email protected])
- *
- */
-
-/*
- * This lowering pass detects when a global variable is only being used by
- * one function and makes it local to that function
- */
-
-#include "nir.h"
-
-struct global_to_local_state {
- nir_function_impl *impl;
- /* A hash table keyed on variable pointers that stores the unique
- * nir_function_impl that uses the given variable. If a variable is
- * used in multiple functions, the data for the given key will be NULL.
- */
- struct hash_table *var_func_table;
-};
-
-static bool
-mark_global_var_uses_block(nir_block *block, void *void_state)
-{
- struct global_to_local_state *state = void_state;
-
- nir_foreach_instr(block, instr) {
- if (instr->type != nir_instr_type_intrinsic)
- continue;
-
- nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
- unsigned num_vars = nir_intrinsic_infos[intrin->intrinsic].num_variables;
-
- for (unsigned i = 0; i < num_vars; i++) {
- nir_variable *var = intrin->variables[i]->var;
- if (var->data.mode != nir_var_global)
- continue;
-
- struct hash_entry *entry =
- _mesa_hash_table_search(state->var_func_table, var);
-
- if (entry) {
- if (entry->data != state->impl)
- entry->data = NULL;
- } else {
- _mesa_hash_table_insert(state->var_func_table, var, state->impl);
- }
- }
- }
-
- return true;
-}
-
-bool
-nir_lower_global_vars_to_local(nir_shader *shader)
-{
- struct global_to_local_state state;
- bool progress = false;
-
- state.var_func_table = _mesa_hash_table_create(NULL, _mesa_hash_pointer,
- _mesa_key_pointer_equal);
-
- nir_foreach_function(shader, function) {
- if (function->impl) {
- state.impl = function->impl;
- nir_foreach_block(function->impl, mark_global_var_uses_block, &state);
- }
- }
-
- struct hash_entry *entry;
- hash_table_foreach(state.var_func_table, entry) {
- nir_variable *var = (void *)entry->key;
- nir_function_impl *impl = entry->data;
-
- assert(var->data.mode == nir_var_global);
-
- if (impl != NULL) {
- exec_node_remove(&var->node);
- var->data.mode = nir_var_local;
- exec_list_push_tail(&impl->locals, &var->node);
- nir_metadata_preserve(impl, nir_metadata_block_index |
- nir_metadata_dominance |
- nir_metadata_live_ssa_defs);
- progress = true;
- }
- }
-
- _mesa_hash_table_destroy(state.var_func_table, NULL);
-
- return progress;
-}
diff --git a/src/glsl/nir/nir_lower_gs_intrinsics.c b/src/glsl/nir/nir_lower_gs_intrinsics.c
deleted file mode 100644
index fdff1656b4d..00000000000
--- a/src/glsl/nir/nir_lower_gs_intrinsics.c
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- * Copyright © 2015 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include "nir.h"
-#include "nir_builder.h"
-
-/**
- * \file nir_lower_gs_intrinsics.c
- *
- * Geometry Shaders can call EmitVertex()/EmitStreamVertex() to output an
- * arbitrary number of vertices. However, the shader must declare the maximum
- * number of vertices that it will ever output - further attempts to emit
- * vertices result in undefined behavior according to the GLSL specification.
- *
- * Drivers might use this maximum number of vertices to allocate enough space
- * to hold the geometry shader's output. Some drivers (such as i965) need to
- * implement "safety checks" which ensure that the shader hasn't emitted too
- * many vertices, to avoid overflowing that space and trashing other memory.
- *
- * The count of emitted vertices can also be useful in buffer offset
- * calculations, so drivers know where to write the GS output.
- *
- * However, for simple geometry shaders that emit a statically determinable
- * number of vertices, this extra bookkeeping is unnecessary and inefficient.
- * By tracking the vertex count in NIR, we allow constant folding/propagation
- * and dead control flow optimizations to eliminate most of it where possible.
- *
- * This pass introduces a new global variable which stores the current vertex
- * count (initialized to 0), and converts emit_vertex/end_primitive intrinsics
- * to their *_with_counter variants. emit_vertex is also wrapped in a safety
- * check to avoid buffer overflows. Finally, it adds a set_vertex_count
- * intrinsic at the end of the program, informing the driver of the final
- * vertex count.
- */
-
-struct state {
- nir_builder *builder;
- nir_variable *vertex_count_var;
- bool progress;
-};
-
-/**
- * Replace emit_vertex intrinsics with:
- *
- * if (vertex_count < max_vertices) {
- * emit_vertex_with_counter vertex_count ...
- * vertex_count += 1
- * }
- */
-static void
-rewrite_emit_vertex(nir_intrinsic_instr *intrin, struct state *state)
-{
- nir_builder *b = state->builder;
-
- /* Load the vertex count */
- b->cursor = nir_before_instr(&intrin->instr);
- nir_ssa_def *count = nir_load_var(b, state->vertex_count_var);
-
- nir_ssa_def *max_vertices = nir_imm_int(b, b->shader->info.gs.vertices_out);
-
- /* Create: if (vertex_count < max_vertices) and insert it.
- *
- * The new if statement needs to be hooked up to the control flow graph
- * before we start inserting instructions into it.
- */
- nir_if *if_stmt = nir_if_create(b->shader);
- if_stmt->condition = nir_src_for_ssa(nir_ilt(b, count, max_vertices));
- nir_builder_cf_insert(b, &if_stmt->cf_node);
-
- /* Fill out the new then-block */
- b->cursor = nir_after_cf_list(&if_stmt->then_list);
-
- nir_intrinsic_instr *lowered =
- nir_intrinsic_instr_create(b->shader,
- nir_intrinsic_emit_vertex_with_counter);
- lowered->const_index[0] = intrin->const_index[0];
- lowered->src[0] = nir_src_for_ssa(count);
- nir_builder_instr_insert(b, &lowered->instr);
-
- /* Increment the vertex count by 1 */
- nir_store_var(b, state->vertex_count_var,
- nir_iadd(b, count, nir_imm_int(b, 1)),
- 0x1); /* .x */
-
- nir_instr_remove(&intrin->instr);
-
- state->progress = true;
-}
-
-/**
- * Replace end_primitive with end_primitive_with_counter.
- */
-static void
-rewrite_end_primitive(nir_intrinsic_instr *intrin, struct state *state)
-{
- nir_builder *b = state->builder;
-
- b->cursor = nir_before_instr(&intrin->instr);
- nir_ssa_def *count = nir_load_var(b, state->vertex_count_var);
-
- nir_intrinsic_instr *lowered =
- nir_intrinsic_instr_create(b->shader,
- nir_intrinsic_end_primitive_with_counter);
- lowered->const_index[0] = intrin->const_index[0];
- lowered->src[0] = nir_src_for_ssa(count);
- nir_builder_instr_insert(b, &lowered->instr);
-
- nir_instr_remove(&intrin->instr);
-
- state->progress = true;
-}
-
-static bool
-rewrite_intrinsics(nir_block *block, void *closure)
-{
- struct state *state = closure;
-
- nir_foreach_instr_safe(block, instr) {
- if (instr->type != nir_instr_type_intrinsic)
- continue;
-
- nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
- switch (intrin->intrinsic) {
- case nir_intrinsic_emit_vertex:
- rewrite_emit_vertex(intrin, state);
- break;
- case nir_intrinsic_end_primitive:
- rewrite_end_primitive(intrin, state);
- break;
- default:
- /* not interesting; skip this */
- break;
- }
- }
-
- return true;
-}
-
-/**
- * Add a set_vertex_count intrinsic at the end of the program
- * (representing the final vertex count).
- */
-static void
-append_set_vertex_count(nir_block *end_block, struct state *state)
-{
- nir_builder *b = state->builder;
- nir_shader *shader = state->builder->shader;
-
- /* Insert the new intrinsic in all of the predecessors of the end block,
- * but before any jump instructions (return).
- */
- struct set_entry *entry;
- set_foreach(end_block->predecessors, entry) {
- nir_block *pred = (nir_block *) entry->key;
- b->cursor = nir_after_block_before_jump(pred);
-
- nir_ssa_def *count = nir_load_var(b, state->vertex_count_var);
-
- nir_intrinsic_instr *set_vertex_count =
- nir_intrinsic_instr_create(shader, nir_intrinsic_set_vertex_count);
- set_vertex_count->src[0] = nir_src_for_ssa(count);
-
- nir_builder_instr_insert(b, &set_vertex_count->instr);
- }
-}
-
-bool
-nir_lower_gs_intrinsics(nir_shader *shader)
-{
- struct state state;
- state.progress = false;
-
- /* Create the counter variable */
- nir_variable *var = rzalloc(shader, nir_variable);
- var->data.mode = nir_var_global;
- var->type = glsl_uint_type();
- var->name = "vertex_count";
- var->constant_initializer = rzalloc(shader, nir_constant); /* initialize to 0 */
-
- exec_list_push_tail(&shader->globals, &var->node);
- state.vertex_count_var = var;
-
- nir_foreach_function(shader, function) {
- if (function->impl) {
- nir_builder b;
- nir_builder_init(&b, function->impl);
- state.builder = &b;
-
- nir_foreach_block(function->impl, rewrite_intrinsics, &state);
-
- /* This only works because we have a single main() function. */
- append_set_vertex_count(function->impl->end_block, &state);
-
- nir_metadata_preserve(function->impl, 0);
- }
- }
-
- return state.progress;
-}
diff --git a/src/glsl/nir/nir_lower_idiv.c b/src/glsl/nir/nir_lower_idiv.c
deleted file mode 100644
index a084ad9c0e5..00000000000
--- a/src/glsl/nir/nir_lower_idiv.c
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * Copyright © 2015 Red Hat
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- *
- * Authors:
- * Rob Clark <[email protected]>
- */
-
-#include "nir.h"
-#include "nir_builder.h"
-
-/* Lowers idiv/udiv/umod
- * Based on NV50LegalizeSSA::handleDIV()
- *
- * Note that this is probably not enough precision for compute shaders.
- * Perhaps we want a second higher precision (looping) version of this?
- * Or perhaps we assume if you can do compute shaders you can also
- * branch out to a pre-optimized shader library routine..
- */
-
-static void
-convert_instr(nir_builder *bld, nir_alu_instr *alu)
-{
- nir_ssa_def *numer, *denom, *af, *bf, *a, *b, *q, *r;
- nir_op op = alu->op;
- bool is_signed;
-
- if ((op != nir_op_idiv) &&
- (op != nir_op_udiv) &&
- (op != nir_op_umod))
- return;
-
- is_signed = (op == nir_op_idiv);
-
- bld->cursor = nir_before_instr(&alu->instr);
-
- numer = nir_ssa_for_alu_src(bld, alu, 0);
- denom = nir_ssa_for_alu_src(bld, alu, 1);
-
- if (is_signed) {
- af = nir_i2f(bld, numer);
- bf = nir_i2f(bld, denom);
- af = nir_fabs(bld, af);
- bf = nir_fabs(bld, bf);
- a = nir_iabs(bld, numer);
- b = nir_iabs(bld, denom);
- } else {
- af = nir_u2f(bld, numer);
- bf = nir_u2f(bld, denom);
- a = numer;
- b = denom;
- }
-
- /* get first result: */
- bf = nir_frcp(bld, bf);
- bf = nir_isub(bld, bf, nir_imm_int(bld, 2)); /* yes, really */
- q = nir_fmul(bld, af, bf);
-
- if (is_signed) {
- q = nir_f2i(bld, q);
- } else {
- q = nir_f2u(bld, q);
- }
-
- /* get error of first result: */
- r = nir_imul(bld, q, b);
- r = nir_isub(bld, a, r);
- r = nir_u2f(bld, r);
- r = nir_fmul(bld, r, bf);
- r = nir_f2u(bld, r);
-
- /* add quotients: */
- q = nir_iadd(bld, q, r);
-
- /* correction: if modulus >= divisor, add 1 */
- r = nir_imul(bld, q, b);
- r = nir_isub(bld, a, r);
-
- r = nir_uge(bld, r, b);
- r = nir_b2i(bld, r);
-
- q = nir_iadd(bld, q, r);
- if (is_signed) {
- /* fix the sign: */
- r = nir_ixor(bld, numer, denom);
- r = nir_ushr(bld, r, nir_imm_int(bld, 31));
- r = nir_i2b(bld, r);
- b = nir_ineg(bld, q);
- q = nir_bcsel(bld, r, b, q);
- }
-
- if (op == nir_op_umod) {
- /* division result in q */
- r = nir_imul(bld, q, b);
- q = nir_isub(bld, a, r);
- }
-
- assert(alu->dest.dest.is_ssa);
- nir_ssa_def_rewrite_uses(&alu->dest.dest.ssa, nir_src_for_ssa(q));
-}
-
-static bool
-convert_block(nir_block *block, void *state)
-{
- nir_builder *b = state;
-
- nir_foreach_instr_safe(block, instr) {
- if (instr->type == nir_instr_type_alu)
- convert_instr(b, nir_instr_as_alu(instr));
- }
-
- return true;
-}
-
-static void
-convert_impl(nir_function_impl *impl)
-{
- nir_builder b;
- nir_builder_init(&b, impl);
-
- nir_foreach_block(impl, convert_block, &b);
- nir_metadata_preserve(impl, nir_metadata_block_index |
- nir_metadata_dominance);
-}
-
-void
-nir_lower_idiv(nir_shader *shader)
-{
- nir_foreach_function(shader, function) {
- if (function->impl)
- convert_impl(function->impl);
- }
-}
diff --git a/src/glsl/nir/nir_lower_indirect_derefs.c b/src/glsl/nir/nir_lower_indirect_derefs.c
deleted file mode 100644
index 69f2df4ba6d..00000000000
--- a/src/glsl/nir/nir_lower_indirect_derefs.c
+++ /dev/null
@@ -1,239 +0,0 @@
-/*
- * Copyright © 2016 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include "nir.h"
-#include "nir_builder.h"
-
-static void
-emit_load_store(nir_builder *b, nir_intrinsic_instr *orig_instr,
- nir_deref_var *deref, nir_deref *tail,
- nir_ssa_def **dest, nir_ssa_def *src);
-
-static void
-emit_indirect_load_store(nir_builder *b, nir_intrinsic_instr *orig_instr,
- nir_deref_var *deref, nir_deref *arr_parent,
- int start, int end,
- nir_ssa_def **dest, nir_ssa_def *src)
-{
- assert(arr_parent->child &&
- arr_parent->child->deref_type == nir_deref_type_array);
- nir_deref_array *arr = nir_deref_as_array(arr_parent->child);
- assert(arr->deref_array_type == nir_deref_array_type_indirect);
- assert(arr->indirect.is_ssa);
-
- assert(start < end);
- if (start == end - 1) {
- /* Base case. Just emit the load/store op */
- nir_deref_array direct = *arr;
- direct.deref_array_type = nir_deref_array_type_direct;
- direct.base_offset += start;
- direct.indirect = NIR_SRC_INIT;
-
- arr_parent->child = &direct.deref;
- emit_load_store(b, orig_instr, deref, &arr->deref, dest, src);
- arr_parent->child = &arr->deref;
- } else {
- int mid = start + (end - start) / 2;
-
- nir_ssa_def *then_dest, *else_dest;
-
- nir_if *if_stmt = nir_if_create(b->shader);
- if_stmt->condition = nir_src_for_ssa(nir_ilt(b, arr->indirect.ssa,
- nir_imm_int(b, mid)));
- nir_cf_node_insert(b->cursor, &if_stmt->cf_node);
-
- b->cursor = nir_after_cf_list(&if_stmt->then_list);
- emit_indirect_load_store(b, orig_instr, deref, arr_parent,
- start, mid, &then_dest, src);
-
- b->cursor = nir_after_cf_list(&if_stmt->else_list);
- emit_indirect_load_store(b, orig_instr, deref, arr_parent,
- mid, end, &else_dest, src);
-
- b->cursor = nir_after_cf_node(&if_stmt->cf_node);
-
- if (src == NULL) {
- /* We're a load. We need to insert a phi node */
- nir_phi_instr *phi = nir_phi_instr_create(b->shader);
- nir_ssa_dest_init(&phi->instr, &phi->dest,
- then_dest->num_components, NULL);
-
- nir_phi_src *src0 = ralloc(phi, nir_phi_src);
- src0->pred = nir_cf_node_as_block(nir_if_last_then_node(if_stmt));
- src0->src = nir_src_for_ssa(then_dest);
- exec_list_push_tail(&phi->srcs, &src0->node);
-
- nir_phi_src *src1 = ralloc(phi, nir_phi_src);
- src1->pred = nir_cf_node_as_block(nir_if_last_else_node(if_stmt));
- src1->src = nir_src_for_ssa(else_dest);
- exec_list_push_tail(&phi->srcs, &src1->node);
-
- nir_builder_instr_insert(b, &phi->instr);
- *dest = &phi->dest.ssa;
- }
- }
-}
-
-static void
-emit_load_store(nir_builder *b, nir_intrinsic_instr *orig_instr,
- nir_deref_var *deref, nir_deref *tail,
- nir_ssa_def **dest, nir_ssa_def *src)
-{
- for (; tail->child; tail = tail->child) {
- if (tail->child->deref_type != nir_deref_type_array)
- continue;
-
- nir_deref_array *arr = nir_deref_as_array(tail->child);
- if (arr->deref_array_type != nir_deref_array_type_indirect)
- continue;
-
- int length = glsl_get_length(tail->type);
-
- emit_indirect_load_store(b, orig_instr, deref, tail, -arr->base_offset,
- length - arr->base_offset, dest, src);
- return;
- }
-
- assert(tail && tail->child == NULL);
-
- /* We reached the end of the deref chain. Emit the instruction */
-
- if (src == NULL) {
- /* This is a load instruction */
- nir_intrinsic_instr *load =
- nir_intrinsic_instr_create(b->shader, nir_intrinsic_load_var);
- load->num_components = orig_instr->num_components;
- load->variables[0] =
- nir_deref_as_var(nir_copy_deref(load, &deref->deref));
- nir_ssa_dest_init(&load->instr, &load->dest,
- load->num_components, NULL);
- nir_builder_instr_insert(b, &load->instr);
- *dest = &load->dest.ssa;
- } else {
- /* This is a store instruction */
- nir_intrinsic_instr *store =
- nir_intrinsic_instr_create(b->shader, nir_intrinsic_store_var);
- store->num_components = orig_instr->num_components;
- store->const_index[0] = orig_instr->const_index[0]; /* writemask */
- store->variables[0] =
- nir_deref_as_var(nir_copy_deref(store, &deref->deref));
- store->src[0] = nir_src_for_ssa(src);
- nir_builder_instr_insert(b, &store->instr);
- }
-}
-
-static bool
-deref_has_indirect(nir_deref_var *deref)
-{
- for (nir_deref *tail = deref->deref.child; tail; tail = tail->child) {
- if (tail->deref_type != nir_deref_type_array)
- continue;
-
- nir_deref_array *arr = nir_deref_as_array(tail);
- if (arr->deref_array_type == nir_deref_array_type_indirect)
- return true;
- }
-
- return false;
-}
-
-struct lower_indirect_state {
- nir_builder builder;
- uint32_t mode_mask;
- bool progress;
-};
-
-static bool
-lower_indirect_block(nir_block *block, void *void_state)
-{
- struct lower_indirect_state *state = void_state;
-
- nir_foreach_instr_safe(block, instr) {
- if (instr->type != nir_instr_type_intrinsic)
- continue;
-
- nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
- if (intrin->intrinsic != nir_intrinsic_load_var &&
- intrin->intrinsic != nir_intrinsic_store_var)
- continue;
-
- if (!deref_has_indirect(intrin->variables[0]))
- continue;
-
- /* Only lower variables whose mode is in the mask */
- if (!(state->mode_mask & (1 << intrin->variables[0]->var->data.mode)))
- continue;
-
- state->builder.cursor = nir_before_instr(&intrin->instr);
-
- if (intrin->intrinsic == nir_intrinsic_load_var) {
- nir_ssa_def *result;
- emit_load_store(&state->builder, intrin, intrin->variables[0],
- &intrin->variables[0]->deref, &result, NULL);
- nir_ssa_def_rewrite_uses(&intrin->dest.ssa, nir_src_for_ssa(result));
- } else {
- assert(intrin->src[0].is_ssa);
- emit_load_store(&state->builder, intrin, intrin->variables[0],
- &intrin->variables[0]->deref, NULL, intrin->src[0].ssa);
- }
- nir_instr_remove(&intrin->instr);
- state->progress = true;
- }
-
- return true;
-}
-
-static bool
-lower_indirects_impl(nir_function_impl *impl, uint32_t mode_mask)
-{
- struct lower_indirect_state state;
-
- state.progress = false;
- state.mode_mask = mode_mask;
- nir_builder_init(&state.builder, impl);
-
- nir_foreach_block(impl, lower_indirect_block, &state);
-
- if (state.progress)
- nir_metadata_preserve(impl, nir_metadata_none);
-
- return state.progress;
-}
-
-/** Lowers indirect variable loads/stores to direct loads/stores.
- *
- * The pass works by replacing any indirect load or store with an if-ladder
- * that does a binary search on the array index.
- */
-bool
-nir_lower_indirect_derefs(nir_shader *shader, uint32_t mode_mask)
-{
- bool progress = false;
-
- nir_foreach_function(shader, function) {
- if (function->impl)
- progress = lower_indirects_impl(function->impl, mode_mask) || progress;
- }
-
- return progress;
-}
diff --git a/src/glsl/nir/nir_lower_io.c b/src/glsl/nir/nir_lower_io.c
deleted file mode 100644
index 2c5fa16af5e..00000000000
--- a/src/glsl/nir/nir_lower_io.c
+++ /dev/null
@@ -1,461 +0,0 @@
-/*
- * Copyright © 2014 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- *
- * Authors:
- * Connor Abbott ([email protected])
- * Jason Ekstrand ([email protected])
- *
- */
-
-/*
- * This lowering pass converts references to input/output variables with
- * loads/stores to actual input/output intrinsics.
- */
-
-#include "nir.h"
-#include "nir_builder.h"
-
-struct lower_io_state {
- nir_builder builder;
- void *mem_ctx;
- int (*type_size)(const struct glsl_type *type);
- nir_variable_mode mode;
-};
-
-void
-nir_assign_var_locations(struct exec_list *var_list, unsigned *size,
- int (*type_size)(const struct glsl_type *))
-{
- unsigned location = 0;
-
- nir_foreach_variable(var, var_list) {
- /*
- * UBO's have their own address spaces, so don't count them towards the
- * number of global uniforms
- */
- if ((var->data.mode == nir_var_uniform || var->data.mode == nir_var_shader_storage) &&
- var->interface_type != NULL)
- continue;
-
- var->data.driver_location = location;
- location += type_size(var->type);
- }
-
- *size = location;
-}
-
-/**
- * Returns true if we're processing a stage whose inputs are arrays indexed
- * by a vertex number (such as geometry shader inputs).
- */
-static bool
-is_per_vertex_input(struct lower_io_state *state, nir_variable *var)
-{
- gl_shader_stage stage = state->builder.shader->stage;
-
- return var->data.mode == nir_var_shader_in && !var->data.patch &&
- (stage == MESA_SHADER_TESS_CTRL ||
- stage == MESA_SHADER_TESS_EVAL ||
- stage == MESA_SHADER_GEOMETRY);
-}
-
-static bool
-is_per_vertex_output(struct lower_io_state *state, nir_variable *var)
-{
- gl_shader_stage stage = state->builder.shader->stage;
- return var->data.mode == nir_var_shader_out && !var->data.patch &&
- stage == MESA_SHADER_TESS_CTRL;
-}
-
-static nir_ssa_def *
-get_io_offset(nir_builder *b, nir_deref_var *deref,
- nir_ssa_def **vertex_index,
- int (*type_size)(const struct glsl_type *))
-{
- nir_deref *tail = &deref->deref;
-
- /* For per-vertex input arrays (i.e. geometry shader inputs), keep the
- * outermost array index separate. Process the rest normally.
- */
- if (vertex_index != NULL) {
- tail = tail->child;
- assert(tail->deref_type == nir_deref_type_array);
- nir_deref_array *deref_array = nir_deref_as_array(tail);
-
- nir_ssa_def *vtx = nir_imm_int(b, deref_array->base_offset);
- if (deref_array->deref_array_type == nir_deref_array_type_indirect) {
- vtx = nir_iadd(b, vtx, nir_ssa_for_src(b, deref_array->indirect, 1));
- }
- *vertex_index = vtx;
- }
-
- /* Just emit code and let constant-folding go to town */
- nir_ssa_def *offset = nir_imm_int(b, 0);
-
- while (tail->child != NULL) {
- const struct glsl_type *parent_type = tail->type;
- tail = tail->child;
-
- if (tail->deref_type == nir_deref_type_array) {
- nir_deref_array *deref_array = nir_deref_as_array(tail);
- unsigned size = type_size(tail->type);
-
- offset = nir_iadd(b, offset,
- nir_imm_int(b, size * deref_array->base_offset));
-
- if (deref_array->deref_array_type == nir_deref_array_type_indirect) {
- nir_ssa_def *mul =
- nir_imul(b, nir_imm_int(b, size),
- nir_ssa_for_src(b, deref_array->indirect, 1));
-
- offset = nir_iadd(b, offset, mul);
- }
- } else if (tail->deref_type == nir_deref_type_struct) {
- nir_deref_struct *deref_struct = nir_deref_as_struct(tail);
-
- unsigned field_offset = 0;
- for (unsigned i = 0; i < deref_struct->index; i++) {
- field_offset += type_size(glsl_get_struct_field(parent_type, i));
- }
- offset = nir_iadd(b, offset, nir_imm_int(b, field_offset));
- }
- }
-
- return offset;
-}
-
-static nir_intrinsic_op
-load_op(struct lower_io_state *state,
- nir_variable_mode mode, bool per_vertex)
-{
- nir_intrinsic_op op;
- switch (mode) {
- case nir_var_shader_in:
- op = per_vertex ? nir_intrinsic_load_per_vertex_input :
- nir_intrinsic_load_input;
- break;
- case nir_var_shader_out:
- op = per_vertex ? nir_intrinsic_load_per_vertex_output :
- nir_intrinsic_load_output;
- break;
- case nir_var_uniform:
- op = nir_intrinsic_load_uniform;
- break;
- case nir_var_shared:
- op = nir_intrinsic_load_shared;
- break;
- default:
- unreachable("Unknown variable mode");
- }
- return op;
-}
-
-static nir_intrinsic_op
-store_op(struct lower_io_state *state,
- nir_variable_mode mode, bool per_vertex)
-{
- nir_intrinsic_op op;
- switch (mode) {
- case nir_var_shader_in:
- case nir_var_shader_out:
- op = per_vertex ? nir_intrinsic_store_per_vertex_output :
- nir_intrinsic_store_output;
- break;
- case nir_var_shared:
- op = nir_intrinsic_store_shared;
- break;
- default:
- unreachable("Unknown variable mode");
- }
- return op;
-}
-
-static nir_intrinsic_op
-atomic_op(nir_intrinsic_op opcode)
-{
- switch (opcode) {
-#define OP(O) case nir_intrinsic_var_##O: return nir_intrinsic_shared_##O;
- OP(atomic_exchange)
- OP(atomic_comp_swap)
- OP(atomic_add)
- OP(atomic_imin)
- OP(atomic_umin)
- OP(atomic_imax)
- OP(atomic_umax)
- OP(atomic_and)
- OP(atomic_or)
- OP(atomic_xor)
-#undef OP
- default:
- unreachable("Invalid atomic");
- }
-}
-
-static bool
-nir_lower_io_block(nir_block *block, void *void_state)
-{
- struct lower_io_state *state = void_state;
-
- nir_builder *b = &state->builder;
-
- nir_foreach_instr_safe(block, instr) {
- if (instr->type != nir_instr_type_intrinsic)
- continue;
-
- nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
-
- switch (intrin->intrinsic) {
- case nir_intrinsic_load_var:
- case nir_intrinsic_store_var:
- case nir_intrinsic_var_atomic_add:
- case nir_intrinsic_var_atomic_imin:
- case nir_intrinsic_var_atomic_umin:
- case nir_intrinsic_var_atomic_imax:
- case nir_intrinsic_var_atomic_umax:
- case nir_intrinsic_var_atomic_and:
- case nir_intrinsic_var_atomic_or:
- case nir_intrinsic_var_atomic_xor:
- case nir_intrinsic_var_atomic_exchange:
- case nir_intrinsic_var_atomic_comp_swap:
- /* We can lower the io for this nir instrinsic */
- break;
- default:
- /* We can't lower the io for this nir instrinsic, so skip it */
- continue;
- }
-
- nir_variable_mode mode = intrin->variables[0]->var->data.mode;
-
- if (state->mode != nir_var_all && state->mode != mode)
- continue;
-
- if (mode != nir_var_shader_in &&
- mode != nir_var_shader_out &&
- mode != nir_var_shared &&
- mode != nir_var_uniform)
- continue;
-
- b->cursor = nir_before_instr(instr);
-
- switch (intrin->intrinsic) {
- case nir_intrinsic_load_var: {
- bool per_vertex =
- is_per_vertex_input(state, intrin->variables[0]->var) ||
- is_per_vertex_output(state, intrin->variables[0]->var);
-
- nir_ssa_def *offset;
- nir_ssa_def *vertex_index;
-
- offset = get_io_offset(b, intrin->variables[0],
- per_vertex ? &vertex_index : NULL,
- state->type_size);
-
- nir_intrinsic_instr *load =
- nir_intrinsic_instr_create(state->mem_ctx,
- load_op(state, mode, per_vertex));
- load->num_components = intrin->num_components;
-
- load->const_index[0] =
- intrin->variables[0]->var->data.driver_location;
-
- if (load->intrinsic == nir_intrinsic_load_uniform) {
- load->const_index[1] =
- state->type_size(intrin->variables[0]->var->type);
- }
-
- if (per_vertex)
- load->src[0] = nir_src_for_ssa(vertex_index);
-
- load->src[per_vertex ? 1 : 0] = nir_src_for_ssa(offset);
-
- if (intrin->dest.is_ssa) {
- nir_ssa_dest_init(&load->instr, &load->dest,
- intrin->num_components, NULL);
- nir_ssa_def_rewrite_uses(&intrin->dest.ssa,
- nir_src_for_ssa(&load->dest.ssa));
- } else {
- nir_dest_copy(&load->dest, &intrin->dest, state->mem_ctx);
- }
-
- nir_instr_insert_before(&intrin->instr, &load->instr);
- nir_instr_remove(&intrin->instr);
- break;
- }
-
- case nir_intrinsic_store_var: {
- assert(mode == nir_var_shader_out || mode == nir_var_shared);
-
- nir_ssa_def *offset;
- nir_ssa_def *vertex_index;
-
- bool per_vertex =
- is_per_vertex_output(state, intrin->variables[0]->var);
-
- offset = get_io_offset(b, intrin->variables[0],
- per_vertex ? &vertex_index : NULL,
- state->type_size);
-
- nir_intrinsic_instr *store =
- nir_intrinsic_instr_create(state->mem_ctx,
- store_op(state, mode, per_vertex));
- store->num_components = intrin->num_components;
-
- nir_src_copy(&store->src[0], &intrin->src[0], store);
-
- store->const_index[0] =
- intrin->variables[0]->var->data.driver_location;
-
- /* Copy the writemask */
- store->const_index[1] = intrin->const_index[0];
-
- if (per_vertex)
- store->src[1] = nir_src_for_ssa(vertex_index);
-
- store->src[per_vertex ? 2 : 1] = nir_src_for_ssa(offset);
-
- nir_instr_insert_before(&intrin->instr, &store->instr);
- nir_instr_remove(&intrin->instr);
- break;
- }
-
- case nir_intrinsic_var_atomic_add:
- case nir_intrinsic_var_atomic_imin:
- case nir_intrinsic_var_atomic_umin:
- case nir_intrinsic_var_atomic_imax:
- case nir_intrinsic_var_atomic_umax:
- case nir_intrinsic_var_atomic_and:
- case nir_intrinsic_var_atomic_or:
- case nir_intrinsic_var_atomic_xor:
- case nir_intrinsic_var_atomic_exchange:
- case nir_intrinsic_var_atomic_comp_swap: {
- assert(mode == nir_var_shared);
-
- nir_ssa_def *offset;
-
- offset = get_io_offset(b, intrin->variables[0],
- NULL, state->type_size);
-
- nir_intrinsic_instr *atomic =
- nir_intrinsic_instr_create(state->mem_ctx,
- atomic_op(intrin->intrinsic));
-
- atomic->src[0] = nir_src_for_ssa(offset);
-
- atomic->const_index[0] =
- intrin->variables[0]->var->data.driver_location;
-
- nir_src_copy(&atomic->src[1], &intrin->src[0], atomic);
-
- if (intrin->intrinsic == nir_intrinsic_var_atomic_comp_swap)
- nir_src_copy(&atomic->src[2], &intrin->src[1], atomic);
-
- if (intrin->dest.is_ssa) {
- nir_ssa_dest_init(&atomic->instr, &atomic->dest,
- intrin->dest.ssa.num_components, NULL);
- nir_ssa_def_rewrite_uses(&intrin->dest.ssa,
- nir_src_for_ssa(&atomic->dest.ssa));
- } else {
- nir_dest_copy(&atomic->dest, &intrin->dest, state->mem_ctx);
- }
-
- nir_instr_insert_before(&intrin->instr, &atomic->instr);
- nir_instr_remove(&intrin->instr);
- break;
- }
-
- default:
- break;
- }
- }
-
- return true;
-}
-
-static void
-nir_lower_io_impl(nir_function_impl *impl,
- nir_variable_mode mode,
- int (*type_size)(const struct glsl_type *))
-{
- struct lower_io_state state;
-
- nir_builder_init(&state.builder, impl);
- state.mem_ctx = ralloc_parent(impl);
- state.mode = mode;
- state.type_size = type_size;
-
- nir_foreach_block(impl, nir_lower_io_block, &state);
-
- nir_metadata_preserve(impl, nir_metadata_block_index |
- nir_metadata_dominance);
-}
-
-void
-nir_lower_io(nir_shader *shader, nir_variable_mode mode,
- int (*type_size)(const struct glsl_type *))
-{
- nir_foreach_function(shader, function) {
- if (function->impl)
- nir_lower_io_impl(function->impl, mode, type_size);
- }
-}
-
-/**
- * Return the offset soruce for a load/store intrinsic.
- */
-nir_src *
-nir_get_io_offset_src(nir_intrinsic_instr *instr)
-{
- switch (instr->intrinsic) {
- case nir_intrinsic_load_input:
- case nir_intrinsic_load_output:
- case nir_intrinsic_load_uniform:
- return &instr->src[0];
- case nir_intrinsic_load_ubo:
- case nir_intrinsic_load_ssbo:
- case nir_intrinsic_load_per_vertex_input:
- case nir_intrinsic_load_per_vertex_output:
- case nir_intrinsic_store_output:
- return &instr->src[1];
- case nir_intrinsic_store_ssbo:
- case nir_intrinsic_store_per_vertex_output:
- return &instr->src[2];
- default:
- return NULL;
- }
-}
-
-/**
- * Return the vertex index source for a load/store per_vertex intrinsic.
- */
-nir_src *
-nir_get_io_vertex_index_src(nir_intrinsic_instr *instr)
-{
- switch (instr->intrinsic) {
- case nir_intrinsic_load_per_vertex_input:
- case nir_intrinsic_load_per_vertex_output:
- return &instr->src[0];
- case nir_intrinsic_store_per_vertex_output:
- return &instr->src[1];
- default:
- return NULL;
- }
-}
diff --git a/src/glsl/nir/nir_lower_load_const_to_scalar.c b/src/glsl/nir/nir_lower_load_const_to_scalar.c
deleted file mode 100644
index 1eeed13cbac..00000000000
--- a/src/glsl/nir/nir_lower_load_const_to_scalar.c
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright © 2015 Broadcom
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include "util/macros.h"
-#include "nir.h"
-#include "nir_builder.h"
-
-/** @file nir_lower_load_const_to_scalar.c
- *
- * Replaces vector nir_load_const instructions with a series of loads and a
- * vec[234] to reconstruct the original vector (on the assumption that
- * nir_lower_alu_to_scalar() will then be used to split it up).
- *
- * This gives NIR a chance to CSE more operations on a scalar shader, when the
- * same value was used in different vector contant loads.
- */
-
-static void
-lower_load_const_instr_scalar(nir_load_const_instr *lower)
-{
- if (lower->def.num_components == 1)
- return;
-
- nir_builder b;
- nir_builder_init(&b, nir_cf_node_get_function(&lower->instr.block->cf_node));
- b.cursor = nir_before_instr(&lower->instr);
-
- /* Emit the individual loads. */
- nir_ssa_def *loads[4];
- for (unsigned i = 0; i < lower->def.num_components; i++) {
- nir_load_const_instr *load_comp = nir_load_const_instr_create(b.shader, 1);
- load_comp->value.u[0] = lower->value.u[i];
- nir_builder_instr_insert(&b, &load_comp->instr);
- loads[i] = &load_comp->def;
- }
-
- /* Batch things back together into a vector. */
- nir_ssa_def *vec = nir_vec(&b, loads, lower->def.num_components);
-
- /* Replace the old load with a reference to our reconstructed vector. */
- nir_ssa_def_rewrite_uses(&lower->def, nir_src_for_ssa(vec));
- nir_instr_remove(&lower->instr);
-}
-
-static bool
-lower_load_const_to_scalar_block(nir_block *block, void *data)
-{
- nir_foreach_instr_safe(block, instr) {
- if (instr->type == nir_instr_type_load_const)
- lower_load_const_instr_scalar(nir_instr_as_load_const(instr));
- }
-
- return true;
-}
-
-static void
-nir_lower_load_const_to_scalar_impl(nir_function_impl *impl)
-{
- nir_foreach_block(impl, lower_load_const_to_scalar_block, NULL);
-}
-
-void
-nir_lower_load_const_to_scalar(nir_shader *shader)
-{
- nir_foreach_function(shader, function) {
- if (function->impl)
- nir_lower_load_const_to_scalar_impl(function->impl);
- }
-}
diff --git a/src/glsl/nir/nir_lower_locals_to_regs.c b/src/glsl/nir/nir_lower_locals_to_regs.c
deleted file mode 100644
index 51b0fa733f2..00000000000
--- a/src/glsl/nir/nir_lower_locals_to_regs.c
+++ /dev/null
@@ -1,396 +0,0 @@
-/*
- * Copyright © 2014 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- *
- * Authors:
- * Jason Ekstrand ([email protected])
- *
- */
-
-#include "nir.h"
-#include "nir_array.h"
-
-struct locals_to_regs_state {
- nir_shader *shader;
- nir_function_impl *impl;
-
- /* A hash table mapping derefs to registers */
- struct hash_table *regs_table;
-
- /* A growing array of derefs that we have encountered. There is exactly
- * one element of this array per element in the hash table. This is
- * used to make adding register initialization code deterministic.
- */
- nir_array derefs_array;
-
- bool progress;
-};
-
-/* The following two functions implement a hash and equality check for
- * variable dreferences. When the hash or equality function encounters an
- * array, it ignores the offset and whether it is direct or indirect
- * entirely.
- */
-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) {
- if (deref->deref_type == nir_deref_type_struct) {
- const nir_deref_struct *deref_struct = nir_deref_as_struct(deref);
- hash = _mesa_fnv32_1a_accumulate(hash, deref_struct->index);
- }
- }
-
- 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;
-
- if (a->deref_type == nir_deref_type_struct) {
- if (nir_deref_as_struct(a)->index != nir_deref_as_struct(b)->index)
- return false;
- }
- /* Do nothing for arrays. They're all the same. */
-
- assert((a->child == NULL) == (b->child == NULL));
- if((a->child == NULL) != (b->child == NULL))
- return false;
- }
-
- return true;
-}
-
-static nir_register *
-get_reg_for_deref(nir_deref_var *deref, struct locals_to_regs_state *state)
-{
- uint32_t hash = hash_deref(deref);
-
- struct hash_entry *entry =
- _mesa_hash_table_search_pre_hashed(state->regs_table, hash, deref);
- if (entry)
- return entry->data;
-
- unsigned array_size = 1;
- nir_deref *tail = &deref->deref;
- while (tail->child) {
- if (tail->child->deref_type == nir_deref_type_array)
- array_size *= glsl_get_length(tail->type);
- tail = tail->child;
- }
-
- assert(glsl_type_is_vector(tail->type) || glsl_type_is_scalar(tail->type));
-
- nir_register *reg = nir_local_reg_create(state->impl);
- reg->num_components = glsl_get_vector_elements(tail->type);
- reg->num_array_elems = array_size > 1 ? array_size : 0;
-
- _mesa_hash_table_insert_pre_hashed(state->regs_table, hash, deref, reg);
- nir_array_add(&state->derefs_array, nir_deref_var *, deref);
-
- return reg;
-}
-
-static nir_src
-get_deref_reg_src(nir_deref_var *deref, nir_instr *instr,
- struct locals_to_regs_state *state)
-{
- nir_src src;
-
- src.is_ssa = false;
- src.reg.reg = get_reg_for_deref(deref, state);
- src.reg.base_offset = 0;
- src.reg.indirect = NULL;
-
- /* It is possible for a user to create a shader that has an array with a
- * single element and then proceed to access it indirectly. Indirectly
- * accessing a non-array register is not allowed in NIR. In order to
- * handle this case we just convert it to a direct reference.
- */
- if (src.reg.reg->num_array_elems == 0)
- return src;
-
- nir_deref *tail = &deref->deref;
- while (tail->child != NULL) {
- const struct glsl_type *parent_type = tail->type;
- tail = tail->child;
-
- if (tail->deref_type != nir_deref_type_array)
- continue;
-
- nir_deref_array *deref_array = nir_deref_as_array(tail);
-
- src.reg.base_offset *= glsl_get_length(parent_type);
- src.reg.base_offset += deref_array->base_offset;
-
- if (src.reg.indirect) {
- nir_load_const_instr *load_const =
- nir_load_const_instr_create(state->shader, 1);
- load_const->value.u[0] = glsl_get_length(parent_type);
- nir_instr_insert_before(instr, &load_const->instr);
-
- nir_alu_instr *mul = nir_alu_instr_create(state->shader, nir_op_imul);
- mul->src[0].src = *src.reg.indirect;
- mul->src[1].src.is_ssa = true;
- mul->src[1].src.ssa = &load_const->def;
- mul->dest.write_mask = 1;
- nir_ssa_dest_init(&mul->instr, &mul->dest.dest, 1, NULL);
- nir_instr_insert_before(instr, &mul->instr);
-
- src.reg.indirect->is_ssa = true;
- src.reg.indirect->ssa = &mul->dest.dest.ssa;
- }
-
- if (deref_array->deref_array_type == nir_deref_array_type_indirect) {
- if (src.reg.indirect == NULL) {
- src.reg.indirect = ralloc(state->shader, nir_src);
- nir_src_copy(src.reg.indirect, &deref_array->indirect,
- state->shader);
- } else {
- nir_alu_instr *add = nir_alu_instr_create(state->shader,
- nir_op_iadd);
- add->src[0].src = *src.reg.indirect;
- nir_src_copy(&add->src[1].src, &deref_array->indirect, add);
- add->dest.write_mask = 1;
- nir_ssa_dest_init(&add->instr, &add->dest.dest, 1, NULL);
- nir_instr_insert_before(instr, &add->instr);
-
- src.reg.indirect->is_ssa = true;
- src.reg.indirect->ssa = &add->dest.dest.ssa;
- }
- }
- }
-
- return src;
-}
-
-static bool
-lower_locals_to_regs_block(nir_block *block, void *void_state)
-{
- struct locals_to_regs_state *state = void_state;
-
- nir_foreach_instr_safe(block, instr) {
- if (instr->type != nir_instr_type_intrinsic)
- continue;
-
- nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
-
- switch (intrin->intrinsic) {
- case nir_intrinsic_load_var: {
- if (intrin->variables[0]->var->data.mode != nir_var_local)
- continue;
-
- nir_alu_instr *mov = nir_alu_instr_create(state->shader, nir_op_imov);
- mov->src[0].src = get_deref_reg_src(intrin->variables[0],
- &intrin->instr, state);
- mov->dest.write_mask = (1 << intrin->num_components) - 1;
- if (intrin->dest.is_ssa) {
- nir_ssa_dest_init(&mov->instr, &mov->dest.dest,
- intrin->num_components, NULL);
- nir_ssa_def_rewrite_uses(&intrin->dest.ssa,
- nir_src_for_ssa(&mov->dest.dest.ssa));
- } else {
- nir_dest_copy(&mov->dest.dest, &intrin->dest, &mov->instr);
- }
- nir_instr_insert_before(&intrin->instr, &mov->instr);
-
- nir_instr_remove(&intrin->instr);
- state->progress = true;
- break;
- }
-
- case nir_intrinsic_store_var: {
- if (intrin->variables[0]->var->data.mode != nir_var_local)
- continue;
-
- nir_src reg_src = get_deref_reg_src(intrin->variables[0],
- &intrin->instr, state);
-
- nir_alu_instr *mov = nir_alu_instr_create(state->shader, nir_op_imov);
- nir_src_copy(&mov->src[0].src, &intrin->src[0], mov);
- mov->dest.write_mask = intrin->const_index[0];
- mov->dest.dest.is_ssa = false;
- mov->dest.dest.reg.reg = reg_src.reg.reg;
- mov->dest.dest.reg.base_offset = reg_src.reg.base_offset;
- mov->dest.dest.reg.indirect = reg_src.reg.indirect;
-
- nir_instr_insert_before(&intrin->instr, &mov->instr);
-
- nir_instr_remove(&intrin->instr);
- state->progress = true;
- break;
- }
-
- case nir_intrinsic_copy_var:
- unreachable("There should be no copies whatsoever at this point");
- break;
-
- default:
- continue;
- }
- }
-
- return true;
-}
-
-static nir_block *
-compute_reg_usedef_lca(nir_register *reg)
-{
- nir_block *lca = NULL;
-
- list_for_each_entry(nir_dest, def_dest, &reg->defs, reg.def_link)
- lca = nir_dominance_lca(lca, def_dest->reg.parent_instr->block);
-
- list_for_each_entry(nir_src, use_src, &reg->uses, use_link)
- lca = nir_dominance_lca(lca, use_src->parent_instr->block);
-
- list_for_each_entry(nir_src, use_src, &reg->if_uses, use_link) {
- nir_cf_node *prev_node = nir_cf_node_prev(&use_src->parent_if->cf_node);
- assert(prev_node->type == nir_cf_node_block);
- lca = nir_dominance_lca(lca, nir_cf_node_as_block(prev_node));
- }
-
- return lca;
-}
-
-static void
-insert_constant_initializer(nir_deref_var *deref_head, nir_deref *deref_tail,
- nir_block *block,
- struct locals_to_regs_state *state)
-{
- if (deref_tail->child) {
- switch (deref_tail->child->deref_type) {
- case nir_deref_type_array: {
- unsigned array_elems = glsl_get_length(deref_tail->type);
-
- nir_deref_array arr_deref;
- arr_deref.deref = *deref_tail->child;
- arr_deref.deref_array_type = nir_deref_array_type_direct;
-
- nir_deref *old_child = deref_tail->child;
- deref_tail->child = &arr_deref.deref;
- for (unsigned i = 0; i < array_elems; i++) {
- arr_deref.base_offset = i;
- insert_constant_initializer(deref_head, &arr_deref.deref,
- block, state);
- }
- deref_tail->child = old_child;
- return;
- }
-
- case nir_deref_type_struct:
- insert_constant_initializer(deref_head, deref_tail->child,
- block, state);
- return;
-
- default:
- unreachable("Invalid deref child type");
- }
- }
-
- assert(deref_tail->child == NULL);
-
- nir_load_const_instr *load =
- nir_deref_get_const_initializer_load(state->shader, deref_head);
- nir_instr_insert_before_block(block, &load->instr);
-
- nir_src reg_src = get_deref_reg_src(deref_head, &load->instr, state);
-
- nir_alu_instr *mov = nir_alu_instr_create(state->shader, nir_op_imov);
- mov->src[0].src = nir_src_for_ssa(&load->def);
- mov->dest.write_mask = (1 << load->def.num_components) - 1;
- mov->dest.dest.is_ssa = false;
- mov->dest.dest.reg.reg = reg_src.reg.reg;
- mov->dest.dest.reg.base_offset = reg_src.reg.base_offset;
- mov->dest.dest.reg.indirect = reg_src.reg.indirect;
-
- nir_instr_insert_after(&load->instr, &mov->instr);
- state->progress = true;
-}
-
-static bool
-nir_lower_locals_to_regs_impl(nir_function_impl *impl)
-{
- struct locals_to_regs_state state;
-
- state.shader = impl->function->shader;
- state.impl = impl;
- state.progress = false;
- state.regs_table = _mesa_hash_table_create(NULL, hash_deref, derefs_equal);
- nir_array_init(&state.derefs_array, NULL);
-
- nir_metadata_require(impl, nir_metadata_dominance);
-
- nir_foreach_block(impl, lower_locals_to_regs_block, &state);
-
- nir_array_foreach(&state.derefs_array, nir_deref_var *, deref_ptr) {
- nir_deref_var *deref = *deref_ptr;
- struct hash_entry *deref_entry =
- _mesa_hash_table_search(state.regs_table, deref);
- assert(deref_entry && deref_entry->key == deref);
- nir_register *reg = (nir_register *)deref_entry->data;
-
- if (deref->var->constant_initializer == NULL)
- continue;
-
- nir_block *usedef_lca = compute_reg_usedef_lca(reg);
-
- insert_constant_initializer(deref, &deref->deref, usedef_lca, &state);
- }
-
- nir_metadata_preserve(impl, nir_metadata_block_index |
- nir_metadata_dominance);
-
- nir_array_fini(&state.derefs_array);
- _mesa_hash_table_destroy(state.regs_table, NULL);
-
- return state.progress;
-}
-
-bool
-nir_lower_locals_to_regs(nir_shader *shader)
-{
- bool progress = false;
-
- nir_foreach_function(shader, function) {
- if (function->impl)
- progress = nir_lower_locals_to_regs_impl(function->impl) || progress;
- }
-
- return progress;
-}
diff --git a/src/glsl/nir/nir_lower_outputs_to_temporaries.c b/src/glsl/nir/nir_lower_outputs_to_temporaries.c
deleted file mode 100644
index 00ac09114cf..00000000000
--- a/src/glsl/nir/nir_lower_outputs_to_temporaries.c
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Copyright © 2015 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-/*
- * Implements a pass that lowers output variables to a temporary plus an
- * output variable with a single copy at each exit point of the shader.
- * This way the output variable is only ever written.
- *
- * Because valid NIR requires that output variables are never read, this
- * pass is more of a helper for NIR producers and must be run before the
- * shader is ever validated.
- */
-
-#include "nir.h"
-
-struct lower_outputs_state {
- nir_shader *shader;
- struct exec_list old_outputs;
-};
-
-static void
-emit_output_copies(nir_cursor cursor, struct lower_outputs_state *state)
-{
- assert(exec_list_length(&state->shader->outputs) ==
- exec_list_length(&state->old_outputs));
-
- foreach_two_lists(out_node, &state->shader->outputs,
- temp_node, &state->old_outputs) {
- nir_variable *output = exec_node_data(nir_variable, out_node, node);
- nir_variable *temp = exec_node_data(nir_variable, temp_node, node);
-
- nir_intrinsic_instr *copy =
- nir_intrinsic_instr_create(state->shader, nir_intrinsic_copy_var);
- copy->variables[0] = nir_deref_var_create(copy, output);
- copy->variables[1] = nir_deref_var_create(copy, temp);
-
- nir_instr_insert(cursor, &copy->instr);
- }
-}
-
-static bool
-emit_output_copies_block(nir_block *block, void *state)
-{
- nir_foreach_instr(block, instr) {
- if (instr->type != nir_instr_type_intrinsic)
- continue;
-
- nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
- if (intrin->intrinsic == nir_intrinsic_emit_vertex)
- emit_output_copies(nir_before_instr(&intrin->instr), state);
- }
-
- return true;
-}
-
-void
-nir_lower_outputs_to_temporaries(nir_shader *shader, nir_function *entrypoint)
-{
- struct lower_outputs_state state;
-
- if (shader->stage == MESA_SHADER_TESS_CTRL)
- return;
-
- state.shader = shader;
- exec_list_move_nodes_to(&shader->outputs, &state.old_outputs);
-
- /* Walk over all of the outputs turn each output into a temporary and
- * make a new variable for the actual output.
- */
- nir_foreach_variable(var, &state.old_outputs) {
- nir_variable *output = ralloc(shader, nir_variable);
- memcpy(output, var, sizeof *output);
-
- /* The orignal is now the temporary */
- nir_variable *temp = var;
-
- /* Reparent the name to the new variable */
- ralloc_steal(output, output->name);
-
- /* Reparent the constant initializer (if any) */
- ralloc_steal(output, output->constant_initializer);
-
- /* Give the output a new name with @out-temp appended */
- temp->name = ralloc_asprintf(var, "%s@out-temp", output->name);
- temp->data.mode = nir_var_global;
- temp->constant_initializer = NULL;
-
- exec_list_push_tail(&shader->outputs, &output->node);
- }
-
- nir_foreach_function(shader, function) {
- if (function->impl == NULL)
- continue;
-
- if (shader->stage == MESA_SHADER_GEOMETRY) {
- /* For geometry shaders, we have to emit the output copies right
- * before each EmitVertex call.
- */
- nir_foreach_block(function->impl, emit_output_copies_block, &state);
- } else if (function == entrypoint) {
- /* For all other shader types, we need to do the copies right before
- * the jumps to the end block.
- */
- struct set_entry *block_entry;
- set_foreach(function->impl->end_block->predecessors, block_entry) {
- struct nir_block *block = (void *)block_entry->key;
- emit_output_copies(nir_after_block_before_jump(block), &state);
- }
- }
-
- nir_metadata_preserve(function->impl, nir_metadata_block_index |
- nir_metadata_dominance);
- }
-
- exec_list_append(&shader->globals, &state.old_outputs);
-}
diff --git a/src/glsl/nir/nir_lower_phis_to_scalar.c b/src/glsl/nir/nir_lower_phis_to_scalar.c
deleted file mode 100644
index dd2abcf72f8..00000000000
--- a/src/glsl/nir/nir_lower_phis_to_scalar.c
+++ /dev/null
@@ -1,293 +0,0 @@
-/*
- * Copyright © 2015 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- *
- * Authors:
- * Jason Ekstrand ([email protected])
- *
- */
-
-#include "nir.h"
-
-/*
- * Implements a pass that lowers vector phi nodes to scalar phi nodes when
- * we don't think it will hurt anything.
- */
-
-struct lower_phis_to_scalar_state {
- void *mem_ctx;
- void *dead_ctx;
-
- /* Hash table marking which phi nodes are scalarizable. The key is
- * pointers to phi instructions and the entry is either NULL for not
- * scalarizable or non-null for scalarizable.
- */
- struct hash_table *phi_table;
-};
-
-static bool
-should_lower_phi(nir_phi_instr *phi, struct lower_phis_to_scalar_state *state);
-
-static bool
-is_phi_src_scalarizable(nir_phi_src *src,
- struct lower_phis_to_scalar_state *state)
-{
- /* Don't know what to do with non-ssa sources */
- if (!src->src.is_ssa)
- return false;
-
- nir_instr *src_instr = src->src.ssa->parent_instr;
- switch (src_instr->type) {
- case nir_instr_type_alu: {
- nir_alu_instr *src_alu = nir_instr_as_alu(src_instr);
-
- /* ALU operations with output_size == 0 should be scalarized. We
- * will also see a bunch of vecN operations from scalarizing ALU
- * operations and, since they can easily be copy-propagated, they
- * are ok too.
- */
- return nir_op_infos[src_alu->op].output_size == 0 ||
- src_alu->op == nir_op_vec2 ||
- src_alu->op == nir_op_vec3 ||
- src_alu->op == nir_op_vec4;
- }
-
- case nir_instr_type_phi:
- /* A phi is scalarizable if we're going to lower it */
- return should_lower_phi(nir_instr_as_phi(src_instr), state);
-
- case nir_instr_type_load_const:
- case nir_instr_type_ssa_undef:
- /* These are trivially scalarizable */
- return true;
-
- case nir_instr_type_intrinsic: {
- nir_intrinsic_instr *src_intrin = nir_instr_as_intrinsic(src_instr);
-
- switch (src_intrin->intrinsic) {
- case nir_intrinsic_load_var:
- return src_intrin->variables[0]->var->data.mode == nir_var_shader_in ||
- src_intrin->variables[0]->var->data.mode == nir_var_uniform;
-
- case nir_intrinsic_interp_var_at_centroid:
- case nir_intrinsic_interp_var_at_sample:
- case nir_intrinsic_interp_var_at_offset:
- case nir_intrinsic_load_uniform:
- case nir_intrinsic_load_ubo:
- case nir_intrinsic_load_ssbo:
- case nir_intrinsic_load_input:
- return true;
- default:
- break;
- }
- }
-
- default:
- /* We can't scalarize this type of instruction */
- return false;
- }
-}
-
-/**
- * Determines if the given phi node should be lowered. The only phi nodes
- * we will scalarize at the moment are those where all of the sources are
- * scalarizable.
- *
- * The reason for this comes down to coalescing. Since phi sources can't
- * swizzle, swizzles on phis have to be resolved by inserting a mov right
- * before the phi. The choice then becomes between movs to pick off
- * components for a scalar phi or potentially movs to recombine components
- * for a vector phi. The problem is that the movs generated to pick off
- * the components are almost uncoalescable. We can't coalesce them in NIR
- * because we need them to pick off components and we can't coalesce them
- * in the backend because the source register is a vector and the
- * destination is a scalar that may be used at other places in the program.
- * On the other hand, if we have a bunch of scalars going into a vector
- * phi, the situation is much better. In this case, if the SSA def is
- * generated in the predecessor block to the corresponding phi source, the
- * backend code will be an ALU op into a temporary and then a mov into the
- * given vector component; this move can almost certainly be coalesced
- * away.
- */
-static bool
-should_lower_phi(nir_phi_instr *phi, struct lower_phis_to_scalar_state *state)
-{
- /* Already scalar */
- if (phi->dest.ssa.num_components == 1)
- return false;
-
- struct hash_entry *entry = _mesa_hash_table_search(state->phi_table, phi);
- if (entry)
- return entry->data != NULL;
-
- /* Insert an entry and mark it as scalarizable for now. That way
- * we don't recurse forever and a cycle in the dependence graph
- * won't automatically make us fail to scalarize.
- */
- entry = _mesa_hash_table_insert(state->phi_table, phi, (void *)(intptr_t)1);
-
- bool scalarizable = true;
-
- nir_foreach_phi_src(phi, src) {
- scalarizable = is_phi_src_scalarizable(src, state);
- if (!scalarizable)
- break;
- }
-
- /* The hash table entry for 'phi' may have changed while recursing the
- * dependence graph, so we need to reset it */
- entry = _mesa_hash_table_search(state->phi_table, phi);
- assert(entry);
-
- entry->data = (void *)(intptr_t)scalarizable;
-
- return scalarizable;
-}
-
-static bool
-lower_phis_to_scalar_block(nir_block *block, void *void_state)
-{
- struct lower_phis_to_scalar_state *state = void_state;
-
- /* Find the last phi node in the block */
- nir_phi_instr *last_phi = NULL;
- nir_foreach_instr(block, instr) {
- if (instr->type != nir_instr_type_phi)
- break;
-
- last_phi = nir_instr_as_phi(instr);
- }
-
- /* We have to handle the phi nodes in their own pass due to the way
- * we're modifying the linked list of instructions.
- */
- nir_foreach_instr_safe(block, instr) {
- if (instr->type != nir_instr_type_phi)
- break;
-
- nir_phi_instr *phi = nir_instr_as_phi(instr);
-
- if (!should_lower_phi(phi, state))
- continue;
-
- /* Create a vecN operation to combine the results. Most of these
- * will be redundant, but copy propagation should clean them up for
- * us. No need to add the complexity here.
- */
- nir_op vec_op;
- switch (phi->dest.ssa.num_components) {
- case 2: vec_op = nir_op_vec2; break;
- case 3: vec_op = nir_op_vec3; break;
- case 4: vec_op = nir_op_vec4; break;
- default: unreachable("Invalid number of components");
- }
-
- nir_alu_instr *vec = nir_alu_instr_create(state->mem_ctx, vec_op);
- nir_ssa_dest_init(&vec->instr, &vec->dest.dest,
- phi->dest.ssa.num_components, NULL);
- vec->dest.write_mask = (1 << phi->dest.ssa.num_components) - 1;
-
- for (unsigned i = 0; i < phi->dest.ssa.num_components; i++) {
- nir_phi_instr *new_phi = nir_phi_instr_create(state->mem_ctx);
- nir_ssa_dest_init(&new_phi->instr, &new_phi->dest, 1, NULL);
-
- vec->src[i].src = nir_src_for_ssa(&new_phi->dest.ssa);
-
- nir_foreach_phi_src(phi, src) {
- /* We need to insert a mov to grab the i'th component of src */
- nir_alu_instr *mov = nir_alu_instr_create(state->mem_ctx,
- nir_op_imov);
- nir_ssa_dest_init(&mov->instr, &mov->dest.dest, 1, NULL);
- mov->dest.write_mask = 1;
- nir_src_copy(&mov->src[0].src, &src->src, state->mem_ctx);
- mov->src[0].swizzle[0] = i;
-
- /* Insert at the end of the predecessor but before the jump */
- nir_instr *pred_last_instr = nir_block_last_instr(src->pred);
- if (pred_last_instr && pred_last_instr->type == nir_instr_type_jump)
- nir_instr_insert_before(pred_last_instr, &mov->instr);
- else
- nir_instr_insert_after_block(src->pred, &mov->instr);
-
- nir_phi_src *new_src = ralloc(new_phi, nir_phi_src);
- new_src->pred = src->pred;
- new_src->src = nir_src_for_ssa(&mov->dest.dest.ssa);
-
- exec_list_push_tail(&new_phi->srcs, &new_src->node);
- }
-
- nir_instr_insert_before(&phi->instr, &new_phi->instr);
- }
-
- nir_instr_insert_after(&last_phi->instr, &vec->instr);
-
- nir_ssa_def_rewrite_uses(&phi->dest.ssa,
- nir_src_for_ssa(&vec->dest.dest.ssa));
-
- ralloc_steal(state->dead_ctx, phi);
- nir_instr_remove(&phi->instr);
-
- /* We're using the safe iterator and inserting all the newly
- * scalarized phi nodes before their non-scalarized version so that's
- * ok. However, we are also inserting vec operations after all of
- * the last phi node so once we get here, we can't trust even the
- * safe iterator to stop properly. We have to break manually.
- */
- if (instr == &last_phi->instr)
- break;
- }
-
- return true;
-}
-
-static void
-lower_phis_to_scalar_impl(nir_function_impl *impl)
-{
- struct lower_phis_to_scalar_state state;
-
- state.mem_ctx = ralloc_parent(impl);
- state.dead_ctx = ralloc_context(NULL);
- state.phi_table = _mesa_hash_table_create(state.dead_ctx, _mesa_hash_pointer,
- _mesa_key_pointer_equal);
-
- nir_foreach_block(impl, lower_phis_to_scalar_block, &state);
-
- nir_metadata_preserve(impl, nir_metadata_block_index |
- nir_metadata_dominance);
-
- ralloc_free(state.dead_ctx);
-}
-
-/** A pass that lowers vector phi nodes to scalar
- *
- * This pass loops through the blocks and lowers looks for vector phi nodes
- * it can lower to scalar phi nodes. Not all phi nodes are lowered. For
- * instance, if one of the sources is a non-scalarizable vector, then we
- * don't bother lowering because that would generate hard-to-coalesce movs.
- */
-void
-nir_lower_phis_to_scalar(nir_shader *shader)
-{
- nir_foreach_function(shader, function) {
- if (function->impl)
- lower_phis_to_scalar_impl(function->impl);
- }
-}
diff --git a/src/glsl/nir/nir_lower_returns.c b/src/glsl/nir/nir_lower_returns.c
deleted file mode 100644
index 91bb2f7dfeb..00000000000
--- a/src/glsl/nir/nir_lower_returns.c
+++ /dev/null
@@ -1,246 +0,0 @@
-/*
- * Copyright © 2015 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include "nir.h"
-#include "nir_builder.h"
-#include "nir_control_flow.h"
-
-struct lower_returns_state {
- nir_builder builder;
- struct exec_list *cf_list;
- nir_loop *loop;
- nir_variable *return_flag;
-};
-
-static bool lower_returns_in_cf_list(struct exec_list *cf_list,
- struct lower_returns_state *state);
-
-static void
-predicate_following(nir_cf_node *node, struct lower_returns_state *state)
-{
- nir_builder *b = &state->builder;
- b->cursor = nir_after_cf_node_and_phis(node);
-
- if (nir_cursors_equal(b->cursor, nir_after_cf_list(state->cf_list)))
- return; /* Nothing to predicate */
-
- assert(state->return_flag);
-
- nir_if *if_stmt = nir_if_create(b->shader);
- if_stmt->condition = nir_src_for_ssa(nir_load_var(b, state->return_flag));
- nir_cf_node_insert(b->cursor, &if_stmt->cf_node);
-
- if (state->loop) {
- /* If we're inside of a loop, then all we need to do is insert a
- * conditional break.
- */
- nir_jump_instr *brk =
- nir_jump_instr_create(state->builder.shader, nir_jump_break);
- nir_instr_insert(nir_before_cf_list(&if_stmt->then_list), &brk->instr);
- } else {
- /* Otherwise, we need to actually move everything into the else case
- * of the if statement.
- */
- nir_cf_list list;
- nir_cf_extract(&list, nir_after_cf_node(&if_stmt->cf_node),
- nir_after_cf_list(state->cf_list));
- assert(!exec_list_is_empty(&list.list));
- nir_cf_reinsert(&list, nir_before_cf_list(&if_stmt->else_list));
- }
-}
-
-static bool
-lower_returns_in_loop(nir_loop *loop, struct lower_returns_state *state)
-{
- nir_loop *parent = state->loop;
- state->loop = loop;
- bool progress = lower_returns_in_cf_list(&loop->body, state);
- state->loop = parent;
-
- /* If the recursive call made progress, then there were returns inside
- * of the loop. These would have been lowered to breaks with the return
- * flag set to true. We need to predicate everything following the loop
- * on the return flag.
- */
- if (progress)
- predicate_following(&loop->cf_node, state);
-
- return progress;
-}
-
-static bool
-lower_returns_in_if(nir_if *if_stmt, struct lower_returns_state *state)
-{
- bool progress;
-
- progress = lower_returns_in_cf_list(&if_stmt->then_list, state);
- progress = lower_returns_in_cf_list(&if_stmt->else_list, state) || progress;
-
- /* If either of the recursive calls made progress, then there were
- * returns inside of the body of the if. If we're in a loop, then these
- * were lowered to breaks which automatically skip to the end of the
- * loop so we don't have to do anything. If we're not in a loop, then
- * all we know is that the return flag is set appropreately and that the
- * recursive calls ensured that nothing gets executed *inside* the if
- * after a return. In order to ensure nothing outside gets executed
- * after a return, we need to predicate everything following on the
- * return flag.
- */
- if (progress && !state->loop)
- predicate_following(&if_stmt->cf_node, state);
-
- return progress;
-}
-
-static bool
-lower_returns_in_block(nir_block *block, struct lower_returns_state *state)
-{
- if (block->predecessors->entries == 0 &&
- block != nir_start_block(state->builder.impl)) {
- /* This block is unreachable. Delete it and everything after it. */
- nir_cf_list list;
- nir_cf_extract(&list, nir_before_cf_node(&block->cf_node),
- nir_after_cf_list(state->cf_list));
-
- if (exec_list_is_empty(&list.list)) {
- /* There's nothing here, which also means there's nothing in this
- * block so we have nothing to do.
- */
- return false;
- } else {
- nir_cf_delete(&list);
- return true;
- }
- }
-
- nir_instr *last_instr = nir_block_last_instr(block);
- if (last_instr == NULL)
- return false;
-
- if (last_instr->type != nir_instr_type_jump)
- return false;
-
- nir_jump_instr *jump = nir_instr_as_jump(last_instr);
- if (jump->type != nir_jump_return)
- return false;
-
- nir_instr_remove(&jump->instr);
-
- nir_builder *b = &state->builder;
- b->cursor = nir_after_block(block);
-
- /* Set the return flag */
- if (state->return_flag == NULL) {
- state->return_flag =
- nir_local_variable_create(b->impl, glsl_bool_type(), "return");
-
- /* Set a default value of false */
- state->return_flag->constant_initializer =
- rzalloc(state->return_flag, nir_constant);
- }
- nir_store_var(b, state->return_flag, nir_imm_int(b, NIR_TRUE), 1);
-
- if (state->loop) {
- /* We're in a loop; we need to break out of it. */
- nir_jump(b, nir_jump_break);
- } else {
- /* Not in a loop; we'll deal with predicating later*/
- assert(nir_cf_node_next(&block->cf_node) == NULL);
- }
-
- return true;
-}
-
-static bool
-lower_returns_in_cf_list(struct exec_list *cf_list,
- struct lower_returns_state *state)
-{
- bool progress = false;
-
- struct exec_list *parent_list = state->cf_list;
- state->cf_list = cf_list;
-
- /* We iterate over the list backwards because any given lower call may
- * take everything following the given CF node and predicate it. In
- * order to avoid recursion/iteration problems, we want everything after
- * a given node to already be lowered before this happens.
- */
- foreach_list_typed_reverse_safe(nir_cf_node, node, node, cf_list) {
- switch (node->type) {
- case nir_cf_node_block:
- if (lower_returns_in_block(nir_cf_node_as_block(node), state))
- progress = true;
- break;
-
- case nir_cf_node_if:
- if (lower_returns_in_if(nir_cf_node_as_if(node), state))
- progress = true;
- break;
-
- case nir_cf_node_loop:
- if (lower_returns_in_loop(nir_cf_node_as_loop(node), state))
- progress = true;
- break;
-
- default:
- unreachable("Invalid inner CF node type");
- }
- }
-
- state->cf_list = parent_list;
-
- return progress;
-}
-
-bool
-nir_lower_returns_impl(nir_function_impl *impl)
-{
- struct lower_returns_state state;
-
- state.cf_list = &impl->body;
- state.loop = NULL;
- state.return_flag = NULL;
- nir_builder_init(&state.builder, impl);
-
- bool progress = lower_returns_in_cf_list(&impl->body, &state);
-
- if (progress) {
- nir_metadata_preserve(impl, nir_metadata_none);
- nir_repair_ssa_impl(impl);
- }
-
- return progress;
-}
-
-bool
-nir_lower_returns(nir_shader *shader)
-{
- bool progress = false;
-
- nir_foreach_function(shader, function) {
- if (function->impl)
- progress = nir_lower_returns_impl(function->impl) || progress;
- }
-
- return progress;
-}
diff --git a/src/glsl/nir/nir_lower_samplers.c b/src/glsl/nir/nir_lower_samplers.c
deleted file mode 100644
index e4cd415a9c3..00000000000
--- a/src/glsl/nir/nir_lower_samplers.c
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
- * Copyright (C) 2005-2007 Brian Paul All Rights Reserved.
- * Copyright (C) 2008 VMware, Inc. All Rights Reserved.
- * Copyright © 2014 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-#include "nir.h"
-#include "nir_builder.h"
-#include "program/hash_table.h"
-#include "ir_uniform.h"
-
-#include "main/compiler.h"
-#include "main/mtypes.h"
-#include "program/prog_parameter.h"
-#include "program/program.h"
-
-/* Calculate the sampler index based on array indicies and also
- * calculate the base uniform location for struct members.
- */
-static void
-calc_sampler_offsets(nir_deref *tail, nir_tex_instr *instr,
- unsigned *array_elements, nir_ssa_def **indirect,
- nir_builder *b, unsigned *location)
-{
- if (tail->child == NULL)
- return;
-
- switch (tail->child->deref_type) {
- case nir_deref_type_array: {
- nir_deref_array *deref_array = nir_deref_as_array(tail->child);
-
- assert(deref_array->deref_array_type != nir_deref_array_type_wildcard);
-
- calc_sampler_offsets(tail->child, instr, array_elements,
- indirect, b, location);
- instr->sampler_index += deref_array->base_offset * *array_elements;
-
- if (deref_array->deref_array_type == nir_deref_array_type_indirect) {
- nir_ssa_def *mul =
- nir_imul(b, nir_imm_int(b, *array_elements),
- nir_ssa_for_src(b, deref_array->indirect, 1));
-
- nir_instr_rewrite_src(&instr->instr, &deref_array->indirect,
- NIR_SRC_INIT);
-
- if (*indirect) {
- *indirect = nir_iadd(b, *indirect, mul);
- } else {
- *indirect = mul;
- }
- }
-
- *array_elements *= glsl_get_length(tail->type);
- break;
- }
-
- case nir_deref_type_struct: {
- nir_deref_struct *deref_struct = nir_deref_as_struct(tail->child);
- *location += glsl_get_record_location_offset(tail->type, deref_struct->index);
- calc_sampler_offsets(tail->child, instr, array_elements,
- indirect, b, location);
- break;
- }
-
- default:
- unreachable("Invalid deref type");
- break;
- }
-}
-
-static void
-lower_sampler(nir_tex_instr *instr, const struct gl_shader_program *shader_program,
- gl_shader_stage stage, nir_builder *builder)
-{
- if (instr->sampler == NULL)
- return;
-
- /* GLSL only has combined textures/samplers */
- assert(instr->texture == NULL);
-
- instr->sampler_index = 0;
- unsigned location = instr->sampler->var->data.location;
- unsigned array_elements = 1;
- nir_ssa_def *indirect = NULL;
-
- builder->cursor = nir_before_instr(&instr->instr);
- calc_sampler_offsets(&instr->sampler->deref, instr, &array_elements,
- &indirect, builder, &location);
-
- if (indirect) {
- /* First, we have to resize the array of texture sources */
- nir_tex_src *new_srcs = rzalloc_array(instr, nir_tex_src,
- instr->num_srcs + 2);
-
- for (unsigned i = 0; i < instr->num_srcs; i++) {
- new_srcs[i].src_type = instr->src[i].src_type;
- nir_instr_move_src(&instr->instr, &new_srcs[i].src,
- &instr->src[i].src);
- }
-
- ralloc_free(instr->src);
- instr->src = new_srcs;
-
- /* Now we can go ahead and move the source over to being a
- * first-class texture source.
- */
- instr->src[instr->num_srcs].src_type = nir_tex_src_texture_offset;
- instr->num_srcs++;
- nir_instr_rewrite_src(&instr->instr,
- &instr->src[instr->num_srcs - 1].src,
- nir_src_for_ssa(indirect));
-
- instr->src[instr->num_srcs].src_type = nir_tex_src_sampler_offset;
- instr->num_srcs++;
- nir_instr_rewrite_src(&instr->instr,
- &instr->src[instr->num_srcs - 1].src,
- nir_src_for_ssa(indirect));
-
- instr->texture_array_size = array_elements;
- }
-
- if (location > shader_program->NumUniformStorage - 1 ||
- !shader_program->UniformStorage[location].opaque[stage].active) {
- assert(!"cannot return a sampler");
- return;
- }
-
- instr->sampler_index +=
- shader_program->UniformStorage[location].opaque[stage].index;
-
- instr->sampler = NULL;
-
- instr->texture_index = instr->sampler_index;
-}
-
-typedef struct {
- nir_builder builder;
- const struct gl_shader_program *shader_program;
- gl_shader_stage stage;
-} lower_state;
-
-static bool
-lower_block_cb(nir_block *block, void *_state)
-{
- lower_state *state = (lower_state *) _state;
-
- nir_foreach_instr(block, instr) {
- if (instr->type == nir_instr_type_tex) {
- nir_tex_instr *tex_instr = nir_instr_as_tex(instr);
- lower_sampler(tex_instr, state->shader_program, state->stage,
- &state->builder);
- }
- }
-
- return true;
-}
-
-static void
-lower_impl(nir_function_impl *impl, const struct gl_shader_program *shader_program,
- gl_shader_stage stage)
-{
- lower_state state;
-
- nir_builder_init(&state.builder, impl);
- state.shader_program = shader_program;
- state.stage = stage;
-
- nir_foreach_block(impl, lower_block_cb, &state);
-}
-
-void
-nir_lower_samplers(nir_shader *shader,
- const struct gl_shader_program *shader_program)
-{
- nir_foreach_function(shader, function) {
- if (function->impl)
- lower_impl(function->impl, shader_program, shader->stage);
- }
-}
diff --git a/src/glsl/nir/nir_lower_system_values.c b/src/glsl/nir/nir_lower_system_values.c
deleted file mode 100644
index 79f6bedc990..00000000000
--- a/src/glsl/nir/nir_lower_system_values.c
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * Copyright © 2014 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- *
- * Authors:
- * Connor Abbott ([email protected])
- *
- */
-
-#include "nir.h"
-#include "nir_builder.h"
-
-struct lower_system_values_state {
- nir_builder builder;
- bool progress;
-};
-
-static bool
-convert_block(nir_block *block, void *void_state)
-{
- struct lower_system_values_state *state = void_state;
-
- nir_builder *b = &state->builder;
-
- nir_foreach_instr_safe(block, instr) {
- if (instr->type != nir_instr_type_intrinsic)
- continue;
-
- nir_intrinsic_instr *load_var = nir_instr_as_intrinsic(instr);
-
- if (load_var->intrinsic != nir_intrinsic_load_var)
- continue;
-
- nir_variable *var = load_var->variables[0]->var;
- if (var->data.mode != nir_var_system_value)
- continue;
-
- b->cursor = nir_after_instr(&load_var->instr);
-
- nir_ssa_def *sysval;
- switch (var->data.location) {
- case SYSTEM_VALUE_GLOBAL_INVOCATION_ID: {
- /* From the GLSL man page for gl_GlobalInvocationID:
- *
- * "The value of gl_GlobalInvocationID is equal to
- * gl_WorkGroupID * gl_WorkGroupSize + gl_LocalInvocationID"
- */
-
- nir_const_value local_size;
- local_size.u[0] = b->shader->info.cs.local_size[0];
- local_size.u[1] = b->shader->info.cs.local_size[1];
- local_size.u[2] = b->shader->info.cs.local_size[2];
-
- nir_ssa_def *group_id =
- nir_load_system_value(b, nir_intrinsic_load_work_group_id, 0);
- nir_ssa_def *local_id =
- nir_load_system_value(b, nir_intrinsic_load_local_invocation_id, 0);
-
- sysval = nir_iadd(b, nir_imul(b, group_id,
- nir_build_imm(b, 3, local_size)),
- local_id);
- break;
- }
-
- case SYSTEM_VALUE_LOCAL_INVOCATION_INDEX: {
- /* From the GLSL man page for gl_LocalInvocationIndex:
- *
- * ?The value of gl_LocalInvocationIndex is equal to
- * gl_LocalInvocationID.z * gl_WorkGroupSize.x *
- * gl_WorkGroupSize.y + gl_LocalInvocationID.y *
- * gl_WorkGroupSize.x + gl_LocalInvocationID.x"
- */
- nir_ssa_def *local_id =
- nir_load_system_value(b, nir_intrinsic_load_local_invocation_id, 0);
-
- unsigned stride_y = b->shader->info.cs.local_size[0];
- unsigned stride_z = b->shader->info.cs.local_size[0] *
- b->shader->info.cs.local_size[1];
-
- sysval = nir_iadd(b, nir_imul(b, nir_channel(b, local_id, 2),
- nir_imm_int(b, stride_z)),
- nir_iadd(b, nir_imul(b, nir_channel(b, local_id, 1),
- nir_imm_int(b, stride_y)),
- nir_channel(b, local_id, 0)));
- break;
- }
-
- case SYSTEM_VALUE_VERTEX_ID:
- if (b->shader->options->vertex_id_zero_based) {
- sysval = nir_iadd(b,
- nir_load_system_value(b, nir_intrinsic_load_vertex_id_zero_base, 0),
- nir_load_system_value(b, nir_intrinsic_load_base_vertex, 0));
- } else {
- sysval = nir_load_system_value(b, nir_intrinsic_load_vertex_id, 0);
- }
- break;
-
- case SYSTEM_VALUE_INSTANCE_INDEX:
- sysval = nir_iadd(b,
- nir_load_system_value(b, nir_intrinsic_load_instance_id, 0),
- nir_load_system_value(b, nir_intrinsic_load_base_instance, 0));
- break;
-
- default: {
- nir_intrinsic_op sysval_op =
- nir_intrinsic_from_system_value(var->data.location);
- sysval = nir_load_system_value(b, sysval_op, 0);
- break;
- } /* default */
- }
-
- nir_ssa_def_rewrite_uses(&load_var->dest.ssa, nir_src_for_ssa(sysval));
- nir_instr_remove(&load_var->instr);
-
- state->progress = true;
- }
-
- return true;
-}
-
-static bool
-convert_impl(nir_function_impl *impl)
-{
- struct lower_system_values_state state;
-
- state.progress = false;
- nir_builder_init(&state.builder, impl);
-
- nir_foreach_block(impl, convert_block, &state);
- nir_metadata_preserve(impl, nir_metadata_block_index |
- nir_metadata_dominance);
- return state.progress;
-}
-
-bool
-nir_lower_system_values(nir_shader *shader)
-{
- bool progress = false;
-
- nir_foreach_function(shader, function) {
- if (function->impl)
- progress = convert_impl(function->impl) || progress;
- }
-
- exec_list_make_empty(&shader->system_values);
-
- return progress;
-}
diff --git a/src/glsl/nir/nir_lower_tex.c b/src/glsl/nir/nir_lower_tex.c
deleted file mode 100644
index ae24fb2e16a..00000000000
--- a/src/glsl/nir/nir_lower_tex.c
+++ /dev/null
@@ -1,355 +0,0 @@
-/*
- * Copyright © 2015 Broadcom
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-/*
- * This lowering pass supports (as configured via nir_lower_tex_options)
- * various texture related conversions:
- * + texture projector lowering: converts the coordinate division for
- * texture projection to be done in ALU instructions instead of
- * asking the texture operation to do so.
- * + lowering RECT: converts the un-normalized RECT texture coordinates
- * to normalized coordinates with txs plus ALU instructions
- * + saturate s/t/r coords: to emulate certain texture clamp/wrap modes,
- * inserts instructions to clamp specified coordinates to [0.0, 1.0].
- * Note that this automatically triggers texture projector lowering if
- * needed, since clamping must happen after projector lowering.
- */
-
-#include "nir.h"
-#include "nir_builder.h"
-
-typedef struct {
- nir_builder b;
- const nir_lower_tex_options *options;
- bool progress;
-} lower_tex_state;
-
-static void
-project_src(nir_builder *b, nir_tex_instr *tex)
-{
- /* Find the projector in the srcs list, if present. */
- unsigned proj_index;
- for (proj_index = 0; proj_index < tex->num_srcs; proj_index++) {
- if (tex->src[proj_index].src_type == nir_tex_src_projector)
- break;
- }
- if (proj_index == tex->num_srcs)
- return;
-
- b->cursor = nir_before_instr(&tex->instr);
-
- nir_ssa_def *inv_proj =
- nir_frcp(b, nir_ssa_for_src(b, tex->src[proj_index].src, 1));
-
- /* Walk through the sources projecting the arguments. */
- for (unsigned i = 0; i < tex->num_srcs; i++) {
- switch (tex->src[i].src_type) {
- case nir_tex_src_coord:
- case nir_tex_src_comparitor:
- break;
- default:
- continue;
- }
- nir_ssa_def *unprojected =
- nir_ssa_for_src(b, tex->src[i].src, nir_tex_instr_src_size(tex, i));
- nir_ssa_def *projected = nir_fmul(b, unprojected, inv_proj);
-
- /* Array indices don't get projected, so make an new vector with the
- * coordinate's array index untouched.
- */
- if (tex->is_array && tex->src[i].src_type == nir_tex_src_coord) {
- switch (tex->coord_components) {
- case 4:
- projected = nir_vec4(b,
- nir_channel(b, projected, 0),
- nir_channel(b, projected, 1),
- nir_channel(b, projected, 2),
- nir_channel(b, unprojected, 3));
- break;
- case 3:
- projected = nir_vec3(b,
- nir_channel(b, projected, 0),
- nir_channel(b, projected, 1),
- nir_channel(b, unprojected, 2));
- break;
- case 2:
- projected = nir_vec2(b,
- nir_channel(b, projected, 0),
- nir_channel(b, unprojected, 1));
- break;
- default:
- unreachable("bad texture coord count for array");
- break;
- }
- }
-
- nir_instr_rewrite_src(&tex->instr,
- &tex->src[i].src,
- nir_src_for_ssa(projected));
- }
-
- /* Now move the later tex sources down the array so that the projector
- * disappears.
- */
- nir_instr_rewrite_src(&tex->instr, &tex->src[proj_index].src,
- NIR_SRC_INIT);
- for (unsigned i = proj_index + 1; i < tex->num_srcs; i++) {
- tex->src[i-1].src_type = tex->src[i].src_type;
- nir_instr_move_src(&tex->instr, &tex->src[i-1].src, &tex->src[i].src);
- }
- tex->num_srcs--;
-}
-
-static nir_ssa_def *
-get_texture_size(nir_builder *b, nir_tex_instr *tex)
-{
- b->cursor = nir_before_instr(&tex->instr);
-
- /* RECT textures should not be array: */
- assert(!tex->is_array);
-
- nir_tex_instr *txs;
-
- txs = nir_tex_instr_create(b->shader, 1);
- txs->op = nir_texop_txs;
- txs->sampler_dim = GLSL_SAMPLER_DIM_RECT;
- txs->sampler_index = tex->sampler_index;
- txs->dest_type = nir_type_int;
-
- /* only single src, the lod: */
- txs->src[0].src = nir_src_for_ssa(nir_imm_int(b, 0));
- txs->src[0].src_type = nir_tex_src_lod;
-
- nir_ssa_dest_init(&txs->instr, &txs->dest, 2, NULL);
- nir_builder_instr_insert(b, &txs->instr);
-
- return nir_i2f(b, &txs->dest.ssa);
-}
-
-static void
-lower_rect(nir_builder *b, nir_tex_instr *tex)
-{
- nir_ssa_def *txs = get_texture_size(b, tex);
- nir_ssa_def *scale = nir_frcp(b, txs);
-
- /* Walk through the sources normalizing the requested arguments. */
- for (unsigned i = 0; i < tex->num_srcs; i++) {
- if (tex->src[i].src_type != nir_tex_src_coord)
- continue;
-
- nir_ssa_def *coords =
- nir_ssa_for_src(b, tex->src[i].src, tex->coord_components);
- nir_instr_rewrite_src(&tex->instr,
- &tex->src[i].src,
- nir_src_for_ssa(nir_fmul(b, coords, scale)));
- }
-
- tex->sampler_dim = GLSL_SAMPLER_DIM_2D;
-}
-
-static void
-saturate_src(nir_builder *b, nir_tex_instr *tex, unsigned sat_mask)
-{
- b->cursor = nir_before_instr(&tex->instr);
-
- /* Walk through the sources saturating the requested arguments. */
- for (unsigned i = 0; i < tex->num_srcs; i++) {
- if (tex->src[i].src_type != nir_tex_src_coord)
- continue;
-
- nir_ssa_def *src =
- nir_ssa_for_src(b, tex->src[i].src, tex->coord_components);
-
- /* split src into components: */
- nir_ssa_def *comp[4];
-
- for (unsigned j = 0; j < tex->coord_components; j++)
- comp[j] = nir_channel(b, src, j);
-
- /* clamp requested components, array index does not get clamped: */
- unsigned ncomp = tex->coord_components;
- if (tex->is_array)
- ncomp--;
-
- for (unsigned j = 0; j < ncomp; j++) {
- if ((1 << j) & sat_mask) {
- if (tex->sampler_dim == GLSL_SAMPLER_DIM_RECT) {
- /* non-normalized texture coords, so clamp to texture
- * size rather than [0.0, 1.0]
- */
- nir_ssa_def *txs = get_texture_size(b, tex);
- comp[j] = nir_fmax(b, comp[j], nir_imm_float(b, 0.0));
- comp[j] = nir_fmin(b, comp[j], nir_channel(b, txs, j));
- } else {
- comp[j] = nir_fsat(b, comp[j]);
- }
- }
- }
-
- /* and move the result back into a single vecN: */
- src = nir_vec(b, comp, tex->coord_components);
-
- nir_instr_rewrite_src(&tex->instr,
- &tex->src[i].src,
- nir_src_for_ssa(src));
- }
-}
-
-static nir_ssa_def *
-get_zero_or_one(nir_builder *b, nir_alu_type type, uint8_t swizzle_val)
-{
- nir_const_value v;
-
- memset(&v, 0, sizeof(v));
-
- if (swizzle_val == 4) {
- v.u[0] = v.u[1] = v.u[2] = v.u[3] = 0;
- } else {
- assert(swizzle_val == 5);
- if (type == nir_type_float)
- v.f[0] = v.f[1] = v.f[2] = v.f[3] = 1.0;
- else
- v.u[0] = v.u[1] = v.u[2] = v.u[3] = 1;
- }
-
- return nir_build_imm(b, 4, v);
-}
-
-static void
-swizzle_result(nir_builder *b, nir_tex_instr *tex, const uint8_t swizzle[4])
-{
- assert(tex->dest.is_ssa);
-
- b->cursor = nir_after_instr(&tex->instr);
-
- nir_ssa_def *swizzled;
- if (tex->op == nir_texop_tg4) {
- if (swizzle[tex->component] < 4) {
- /* This one's easy */
- tex->component = swizzle[tex->component];
- return;
- } else {
- swizzled = get_zero_or_one(b, tex->dest_type, swizzle[tex->component]);
- }
- } else {
- assert(nir_tex_instr_dest_size(tex) == 4);
- if (swizzle[0] < 4 && swizzle[1] < 4 &&
- swizzle[2] < 4 && swizzle[3] < 4) {
- unsigned swiz[4] = { swizzle[0], swizzle[1], swizzle[2], swizzle[3] };
- /* We have no 0's or 1's, just emit a swizzling MOV */
- swizzled = nir_swizzle(b, &tex->dest.ssa, swiz, 4, false);
- } else {
- nir_ssa_def *srcs[4];
- for (unsigned i = 0; i < 4; i++) {
- if (swizzle[i] < 4) {
- srcs[i] = nir_channel(b, &tex->dest.ssa, swizzle[i]);
- } else {
- srcs[i] = get_zero_or_one(b, tex->dest_type, swizzle[i]);
- }
- }
- swizzled = nir_vec(b, srcs, 4);
- }
- }
-
- nir_ssa_def_rewrite_uses_after(&tex->dest.ssa, nir_src_for_ssa(swizzled),
- swizzled->parent_instr);
-}
-
-static bool
-nir_lower_tex_block(nir_block *block, void *void_state)
-{
- lower_tex_state *state = void_state;
- nir_builder *b = &state->b;
-
- nir_foreach_instr_safe(block, instr) {
- if (instr->type != nir_instr_type_tex)
- continue;
-
- nir_tex_instr *tex = nir_instr_as_tex(instr);
- bool lower_txp = !!(state->options->lower_txp & (1 << tex->sampler_dim));
-
- /* mask of src coords to saturate (clamp): */
- unsigned sat_mask = 0;
-
- if ((1 << tex->sampler_index) & state->options->saturate_r)
- sat_mask |= (1 << 2); /* .z */
- if ((1 << tex->sampler_index) & state->options->saturate_t)
- sat_mask |= (1 << 1); /* .y */
- if ((1 << tex->sampler_index) & state->options->saturate_s)
- sat_mask |= (1 << 0); /* .x */
-
- /* If we are clamping any coords, we must lower projector first
- * as clamping happens *after* projection:
- */
- if (lower_txp || sat_mask) {
- project_src(b, tex);
- state->progress = true;
- }
-
- if ((tex->sampler_dim == GLSL_SAMPLER_DIM_RECT) &&
- state->options->lower_rect) {
- lower_rect(b, tex);
- state->progress = true;
- }
-
- if (sat_mask) {
- saturate_src(b, tex, sat_mask);
- state->progress = true;
- }
-
- if (((1 << tex->sampler_index) & state->options->swizzle_result) &&
- !nir_tex_instr_is_query(tex) &&
- !(tex->is_shadow && tex->is_new_style_shadow)) {
- swizzle_result(b, tex, state->options->swizzles[tex->sampler_index]);
- state->progress = true;
- }
- }
-
- return true;
-}
-
-static void
-nir_lower_tex_impl(nir_function_impl *impl, lower_tex_state *state)
-{
- nir_builder_init(&state->b, impl);
-
- nir_foreach_block(impl, nir_lower_tex_block, state);
-
- nir_metadata_preserve(impl, nir_metadata_block_index |
- nir_metadata_dominance);
-}
-
-bool
-nir_lower_tex(nir_shader *shader, const nir_lower_tex_options *options)
-{
- lower_tex_state state;
- state.options = options;
- state.progress = false;
-
- nir_foreach_function(shader, function) {
- if (function->impl)
- nir_lower_tex_impl(function->impl, &state);
- }
-
- return state.progress;
-}
diff --git a/src/glsl/nir/nir_lower_to_source_mods.c b/src/glsl/nir/nir_lower_to_source_mods.c
deleted file mode 100644
index 6c4e1f0d3f3..00000000000
--- a/src/glsl/nir/nir_lower_to_source_mods.c
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * Copyright © 2014 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- *
- * Authors:
- * Jason Ekstrand ([email protected])
- *
- */
-
-#include "nir.h"
-
-/*
- * This pass lowers the neg, abs, and sat operations to source modifiers on
- * ALU operations to make things nicer for the backend. It's just much
- * easier to not have them when we're doing optimizations.
- */
-
-static bool
-nir_lower_to_source_mods_block(nir_block *block, void *state)
-{
- nir_foreach_instr(block, instr) {
- if (instr->type != nir_instr_type_alu)
- continue;
-
- nir_alu_instr *alu = nir_instr_as_alu(instr);
-
- for (unsigned i = 0; i < nir_op_infos[alu->op].num_inputs; i++) {
- if (!alu->src[i].src.is_ssa)
- continue;
-
- if (alu->src[i].src.ssa->parent_instr->type != nir_instr_type_alu)
- continue;
-
- nir_alu_instr *parent = nir_instr_as_alu(alu->src[i].src.ssa->parent_instr);
-
- if (parent->dest.saturate)
- continue;
-
- switch (nir_op_infos[alu->op].input_types[i]) {
- case nir_type_float:
- if (parent->op != nir_op_fmov)
- continue;
- break;
- case nir_type_int:
- if (parent->op != nir_op_imov)
- continue;
- break;
- default:
- continue;
- }
-
- /* We can only do a rewrite if the source we are copying is SSA.
- * Otherwise, moving the read might invalidly reorder reads/writes
- * on a register.
- */
- if (!parent->src[0].src.is_ssa)
- continue;
-
- nir_instr_rewrite_src(instr, &alu->src[i].src, parent->src[0].src);
- if (alu->src[i].abs) {
- /* abs trumps both neg and abs, do nothing */
- } else {
- alu->src[i].negate = (alu->src[i].negate != parent->src[0].negate);
- alu->src[i].abs |= parent->src[0].abs;
- }
-
- for (int j = 0; j < 4; ++j) {
- if (!nir_alu_instr_channel_used(alu, i, j))
- continue;
- alu->src[i].swizzle[j] = parent->src[0].swizzle[alu->src[i].swizzle[j]];
- }
-
- if (list_empty(&parent->dest.dest.ssa.uses) &&
- list_empty(&parent->dest.dest.ssa.if_uses))
- nir_instr_remove(&parent->instr);
- }
-
- switch (alu->op) {
- case nir_op_fsat:
- alu->op = nir_op_fmov;
- alu->dest.saturate = true;
- break;
- case nir_op_ineg:
- alu->op = nir_op_imov;
- alu->src[0].negate = !alu->src[0].negate;
- break;
- case nir_op_fneg:
- alu->op = nir_op_fmov;
- alu->src[0].negate = !alu->src[0].negate;
- break;
- case nir_op_iabs:
- alu->op = nir_op_imov;
- alu->src[0].abs = true;
- alu->src[0].negate = false;
- break;
- case nir_op_fabs:
- alu->op = nir_op_fmov;
- alu->src[0].abs = true;
- alu->src[0].negate = false;
- break;
- default:
- break;
- }
-
- /* We've covered sources. Now we're going to try and saturate the
- * destination if we can.
- */
-
- if (!alu->dest.dest.is_ssa)
- continue;
-
- /* We can only saturate float destinations */
- if (nir_op_infos[alu->op].output_type != nir_type_float)
- continue;
-
- if (!list_empty(&alu->dest.dest.ssa.if_uses))
- continue;
-
- bool all_children_are_sat = true;
- nir_foreach_use(&alu->dest.dest.ssa, child_src) {
- assert(child_src->is_ssa);
- nir_instr *child = child_src->parent_instr;
- if (child->type != nir_instr_type_alu) {
- all_children_are_sat = false;
- continue;
- }
-
- nir_alu_instr *child_alu = nir_instr_as_alu(child);
- if (child_alu->src[0].negate || child_alu->src[0].abs) {
- all_children_are_sat = false;
- continue;
- }
-
- if (child_alu->op != nir_op_fsat &&
- !(child_alu->op == nir_op_fmov && child_alu->dest.saturate)) {
- all_children_are_sat = false;
- continue;
- }
- }
-
- if (!all_children_are_sat)
- continue;
-
- alu->dest.saturate = true;
-
- nir_foreach_use(&alu->dest.dest.ssa, child_src) {
- assert(child_src->is_ssa);
- nir_instr *child = child_src->parent_instr;
- assert(child->type == nir_instr_type_alu);
- nir_alu_instr *child_alu = nir_instr_as_alu(child);
-
- child_alu->op = nir_op_fmov;
- child_alu->dest.saturate = false;
- /* We could propagate the dest of our instruction to the
- * destinations of the uses here. However, one quick round of
- * copy propagation will clean that all up and then we don't have
- * the complexity.
- */
- }
- }
-
- return true;
-}
-
-static void
-nir_lower_to_source_mods_impl(nir_function_impl *impl)
-{
- nir_foreach_block(impl, nir_lower_to_source_mods_block, NULL);
-}
-
-void
-nir_lower_to_source_mods(nir_shader *shader)
-{
- nir_foreach_function(shader, function) {
- if (function->impl)
- nir_lower_to_source_mods_impl(function->impl);
- }
-}
diff --git a/src/glsl/nir/nir_lower_two_sided_color.c b/src/glsl/nir/nir_lower_two_sided_color.c
deleted file mode 100644
index 1294cb89004..00000000000
--- a/src/glsl/nir/nir_lower_two_sided_color.c
+++ /dev/null
@@ -1,212 +0,0 @@
-/*
- * Copyright © 2015 Red Hat
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- *
- * Authors:
- * Rob Clark <[email protected]>
- */
-
-#include "nir.h"
-#include "nir_builder.h"
-
-#define MAX_COLORS 2 /* VARYING_SLOT_COL0/COL1 */
-
-typedef struct {
- nir_builder b;
- nir_shader *shader;
- nir_variable *face;
- struct {
- nir_variable *front; /* COLn */
- nir_variable *back; /* BFCn */
- } colors[MAX_COLORS];
- int colors_count;
-} lower_2side_state;
-
-
-/* Lowering pass for fragment shaders to emulated two-sided-color. For
- * each COLOR input, a corresponding BCOLOR input is created, and bcsel
- * instruction used to select front or back color based on FACE.
- */
-
-static nir_variable *
-create_input(nir_shader *shader, unsigned drvloc, gl_varying_slot slot)
-{
- nir_variable *var = rzalloc(shader, nir_variable);
-
- var->data.driver_location = drvloc;
- var->type = glsl_vec4_type();
- var->data.mode = nir_var_shader_in;
- var->name = ralloc_asprintf(var, "in_%d", drvloc);
- var->data.index = 0;
- var->data.location = slot;
-
- exec_list_push_tail(&shader->inputs, &var->node);
-
- shader->num_inputs++; /* TODO use type_size() */
-
- return var;
-}
-
-static nir_ssa_def *
-load_input(nir_builder *b, nir_variable *in)
-{
- nir_intrinsic_instr *load;
-
- load = nir_intrinsic_instr_create(b->shader, nir_intrinsic_load_input);
- load->num_components = 4;
- load->const_index[0] = in->data.driver_location;
- load->src[0] = nir_src_for_ssa(nir_imm_int(b, 0));
- nir_ssa_dest_init(&load->instr, &load->dest, 4, NULL);
- nir_builder_instr_insert(b, &load->instr);
-
- return &load->dest.ssa;
-}
-
-static int
-setup_inputs(lower_2side_state *state)
-{
- int maxloc = -1;
-
- /* find color/face inputs: */
- nir_foreach_variable(var, &state->shader->inputs) {
- int loc = var->data.driver_location;
-
- /* keep track of last used driver-location.. we'll be
- * appending BCLr/FACE after last existing input:
- */
- maxloc = MAX2(maxloc, loc);
-
- switch (var->data.location) {
- case VARYING_SLOT_COL0:
- case VARYING_SLOT_COL1:
- assert(state->colors_count < ARRAY_SIZE(state->colors));
- state->colors[state->colors_count].front = var;
- state->colors_count++;
- break;
- case VARYING_SLOT_FACE:
- state->face = var;
- break;
- }
- }
-
- /* if we don't have any color inputs, nothing to do: */
- if (state->colors_count == 0)
- return -1;
-
- /* if we don't already have one, insert a FACE input: */
- if (!state->face) {
- state->face = create_input(state->shader, ++maxloc, VARYING_SLOT_FACE);
- state->face->data.interpolation = INTERP_QUALIFIER_FLAT;
- }
-
- /* add required back-face color inputs: */
- for (int i = 0; i < state->colors_count; i++) {
- gl_varying_slot slot;
-
- if (state->colors[i].front->data.location == VARYING_SLOT_COL0)
- slot = VARYING_SLOT_BFC0;
- else
- slot = VARYING_SLOT_BFC1;
-
- state->colors[i].back = create_input(state->shader, ++maxloc, slot);
- }
-
- return 0;
-}
-
-static bool
-nir_lower_two_sided_color_block(nir_block *block, void *void_state)
-{
- lower_2side_state *state = void_state;
- nir_builder *b = &state->b;
-
- nir_foreach_instr_safe(block, instr) {
- if (instr->type != nir_instr_type_intrinsic)
- continue;
-
- nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
-
- if (intr->intrinsic != nir_intrinsic_load_input)
- continue;
-
- int idx;
- for (idx = 0; idx < state->colors_count; idx++) {
- unsigned drvloc =
- state->colors[idx].front->data.driver_location;
- if (intr->const_index[0] == drvloc) {
- assert(nir_src_as_const_value(intr->src[0]));
- break;
- }
- }
-
- if (idx == state->colors_count)
- continue;
-
- /* replace load_input(COLn) with
- * bcsel(load_input(FACE), load_input(COLn), load_input(BFCn))
- */
- b->cursor = nir_before_instr(&intr->instr);
- nir_ssa_def *face = nir_channel(b, load_input(b, state->face), 0);
- nir_ssa_def *front = load_input(b, state->colors[idx].front);
- nir_ssa_def *back = load_input(b, state->colors[idx].back);
- nir_ssa_def *cond = nir_flt(b, face, nir_imm_float(b, 0.0));
- nir_ssa_def *color = nir_bcsel(b, cond, back, front);
-
- assert(intr->dest.is_ssa);
- nir_ssa_def_rewrite_uses(&intr->dest.ssa, nir_src_for_ssa(color));
- }
-
- return true;
-}
-
-static void
-nir_lower_two_sided_color_impl(nir_function_impl *impl,
- lower_2side_state *state)
-{
- nir_builder *b = &state->b;
-
- nir_builder_init(b, impl);
-
- nir_foreach_block(impl, nir_lower_two_sided_color_block, state);
-
- nir_metadata_preserve(impl, nir_metadata_block_index |
- nir_metadata_dominance);
-}
-
-void
-nir_lower_two_sided_color(nir_shader *shader)
-{
- lower_2side_state state = {
- .shader = shader,
- };
-
- if (shader->stage != MESA_SHADER_FRAGMENT)
- return;
-
- if (setup_inputs(&state) != 0)
- return;
-
- nir_foreach_function(shader, function) {
- if (function->impl)
- nir_lower_two_sided_color_impl(function->impl, &state);
- }
-
-}
diff --git a/src/glsl/nir/nir_lower_var_copies.c b/src/glsl/nir/nir_lower_var_copies.c
deleted file mode 100644
index 350e99c3423..00000000000
--- a/src/glsl/nir/nir_lower_var_copies.c
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- * Copyright © 2014 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- *
- * Authors:
- * Jason Ekstrand ([email protected])
- *
- */
-
-#include "nir.h"
-#include "nir_types.h"
-
-/*
- * Lowers all copy intrinsics to sequences of load/store intrinsics.
- */
-
-/* Walks down the deref chain and returns the next deref in the chain whose
- * child is a wildcard. In other words, given the chain a[1].foo[*].bar,
- * this function will return the deref to foo. Calling it a second time
- * with the [*].bar, it will return NULL.
- */
-static nir_deref *
-deref_next_wildcard_parent(nir_deref *deref)
-{
- for (nir_deref *tail = deref; tail->child; tail = tail->child) {
- if (tail->child->deref_type != nir_deref_type_array)
- continue;
-
- nir_deref_array *arr = nir_deref_as_array(tail->child);
-
- if (arr->deref_array_type == nir_deref_array_type_wildcard)
- return tail;
- }
-
- return NULL;
-}
-
-/* This function recursively walks the given deref chain and replaces the
- * given copy instruction with an equivalent sequence load/store
- * operations.
- *
- * @copy_instr The copy instruction to replace; new instructions will be
- * inserted before this one
- *
- * @dest_head The head of the destination variable deref chain
- *
- * @src_head The head of the source variable deref chain
- *
- * @dest_tail The current tail of the destination variable deref chain;
- * this is used for recursion and external callers of this
- * function should call it with tail == head
- *
- * @src_tail The current tail of the source variable deref chain;
- * this is used for recursion and external callers of this
- * function should call it with tail == head
- *
- * @state The current variable lowering state
- */
-static void
-emit_copy_load_store(nir_intrinsic_instr *copy_instr,
- nir_deref_var *dest_head, nir_deref_var *src_head,
- nir_deref *dest_tail, nir_deref *src_tail, void *mem_ctx)
-{
- /* Find the next pair of wildcards */
- nir_deref *src_arr_parent = deref_next_wildcard_parent(src_tail);
- nir_deref *dest_arr_parent = deref_next_wildcard_parent(dest_tail);
-
- if (src_arr_parent || dest_arr_parent) {
- /* Wildcards had better come in matched pairs */
- assert(dest_arr_parent && dest_arr_parent);
-
- nir_deref_array *src_arr = nir_deref_as_array(src_arr_parent->child);
- nir_deref_array *dest_arr = nir_deref_as_array(dest_arr_parent->child);
-
- unsigned length = glsl_get_length(src_arr_parent->type);
- /* The wildcards should represent the same number of elements */
- assert(length == glsl_get_length(dest_arr_parent->type));
- assert(length > 0);
-
- /* Walk over all of the elements that this wildcard refers to and
- * call emit_copy_load_store on each one of them */
- src_arr->deref_array_type = nir_deref_array_type_direct;
- dest_arr->deref_array_type = nir_deref_array_type_direct;
- for (unsigned i = 0; i < length; i++) {
- src_arr->base_offset = i;
- dest_arr->base_offset = i;
- emit_copy_load_store(copy_instr, dest_head, src_head,
- &dest_arr->deref, &src_arr->deref, mem_ctx);
- }
- src_arr->deref_array_type = nir_deref_array_type_wildcard;
- dest_arr->deref_array_type = nir_deref_array_type_wildcard;
- } else {
- /* In this case, we have no wildcards anymore, so all we have to do
- * is just emit the load and store operations. */
- src_tail = nir_deref_tail(src_tail);
- dest_tail = nir_deref_tail(dest_tail);
-
- assert(src_tail->type == dest_tail->type);
-
- unsigned num_components = glsl_get_vector_elements(src_tail->type);
-
- nir_intrinsic_instr *load =
- nir_intrinsic_instr_create(mem_ctx, nir_intrinsic_load_var);
- load->num_components = num_components;
- load->variables[0] = nir_deref_as_var(nir_copy_deref(load, &src_head->deref));
- nir_ssa_dest_init(&load->instr, &load->dest, num_components, NULL);
-
- nir_instr_insert_before(&copy_instr->instr, &load->instr);
-
- nir_intrinsic_instr *store =
- nir_intrinsic_instr_create(mem_ctx, nir_intrinsic_store_var);
- store->num_components = num_components;
- store->const_index[0] = (1 << num_components) - 1;
- store->variables[0] = nir_deref_as_var(nir_copy_deref(store, &dest_head->deref));
-
- store->src[0].is_ssa = true;
- store->src[0].ssa = &load->dest.ssa;
-
- nir_instr_insert_before(&copy_instr->instr, &store->instr);
- }
-}
-
-/* Lowers a copy instruction to a sequence of load/store instructions
- *
- * The new instructions are placed before the copy instruction in the IR.
- */
-void
-nir_lower_var_copy_instr(nir_intrinsic_instr *copy, void *mem_ctx)
-{
- assert(copy->intrinsic == nir_intrinsic_copy_var);
- emit_copy_load_store(copy, copy->variables[0], copy->variables[1],
- &copy->variables[0]->deref,
- &copy->variables[1]->deref, mem_ctx);
-}
-
-static bool
-lower_var_copies_block(nir_block *block, void *mem_ctx)
-{
- nir_foreach_instr_safe(block, instr) {
- if (instr->type != nir_instr_type_intrinsic)
- continue;
-
- nir_intrinsic_instr *copy = nir_instr_as_intrinsic(instr);
- if (copy->intrinsic != nir_intrinsic_copy_var)
- continue;
-
- nir_lower_var_copy_instr(copy, mem_ctx);
-
- nir_instr_remove(&copy->instr);
- ralloc_free(copy);
- }
-
- return true;
-}
-
-static void
-lower_var_copies_impl(nir_function_impl *impl)
-{
- nir_foreach_block(impl, lower_var_copies_block, ralloc_parent(impl));
-}
-
-/* Lowers every copy_var instruction in the program to a sequence of
- * load/store instructions.
- */
-void
-nir_lower_var_copies(nir_shader *shader)
-{
- nir_foreach_function(shader, function) {
- if (function->impl)
- lower_var_copies_impl(function->impl);
- }
-}
diff --git a/src/glsl/nir/nir_lower_vars_to_ssa.c b/src/glsl/nir/nir_lower_vars_to_ssa.c
deleted file mode 100644
index e1f368d2f2b..00000000000
--- a/src/glsl/nir/nir_lower_vars_to_ssa.c
+++ /dev/null
@@ -1,751 +0,0 @@
-/*
- * Copyright © 2014 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- *
- * Authors:
- * Jason Ekstrand ([email protected])
- *
- */
-
-#include "nir.h"
-#include "nir_builder.h"
-#include "nir_phi_builder.h"
-#include "nir_vla.h"
-
-
-struct deref_node {
- struct deref_node *parent;
- const struct glsl_type *type;
-
- 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;
-
- struct nir_phi_builder_value *pb_value;
-
- struct deref_node *wildcard;
- struct deref_node *indirect;
- struct deref_node *children[0];
-};
-
-struct lower_variables_state {
- nir_shader *shader;
- void *dead_ctx;
- nir_function_impl *impl;
-
- /* A hash table mapping variables to deref_node data */
- struct hash_table *deref_var_nodes;
-
- /* A hash table mapping fully-qualified direct dereferences, i.e.
- * dereferences with no indirect or wildcard array dereferences, to
- * deref_node data.
- *
- * At the moment, we only lower loads, stores, and copies that can be
- * trivially lowered to loads and stores, i.e. copies with no indirects
- * and no wildcards. If a part of a variable that is being loaded from
- * and/or stored into is also involved in a copy operation with
- * wildcards, then we lower that copy operation to loads and stores, but
- * otherwise we leave copies with wildcards alone. Since the only derefs
- * used in these loads, stores, and trivial copies are ones with no
- * wildcards and no indirects, these are precisely the derefs that we
- * can actually consider lowering.
- */
- 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
- * scanning for load/store instructions. It is then turned off so we
- * don't accidentally change the direct_deref_nodes table while we're
- * iterating throug it.
- */
- bool add_to_direct_deref_nodes;
-
- struct nir_phi_builder *phi_builder;
-};
-
-static struct deref_node *
-deref_node_create(struct deref_node *parent,
- const struct glsl_type *type, nir_shader *shader)
-{
- size_t size = sizeof(struct deref_node) +
- glsl_get_length(type) * sizeof(struct deref_node *);
-
- struct deref_node *node = rzalloc_size(shader, size);
- node->type = type;
- node->parent = parent;
- node->deref = NULL;
- exec_node_init(&node->direct_derefs_link);
-
- return node;
-}
-
-/* Returns the deref node associated with the given variable. This will be
- * the root of the tree representing all of the derefs of the given variable.
- */
-static struct deref_node *
-get_deref_node_for_var(nir_variable *var, struct lower_variables_state *state)
-{
- struct deref_node *node;
-
- struct hash_entry *var_entry =
- _mesa_hash_table_search(state->deref_var_nodes, var);
-
- if (var_entry) {
- return var_entry->data;
- } else {
- node = deref_node_create(NULL, var->type, state->dead_ctx);
- _mesa_hash_table_insert(state->deref_var_nodes, var, node);
- return node;
- }
-}
-
-/* Gets the deref_node for the given deref chain and creates it if it
- * doesn't yet exist. If the deref is fully-qualified and direct and
- * state->add_to_direct_deref_nodes is true, it will be added to the hash
- * table of of fully-qualified direct derefs.
- */
-static struct deref_node *
-get_deref_node(nir_deref_var *deref, struct lower_variables_state *state)
-{
- bool is_direct = true;
-
- /* Start at the base of the chain. */
- struct deref_node *node = get_deref_node_for_var(deref->var, state);
- assert(deref->deref.type == node->type);
-
- for (nir_deref *tail = deref->deref.child; tail; tail = tail->child) {
- switch (tail->deref_type) {
- case nir_deref_type_struct: {
- nir_deref_struct *deref_struct = nir_deref_as_struct(tail);
-
- assert(deref_struct->index < glsl_get_length(node->type));
-
- if (node->children[deref_struct->index] == NULL)
- node->children[deref_struct->index] =
- deref_node_create(node, tail->type, state->dead_ctx);
-
- node = node->children[deref_struct->index];
- break;
- }
-
- case nir_deref_type_array: {
- nir_deref_array *arr = nir_deref_as_array(tail);
-
- switch (arr->deref_array_type) {
- case nir_deref_array_type_direct:
- /* This is possible if a loop unrolls and generates an
- * out-of-bounds offset. We need to handle this at least
- * somewhat gracefully.
- */
- if (arr->base_offset >= glsl_get_length(node->type))
- return NULL;
-
- if (node->children[arr->base_offset] == NULL)
- node->children[arr->base_offset] =
- deref_node_create(node, tail->type, state->dead_ctx);
-
- node = node->children[arr->base_offset];
- break;
-
- case nir_deref_array_type_indirect:
- if (node->indirect == NULL)
- node->indirect = deref_node_create(node, tail->type,
- state->dead_ctx);
-
- node = node->indirect;
- is_direct = false;
- break;
-
- case nir_deref_array_type_wildcard:
- if (node->wildcard == NULL)
- node->wildcard = deref_node_create(node, tail->type,
- state->dead_ctx);
-
- node = node->wildcard;
- is_direct = false;
- break;
-
- default:
- unreachable("Invalid array deref type");
- }
- break;
- }
- default:
- unreachable("Invalid deref type");
- }
- }
-
- assert(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;
-}
-
-/* \sa foreach_deref_node_match */
-static bool
-foreach_deref_node_worker(struct deref_node *node, nir_deref *deref,
- bool (* cb)(struct deref_node *node,
- struct lower_variables_state *state),
- struct lower_variables_state *state)
-{
- if (deref->child == NULL) {
- return cb(node, state);
- } else {
- switch (deref->child->deref_type) {
- case nir_deref_type_array: {
- nir_deref_array *arr = nir_deref_as_array(deref->child);
- assert(arr->deref_array_type == nir_deref_array_type_direct);
- if (node->children[arr->base_offset] &&
- !foreach_deref_node_worker(node->children[arr->base_offset],
- deref->child, cb, state))
- return false;
-
- if (node->wildcard &&
- !foreach_deref_node_worker(node->wildcard,
- deref->child, cb, state))
- return false;
-
- return true;
- }
-
- case nir_deref_type_struct: {
- nir_deref_struct *str = nir_deref_as_struct(deref->child);
- return foreach_deref_node_worker(node->children[str->index],
- deref->child, cb, state);
- }
-
- default:
- unreachable("Invalid deref child type");
- }
- }
-}
-
-/* Walks over every "matching" deref_node and calls the callback. A node
- * is considered to "match" if either refers to that deref or matches up t
- * a wildcard. In other words, the following would match a[6].foo[3].bar:
- *
- * a[6].foo[3].bar
- * a[*].foo[3].bar
- * a[6].foo[*].bar
- * a[*].foo[*].bar
- *
- * The given deref must be a full-length and fully qualified (no wildcards
- * or indirects) deref chain.
- */
-static bool
-foreach_deref_node_match(nir_deref_var *deref,
- bool (* cb)(struct deref_node *node,
- struct lower_variables_state *state),
- struct lower_variables_state *state)
-{
- nir_deref_var var_deref = *deref;
- var_deref.deref.child = NULL;
- struct deref_node *node = get_deref_node(&var_deref, state);
-
- if (node == NULL)
- return false;
-
- return foreach_deref_node_worker(node, &deref->deref, cb, state);
-}
-
-/* \sa deref_may_be_aliased */
-static bool
-deref_may_be_aliased_node(struct deref_node *node, nir_deref *deref,
- struct lower_variables_state *state)
-{
- if (deref->child == NULL) {
- return false;
- } else {
- switch (deref->child->deref_type) {
- case nir_deref_type_array: {
- nir_deref_array *arr = nir_deref_as_array(deref->child);
- if (arr->deref_array_type == nir_deref_array_type_indirect)
- return true;
-
- /* If there is an indirect at this level, we're aliased. */
- if (node->indirect)
- return true;
-
- assert(arr->deref_array_type == nir_deref_array_type_direct);
-
- if (node->children[arr->base_offset] &&
- deref_may_be_aliased_node(node->children[arr->base_offset],
- deref->child, state))
- return true;
-
- if (node->wildcard &&
- deref_may_be_aliased_node(node->wildcard, deref->child, state))
- return true;
-
- return false;
- }
-
- case nir_deref_type_struct: {
- nir_deref_struct *str = nir_deref_as_struct(deref->child);
- if (node->children[str->index]) {
- return deref_may_be_aliased_node(node->children[str->index],
- deref->child, state);
- } else {
- return false;
- }
- }
-
- default:
- unreachable("Invalid nir_deref child type");
- }
- }
-}
-
-/* Returns true if there are no indirects that can ever touch this deref.
- *
- * For example, if the given deref is a[6].foo, then any uses of a[i].foo
- * would cause this to return false, but a[i].bar would not affect it
- * because it's a different structure member. A var_copy involving of
- * a[*].bar also doesn't affect it because that can be lowered to entirely
- * direct load/stores.
- *
- * We only support asking this question about fully-qualified derefs.
- * Obviously, it's pointless to ask this about indirects, but we also
- * rule-out wildcards. Handling Wildcard dereferences would involve
- * checking each array index to make sure that there aren't any indirect
- * references.
- */
-static bool
-deref_may_be_aliased(nir_deref_var *deref,
- struct lower_variables_state *state)
-{
- return deref_may_be_aliased_node(get_deref_node_for_var(deref->var, state),
- &deref->deref, state);
-}
-
-static void
-register_load_instr(nir_intrinsic_instr *load_instr,
- struct lower_variables_state *state)
-{
- struct deref_node *node = get_deref_node(load_instr->variables[0], state);
- if (node == NULL)
- return;
-
- if (node->loads == NULL)
- node->loads = _mesa_set_create(state->dead_ctx, _mesa_hash_pointer,
- _mesa_key_pointer_equal);
-
- _mesa_set_add(node->loads, load_instr);
-}
-
-static void
-register_store_instr(nir_intrinsic_instr *store_instr,
- struct lower_variables_state *state)
-{
- struct deref_node *node = get_deref_node(store_instr->variables[0], state);
- if (node == NULL)
- return;
-
- if (node->stores == NULL)
- node->stores = _mesa_set_create(state->dead_ctx, _mesa_hash_pointer,
- _mesa_key_pointer_equal);
-
- _mesa_set_add(node->stores, store_instr);
-}
-
-static void
-register_copy_instr(nir_intrinsic_instr *copy_instr,
- struct lower_variables_state *state)
-{
- for (unsigned idx = 0; idx < 2; idx++) {
- struct deref_node *node =
- get_deref_node(copy_instr->variables[idx], state);
-
- if (node == NULL)
- continue;
-
- if (node->copies == NULL)
- node->copies = _mesa_set_create(state->dead_ctx, _mesa_hash_pointer,
- _mesa_key_pointer_equal);
-
- _mesa_set_add(node->copies, copy_instr);
- }
-}
-
-/* Registers all variable uses in the given block. */
-static bool
-register_variable_uses_block(nir_block *block, void *void_state)
-{
- struct lower_variables_state *state = void_state;
-
- nir_foreach_instr_safe(block, instr) {
- if (instr->type != nir_instr_type_intrinsic)
- continue;
-
- nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
-
- switch (intrin->intrinsic) {
- case nir_intrinsic_load_var:
- register_load_instr(intrin, state);
- break;
-
- case nir_intrinsic_store_var:
- register_store_instr(intrin, state);
- break;
-
- case nir_intrinsic_copy_var:
- register_copy_instr(intrin, state);
- break;
-
- default:
- continue;
- }
- }
-
- return true;
-}
-
-/* Walks over all of the copy instructions to or from the given deref_node
- * and lowers them to load/store intrinsics.
- */
-static bool
-lower_copies_to_load_store(struct deref_node *node,
- struct lower_variables_state *state)
-{
- if (!node->copies)
- return true;
-
- struct set_entry *copy_entry;
- set_foreach(node->copies, copy_entry) {
- nir_intrinsic_instr *copy = (void *)copy_entry->key;
-
- nir_lower_var_copy_instr(copy, state->shader);
-
- for (unsigned i = 0; i < 2; ++i) {
- struct deref_node *arg_node =
- get_deref_node(copy->variables[i], state);
-
- /* Only bother removing copy entries for other nodes */
- if (arg_node == NULL || arg_node == node)
- continue;
-
- struct set_entry *arg_entry = _mesa_set_search(arg_node->copies, copy);
- assert(arg_entry);
- _mesa_set_remove(node->copies, arg_entry);
- }
-
- nir_instr_remove(&copy->instr);
- }
-
- node->copies = NULL;
-
- return true;
-}
-
-/* Performs variable renaming by doing a DFS of the dominance tree
- *
- * This algorithm is very similar to the one outlined in "Efficiently
- * Computing Static Single Assignment Form and the Control Dependence
- * Graph" by Cytron et. al. The primary difference is that we only put one
- * SSA def on the stack per block.
- */
-static bool
-rename_variables_block(nir_block *block, struct lower_variables_state *state)
-{
- nir_builder b;
- nir_builder_init(&b, state->impl);
-
- nir_foreach_instr_safe(block, instr) {
- if (instr->type != nir_instr_type_intrinsic)
- continue;
-
- nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
-
- switch (intrin->intrinsic) {
- case nir_intrinsic_load_var: {
- struct deref_node *node =
- get_deref_node(intrin->variables[0], state);
-
- if (node == NULL) {
- /* If we hit this path then we are referencing an invalid
- * value. Most likely, we unrolled something and are
- * reading past the end of some array. In any case, this
- * should result in an undefined value.
- */
- nir_ssa_undef_instr *undef =
- nir_ssa_undef_instr_create(state->shader,
- intrin->num_components);
-
- nir_instr_insert_before(&intrin->instr, &undef->instr);
- nir_instr_remove(&intrin->instr);
-
- nir_ssa_def_rewrite_uses(&intrin->dest.ssa,
- nir_src_for_ssa(&undef->def));
- continue;
- }
-
- if (!node->lower_to_ssa)
- continue;
-
- nir_alu_instr *mov = nir_alu_instr_create(state->shader,
- nir_op_imov);
- mov->src[0].src = nir_src_for_ssa(
- nir_phi_builder_value_get_block_def(node->pb_value, block));
- for (unsigned i = intrin->num_components; i < 4; i++)
- mov->src[0].swizzle[i] = 0;
-
- assert(intrin->dest.is_ssa);
-
- mov->dest.write_mask = (1 << intrin->num_components) - 1;
- nir_ssa_dest_init(&mov->instr, &mov->dest.dest,
- intrin->num_components, NULL);
-
- nir_instr_insert_before(&intrin->instr, &mov->instr);
- nir_instr_remove(&intrin->instr);
-
- nir_ssa_def_rewrite_uses(&intrin->dest.ssa,
- nir_src_for_ssa(&mov->dest.dest.ssa));
- break;
- }
-
- case nir_intrinsic_store_var: {
- struct deref_node *node =
- get_deref_node(intrin->variables[0], state);
-
- if (node == NULL) {
- /* Probably an out-of-bounds array store. That should be a
- * no-op. */
- nir_instr_remove(&intrin->instr);
- continue;
- }
-
- if (!node->lower_to_ssa)
- continue;
-
- assert(intrin->num_components ==
- glsl_get_vector_elements(node->type));
-
- assert(intrin->src[0].is_ssa);
-
- nir_ssa_def *new_def;
- b.cursor = nir_before_instr(&intrin->instr);
-
- if (intrin->const_index[0] == (1 << intrin->num_components) - 1) {
- /* Whole variable store - just copy the source. Note that
- * intrin->num_components and intrin->src[0].ssa->num_components
- * may differ.
- */
- unsigned swiz[4];
- for (unsigned i = 0; i < 4; i++)
- swiz[i] = i < intrin->num_components ? i : 0;
-
- new_def = nir_swizzle(&b, intrin->src[0].ssa, swiz,
- intrin->num_components, false);
- } else {
- nir_ssa_def *old_def =
- nir_phi_builder_value_get_block_def(node->pb_value, block);
- /* For writemasked store_var intrinsics, we combine the newly
- * written values with the existing contents of unwritten
- * channels, creating a new SSA value for the whole vector.
- */
- nir_ssa_def *srcs[4];
- for (unsigned i = 0; i < intrin->num_components; i++) {
- if (intrin->const_index[0] & (1 << i)) {
- srcs[i] = nir_channel(&b, intrin->src[0].ssa, i);
- } else {
- srcs[i] = nir_channel(&b, old_def, i);
- }
- }
- new_def = nir_vec(&b, srcs, intrin->num_components);
- }
-
- assert(new_def->num_components == intrin->num_components);
-
- nir_phi_builder_value_set_block_def(node->pb_value, block, new_def);
- nir_instr_remove(&intrin->instr);
- break;
- }
-
- default:
- break;
- }
- }
-
- for (unsigned i = 0; i < block->num_dom_children; ++i)
- rename_variables_block(block->dom_children[i], state);
-
- return true;
-}
-
-/** Implements a pass to lower variable uses to SSA values
- *
- * This path walks the list of instructions and tries to lower as many
- * local variable load/store operations to SSA defs and uses as it can.
- * The process involves four passes:
- *
- * 1) Iterate over all of the instructions and mark where each local
- * variable deref is used in a load, store, or copy. While we're at
- * it, we keep track of all of the fully-qualified (no wildcards) and
- * fully-direct references we see and store them in the
- * direct_deref_nodes hash table.
- *
- * 2) Walk over the the list of fully-qualified direct derefs generated in
- * the previous pass. For each deref, we determine if it can ever be
- * aliased, i.e. if there is an indirect reference anywhere that may
- * refer to it. If it cannot be aliased, we mark it for lowering to an
- * SSA value. At this point, we lower any var_copy instructions that
- * use the given deref to load/store operations and, if the deref has a
- * constant initializer, we go ahead and add a load_const value at the
- * beginning of the function with the initialized value.
- *
- * 3) Walk over the list of derefs we plan to lower to SSA values and
- * insert phi nodes as needed.
- *
- * 4) Perform "variable renaming" by replacing the load/store instructions
- * with SSA definitions and SSA uses.
- */
-static bool
-nir_lower_vars_to_ssa_impl(nir_function_impl *impl)
-{
- struct lower_variables_state state;
-
- state.shader = impl->function->shader;
- state.dead_ctx = ralloc_context(state.shader);
- state.impl = impl;
-
- state.deref_var_nodes = _mesa_hash_table_create(state.dead_ctx,
- _mesa_hash_pointer,
- _mesa_key_pointer_equal);
- exec_list_make_empty(&state.direct_deref_nodes);
-
- /* Build the initial deref structures and direct_deref_nodes table */
- state.add_to_direct_deref_nodes = true;
- nir_foreach_block(impl, register_variable_uses_block, &state);
-
- bool progress = false;
-
- nir_metadata_require(impl, nir_metadata_block_index);
-
- /* We're about to iterate through direct_deref_nodes. Don't modify it. */
- state.add_to_direct_deref_nodes = false;
-
- 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) {
- exec_node_remove(&node->direct_derefs_link);
- continue;
- }
-
- if (deref_may_be_aliased(deref, &state)) {
- exec_node_remove(&node->direct_derefs_link);
- continue;
- }
-
- node->lower_to_ssa = true;
- progress = true;
-
- foreach_deref_node_match(deref, lower_copies_to_load_store, &state);
- }
-
- if (!progress)
- return false;
-
- nir_metadata_require(impl, nir_metadata_dominance);
-
- /* We may have lowered some copy instructions to load/store
- * instructions. The uses from the copy instructions hav already been
- * removed but we need to rescan to ensure that the uses from the newly
- * added load/store instructions are registered. We need this
- * information for phi node insertion below.
- */
- nir_foreach_block(impl, register_variable_uses_block, &state);
-
- state.phi_builder = nir_phi_builder_create(state.impl);
-
- NIR_VLA(BITSET_WORD, store_blocks, BITSET_WORDS(state.impl->num_blocks));
- foreach_list_typed(struct deref_node, node, direct_derefs_link,
- &state.direct_deref_nodes) {
- if (!node->lower_to_ssa)
- continue;
-
- memset(store_blocks, 0,
- BITSET_WORDS(state.impl->num_blocks) * sizeof(*store_blocks));
-
- if (node->stores) {
- struct set_entry *store_entry;
- set_foreach(node->stores, store_entry) {
- nir_intrinsic_instr *store =
- (nir_intrinsic_instr *)store_entry->key;
- BITSET_SET(store_blocks, store->instr.block->index);
- }
- }
-
- if (node->deref->var->constant_initializer)
- BITSET_SET(store_blocks, 0);
-
- node->pb_value =
- nir_phi_builder_add_value(state.phi_builder,
- glsl_get_vector_elements(node->type),
- store_blocks);
-
- if (node->deref->var->constant_initializer) {
- nir_load_const_instr *load =
- nir_deref_get_const_initializer_load(state.shader, node->deref);
- nir_instr_insert_before_cf_list(&impl->body, &load->instr);
- nir_phi_builder_value_set_block_def(node->pb_value,
- nir_start_block(impl), &load->def);
- }
- }
-
- rename_variables_block(nir_start_block(impl), &state);
-
- nir_phi_builder_finish(state.phi_builder);
-
- nir_metadata_preserve(impl, nir_metadata_block_index |
- nir_metadata_dominance);
-
- ralloc_free(state.dead_ctx);
-
- return progress;
-}
-
-void
-nir_lower_vars_to_ssa(nir_shader *shader)
-{
- nir_foreach_function(shader, function) {
- if (function->impl)
- nir_lower_vars_to_ssa_impl(function->impl);
- }
-}
diff --git a/src/glsl/nir/nir_lower_vec_to_movs.c b/src/glsl/nir/nir_lower_vec_to_movs.c
deleted file mode 100644
index 06d627900c6..00000000000
--- a/src/glsl/nir/nir_lower_vec_to_movs.c
+++ /dev/null
@@ -1,310 +0,0 @@
-/*
- * Copyright © 2014 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- *
- * Authors:
- * Jason Ekstrand ([email protected])
- *
- */
-
-#include "nir.h"
-
-/*
- * Implements a simple pass that lowers vecN instructions to a series of
- * moves with partial writes.
- */
-
-struct vec_to_movs_state {
- nir_function_impl *impl;
- bool progress;
-};
-
-static bool
-src_matches_dest_reg(nir_dest *dest, nir_src *src)
-{
- if (dest->is_ssa || src->is_ssa)
- return false;
-
- return (dest->reg.reg == src->reg.reg &&
- dest->reg.base_offset == src->reg.base_offset &&
- !dest->reg.indirect &&
- !src->reg.indirect);
-}
-
-/**
- * For a given starting writemask channel and corresponding source index in
- * the vec instruction, insert a MOV to the vec instruction's dest of all the
- * writemask channels that get read from the same src reg.
- *
- * Returns the writemask of our MOV, so the parent loop calling this knows
- * which ones have been processed.
- */
-static unsigned
-insert_mov(nir_alu_instr *vec, unsigned start_idx, nir_shader *shader)
-{
- assert(start_idx < nir_op_infos[vec->op].num_inputs);
-
- nir_alu_instr *mov = nir_alu_instr_create(shader, nir_op_imov);
- nir_alu_src_copy(&mov->src[0], &vec->src[start_idx], mov);
- nir_alu_dest_copy(&mov->dest, &vec->dest, mov);
-
- mov->dest.write_mask = (1u << start_idx);
- mov->src[0].swizzle[start_idx] = vec->src[start_idx].swizzle[0];
- mov->src[0].negate = vec->src[start_idx].negate;
- mov->src[0].abs = vec->src[start_idx].abs;
-
- for (unsigned i = start_idx + 1; i < 4; i++) {
- if (!(vec->dest.write_mask & (1 << i)))
- continue;
-
- if (nir_srcs_equal(vec->src[i].src, vec->src[start_idx].src) &&
- vec->src[i].negate == vec->src[start_idx].negate &&
- vec->src[i].abs == vec->src[start_idx].abs) {
- mov->dest.write_mask |= (1 << i);
- mov->src[0].swizzle[i] = vec->src[i].swizzle[0];
- }
- }
-
- /* In some situations (if the vecN is involved in a phi-web), we can end
- * up with a mov from a register to itself. Some of those channels may end
- * up doing nothing and there's no reason to have them as part of the mov.
- */
- if (src_matches_dest_reg(&mov->dest.dest, &mov->src[0].src) &&
- !mov->src[0].abs && !mov->src[0].negate) {
- for (unsigned i = 0; i < 4; i++) {
- if (mov->src[0].swizzle[i] == i) {
- mov->dest.write_mask &= ~(1 << i);
- }
- }
- }
-
- /* Only emit the instruction if it actually does something */
- if (mov->dest.write_mask) {
- nir_instr_insert_before(&vec->instr, &mov->instr);
- } else {
- ralloc_free(mov);
- }
-
- return mov->dest.write_mask;
-}
-
-static bool
-has_replicated_dest(nir_alu_instr *alu)
-{
- return alu->op == nir_op_fdot_replicated2 ||
- alu->op == nir_op_fdot_replicated3 ||
- alu->op == nir_op_fdot_replicated4 ||
- alu->op == nir_op_fdph_replicated;
-}
-
-/* Attempts to coalesce the "move" from the given source of the vec to the
- * destination of the instruction generating the value. If, for whatever
- * reason, we cannot coalesce the mmove, it does nothing and returns 0. We
- * can then call insert_mov as normal.
- */
-static unsigned
-try_coalesce(nir_alu_instr *vec, unsigned start_idx, nir_shader *shader)
-{
- assert(start_idx < nir_op_infos[vec->op].num_inputs);
-
- /* We will only even try if the source is SSA */
- if (!vec->src[start_idx].src.is_ssa)
- return 0;
-
- assert(vec->src[start_idx].src.ssa);
-
- /* If we are going to do a reswizzle, then the vecN operation must be the
- * only use of the source value. We also can't have any source modifiers.
- */
- nir_foreach_use(vec->src[start_idx].src.ssa, src) {
- if (src->parent_instr != &vec->instr)
- return 0;
-
- nir_alu_src *alu_src = exec_node_data(nir_alu_src, src, src);
- if (alu_src->abs || alu_src->negate)
- return 0;
- }
-
- if (!list_empty(&vec->src[start_idx].src.ssa->if_uses))
- return 0;
-
- if (vec->src[start_idx].src.ssa->parent_instr->type != nir_instr_type_alu)
- return 0;
-
- nir_alu_instr *src_alu =
- nir_instr_as_alu(vec->src[start_idx].src.ssa->parent_instr);
-
- if (has_replicated_dest(src_alu)) {
- /* The fdot instruction is special: It replicates its result to all
- * components. This means that we can always rewrite its destination
- * and we don't need to swizzle anything.
- */
- } else {
- /* We only care about being able to re-swizzle the instruction if it is
- * something that we can reswizzle. It must be per-component. The one
- * exception to this is the fdotN instructions which implicitly splat
- * their result out to all channels.
- */
- if (nir_op_infos[src_alu->op].output_size != 0)
- return 0;
-
- /* If we are going to reswizzle the instruction, we can't have any
- * non-per-component sources either.
- */
- for (unsigned j = 0; j < nir_op_infos[src_alu->op].num_inputs; j++)
- if (nir_op_infos[src_alu->op].input_sizes[j] != 0)
- return 0;
- }
-
- /* Stash off all of the ALU instruction's swizzles. */
- uint8_t swizzles[4][4];
- for (unsigned j = 0; j < nir_op_infos[src_alu->op].num_inputs; j++)
- for (unsigned i = 0; i < 4; i++)
- swizzles[j][i] = src_alu->src[j].swizzle[i];
-
- unsigned write_mask = 0;
- for (unsigned i = start_idx; i < 4; i++) {
- if (!(vec->dest.write_mask & (1 << i)))
- continue;
-
- if (!vec->src[i].src.is_ssa ||
- vec->src[i].src.ssa != &src_alu->dest.dest.ssa)
- continue;
-
- /* At this point, the give vec source matchese up with the ALU
- * instruction so we can re-swizzle that component to match.
- */
- write_mask |= 1 << i;
- if (has_replicated_dest(src_alu)) {
- /* Since the destination is a single replicated value, we don't need
- * to do any reswizzling
- */
- } else {
- for (unsigned j = 0; j < nir_op_infos[src_alu->op].num_inputs; j++)
- src_alu->src[j].swizzle[i] = swizzles[j][vec->src[i].swizzle[0]];
- }
-
- /* Clear the no longer needed vec source */
- nir_instr_rewrite_src(&vec->instr, &vec->src[i].src, NIR_SRC_INIT);
- }
-
- nir_instr_rewrite_dest(&src_alu->instr, &src_alu->dest.dest, vec->dest.dest);
- src_alu->dest.write_mask = write_mask;
-
- return write_mask;
-}
-
-static bool
-lower_vec_to_movs_block(nir_block *block, void *void_state)
-{
- struct vec_to_movs_state *state = void_state;
- nir_function_impl *impl = state->impl;
- nir_shader *shader = impl->function->shader;
-
- nir_foreach_instr_safe(block, instr) {
- if (instr->type != nir_instr_type_alu)
- continue;
-
- nir_alu_instr *vec = nir_instr_as_alu(instr);
-
- switch (vec->op) {
- case nir_op_vec2:
- case nir_op_vec3:
- case nir_op_vec4:
- break;
- default:
- continue; /* The loop */
- }
-
- if (vec->dest.dest.is_ssa) {
- /* Since we insert multiple MOVs, we have a register destination. */
- nir_register *reg = nir_local_reg_create(impl);
- reg->num_components = vec->dest.dest.ssa.num_components;
-
- nir_ssa_def_rewrite_uses(&vec->dest.dest.ssa, nir_src_for_reg(reg));
-
- nir_instr_rewrite_dest(&vec->instr, &vec->dest.dest,
- nir_dest_for_reg(reg));
- }
-
- unsigned finished_write_mask = 0;
-
- /* First, emit a MOV for all the src channels that are in the
- * destination reg, in case other values we're populating in the dest
- * might overwrite them.
- */
- for (unsigned i = 0; i < 4; i++) {
- if (!(vec->dest.write_mask & (1 << i)))
- continue;
-
- if (src_matches_dest_reg(&vec->dest.dest, &vec->src[i].src)) {
- finished_write_mask |= insert_mov(vec, i, shader);
- break;
- }
- }
-
- /* Now, emit MOVs for all the other src channels. */
- for (unsigned i = 0; i < 4; i++) {
- if (!(vec->dest.write_mask & (1 << i)))
- continue;
-
- if (!(finished_write_mask & (1 << i)))
- finished_write_mask |= try_coalesce(vec, i, shader);
-
- if (!(finished_write_mask & (1 << i)))
- finished_write_mask |= insert_mov(vec, i, shader);
- }
-
- nir_instr_remove(&vec->instr);
- ralloc_free(vec);
- state->progress = true;
- }
-
- return true;
-}
-
-static bool
-nir_lower_vec_to_movs_impl(nir_function_impl *impl)
-{
- struct vec_to_movs_state state = { impl, false };
-
- nir_foreach_block(impl, lower_vec_to_movs_block, &state);
-
- if (state.progress) {
- nir_metadata_preserve(impl, nir_metadata_block_index |
- nir_metadata_dominance);
- }
-
- return state.progress;
-}
-
-bool
-nir_lower_vec_to_movs(nir_shader *shader)
-{
- bool progress = false;
-
- nir_foreach_function(shader, function) {
- if (function->impl)
- progress = nir_lower_vec_to_movs_impl(function->impl) || progress;
- }
-
- return progress;
-}
diff --git a/src/glsl/nir/nir_metadata.c b/src/glsl/nir/nir_metadata.c
deleted file mode 100644
index 61aae73221e..00000000000
--- a/src/glsl/nir/nir_metadata.c
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright © 2014 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- *
- * Authors:
- * Jason Ekstrand ([email protected])
- */
-
-#include "nir.h"
-
-/*
- * Handles management of the metadata.
- */
-
-void
-nir_metadata_require(nir_function_impl *impl, nir_metadata required)
-{
-#define NEEDS_UPDATE(X) ((required & ~impl->valid_metadata) & (X))
-
- if (NEEDS_UPDATE(nir_metadata_block_index))
- nir_index_blocks(impl);
- if (NEEDS_UPDATE(nir_metadata_dominance))
- nir_calc_dominance_impl(impl);
- if (NEEDS_UPDATE(nir_metadata_live_ssa_defs))
- nir_live_ssa_defs_impl(impl);
-
-#undef NEEDS_UPDATE
-
- impl->valid_metadata |= required;
-}
-
-void
-nir_metadata_preserve(nir_function_impl *impl, nir_metadata preserved)
-{
- impl->valid_metadata &= preserved;
-}
-
-#ifdef DEBUG
-/**
- * Make sure passes properly invalidate metadata (part 1).
- *
- * Call this before running a pass to set a bogus metadata flag, which will
- * only be preserved if the pass forgets to call nir_metadata_preserve().
- */
-void
-nir_metadata_set_validation_flag(nir_shader *shader)
-{
- nir_foreach_function(shader, function) {
- if (function->impl) {
- function->impl->valid_metadata |= nir_metadata_not_properly_reset;
- }
- }
-}
-
-/**
- * Make sure passes properly invalidate metadata (part 2).
- *
- * Call this after a pass makes progress to verify that the bogus metadata set by
- * the earlier function was properly thrown away. Note that passes may not call
- * nir_metadata_preserve() if they don't actually make any changes at all.
- */
-void
-nir_metadata_check_validation_flag(nir_shader *shader)
-{
- nir_foreach_function(shader, function) {
- if (function->impl) {
- assert(!(function->impl->valid_metadata &
- nir_metadata_not_properly_reset));
- }
- }
-}
-#endif
diff --git a/src/glsl/nir/nir_move_vec_src_uses_to_dest.c b/src/glsl/nir/nir_move_vec_src_uses_to_dest.c
deleted file mode 100644
index b5186e6e944..00000000000
--- a/src/glsl/nir/nir_move_vec_src_uses_to_dest.c
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
- * Copyright © 2014 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- *
- * Authors:
- * Jason Ekstrand ([email protected])
- *
- */
-
-#include "nir.h"
-
-/*
- * Implements a pass that tries to move uses vecN sources to their
- * destinations. This is kind of like an inverse copy-propagation pass.
- * For instance, if you have
- *
- * ssa_1 = vec4(a, b, c, d)
- * ssa_2 = fadd(a, b)
- *
- * This will be turned into
- *
- * ssa_1 = vec4(a, b, c, d)
- * ssa_2 = fadd(ssa_1.x, ssa_1.y)
- *
- * While this is "worse" because it adds a bunch of unneeded dependencies, it
- * actually makes it much easier for vec4-based backends to coalesce the MOV's
- * that result from the vec4 operation because it doesn't have to worry about
- * quite as many reads.
- */
-
-/* Returns true if the given SSA def dominates the instruction. An SSA def is
- * considered to *not* dominate the instruction that defines it.
- */
-static bool
-ssa_def_dominates_instr(nir_ssa_def *def, nir_instr *instr)
-{
- if (instr->index <= def->parent_instr->index) {
- return false;
- } else if (def->parent_instr->block == instr->block) {
- return def->parent_instr->index < instr->index;
- } else {
- return nir_block_dominates(def->parent_instr->block, instr->block);
- }
-}
-
-static bool
-move_vec_src_uses_to_dest_block(nir_block *block, void *shader)
-{
- nir_foreach_instr(block, instr) {
- if (instr->type != nir_instr_type_alu)
- continue;
-
- nir_alu_instr *vec = nir_instr_as_alu(instr);
-
- switch (vec->op) {
- case nir_op_vec2:
- case nir_op_vec3:
- case nir_op_vec4:
- break;
- default:
- continue; /* The loop */
- }
-
- /* Can't handle non-SSA vec operations */
- if (!vec->dest.dest.is_ssa)
- continue;
-
- /* Can't handle saturation */
- if (vec->dest.saturate)
- continue;
-
- /* First, mark all of the sources we are going to consider for rewriting
- * to the destination
- */
- int srcs_remaining = 0;
- for (unsigned i = 0; i < nir_op_infos[vec->op].num_inputs; i++) {
- /* We can't rewrite a source if it's not in SSA form */
- if (!vec->src[i].src.is_ssa)
- continue;
-
- /* We can't rewrite a source if it has modifiers */
- if (vec->src[i].abs || vec->src[i].negate)
- continue;
-
- srcs_remaining |= 1 << i;
- }
-
- /* We can't actually do anything with this instruction */
- if (srcs_remaining == 0)
- continue;
-
- for (unsigned i; i = ffs(srcs_remaining) - 1, srcs_remaining;) {
- int8_t swizzle[4] = { -1, -1, -1, -1 };
-
- for (unsigned j = i; j < nir_op_infos[vec->op].num_inputs; j++) {
- if (vec->src[j].src.ssa != vec->src[i].src.ssa)
- continue;
-
- /* Mark the given chanle as having been handled */
- srcs_remaining &= ~(1 << j);
-
- /* Mark the appropreate channel as coming from src j */
- swizzle[vec->src[j].swizzle[0]] = j;
- }
-
- nir_foreach_use_safe(vec->src[i].src.ssa, use) {
- if (use->parent_instr == &vec->instr)
- continue;
-
- /* We need to dominate the use if we are going to rewrite it */
- if (!ssa_def_dominates_instr(&vec->dest.dest.ssa, use->parent_instr))
- continue;
-
- /* For now, we'll just rewrite ALU instructions */
- if (use->parent_instr->type != nir_instr_type_alu)
- continue;
-
- assert(use->is_ssa);
-
- nir_alu_instr *use_alu = nir_instr_as_alu(use->parent_instr);
-
- /* Figure out which source we're actually looking at */
- nir_alu_src *use_alu_src = exec_node_data(nir_alu_src, use, src);
- unsigned src_idx = use_alu_src - use_alu->src;
- assert(src_idx < nir_op_infos[use_alu->op].num_inputs);
-
- bool can_reswizzle = true;
- for (unsigned j = 0; j < 4; j++) {
- if (!nir_alu_instr_channel_used(use_alu, src_idx, j))
- continue;
-
- if (swizzle[use_alu_src->swizzle[j]] == -1) {
- can_reswizzle = false;
- break;
- }
- }
-
- if (!can_reswizzle)
- continue;
-
- /* At this point, we have determined that the given use can be
- * reswizzled to actually use the destination of the vecN operation.
- * Go ahead and rewrite it as needed.
- */
- nir_instr_rewrite_src(use->parent_instr, use,
- nir_src_for_ssa(&vec->dest.dest.ssa));
- for (unsigned j = 0; j < 4; j++) {
- if (!nir_alu_instr_channel_used(use_alu, src_idx, j))
- continue;
-
- use_alu_src->swizzle[j] = swizzle[use_alu_src->swizzle[j]];
- }
- }
- }
- }
-
- return true;
-}
-
-static void
-nir_move_vec_src_uses_to_dest_impl(nir_shader *shader, nir_function_impl *impl)
-{
- nir_metadata_require(impl, nir_metadata_dominance);
-
- nir_index_instrs(impl);
- nir_foreach_block(impl, move_vec_src_uses_to_dest_block, shader);
-
- nir_metadata_preserve(impl, nir_metadata_block_index |
- nir_metadata_dominance);
-}
-
-void
-nir_move_vec_src_uses_to_dest(nir_shader *shader)
-{
- nir_foreach_function(shader, function) {
- if (function->impl)
- nir_move_vec_src_uses_to_dest_impl(shader, function->impl);
- }
-}
diff --git a/src/glsl/nir/nir_normalize_cubemap_coords.c b/src/glsl/nir/nir_normalize_cubemap_coords.c
deleted file mode 100644
index 9c15eb8c15c..00000000000
--- a/src/glsl/nir/nir_normalize_cubemap_coords.c
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Copyright © 2015 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- *
- * Authors:
- * Jason Ekstrand <[email protected]>
- */
-
-#include "nir.h"
-#include "nir_builder.h"
-
-/**
- * This file implements a NIR lowering pass to perform the normalization of
- * the cubemap coordinates to have the largest magnitude component be -1.0
- * or 1.0. This is based on the old GLSL IR based pass by Eric.
- */
-
-struct normalize_cubemap_state {
- nir_builder b;
- bool progress;
-};
-
-static bool
-normalize_cubemap_coords_block(nir_block *block, void *void_state)
-{
- struct normalize_cubemap_state *state = void_state;
- nir_builder *b = &state->b;
-
- nir_foreach_instr(block, instr) {
- if (instr->type != nir_instr_type_tex)
- continue;
-
- nir_tex_instr *tex = nir_instr_as_tex(instr);
- if (tex->sampler_dim != GLSL_SAMPLER_DIM_CUBE)
- continue;
-
- b->cursor = nir_before_instr(&tex->instr);
-
- for (unsigned i = 0; i < tex->num_srcs; i++) {
- if (tex->src[i].src_type != nir_tex_src_coord)
- continue;
-
- nir_ssa_def *orig_coord =
- nir_ssa_for_src(b, tex->src[i].src, nir_tex_instr_src_size(tex, i));
- assert(orig_coord->num_components >= 3);
-
- nir_ssa_def *abs = nir_fabs(b, orig_coord);
- nir_ssa_def *norm = nir_fmax(b, nir_channel(b, abs, 0),
- nir_fmax(b, nir_channel(b, abs, 1),
- nir_channel(b, abs, 2)));
-
- nir_ssa_def *normalized = nir_fmul(b, orig_coord, nir_frcp(b, norm));
-
- /* Array indices don't have to be normalized, so make a new vector
- * with the coordinate's array index untouched.
- */
- if (tex->coord_components == 4) {
- normalized = nir_vec4(b,
- nir_channel(b, normalized, 0),
- nir_channel(b, normalized, 1),
- nir_channel(b, normalized, 2),
- nir_channel(b, orig_coord, 3));
- }
-
- nir_instr_rewrite_src(&tex->instr,
- &tex->src[i].src,
- nir_src_for_ssa(normalized));
-
- state->progress = true;
- }
- }
-
- return true;
-}
-
-static bool
-normalize_cubemap_coords_impl(nir_function_impl *impl)
-{
- struct normalize_cubemap_state state;
- nir_builder_init(&state.b, impl);
- state.progress = false;
-
- nir_foreach_block(impl, normalize_cubemap_coords_block, &state);
-
- nir_metadata_preserve(impl, nir_metadata_block_index |
- nir_metadata_dominance);
-
- return state.progress;
-}
-
-bool
-nir_normalize_cubemap_coords(nir_shader *shader)
-{
- bool progress = false;
-
- nir_foreach_function(shader, function) {
- if (function->impl)
- progress = normalize_cubemap_coords_impl(function->impl) || progress;
- }
-
- return progress;
-}
diff --git a/src/glsl/nir/nir_opcodes.py b/src/glsl/nir/nir_opcodes.py
deleted file mode 100644
index 0eff89783dd..00000000000
--- a/src/glsl/nir/nir_opcodes.py
+++ /dev/null
@@ -1,702 +0,0 @@
-#! /usr/bin/env python
-#
-# Copyright (C) 2014 Connor Abbott
-#
-# Permission is hereby granted, free of charge, to any person obtaining a
-# copy of this software and associated documentation files (the "Software"),
-# to deal in the Software without restriction, including without limitation
-# the rights to use, copy, modify, merge, publish, distribute, sublicense,
-# and/or sell copies of the Software, and to permit persons to whom the
-# Software is furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice (including the next
-# paragraph) shall be included in all copies or substantial portions of the
-# Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-# IN THE SOFTWARE.
-#
-# Authors:
-# Connor Abbott ([email protected])
-
-
-# Class that represents all the information we have about the opcode
-# NOTE: this must be kept in sync with nir_op_info
-
-class Opcode(object):
- """Class that represents all the information we have about the opcode
- NOTE: this must be kept in sync with nir_op_info
- """
- def __init__(self, name, output_size, output_type, input_sizes,
- input_types, algebraic_properties, const_expr):
- """Parameters:
-
- - name is the name of the opcode (prepend nir_op_ for the enum name)
- - all types are strings that get nir_type_ prepended to them
- - input_types is a list of types
- - algebraic_properties is a space-seperated string, where nir_op_is_ is
- prepended before each entry
- - const_expr is an expression or series of statements that computes the
- constant value of the opcode given the constant values of its inputs.
-
- Constant expressions are formed from the variables src0, src1, ...,
- src(N-1), where N is the number of arguments. The output of the
- expression should be stored in the dst variable. Per-component input
- and output variables will be scalars and non-per-component input and
- output variables will be a struct with fields named x, y, z, and w
- all of the correct type. Input and output variables can be assumed
- to already be of the correct type and need no conversion. In
- particular, the conversion from the C bool type to/from NIR_TRUE and
- NIR_FALSE happens automatically.
-
- For per-component instructions, the entire expression will be
- executed once for each component. For non-per-component
- instructions, the expression is expected to store the correct values
- in dst.x, dst.y, etc. If "dst" does not exist anywhere in the
- constant expression, an assignment to dst will happen automatically
- and the result will be equivalent to "dst = <expression>" for
- per-component instructions and "dst.x = dst.y = ... = <expression>"
- for non-per-component instructions.
- """
- assert isinstance(name, str)
- assert isinstance(output_size, int)
- assert isinstance(output_type, str)
- assert isinstance(input_sizes, list)
- assert isinstance(input_sizes[0], int)
- assert isinstance(input_types, list)
- assert isinstance(input_types[0], str)
- assert isinstance(algebraic_properties, str)
- assert isinstance(const_expr, str)
- assert len(input_sizes) == len(input_types)
- assert 0 <= output_size <= 4
- for size in input_sizes:
- assert 0 <= size <= 4
- if output_size != 0:
- assert size != 0
- self.name = name
- self.num_inputs = len(input_sizes)
- self.output_size = output_size
- self.output_type = output_type
- self.input_sizes = input_sizes
- self.input_types = input_types
- self.algebraic_properties = algebraic_properties
- self.const_expr = const_expr
-
-# helper variables for strings
-tfloat = "float"
-tint = "int"
-tbool = "bool"
-tuint = "uint"
-
-commutative = "commutative "
-associative = "associative "
-
-# global dictionary of opcodes
-opcodes = {}
-
-def opcode(name, output_size, output_type, input_sizes, input_types,
- algebraic_properties, const_expr):
- assert name not in opcodes
- opcodes[name] = Opcode(name, output_size, output_type, input_sizes,
- input_types, algebraic_properties, const_expr)
-
-def unop_convert(name, out_type, in_type, const_expr):
- opcode(name, 0, out_type, [0], [in_type], "", const_expr)
-
-def unop(name, ty, const_expr):
- opcode(name, 0, ty, [0], [ty], "", const_expr)
-
-def unop_horiz(name, output_size, output_type, input_size, input_type,
- const_expr):
- opcode(name, output_size, output_type, [input_size], [input_type], "",
- const_expr)
-
-def unop_reduce(name, output_size, output_type, input_type, prereduce_expr,
- reduce_expr, final_expr):
- def prereduce(src):
- return "(" + prereduce_expr.format(src=src) + ")"
- def final(src):
- return final_expr.format(src="(" + src + ")")
- def reduce_(src0, src1):
- return reduce_expr.format(src0=src0, src1=src1)
- src0 = prereduce("src0.x")
- src1 = prereduce("src0.y")
- src2 = prereduce("src0.z")
- src3 = prereduce("src0.w")
- unop_horiz(name + "2", output_size, output_type, 2, input_type,
- final(reduce_(src0, src1)))
- unop_horiz(name + "3", output_size, output_type, 3, input_type,
- final(reduce_(reduce_(src0, src1), src2)))
- unop_horiz(name + "4", output_size, output_type, 4, input_type,
- final(reduce_(reduce_(src0, src1), reduce_(src2, src3))))
-
-
-# These two move instructions differ in what modifiers they support and what
-# the negate modifier means. Otherwise, they are identical.
-unop("fmov", tfloat, "src0")
-unop("imov", tint, "src0")
-
-unop("ineg", tint, "-src0")
-unop("fneg", tfloat, "-src0")
-unop("inot", tint, "~src0") # invert every bit of the integer
-unop("fnot", tfloat, "(src0 == 0.0f) ? 1.0f : 0.0f")
-unop("fsign", tfloat, "(src0 == 0.0f) ? 0.0f : ((src0 > 0.0f) ? 1.0f : -1.0f)")
-unop("isign", tint, "(src0 == 0) ? 0 : ((src0 > 0) ? 1 : -1)")
-unop("iabs", tint, "(src0 < 0) ? -src0 : src0")
-unop("fabs", tfloat, "fabsf(src0)")
-unop("fsat", tfloat, "(src0 > 1.0f) ? 1.0f : ((src0 <= 0.0f) ? 0.0f : src0)")
-unop("frcp", tfloat, "1.0f / src0")
-unop("frsq", tfloat, "1.0f / sqrtf(src0)")
-unop("fsqrt", tfloat, "sqrtf(src0)")
-unop("fexp2", tfloat, "exp2f(src0)")
-unop("flog2", tfloat, "log2f(src0)")
-unop_convert("f2i", tint, tfloat, "src0") # Float-to-integer conversion.
-unop_convert("f2u", tuint, tfloat, "src0") # Float-to-unsigned conversion
-unop_convert("i2f", tfloat, tint, "src0") # Integer-to-float conversion.
-# Float-to-boolean conversion
-unop_convert("f2b", tbool, tfloat, "src0 != 0.0f")
-# Boolean-to-float conversion
-unop_convert("b2f", tfloat, tbool, "src0 ? 1.0f : 0.0f")
-# Int-to-boolean conversion
-unop_convert("i2b", tbool, tint, "src0 != 0")
-unop_convert("b2i", tint, tbool, "src0 ? 1 : 0") # Boolean-to-int conversion
-unop_convert("u2f", tfloat, tuint, "src0") # Unsigned-to-float conversion.
-
-# Unary floating-point rounding operations.
-
-
-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_roundevenf(src0)")
-
-unop("fquantize2f16", tfloat, "(fabs(src0) < ldexpf(1.0, -14)) ? copysignf(0.0f, src0) : _mesa_half_to_float(_mesa_float_to_half(src0))")
-
-# Trigonometric operations.
-
-
-unop("fsin", tfloat, "sinf(src0)")
-unop("fcos", tfloat, "cosf(src0)")
-
-
-# Partial derivatives.
-
-
-unop("fddx", tfloat, "0.0f") # the derivative of a constant is 0.
-unop("fddy", tfloat, "0.0f")
-unop("fddx_fine", tfloat, "0.0f")
-unop("fddy_fine", tfloat, "0.0f")
-unop("fddx_coarse", tfloat, "0.0f")
-unop("fddy_coarse", tfloat, "0.0f")
-
-
-# Floating point pack and unpack operations.
-
-def pack_2x16(fmt):
- unop_horiz("pack_" + fmt + "_2x16", 1, tuint, 2, tfloat, """
-dst.x = (uint32_t) pack_fmt_1x16(src0.x);
-dst.x |= ((uint32_t) pack_fmt_1x16(src0.y)) << 16;
-""".replace("fmt", fmt))
-
-def pack_4x8(fmt):
- unop_horiz("pack_" + fmt + "_4x8", 1, tuint, 4, tfloat, """
-dst.x = (uint32_t) pack_fmt_1x8(src0.x);
-dst.x |= ((uint32_t) pack_fmt_1x8(src0.y)) << 8;
-dst.x |= ((uint32_t) pack_fmt_1x8(src0.z)) << 16;
-dst.x |= ((uint32_t) pack_fmt_1x8(src0.w)) << 24;
-""".replace("fmt", fmt))
-
-def unpack_2x16(fmt):
- unop_horiz("unpack_" + fmt + "_2x16", 2, tfloat, 1, tuint, """
-dst.x = unpack_fmt_1x16((uint16_t)(src0.x & 0xffff));
-dst.y = unpack_fmt_1x16((uint16_t)(src0.x << 16));
-""".replace("fmt", fmt))
-
-def unpack_4x8(fmt):
- unop_horiz("unpack_" + fmt + "_4x8", 4, tfloat, 1, tuint, """
-dst.x = unpack_fmt_1x8((uint8_t)(src0.x & 0xff));
-dst.y = unpack_fmt_1x8((uint8_t)((src0.x >> 8) & 0xff));
-dst.z = unpack_fmt_1x8((uint8_t)((src0.x >> 16) & 0xff));
-dst.w = unpack_fmt_1x8((uint8_t)(src0.x >> 24));
-""".replace("fmt", fmt))
-
-
-pack_2x16("snorm")
-pack_4x8("snorm")
-pack_2x16("unorm")
-pack_4x8("unorm")
-pack_2x16("half")
-unpack_2x16("snorm")
-unpack_4x8("snorm")
-unpack_2x16("unorm")
-unpack_4x8("unorm")
-unpack_2x16("half")
-
-unop_horiz("pack_uvec2_to_uint", 0, tuint, 2, tuint, """
-dst = (src0.x & 0xffff) | (src0.y >> 16);
-""")
-
-unop_horiz("pack_uvec4_to_uint", 0, tuint, 4, tuint, """
-dst = (src0.x << 0) |
- (src0.y << 8) |
- (src0.z << 16) |
- (src0.w << 24);
-""")
-
-# Lowered floating point unpacking operations.
-
-
-unop_horiz("unpack_half_2x16_split_x", 1, tfloat, 1, tuint,
- "unpack_half_1x16((uint16_t)(src0.x & 0xffff))")
-unop_horiz("unpack_half_2x16_split_y", 1, tfloat, 1, tuint,
- "unpack_half_1x16((uint16_t)(src0.x >> 16))")
-
-
-# Bit operations, part of ARB_gpu_shader5.
-
-
-unop("bitfield_reverse", tuint, """
-/* we're not winning any awards for speed here, but that's ok */
-dst = 0;
-for (unsigned bit = 0; bit < 32; bit++)
- dst |= ((src0 >> bit) & 1) << (31 - bit);
-""")
-unop("bit_count", tuint, """
-dst = 0;
-for (unsigned bit = 0; bit < 32; bit++) {
- if ((src0 >> bit) & 1)
- dst++;
-}
-""")
-
-unop_convert("ufind_msb", tint, tuint, """
-dst = -1;
-for (int bit = 31; bit > 0; bit--) {
- if ((src0 >> bit) & 1) {
- dst = bit;
- break;
- }
-}
-""")
-
-unop("ifind_msb", tint, """
-dst = -1;
-for (int bit = 31; bit >= 0; bit--) {
- /* If src0 < 0, we're looking for the first 0 bit.
- * if src0 >= 0, we're looking for the first 1 bit.
- */
- if ((((src0 >> bit) & 1) && (src0 >= 0)) ||
- (!((src0 >> bit) & 1) && (src0 < 0))) {
- dst = bit;
- break;
- }
-}
-""")
-
-unop("find_lsb", tint, """
-dst = -1;
-for (unsigned bit = 0; bit < 32; bit++) {
- if ((src0 >> bit) & 1) {
- dst = bit;
- break;
- }
-}
-""")
-
-
-for i in xrange(1, 5):
- for j in xrange(1, 5):
- unop_horiz("fnoise{0}_{1}".format(i, j), i, tfloat, j, tfloat, "0.0f")
-
-def binop_convert(name, out_type, in_type, alg_props, const_expr):
- opcode(name, 0, out_type, [0, 0], [in_type, in_type], alg_props, const_expr)
-
-def binop(name, ty, alg_props, const_expr):
- binop_convert(name, ty, ty, alg_props, const_expr)
-
-def binop_compare(name, ty, alg_props, const_expr):
- binop_convert(name, tbool, ty, alg_props, const_expr)
-
-def binop_horiz(name, out_size, out_type, src1_size, src1_type, src2_size,
- src2_type, const_expr):
- opcode(name, out_size, out_type, [src1_size, src2_size], [src1_type, src2_type],
- "", const_expr)
-
-def binop_reduce(name, output_size, output_type, src_type, prereduce_expr,
- reduce_expr, final_expr):
- def final(src):
- return final_expr.format(src= "(" + src + ")")
- def reduce_(src0, src1):
- return reduce_expr.format(src0=src0, src1=src1)
- def prereduce(src0, src1):
- return "(" + prereduce_expr.format(src0=src0, src1=src1) + ")"
- src0 = prereduce("src0.x", "src1.x")
- src1 = prereduce("src0.y", "src1.y")
- src2 = prereduce("src0.z", "src1.z")
- src3 = prereduce("src0.w", "src1.w")
- opcode(name + "2", output_size, output_type,
- [2, 2], [src_type, src_type], commutative,
- final(reduce_(src0, src1)))
- opcode(name + "3", output_size, output_type,
- [3, 3], [src_type, src_type], commutative,
- final(reduce_(reduce_(src0, src1), src2)))
- opcode(name + "4", output_size, output_type,
- [4, 4], [src_type, src_type], commutative,
- final(reduce_(reduce_(src0, src1), reduce_(src2, src3))))
-
-binop("fadd", tfloat, commutative + associative, "src0 + src1")
-binop("iadd", tint, commutative + associative, "src0 + src1")
-binop("fsub", tfloat, "", "src0 - src1")
-binop("isub", tint, "", "src0 - src1")
-
-binop("fmul", tfloat, commutative + associative, "src0 * src1")
-# low 32-bits of signed/unsigned integer multiply
-binop("imul", tint, commutative + associative, "src0 * src1")
-# high 32-bits of signed integer multiply
-binop("imul_high", tint, commutative,
- "(int32_t)(((int64_t) src0 * (int64_t) src1) >> 32)")
-# high 32-bits of unsigned integer multiply
-binop("umul_high", tuint, commutative,
- "(uint32_t)(((uint64_t) src0 * (uint64_t) src1) >> 32)")
-
-binop("fdiv", tfloat, "", "src0 / src1")
-binop("idiv", tint, "", "src0 / src1")
-binop("udiv", tuint, "", "src0 / src1")
-
-# returns a boolean representing the carry resulting from the addition of
-# the two unsigned arguments.
-
-binop_convert("uadd_carry", tuint, tuint, commutative, "src0 + src1 < src0")
-
-# returns a boolean representing the borrow resulting from the subtraction
-# of the two unsigned arguments.
-
-binop_convert("usub_borrow", tuint, tuint, "", "src0 < src1")
-
-binop("umod", tuint, "", "src1 == 0 ? 0 : src0 % src1")
-
-# For signed integers, there are several different possible definitions of
-# "modulus" or "remainder". We follow the conventions used by LLVM and
-# SPIR-V. The irem opcode implements the standard C/C++ signed "%"
-# operation while the imod opcode implements the more mathematical
-# "modulus" operation. For details on the difference, see
-#
-# http://mathforum.org/library/drmath/view/52343.html
-
-binop("irem", tint, "", "src1 == 0 ? 0 : src0 % src1")
-binop("imod", tint, "",
- "src1 == 0 ? 0 : ((src0 % src1 == 0 || (src0 >= 0) == (src1 >= 0)) ?"
- " src0 % src1 : src0 % src1 + src1)")
-binop("fmod", tfloat, "", "src0 - src1 * floorf(src0 / src1)")
-binop("frem", tfloat, "", "src0 - src1 * truncf(src0 / src1)")
-
-#
-# Comparisons
-#
-
-
-# these integer-aware comparisons return a boolean (0 or ~0)
-
-binop_compare("flt", tfloat, "", "src0 < src1")
-binop_compare("fge", tfloat, "", "src0 >= src1")
-binop_compare("feq", tfloat, commutative, "src0 == src1")
-binop_compare("fne", tfloat, commutative, "src0 != src1")
-binop_compare("ilt", tint, "", "src0 < src1")
-binop_compare("ige", tint, "", "src0 >= src1")
-binop_compare("ieq", tint, commutative, "src0 == src1")
-binop_compare("ine", tint, commutative, "src0 != src1")
-binop_compare("ult", tuint, "", "src0 < src1")
-binop_compare("uge", tuint, "", "src0 >= src1")
-
-# integer-aware GLSL-style comparisons that compare floats and ints
-
-binop_reduce("ball_fequal", 1, tbool, tfloat, "{src0} == {src1}",
- "{src0} && {src1}", "{src}")
-binop_reduce("bany_fnequal", 1, tbool, tfloat, "{src0} != {src1}",
- "{src0} || {src1}", "{src}")
-binop_reduce("ball_iequal", 1, tbool, tint, "{src0} == {src1}",
- "{src0} && {src1}", "{src}")
-binop_reduce("bany_inequal", 1, tbool, tint, "{src0} != {src1}",
- "{src0} || {src1}", "{src}")
-
-# non-integer-aware GLSL-style comparisons that return 0.0 or 1.0
-
-binop_reduce("fall_equal", 1, tfloat, tfloat, "{src0} == {src1}",
- "{src0} && {src1}", "{src} ? 1.0f : 0.0f")
-binop_reduce("fany_nequal", 1, tfloat, tfloat, "{src0} != {src1}",
- "{src0} || {src1}", "{src} ? 1.0f : 0.0f")
-
-# These comparisons for integer-less hardware return 1.0 and 0.0 for true
-# and false respectively
-
-binop("slt", tfloat, "", "(src0 < src1) ? 1.0f : 0.0f") # Set on Less Than
-binop("sge", tfloat, "", "(src0 >= src1) ? 1.0f : 0.0f") # Set on Greater or Equal
-binop("seq", tfloat, commutative, "(src0 == src1) ? 1.0f : 0.0f") # Set on Equal
-binop("sne", tfloat, commutative, "(src0 != src1) ? 1.0f : 0.0f") # Set on Not Equal
-
-
-binop("ishl", tint, "", "src0 << src1")
-binop("ishr", tint, "", "src0 >> src1")
-binop("ushr", tuint, "", "src0 >> src1")
-
-# bitwise logic operators
-#
-# These are also used as boolean and, or, xor for hardware supporting
-# integers.
-
-
-binop("iand", tuint, commutative + associative, "src0 & src1")
-binop("ior", tuint, commutative + associative, "src0 | src1")
-binop("ixor", tuint, commutative + associative, "src0 ^ src1")
-
-
-# floating point logic operators
-#
-# These use (src != 0.0) for testing the truth of the input, and output 1.0
-# for true and 0.0 for false
-
-binop("fand", tfloat, commutative,
- "((src0 != 0.0f) && (src1 != 0.0f)) ? 1.0f : 0.0f")
-binop("for", tfloat, commutative,
- "((src0 != 0.0f) || (src1 != 0.0f)) ? 1.0f : 0.0f")
-binop("fxor", tfloat, commutative,
- "(src0 != 0.0f && src1 == 0.0f) || (src0 == 0.0f && src1 != 0.0f) ? 1.0f : 0.0f")
-
-binop_reduce("fdot", 1, tfloat, tfloat, "{src0} * {src1}", "{src0} + {src1}",
- "{src}")
-
-binop_reduce("fdot_replicated", 4, tfloat, tfloat,
- "{src0} * {src1}", "{src0} + {src1}", "{src}")
-
-opcode("fdph", 1, tfloat, [3, 4], [tfloat, tfloat], "",
- "src0.x * src1.x + src0.y * src1.y + src0.z * src1.z + src1.w")
-opcode("fdph_replicated", 4, tfloat, [3, 4], [tfloat, tfloat], "",
- "src0.x * src1.x + src0.y * src1.y + src0.z * src1.z + src1.w")
-
-binop("fmin", tfloat, "", "fminf(src0, src1)")
-binop("imin", tint, commutative + associative, "src1 > src0 ? src0 : src1")
-binop("umin", tuint, commutative + associative, "src1 > src0 ? src0 : src1")
-binop("fmax", tfloat, "", "fmaxf(src0, src1)")
-binop("imax", tint, commutative + associative, "src1 > src0 ? src1 : src0")
-binop("umax", tuint, commutative + associative, "src1 > src0 ? src1 : src0")
-
-# Saturated vector add for 4 8bit ints.
-binop("usadd_4x8", tint, commutative + associative, """
-dst = 0;
-for (int i = 0; i < 32; i += 8) {
- dst |= MIN2(((src0 >> i) & 0xff) + ((src1 >> i) & 0xff), 0xff) << i;
-}
-""")
-
-# Saturated vector subtract for 4 8bit ints.
-binop("ussub_4x8", tint, "", """
-dst = 0;
-for (int i = 0; i < 32; i += 8) {
- int src0_chan = (src0 >> i) & 0xff;
- int src1_chan = (src1 >> i) & 0xff;
- if (src0_chan > src1_chan)
- dst |= (src0_chan - src1_chan) << i;
-}
-""")
-
-# vector min for 4 8bit ints.
-binop("umin_4x8", tint, commutative + associative, """
-dst = 0;
-for (int i = 0; i < 32; i += 8) {
- dst |= MIN2((src0 >> i) & 0xff, (src1 >> i) & 0xff) << i;
-}
-""")
-
-# vector max for 4 8bit ints.
-binop("umax_4x8", tint, commutative + associative, """
-dst = 0;
-for (int i = 0; i < 32; i += 8) {
- dst |= MAX2((src0 >> i) & 0xff, (src1 >> i) & 0xff) << i;
-}
-""")
-
-# unorm multiply: (a * b) / 255.
-binop("umul_unorm_4x8", tint, commutative + associative, """
-dst = 0;
-for (int i = 0; i < 32; i += 8) {
- int src0_chan = (src0 >> i) & 0xff;
- int src1_chan = (src1 >> i) & 0xff;
- dst |= ((src0_chan * src1_chan) / 255) << i;
-}
-""")
-
-binop("fpow", tfloat, "", "powf(src0, src1)")
-
-binop_horiz("pack_half_2x16_split", 1, tuint, 1, tfloat, 1, tfloat,
- "pack_half_1x16(src0.x) | (pack_half_1x16(src1.x) << 16)")
-
-# bfm implements the behavior of the first operation of the SM5 "bfi" assembly
-# and that of the "bfi1" i965 instruction. That is, it has undefined behavior
-# if either of its arguments are 32.
-binop_convert("bfm", tuint, tint, "", """
-int bits = src0, offset = src1;
-if (offset < 0 || bits < 0 || offset > 31 || bits > 31 || offset + bits > 32)
- dst = 0; /* undefined */
-else
- dst = ((1u << bits) - 1) << offset;
-""")
-
-opcode("ldexp", 0, tfloat, [0, 0], [tfloat, tint], "", """
-dst = ldexpf(src0, src1);
-/* flush denormals to zero. */
-if (!isnormal(dst))
- dst = copysignf(0.0f, src0);
-""")
-
-# Combines the first component of each input to make a 2-component vector.
-
-binop_horiz("vec2", 2, tuint, 1, tuint, 1, tuint, """
-dst.x = src0.x;
-dst.y = src1.x;
-""")
-
-# Byte extraction
-binop("extract_ubyte", tuint, "", "(uint8_t)(src0 >> (src1 * 8))")
-binop("extract_ibyte", tint, "", "(int8_t)(src0 >> (src1 * 8))")
-
-# Word extraction
-binop("extract_uword", tuint, "", "(uint16_t)(src0 >> (src1 * 16))")
-binop("extract_iword", tint, "", "(int16_t)(src0 >> (src1 * 16))")
-
-
-def triop(name, ty, const_expr):
- opcode(name, 0, ty, [0, 0, 0], [ty, ty, ty], "", const_expr)
-def triop_horiz(name, output_size, src1_size, src2_size, src3_size, const_expr):
- opcode(name, output_size, tuint,
- [src1_size, src2_size, src3_size],
- [tuint, tuint, tuint], "", const_expr)
-
-triop("ffma", tfloat, "src0 * src1 + src2")
-
-triop("flrp", tfloat, "src0 * (1 - src2) + src1 * src2")
-
-# Conditional Select
-#
-# A vector conditional select instruction (like ?:, but operating per-
-# component on vectors). There are two versions, one for floating point
-# bools (0.0 vs 1.0) and one for integer bools (0 vs ~0).
-
-
-triop("fcsel", tfloat, "(src0 != 0.0f) ? src1 : src2")
-opcode("bcsel", 0, tuint, [0, 0, 0],
- [tbool, tuint, tuint], "", "src0 ? src1 : src2")
-
-# SM5 bfi assembly
-triop("bfi", tuint, """
-unsigned mask = src0, insert = src1, base = src2;
-if (mask == 0) {
- dst = base;
-} else {
- unsigned tmp = mask;
- while (!(tmp & 1)) {
- tmp >>= 1;
- insert <<= 1;
- }
- dst = (base & ~mask) | (insert & mask);
-}
-""")
-
-# SM5 ubfe/ibfe assembly
-opcode("ubfe", 0, tuint,
- [0, 0, 0], [tuint, tint, tint], "", """
-unsigned base = src0;
-int offset = src1, bits = src2;
-if (bits == 0) {
- dst = 0;
-} else if (bits < 0 || offset < 0) {
- dst = 0; /* undefined */
-} else if (offset + bits < 32) {
- dst = (base << (32 - bits - offset)) >> (32 - bits);
-} else {
- dst = base >> offset;
-}
-""")
-opcode("ibfe", 0, tint,
- [0, 0, 0], [tint, tint, tint], "", """
-int base = src0;
-int offset = src1, bits = src2;
-if (bits == 0) {
- dst = 0;
-} else if (bits < 0 || offset < 0) {
- dst = 0; /* undefined */
-} else if (offset + bits < 32) {
- dst = (base << (32 - bits - offset)) >> (32 - bits);
-} else {
- dst = base >> offset;
-}
-""")
-
-# GLSL bitfieldExtract()
-opcode("ubitfield_extract", 0, tuint,
- [0, 0, 0], [tuint, tint, tint], "", """
-unsigned base = src0;
-int offset = src1, bits = src2;
-if (bits == 0) {
- dst = 0;
-} else if (bits < 0 || offset < 0 || offset + bits > 32) {
- dst = 0; /* undefined per the spec */
-} else {
- dst = (base >> offset) & ((1ull << bits) - 1);
-}
-""")
-opcode("ibitfield_extract", 0, tint,
- [0, 0, 0], [tint, tint, tint], "", """
-int base = src0;
-int offset = src1, bits = src2;
-if (bits == 0) {
- dst = 0;
-} else if (offset < 0 || bits < 0 || offset + bits > 32) {
- dst = 0;
-} else {
- dst = (base << (32 - offset - bits)) >> offset; /* use sign-extending shift */
-}
-""")
-
-# Combines the first component of each input to make a 3-component vector.
-
-triop_horiz("vec3", 3, 1, 1, 1, """
-dst.x = src0.x;
-dst.y = src1.x;
-dst.z = src2.x;
-""")
-
-def quadop_horiz(name, output_size, src1_size, src2_size, src3_size,
- src4_size, const_expr):
- opcode(name, output_size, tuint,
- [src1_size, src2_size, src3_size, src4_size],
- [tuint, tuint, tuint, tuint],
- "", const_expr)
-
-opcode("bitfield_insert", 0, tuint, [0, 0, 0, 0],
- [tuint, tuint, tint, tint], "", """
-unsigned base = src0, insert = src1;
-int offset = src2, bits = src3;
-if (bits == 0) {
- dst = 0;
-} else if (offset < 0 || bits < 0 || bits + offset > 32) {
- dst = 0;
-} else {
- unsigned mask = ((1ull << bits) - 1) << offset;
- dst = (base & ~mask) | ((insert << bits) & mask);
-}
-""")
-
-quadop_horiz("vec4", 4, 1, 1, 1, 1, """
-dst.x = src0.x;
-dst.y = src1.x;
-dst.z = src2.x;
-dst.w = src3.x;
-""")
-
-
diff --git a/src/glsl/nir/nir_opcodes_c.py b/src/glsl/nir/nir_opcodes_c.py
deleted file mode 100644
index 7049c5be676..00000000000
--- a/src/glsl/nir/nir_opcodes_c.py
+++ /dev/null
@@ -1,55 +0,0 @@
-#! /usr/bin/env python
-#
-# Copyright (C) 2014 Connor Abbott
-#
-# Permission is hereby granted, free of charge, to any person obtaining a
-# copy of this software and associated documentation files (the "Software"),
-# to deal in the Software without restriction, including without limitation
-# the rights to use, copy, modify, merge, publish, distribute, sublicense,
-# and/or sell copies of the Software, and to permit persons to whom the
-# Software is furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice (including the next
-# paragraph) shall be included in all copies or substantial portions of the
-# Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-# IN THE SOFTWARE.
-#
-# Authors:
-# Connor Abbott ([email protected])
-
-from nir_opcodes import opcodes
-from mako.template import Template
-
-template = Template("""
-#include "nir.h"
-
-const nir_op_info nir_op_infos[nir_num_opcodes] = {
-% for name, opcode in sorted(opcodes.iteritems()):
-{
- .name = "${name}",
- .num_inputs = ${opcode.num_inputs},
- .output_size = ${opcode.output_size},
- .output_type = ${"nir_type_" + opcode.output_type},
- .input_sizes = {
- ${ ", ".join(str(size) for size in opcode.input_sizes) }
- },
- .input_types = {
- ${ ", ".join("nir_type_" + type for type in opcode.input_types) }
- },
- .algebraic_properties =
- ${ "0" if opcode.algebraic_properties == "" else " | ".join(
- "NIR_OP_IS_" + prop.upper() for prop in
- opcode.algebraic_properties.strip().split(" ")) }
-},
-% endfor
-};
-""")
-
-print template.render(opcodes=opcodes)
diff --git a/src/glsl/nir/nir_opcodes_h.py b/src/glsl/nir/nir_opcodes_h.py
deleted file mode 100644
index be15a96d236..00000000000
--- a/src/glsl/nir/nir_opcodes_h.py
+++ /dev/null
@@ -1,47 +0,0 @@
-#! /usr/bin/env python
-
-template = """\
-/* Copyright (C) 2014 Connor Abbott
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- *
- * Authors:
- * Connor Abbott ([email protected])
- */
-
-#ifndef _NIR_OPCODES_
-#define _NIR_OPCODES_
-
-<% opcode_names = sorted(opcodes.iterkeys()) %>
-
-typedef enum {
-% for name in opcode_names:
- nir_op_${name},
-% endfor
- nir_last_opcode = nir_op_${opcode_names[-1]},
- nir_num_opcodes = nir_last_opcode + 1
-} nir_op;
-
-#endif /* _NIR_OPCODES_ */"""
-
-from nir_opcodes import opcodes
-from mako.template import Template
-
-print Template(template).render(opcodes=opcodes)
diff --git a/src/glsl/nir/nir_opt_algebraic.py b/src/glsl/nir/nir_opt_algebraic.py
deleted file mode 100644
index f4bfd3a921a..00000000000
--- a/src/glsl/nir/nir_opt_algebraic.py
+++ /dev/null
@@ -1,354 +0,0 @@
-#! /usr/bin/env python
-# -*- encoding: utf-8 -*-
-#
-# Copyright (C) 2014 Intel Corporation
-#
-# Permission is hereby granted, free of charge, to any person obtaining a
-# copy of this software and associated documentation files (the "Software"),
-# to deal in the Software without restriction, including without limitation
-# the rights to use, copy, modify, merge, publish, distribute, sublicense,
-# and/or sell copies of the Software, and to permit persons to whom the
-# Software is furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice (including the next
-# paragraph) shall be included in all copies or substantial portions of the
-# Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-# IN THE SOFTWARE.
-#
-# Authors:
-# Jason Ekstrand ([email protected])
-
-import nir_algebraic
-
-# Convenience variables
-a = 'a'
-b = 'b'
-c = 'c'
-d = 'd'
-
-# Written in the form (<search>, <replace>) where <search> is an expression
-# and <replace> is either an expression or a value. An expression is
-# defined as a tuple of the form (<op>, <src0>, <src1>, <src2>, <src3>)
-# where each source is either an expression or a value. A value can be
-# either a numeric constant or a string representing a variable name.
-#
-# Variable names are specified as "[#]name[@type]" where "#" inicates that
-# the given variable will only match constants and the type indicates that
-# the given variable will only match values from ALU instructions with the
-# given output type.
-#
-# For constants, you have to be careful to make sure that it is the right
-# type because python is unaware of the source and destination types of the
-# opcodes.
-
-optimizations = [
- (('fneg', ('fneg', a)), a),
- (('ineg', ('ineg', a)), a),
- (('fabs', ('fabs', a)), ('fabs', a)),
- (('fabs', ('fneg', a)), ('fabs', a)),
- (('iabs', ('iabs', a)), ('iabs', a)),
- (('iabs', ('ineg', a)), ('iabs', a)),
- (('fadd', a, 0.0), a),
- (('iadd', a, 0), a),
- (('usadd_4x8', a, 0), a),
- (('usadd_4x8', a, ~0), ~0),
- (('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),
- (('iadd', ('ineg', a), ('iadd', a, b)), b),
- (('iadd', a, ('iadd', ('ineg', a), b)), b),
- (('fadd', ('fneg', a), ('fadd', a, b)), b),
- (('fadd', a, ('fadd', ('fneg', a), b)), b),
- (('fmul', a, 0.0), 0.0),
- (('imul', a, 0), 0),
- (('umul_unorm_4x8', a, 0), 0),
- (('umul_unorm_4x8', a, ~0), a),
- (('fmul', a, 1.0), a),
- (('imul', a, 1), a),
- (('fmul', a, -1.0), ('fneg', a)),
- (('imul', a, -1), ('ineg', a)),
- (('fdiv', a, b), ('fmul', a, ('frcp', b)), 'options->lower_fdiv'),
- (('ffma', 0.0, a, b), b),
- (('ffma', a, 0.0, b), b),
- (('ffma', a, b, 0.0), ('fmul', a, b)),
- (('ffma', a, 1.0, b), ('fadd', a, b)),
- (('ffma', 1.0, a, b), ('fadd', a, b)),
- (('flrp', a, b, 0.0), a),
- (('flrp', a, b, 1.0), b),
- (('flrp', a, a, b), a),
- (('flrp', 0.0, a, b), ('fmul', a, b)),
- (('flrp', a, b, c), ('fadd', ('fmul', c, ('fsub', b, a)), a), 'options->lower_flrp'),
- (('ffract', a), ('fsub', a, ('ffloor', a)), 'options->lower_ffract'),
- (('fadd', ('fmul', a, ('fadd', 1.0, ('fneg', c))), ('fmul', b, c)), ('flrp', a, b, c), '!options->lower_flrp'),
- (('fadd', a, ('fmul', c, ('fadd', b, ('fneg', a)))), ('flrp', a, b, c), '!options->lower_flrp'),
- (('ffma', a, b, c), ('fadd', ('fmul', a, b), c), 'options->lower_ffma'),
- (('fadd', ('fmul', a, b), c), ('ffma', a, b, c), '!options->lower_ffma'),
- # Comparison simplifications
- (('inot', ('flt', a, b)), ('fge', a, b)),
- (('inot', ('fge', a, b)), ('flt', a, b)),
- (('inot', ('feq', a, b)), ('fne', a, b)),
- (('inot', ('fne', a, b)), ('feq', a, b)),
- (('inot', ('ilt', a, b)), ('ige', a, b)),
- (('inot', ('ige', a, b)), ('ilt', a, b)),
- (('inot', ('ieq', a, b)), ('ine', a, b)),
- (('inot', ('ine', a, b)), ('ieq', a, b)),
- (('fge', ('fneg', ('fabs', a)), 0.0), ('feq', a, 0.0)),
- (('bcsel', ('flt', a, b), a, b), ('fmin', a, b)),
- (('bcsel', ('flt', a, b), b, a), ('fmax', a, b)),
- (('bcsel', ('inot', 'a@bool'), b, c), ('bcsel', a, c, b)),
- (('bcsel', a, ('bcsel', a, b, c), d), ('bcsel', a, b, d)),
- (('fmin', a, a), a),
- (('fmax', a, a), a),
- (('imin', a, a), a),
- (('imax', a, a), a),
- (('umin', a, a), a),
- (('umax', a, a), a),
- (('fmin', ('fmax', a, 0.0), 1.0), ('fsat', a), '!options->lower_fsat'),
- (('fmax', ('fmin', a, 1.0), 0.0), ('fsat', a), '!options->lower_fsat'),
- (('fsat', a), ('fmin', ('fmax', a, 0.0), 1.0), 'options->lower_fsat'),
- (('fsat', ('fsat', a)), ('fsat', a)),
- (('fmin', ('fmax', ('fmin', ('fmax', a, 0.0), 1.0), 0.0), 1.0), ('fmin', ('fmax', a, 0.0), 1.0)),
- (('ior', ('flt', a, b), ('flt', a, c)), ('flt', a, ('fmax', b, c))),
- (('ior', ('flt', a, c), ('flt', b, c)), ('flt', ('fmin', a, b), c)),
- (('ior', ('fge', a, b), ('fge', a, c)), ('fge', a, ('fmin', b, c))),
- (('ior', ('fge', a, c), ('fge', b, c)), ('fge', ('fmax', a, b), c)),
- (('slt', a, b), ('b2f', ('flt', a, b)), 'options->lower_scmp'),
- (('sge', a, b), ('b2f', ('fge', a, b)), 'options->lower_scmp'),
- (('seq', a, b), ('b2f', ('feq', a, b)), 'options->lower_scmp'),
- (('sne', a, b), ('b2f', ('fne', a, b)), 'options->lower_scmp'),
- (('fne', ('fneg', a), a), ('fne', a, 0.0)),
- (('feq', ('fneg', a), a), ('feq', a, 0.0)),
- # Emulating booleans
- (('imul', ('b2i', a), ('b2i', b)), ('b2i', ('iand', a, b))),
- (('fmul', ('b2f', a), ('b2f', b)), ('b2f', ('iand', a, b))),
- (('fsat', ('fadd', ('b2f', a), ('b2f', b))), ('b2f', ('ior', a, b))),
- (('iand', 'a@bool', 1.0), ('b2f', a)),
- (('flt', ('fneg', ('b2f', a)), 0), a), # Generated by TGSI KILL_IF.
- (('flt', ('fsub', 0.0, ('b2f', a)), 0), a), # Generated by TGSI KILL_IF.
- # Comparison with the same args. Note that these are not done for
- # the float versions because NaN always returns false on float
- # inequalities.
- (('ilt', a, a), False),
- (('ige', a, a), True),
- (('ieq', a, a), True),
- (('ine', a, a), False),
- (('ult', a, a), False),
- (('uge', a, a), True),
- # Logical and bit operations
- (('fand', a, 0.0), 0.0),
- (('iand', a, a), a),
- (('iand', a, ~0), a),
- (('iand', a, 0), 0),
- (('ior', a, a), a),
- (('ior', a, 0), a),
- (('fxor', a, a), 0.0),
- (('ixor', a, a), 0),
- (('inot', ('inot', a)), a),
- # DeMorgan's Laws
- (('iand', ('inot', a), ('inot', b)), ('inot', ('ior', a, b))),
- (('ior', ('inot', a), ('inot', b)), ('inot', ('iand', a, b))),
- # Shift optimizations
- (('ishl', 0, a), 0),
- (('ishl', a, 0), a),
- (('ishr', 0, a), 0),
- (('ishr', a, 0), a),
- (('ushr', 0, a), 0),
- (('ushr', a, 0), a),
- # Exponential/logarithmic identities
- (('fexp2', ('flog2', a)), a), # 2^lg2(a) = a
- (('flog2', ('fexp2', a)), a), # lg2(2^a) = a
- (('fpow', a, b), ('fexp2', ('fmul', ('flog2', a), b)), 'options->lower_fpow'), # a^b = 2^(lg2(a)*b)
- (('fexp2', ('fmul', ('flog2', a), b)), ('fpow', a, b), '!options->lower_fpow'), # 2^(lg2(a)*b) = a^b
- (('fpow', a, 1.0), a),
- (('fpow', a, 2.0), ('fmul', a, a)),
- (('fpow', a, 4.0), ('fmul', ('fmul', a, a), ('fmul', a, a))),
- (('fpow', 2.0, a), ('fexp2', a)),
- (('fpow', ('fpow', a, 2.2), 0.454545), a),
- (('fpow', ('fabs', ('fpow', a, 2.2)), 0.454545), ('fabs', a)),
- (('fsqrt', ('fexp2', a)), ('fexp2', ('fmul', 0.5, a))),
- (('frcp', ('fexp2', a)), ('fexp2', ('fneg', a))),
- (('frsq', ('fexp2', a)), ('fexp2', ('fmul', -0.5, a))),
- (('flog2', ('fsqrt', a)), ('fmul', 0.5, ('flog2', a))),
- (('flog2', ('frcp', a)), ('fneg', ('flog2', a))),
- (('flog2', ('frsq', a)), ('fmul', -0.5, ('flog2', a))),
- (('flog2', ('fpow', a, b)), ('fmul', b, ('flog2', a))),
- (('fadd', ('flog2', a), ('flog2', b)), ('flog2', ('fmul', a, b))),
- (('fadd', ('flog2', a), ('fneg', ('flog2', b))), ('flog2', ('fdiv', a, b))),
- (('fmul', ('fexp2', a), ('fexp2', b)), ('fexp2', ('fadd', a, b))),
- # Division and reciprocal
- (('fdiv', 1.0, a), ('frcp', a)),
- (('fdiv', a, b), ('fmul', a, ('frcp', b)), 'options->lower_fdiv'),
- (('frcp', ('frcp', a)), a),
- (('frcp', ('fsqrt', a)), ('frsq', a)),
- (('fsqrt', a), ('frcp', ('frsq', a)), 'options->lower_fsqrt'),
- (('frcp', ('frsq', a)), ('fsqrt', a), '!options->lower_fsqrt'),
- # Boolean simplifications
- (('ieq', 'a@bool', True), a),
- (('ine', 'a@bool', True), ('inot', a)),
- (('ine', 'a@bool', False), a),
- (('ieq', 'a@bool', False), ('inot', 'a')),
- (('bcsel', a, True, False), ('ine', a, 0)),
- (('bcsel', a, False, True), ('ieq', a, 0)),
- (('bcsel', True, b, c), b),
- (('bcsel', False, b, c), c),
- # The result of this should be hit by constant propagation and, in the
- # next round of opt_algebraic, get picked up by one of the above two.
- (('bcsel', '#a', b, c), ('bcsel', ('ine', 'a', 0), b, c)),
-
- (('bcsel', a, b, b), b),
- (('fcsel', a, b, b), b),
-
- # Conversions
- (('i2b', ('b2i', a)), a),
- (('f2i', ('ftrunc', a)), ('f2i', a)),
- (('f2u', ('ftrunc', a)), ('f2u', a)),
-
- # Subtracts
- (('fsub', a, ('fsub', 0.0, b)), ('fadd', a, b)),
- (('isub', a, ('isub', 0, b)), ('iadd', a, b)),
- (('ussub_4x8', a, 0), a),
- (('ussub_4x8', a, ~0), 0),
- (('fsub', a, b), ('fadd', a, ('fneg', b)), 'options->lower_sub'),
- (('isub', a, b), ('iadd', a, ('ineg', b)), 'options->lower_sub'),
- (('fneg', a), ('fsub', 0.0, a), 'options->lower_negate'),
- (('ineg', a), ('isub', 0, a), 'options->lower_negate'),
- (('fadd', a, ('fsub', 0.0, b)), ('fsub', a, b)),
- (('iadd', a, ('isub', 0, b)), ('isub', a, b)),
- (('fabs', ('fsub', 0.0, a)), ('fabs', a)),
- (('iabs', ('isub', 0, a)), ('iabs', a)),
-
- # Misc. lowering
- (('fmod', a, b), ('fsub', a, ('fmul', b, ('ffloor', ('fdiv', a, b)))), 'options->lower_fmod'),
- (('frem', a, b), ('fsub', a, ('fmul', b, ('ftrunc', ('fdiv', a, b)))), 'options->lower_fmod'),
- (('uadd_carry', a, b), ('b2i', ('ult', ('iadd', a, b), a)), 'options->lower_uadd_carry'),
- (('usub_borrow', a, b), ('b2i', ('ult', a, b)), 'options->lower_usub_borrow'),
- (('ldexp', 'x', 'exp'),
- ('fmul', 'x', ('ishl', ('imin', ('imax', ('iadd', 'exp', 0x7f), 0), 0xff), 23))),
-
- (('bitfield_insert', 'base', 'insert', 'offset', 'bits'),
- ('bcsel', ('ilt', 31, 'bits'), 'insert',
- ('bfi', ('bfm', 'bits', 'offset'), 'insert', 'base')),
- 'options->lower_bitfield_insert'),
-
- (('ibitfield_extract', 'value', 'offset', 'bits'),
- ('bcsel', ('ilt', 31, 'bits'), 'value',
- ('ibfe', 'value', 'offset', 'bits')),
- 'options->lower_bitfield_extract'),
-
- (('ubitfield_extract', 'value', 'offset', 'bits'),
- ('bcsel', ('ult', 31, 'bits'), 'value',
- ('ubfe', 'value', 'offset', 'bits')),
- 'options->lower_bitfield_extract'),
-
- (('extract_ibyte', a, b),
- ('ishr', ('ishl', a, ('imul', ('isub', 3, b), 8)), 8),
- 'options->lower_extract_byte'),
-
- (('extract_ubyte', a, b),
- ('iand', ('ushr', a, ('imul', b, 8)), 0xff),
- 'options->lower_extract_byte'),
-
- (('extract_iword', a, b),
- ('ishr', ('ishl', a, ('imul', ('isub', 1, b), 16)), 16),
- 'options->lower_extract_word'),
-
- (('extract_uword', a, b),
- ('iand', ('ushr', a, ('imul', b, 16)), 0xffff),
- 'options->lower_extract_word'),
-
- (('pack_unorm_2x16', 'v'),
- ('pack_uvec2_to_uint',
- ('f2u', ('fround_even', ('fmul', ('fsat', 'v'), 65535.0)))),
- 'options->lower_pack_unorm_2x16'),
-
- (('pack_unorm_4x8', 'v'),
- ('pack_uvec4_to_uint',
- ('f2u', ('fround_even', ('fmul', ('fsat', 'v'), 255.0)))),
- 'options->lower_pack_unorm_4x8'),
-
- (('pack_snorm_2x16', 'v'),
- ('pack_uvec2_to_uint',
- ('f2i', ('fround_even', ('fmul', ('fmin', 1.0, ('fmax', -1.0, 'v')), 32767.0)))),
- 'options->lower_pack_snorm_2x16'),
-
- (('pack_snorm_4x8', 'v'),
- ('pack_uvec4_to_uint',
- ('f2i', ('fround_even', ('fmul', ('fmin', 1.0, ('fmax', -1.0, 'v')), 127.0)))),
- 'options->lower_pack_snorm_4x8'),
-
- (('unpack_unorm_2x16', 'v'),
- ('fdiv', ('u2f', ('vec4', ('extract_uword', 'v', 0),
- ('extract_uword', 'v', 1), 0, 0)),
- 65535.0),
- 'options->lower_unpack_unorm_2x16'),
-
- (('unpack_unorm_4x8', 'v'),
- ('fdiv', ('u2f', ('vec4', ('extract_ubyte', 'v', 0),
- ('extract_ubyte', 'v', 1),
- ('extract_ubyte', 'v', 2),
- ('extract_ubyte', 'v', 3))),
- 255.0),
- 'options->lower_unpack_unorm_4x8'),
-
- (('unpack_snorm_2x16', 'v'),
- ('fmin', 1.0, ('fmax', -1.0, ('fdiv', ('i2f', ('vec4', ('extract_iword', 'v', 0),
- ('extract_iword', 'v', 1), 0, 0)),
- 32767.0))),
- 'options->lower_unpack_snorm_2x16'),
-
- (('unpack_snorm_4x8', 'v'),
- ('fmin', 1.0, ('fmax', -1.0, ('fdiv', ('i2f', ('vec4', ('extract_ibyte', 'v', 0),
- ('extract_ibyte', 'v', 1),
- ('extract_ibyte', 'v', 2),
- ('extract_ibyte', 'v', 3))),
- 127.0))),
- 'options->lower_unpack_snorm_4x8'),
-]
-
-# Add optimizations to handle the case where the result of a ternary is
-# compared to a constant. This way we can take things like
-#
-# (a ? 0 : 1) > 0
-#
-# and turn it into
-#
-# a ? (0 > 0) : (1 > 0)
-#
-# which constant folding will eat for lunch. The resulting ternary will
-# further get cleaned up by the boolean reductions above and we will be
-# left with just the original variable "a".
-for op in ['flt', 'fge', 'feq', 'fne',
- 'ilt', 'ige', 'ieq', 'ine', 'ult', 'uge']:
- optimizations += [
- ((op, ('bcsel', 'a', '#b', '#c'), '#d'),
- ('bcsel', 'a', (op, 'b', 'd'), (op, 'c', 'd'))),
- ((op, '#d', ('bcsel', a, '#b', '#c')),
- ('bcsel', 'a', (op, 'd', 'b'), (op, 'd', 'c'))),
- ]
-
-# This section contains "late" optimizations that should be run after the
-# regular optimizations have finished. Optimizations should go here if
-# they help code generation but do not necessarily produce code that is
-# more easily optimizable.
-late_optimizations = [
- (('flt', ('fadd', a, b), 0.0), ('flt', a, ('fneg', b))),
- (('fge', ('fadd', a, b), 0.0), ('fge', a, ('fneg', b))),
- (('feq', ('fadd', a, b), 0.0), ('feq', a, ('fneg', b))),
- (('fne', ('fadd', a, b), 0.0), ('fne', a, ('fneg', b))),
- (('fdot2', a, b), ('fdot_replicated2', a, b), 'options->fdot_replicates'),
- (('fdot3', a, b), ('fdot_replicated3', a, b), 'options->fdot_replicates'),
- (('fdot4', a, b), ('fdot_replicated4', a, b), 'options->fdot_replicates'),
- (('fdph', a, b), ('fdph_replicated', a, b), 'options->fdot_replicates'),
-]
-
-print nir_algebraic.AlgebraicPass("nir_opt_algebraic", optimizations).render()
-print nir_algebraic.AlgebraicPass("nir_opt_algebraic_late",
- late_optimizations).render()
diff --git a/src/glsl/nir/nir_opt_constant_folding.c b/src/glsl/nir/nir_opt_constant_folding.c
deleted file mode 100644
index 28a73f86f95..00000000000
--- a/src/glsl/nir/nir_opt_constant_folding.c
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- * Copyright © 2014 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- *
- * Authors:
- * Jason Ekstrand ([email protected])
- *
- */
-
-#include "nir_constant_expressions.h"
-#include <math.h>
-
-/*
- * Implements SSA-based constant folding.
- */
-
-struct constant_fold_state {
- void *mem_ctx;
- nir_function_impl *impl;
- bool progress;
-};
-
-static bool
-constant_fold_alu_instr(nir_alu_instr *instr, void *mem_ctx)
-{
- nir_const_value src[4];
-
- if (!instr->dest.dest.is_ssa)
- return false;
-
- for (unsigned i = 0; i < nir_op_infos[instr->op].num_inputs; i++) {
- if (!instr->src[i].src.is_ssa)
- return false;
-
- nir_instr *src_instr = instr->src[i].src.ssa->parent_instr;
-
- if (src_instr->type != nir_instr_type_load_const)
- return false;
- nir_load_const_instr* load_const = nir_instr_as_load_const(src_instr);
-
- for (unsigned j = 0; j < nir_ssa_alu_instr_src_components(instr, i);
- j++) {
- src[i].u[j] = load_const->value.u[instr->src[i].swizzle[j]];
- }
-
- /* We shouldn't have any source modifiers in the optimization loop. */
- assert(!instr->src[i].abs && !instr->src[i].negate);
- }
-
- /* We shouldn't have any saturate modifiers in the optimization loop. */
- assert(!instr->dest.saturate);
-
- nir_const_value dest =
- nir_eval_const_opcode(instr->op, instr->dest.dest.ssa.num_components,
- src);
-
- nir_load_const_instr *new_instr =
- nir_load_const_instr_create(mem_ctx,
- instr->dest.dest.ssa.num_components);
-
- new_instr->value = dest;
-
- nir_instr_insert_before(&instr->instr, &new_instr->instr);
-
- nir_ssa_def_rewrite_uses(&instr->dest.dest.ssa,
- nir_src_for_ssa(&new_instr->def));
-
- nir_instr_remove(&instr->instr);
- ralloc_free(instr);
-
- return true;
-}
-
-static bool
-constant_fold_deref(nir_instr *instr, nir_deref_var *deref)
-{
- bool progress = false;
-
- for (nir_deref *tail = deref->deref.child; tail; tail = tail->child) {
- if (tail->deref_type != nir_deref_type_array)
- continue;
-
- nir_deref_array *arr = nir_deref_as_array(tail);
-
- if (arr->deref_array_type == nir_deref_array_type_indirect &&
- arr->indirect.is_ssa &&
- arr->indirect.ssa->parent_instr->type == nir_instr_type_load_const) {
- nir_load_const_instr *indirect =
- nir_instr_as_load_const(arr->indirect.ssa->parent_instr);
-
- arr->base_offset += indirect->value.u[0];
-
- /* Clear out the source */
- nir_instr_rewrite_src(instr, &arr->indirect, nir_src_for_ssa(NULL));
-
- arr->deref_array_type = nir_deref_array_type_direct;
-
- progress = true;
- }
- }
-
- return progress;
-}
-
-static bool
-constant_fold_intrinsic_instr(nir_intrinsic_instr *instr)
-{
- bool progress = false;
-
- unsigned num_vars = nir_intrinsic_infos[instr->intrinsic].num_variables;
- for (unsigned i = 0; i < num_vars; i++) {
- progress |= constant_fold_deref(&instr->instr, instr->variables[i]);
- }
-
- return progress;
-}
-
-static bool
-constant_fold_tex_instr(nir_tex_instr *instr)
-{
- if (instr->sampler)
- return constant_fold_deref(&instr->instr, instr->sampler);
- else
- return false;
-}
-
-static bool
-constant_fold_block(nir_block *block, void *void_state)
-{
- struct constant_fold_state *state = void_state;
-
- nir_foreach_instr_safe(block, instr) {
- switch (instr->type) {
- case nir_instr_type_alu:
- state->progress |= constant_fold_alu_instr(nir_instr_as_alu(instr),
- state->mem_ctx);
- break;
- case nir_instr_type_intrinsic:
- state->progress |=
- constant_fold_intrinsic_instr(nir_instr_as_intrinsic(instr));
- break;
- case nir_instr_type_tex:
- state->progress |= constant_fold_tex_instr(nir_instr_as_tex(instr));
- break;
- default:
- /* Don't know how to constant fold */
- break;
- }
- }
-
- return true;
-}
-
-static bool
-nir_opt_constant_folding_impl(nir_function_impl *impl)
-{
- struct constant_fold_state state;
-
- state.mem_ctx = ralloc_parent(impl);
- state.impl = impl;
- state.progress = false;
-
- nir_foreach_block(impl, constant_fold_block, &state);
-
- if (state.progress)
- nir_metadata_preserve(impl, nir_metadata_block_index |
- nir_metadata_dominance);
-
- return state.progress;
-}
-
-bool
-nir_opt_constant_folding(nir_shader *shader)
-{
- bool progress = false;
-
- nir_foreach_function(shader, function) {
- if (function->impl)
- progress |= nir_opt_constant_folding_impl(function->impl);
- }
-
- return progress;
-}
diff --git a/src/glsl/nir/nir_opt_copy_propagate.c b/src/glsl/nir/nir_opt_copy_propagate.c
deleted file mode 100644
index d99f78ddb36..00000000000
--- a/src/glsl/nir/nir_opt_copy_propagate.c
+++ /dev/null
@@ -1,290 +0,0 @@
-/*
- * Copyright © 2014 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- *
- * Authors:
- * Connor Abbott ([email protected])
- *
- */
-
-#include "nir.h"
-#include <main/imports.h>
-
-/**
- * SSA-based copy propagation
- */
-
-static bool is_move(nir_alu_instr *instr)
-{
- if (instr->op != nir_op_fmov &&
- instr->op != nir_op_imov)
- return false;
-
- if (instr->dest.saturate)
- return false;
-
- /* we handle modifiers in a separate pass */
-
- if (instr->src[0].abs || instr->src[0].negate)
- return false;
-
- if (!instr->src[0].src.is_ssa)
- return false;
-
- return true;
-
-}
-
-static bool is_vec(nir_alu_instr *instr)
-{
- for (unsigned i = 0; i < nir_op_infos[instr->op].num_inputs; i++) {
- if (!instr->src[i].src.is_ssa)
- return false;
-
- /* we handle modifiers in a separate pass */
- if (instr->src[i].abs || instr->src[i].negate)
- return false;
- }
-
- return instr->op == nir_op_vec2 ||
- instr->op == nir_op_vec3 ||
- instr->op == nir_op_vec4;
-}
-
-static bool
-is_swizzleless_move(nir_alu_instr *instr)
-{
- if (is_move(instr)) {
- for (unsigned i = 0; i < 4; i++) {
- if (!((instr->dest.write_mask >> i) & 1))
- break;
- if (instr->src[0].swizzle[i] != i)
- return false;
- }
- return true;
- } else if (is_vec(instr)) {
- nir_ssa_def *def = NULL;
- for (unsigned i = 0; i < nir_op_infos[instr->op].num_inputs; i++) {
- if (instr->src[i].swizzle[0] != i)
- return false;
-
- if (def == NULL) {
- def = instr->src[i].src.ssa;
- } else if (instr->src[i].src.ssa != def) {
- return false;
- }
- }
- return true;
- } else {
- return false;
- }
-}
-
-static bool
-copy_prop_src(nir_src *src, nir_instr *parent_instr, nir_if *parent_if)
-{
- if (!src->is_ssa) {
- if (src->reg.indirect)
- return copy_prop_src(src, parent_instr, parent_if);
- return false;
- }
-
- nir_instr *src_instr = src->ssa->parent_instr;
- if (src_instr->type != nir_instr_type_alu)
- return false;
-
- nir_alu_instr *alu_instr = nir_instr_as_alu(src_instr);
- if (!is_swizzleless_move(alu_instr))
- return false;
-
- /* Don't let copy propagation land us with a phi that has more
- * components in its source than it has in its destination. That badly
- * messes up out-of-ssa.
- */
- if (parent_instr && parent_instr->type == nir_instr_type_phi) {
- nir_phi_instr *phi = nir_instr_as_phi(parent_instr);
- assert(phi->dest.is_ssa);
- if (phi->dest.ssa.num_components !=
- alu_instr->src[0].src.ssa->num_components)
- return false;
- }
-
- if (parent_instr) {
- nir_instr_rewrite_src(parent_instr, src,
- nir_src_for_ssa(alu_instr->src[0].src.ssa));
- } else {
- assert(src == &parent_if->condition);
- nir_if_rewrite_condition(parent_if,
- nir_src_for_ssa(alu_instr->src[0].src.ssa));
- }
-
- return true;
-}
-
-static bool
-copy_prop_alu_src(nir_alu_instr *parent_alu_instr, unsigned index)
-{
- nir_alu_src *src = &parent_alu_instr->src[index];
- if (!src->src.is_ssa) {
- if (src->src.reg.indirect)
- return copy_prop_src(src->src.reg.indirect, &parent_alu_instr->instr,
- NULL);
- return false;
- }
-
- nir_instr *src_instr = src->src.ssa->parent_instr;
- if (src_instr->type != nir_instr_type_alu)
- return false;
-
- nir_alu_instr *alu_instr = nir_instr_as_alu(src_instr);
- if (!is_move(alu_instr) && !is_vec(alu_instr))
- return false;
-
- nir_ssa_def *def;
- unsigned new_swizzle[4] = {0, 0, 0, 0};
-
- if (alu_instr->op == nir_op_fmov ||
- alu_instr->op == nir_op_imov) {
- for (unsigned i = 0; i < 4; i++)
- new_swizzle[i] = alu_instr->src[0].swizzle[src->swizzle[i]];
- def = alu_instr->src[0].src.ssa;
- } else {
- def = NULL;
-
- for (unsigned i = 0; i < 4; i++) {
- if (!nir_alu_instr_channel_used(parent_alu_instr, index, i))
- continue;
-
- nir_ssa_def *new_def = alu_instr->src[src->swizzle[i]].src.ssa;
- if (def == NULL)
- def = new_def;
- else {
- if (def != new_def)
- return false;
- }
- new_swizzle[i] = alu_instr->src[src->swizzle[i]].swizzle[0];
- }
- }
-
- for (unsigned i = 0; i < 4; i++)
- src->swizzle[i] = new_swizzle[i];
-
- nir_instr_rewrite_src(&parent_alu_instr->instr, &src->src,
- nir_src_for_ssa(def));
-
- return true;
-}
-
-typedef struct {
- nir_instr *parent_instr;
- bool progress;
-} copy_prop_state;
-
-static bool
-copy_prop_src_cb(nir_src *src, void *_state)
-{
- copy_prop_state *state = (copy_prop_state *) _state;
- while (copy_prop_src(src, state->parent_instr, NULL))
- state->progress = true;
-
- return true;
-}
-
-static bool
-copy_prop_instr(nir_instr *instr)
-{
- if (instr->type == nir_instr_type_alu) {
- nir_alu_instr *alu_instr = nir_instr_as_alu(instr);
- bool progress = false;
-
- for (unsigned i = 0; i < nir_op_infos[alu_instr->op].num_inputs; i++)
- while (copy_prop_alu_src(alu_instr, i))
- progress = true;
-
- if (!alu_instr->dest.dest.is_ssa && alu_instr->dest.dest.reg.indirect)
- while (copy_prop_src(alu_instr->dest.dest.reg.indirect, instr, NULL))
- progress = true;
-
- return progress;
- }
-
- copy_prop_state state;
- state.parent_instr = instr;
- state.progress = false;
- nir_foreach_src(instr, copy_prop_src_cb, &state);
-
- return state.progress;
-}
-
-static bool
-copy_prop_if(nir_if *if_stmt)
-{
- return copy_prop_src(&if_stmt->condition, NULL, if_stmt);
-}
-
-static bool
-copy_prop_block(nir_block *block, void *_state)
-{
- bool *progress = (bool *) _state;
-
- nir_foreach_instr(block, instr) {
- if (copy_prop_instr(instr))
- *progress = true;
- }
-
- if (block->cf_node.node.next != NULL && /* check that we aren't the end node */
- !nir_cf_node_is_last(&block->cf_node) &&
- nir_cf_node_next(&block->cf_node)->type == nir_cf_node_if) {
- nir_if *if_stmt = nir_cf_node_as_if(nir_cf_node_next(&block->cf_node));
- if (copy_prop_if(if_stmt))
- *progress = true;
- }
-
- return true;
-}
-
-static bool
-nir_copy_prop_impl(nir_function_impl *impl)
-{
- bool progress = false;
-
- nir_foreach_block(impl, copy_prop_block, &progress);
-
- if (progress) {
- nir_metadata_preserve(impl, nir_metadata_block_index |
- nir_metadata_dominance);
- }
-
- return progress;
-}
-
-bool
-nir_copy_prop(nir_shader *shader)
-{
- bool progress = false;
-
- nir_foreach_function(shader, function) {
- if (function->impl && nir_copy_prop_impl(function->impl))
- progress = true;
- }
-
- return progress;
-}
diff --git a/src/glsl/nir/nir_opt_cse.c b/src/glsl/nir/nir_opt_cse.c
deleted file mode 100644
index 364fb023dce..00000000000
--- a/src/glsl/nir/nir_opt_cse.c
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright © 2014 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- *
- * Authors:
- * Jason Ekstrand ([email protected])
- * Connor Abbott ([email protected])
- *
- */
-
-#include "nir_instr_set.h"
-
-/*
- * Implements common subexpression elimination
- */
-
-/*
- * Visits and CSE's the given block and all its descendants in the dominance
- * tree recursively. Note that the instr_set is guaranteed to only ever
- * contain instructions that dominate the current block.
- */
-
-static bool
-cse_block(nir_block *block, struct set *instr_set)
-{
- bool progress = false;
-
- nir_foreach_instr_safe(block, instr) {
- if (nir_instr_set_add_or_rewrite(instr_set, instr)) {
- progress = true;
- nir_instr_remove(instr);
- }
- }
-
- for (unsigned i = 0; i < block->num_dom_children; i++) {
- nir_block *child = block->dom_children[i];
- progress |= cse_block(child, instr_set);
- }
-
- nir_foreach_instr(block, instr)
- nir_instr_set_remove(instr_set, instr);
-
- return progress;
-}
-
-static bool
-nir_opt_cse_impl(nir_function_impl *impl)
-{
- struct set *instr_set = nir_instr_set_create(NULL);
-
- nir_metadata_require(impl, nir_metadata_dominance);
-
- bool progress = cse_block(nir_start_block(impl), instr_set);
-
- if (progress)
- nir_metadata_preserve(impl, nir_metadata_block_index |
- nir_metadata_dominance);
-
- nir_instr_set_destroy(instr_set);
- return progress;
-}
-
-bool
-nir_opt_cse(nir_shader *shader)
-{
- bool progress = false;
-
- nir_foreach_function(shader, function) {
- if (function->impl)
- progress |= nir_opt_cse_impl(function->impl);
- }
-
- return progress;
-}
-
diff --git a/src/glsl/nir/nir_opt_dce.c b/src/glsl/nir/nir_opt_dce.c
deleted file mode 100644
index 32436c18b60..00000000000
--- a/src/glsl/nir/nir_opt_dce.c
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * Copyright © 2014 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- *
- * Authors:
- * Connor Abbott ([email protected])
- *
- */
-
-#include "nir.h"
-
-/* SSA-based mark-and-sweep dead code elimination */
-
-typedef struct {
- struct exec_node node;
- nir_instr *instr;
-} worklist_elem;
-
-static void
-worklist_push(struct exec_list *worklist, nir_instr *instr)
-{
- worklist_elem *elem = ralloc(worklist, worklist_elem);
- elem->instr = instr;
- instr->pass_flags = 1;
- exec_list_push_tail(worklist, &elem->node);
-}
-
-static nir_instr *
-worklist_pop(struct exec_list *worklist)
-{
- struct exec_node *node = exec_list_pop_head(worklist);
- worklist_elem *elem = exec_node_data(worklist_elem, node, node);
- return elem->instr;
-}
-
-static bool
-mark_live_cb(nir_src *src, void *_state)
-{
- struct exec_list *worklist = (struct exec_list *) _state;
-
- if (src->is_ssa && !src->ssa->parent_instr->pass_flags) {
- worklist_push(worklist, src->ssa->parent_instr);
- }
-
- return true;
-}
-
-static void
-init_instr(nir_instr *instr, struct exec_list *worklist)
-{
- nir_alu_instr *alu_instr;
- nir_intrinsic_instr *intrin_instr;
- nir_tex_instr *tex_instr;
-
- /* We use the pass_flags to store the live/dead information. In DCE, we
- * just treat it as a zero/non-zerl boolean for whether or not the
- * instruction is live.
- */
- instr->pass_flags = 0;
-
- switch (instr->type) {
- case nir_instr_type_call:
- case nir_instr_type_jump:
- worklist_push(worklist, instr);
- break;
-
- case nir_instr_type_alu:
- alu_instr = nir_instr_as_alu(instr);
- if (!alu_instr->dest.dest.is_ssa)
- worklist_push(worklist, instr);
- break;
-
- case nir_instr_type_intrinsic:
- intrin_instr = nir_instr_as_intrinsic(instr);
- if (nir_intrinsic_infos[intrin_instr->intrinsic].flags &
- NIR_INTRINSIC_CAN_ELIMINATE) {
- if (nir_intrinsic_infos[intrin_instr->intrinsic].has_dest &&
- !intrin_instr->dest.is_ssa) {
- worklist_push(worklist, instr);
- }
- } else {
- worklist_push(worklist, instr);
- }
- break;
-
- case nir_instr_type_tex:
- tex_instr = nir_instr_as_tex(instr);
- if (!tex_instr->dest.is_ssa)
- worklist_push(worklist, instr);
- break;
-
- default:
- break;
- }
-}
-
-static bool
-init_block_cb(nir_block *block, void *_state)
-{
- struct exec_list *worklist = (struct exec_list *) _state;
-
- nir_foreach_instr(block, instr)
- init_instr(instr, worklist);
-
- nir_if *following_if = nir_block_get_following_if(block);
- if (following_if) {
- if (following_if->condition.is_ssa &&
- !following_if->condition.ssa->parent_instr->pass_flags)
- worklist_push(worklist, following_if->condition.ssa->parent_instr);
- }
-
- return true;
-}
-
-static bool
-delete_block_cb(nir_block *block, void *_state)
-{
- bool *progress = (bool *) _state;
-
- nir_foreach_instr_safe(block, instr) {
- if (!instr->pass_flags) {
- nir_instr_remove(instr);
- *progress = true;
- }
- }
-
- return true;
-}
-
-static bool
-nir_opt_dce_impl(nir_function_impl *impl)
-{
- struct exec_list *worklist = ralloc(NULL, struct exec_list);
- exec_list_make_empty(worklist);
-
- nir_foreach_block(impl, init_block_cb, worklist);
-
- while (!exec_list_is_empty(worklist)) {
- nir_instr *instr = worklist_pop(worklist);
- nir_foreach_src(instr, mark_live_cb, worklist);
- }
-
- ralloc_free(worklist);
-
- bool progress = false;
- nir_foreach_block(impl, delete_block_cb, &progress);
-
- if (progress)
- nir_metadata_preserve(impl, nir_metadata_block_index |
- nir_metadata_dominance);
-
- return progress;
-}
-
-bool
-nir_opt_dce(nir_shader *shader)
-{
- bool progress = false;
- nir_foreach_function(shader, function) {
- if (function->impl && nir_opt_dce_impl(function->impl))
- progress = true;
- }
-
- return progress;
-}
diff --git a/src/glsl/nir/nir_opt_dead_cf.c b/src/glsl/nir/nir_opt_dead_cf.c
deleted file mode 100644
index 4cc6798702b..00000000000
--- a/src/glsl/nir/nir_opt_dead_cf.c
+++ /dev/null
@@ -1,358 +0,0 @@
-/*
- * Copyright © 2014 Connor Abbott
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- *
- * Authors:
- * Connor Abbott ([email protected])
- *
- */
-
-#include "nir.h"
-#include "nir_control_flow.h"
-
-/*
- * This file implements an optimization that deletes statically
- * unreachable/dead code. In NIR, one way this can happen if if an if
- * statement has a constant condition:
- *
- * if (true) {
- * ...
- * }
- *
- * We delete the if statement and paste the contents of the always-executed
- * branch into the surrounding control flow, possibly removing more code if
- * the branch had a jump at the end.
- *
- * Another way is that control flow can end in a jump so that code after it
- * never gets executed. In particular, this can happen after optimizing
- * something like:
- *
- * if (true) {
- * ...
- * break;
- * }
- * ...
- *
- * We also consider the case where both branches of an if end in a jump, e.g.:
- *
- * if (...) {
- * break;
- * } else {
- * continue;
- * }
- * ...
- *
- * Finally, we also handle removing useless loops, i.e. loops with no side
- * effects and without any definitions that are used elsewhere. This case is a
- * little different from the first two in that the code is actually run (it
- * just never does anything), but there are similar issues with needing to
- * be careful with restarting after deleting the cf_node (see dead_cf_list())
- * so this is a convenient place to remove them.
- */
-
-static void
-remove_after_cf_node(nir_cf_node *node)
-{
- nir_cf_node *end = node;
- while (!nir_cf_node_is_last(end))
- end = nir_cf_node_next(end);
-
- nir_cf_list list;
- nir_cf_extract(&list, nir_after_cf_node(node), nir_after_cf_node(end));
- nir_cf_delete(&list);
-}
-
-static void
-opt_constant_if(nir_if *if_stmt, bool condition)
-{
- /* First, we need to remove any phi nodes after the if by rewriting uses to
- * point to the correct source.
- */
- nir_block *after = nir_cf_node_as_block(nir_cf_node_next(&if_stmt->cf_node));
- nir_block *last_block =
- nir_cf_node_as_block(condition ? nir_if_last_then_node(if_stmt)
- : nir_if_last_else_node(if_stmt));
-
- nir_foreach_instr_safe(after, instr) {
- if (instr->type != nir_instr_type_phi)
- break;
-
- nir_phi_instr *phi = nir_instr_as_phi(instr);
- nir_ssa_def *def = NULL;
- nir_foreach_phi_src(phi, phi_src) {
- if (phi_src->pred != last_block)
- continue;
-
- assert(phi_src->src.is_ssa);
- def = phi_src->src.ssa;
- }
-
- assert(def);
- assert(phi->dest.is_ssa);
- nir_ssa_def_rewrite_uses(&phi->dest.ssa, nir_src_for_ssa(def));
- nir_instr_remove(instr);
- }
-
- /* The control flow list we're about to paste in may include a jump at the
- * end, and in that case we have to delete the rest of the control flow
- * list after the if since it's unreachable and the validator will balk if
- * we don't.
- */
-
- if (!exec_list_is_empty(&last_block->instr_list)) {
- nir_instr *last_instr = nir_block_last_instr(last_block);
- if (last_instr->type == nir_instr_type_jump)
- remove_after_cf_node(&if_stmt->cf_node);
- }
-
- /* Finally, actually paste in the then or else branch and delete the if. */
- struct exec_list *cf_list = condition ? &if_stmt->then_list
- : &if_stmt->else_list;
-
- nir_cf_list list;
- nir_cf_extract(&list, nir_before_cf_list(cf_list),
- nir_after_cf_list(cf_list));
- nir_cf_reinsert(&list, nir_after_cf_node(&if_stmt->cf_node));
- nir_cf_node_remove(&if_stmt->cf_node);
-}
-
-static bool
-block_has_no_side_effects(nir_block *block, void *state)
-{
- (void) state;
-
- nir_foreach_instr(block, instr) {
- if (instr->type == nir_instr_type_call)
- return false;
-
- /* Return instructions can cause us to skip over other side-effecting
- * instructions after the loop, so consider them to have side effects
- * here.
- */
-
- if (instr->type == nir_instr_type_jump &&
- nir_instr_as_jump(instr)->type == nir_jump_return)
- return false;
-
- if (instr->type != nir_instr_type_intrinsic)
- continue;
-
- nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
- if (!nir_intrinsic_infos[intrin->intrinsic].flags &
- NIR_INTRINSIC_CAN_ELIMINATE)
- return false;
- }
-
- return true;
-}
-
-static bool
-def_not_live_out(nir_ssa_def *def, void *state)
-{
- nir_block *after = state;
-
- return !BITSET_TEST(after->live_in, def->live_index);
-}
-
-/*
- * Test if a loop is dead. A loop is dead if:
- *
- * 1) It has no side effects (i.e. intrinsics which could possibly affect the
- * state of the program aside from producing an SSA value, indicated by a lack
- * of NIR_INTRINSIC_CAN_ELIMINATE).
- *
- * 2) It has no phi nodes after it, since those indicate values inside the
- * loop being used after the loop.
- *
- * 3) If there are no phi nodes after the loop, then the only way a value
- * defined inside the loop can be used outside the loop is if its definition
- * dominates the block after the loop. If none of the definitions that
- * dominate the loop exit are used outside the loop, then the loop is dead
- * and it can be deleted.
- */
-
-static bool
-loop_is_dead(nir_loop *loop)
-{
- nir_block *before = nir_cf_node_as_block(nir_cf_node_prev(&loop->cf_node));
- nir_block *after = nir_cf_node_as_block(nir_cf_node_next(&loop->cf_node));
-
- if (!exec_list_is_empty(&after->instr_list) &&
- nir_block_first_instr(after)->type == nir_instr_type_phi)
- return false;
-
- if (!nir_foreach_block_in_cf_node(&loop->cf_node, block_has_no_side_effects,
- NULL))
- return false;
-
- nir_function_impl *impl = nir_cf_node_get_function(&loop->cf_node);
- nir_metadata_require(impl, nir_metadata_live_ssa_defs |
- nir_metadata_dominance);
-
- for (nir_block *cur = after->imm_dom; cur != before; cur = cur->imm_dom) {
- nir_foreach_instr(cur, instr) {
- if (!nir_foreach_ssa_def(instr, def_not_live_out, after))
- return false;
- }
- }
-
- return true;
-}
-
-static bool
-dead_cf_block(nir_block *block)
-{
- nir_if *following_if = nir_block_get_following_if(block);
- if (following_if) {
- nir_const_value *const_value =
- nir_src_as_const_value(following_if->condition);
-
- if (!const_value)
- return false;
-
- opt_constant_if(following_if, const_value->u[0] != 0);
- return true;
- }
-
- nir_loop *following_loop = nir_block_get_following_loop(block);
- if (!following_loop)
- return false;
-
- if (!loop_is_dead(following_loop))
- return false;
-
- nir_cf_node_remove(&following_loop->cf_node);
- return true;
-}
-
-static bool
-ends_in_jump(nir_block *block)
-{
- if (exec_list_is_empty(&block->instr_list))
- return false;
-
- nir_instr *instr = nir_block_last_instr(block);
- return instr->type == nir_instr_type_jump;
-}
-
-static bool
-dead_cf_list(struct exec_list *list, bool *list_ends_in_jump)
-{
- bool progress = false;
- *list_ends_in_jump = false;
-
- nir_cf_node *prev = NULL;
-
- foreach_list_typed(nir_cf_node, cur, node, list) {
- switch (cur->type) {
- case nir_cf_node_block: {
- nir_block *block = nir_cf_node_as_block(cur);
- if (dead_cf_block(block)) {
- /* We just deleted the if or loop after this block, so we may have
- * deleted the block before or after it -- which one is an
- * implementation detail. Therefore, to recover the place we were
- * at, we have to use the previous cf_node.
- */
-
- if (prev) {
- cur = nir_cf_node_next(prev);
- } else {
- cur = exec_node_data(nir_cf_node, exec_list_get_head(list),
- node);
- }
-
- block = nir_cf_node_as_block(cur);
-
- progress = true;
- }
-
- if (ends_in_jump(block)) {
- *list_ends_in_jump = true;
-
- if (!exec_node_is_tail_sentinel(cur->node.next)) {
- remove_after_cf_node(cur);
- return true;
- }
- }
-
- break;
- }
-
- case nir_cf_node_if: {
- nir_if *if_stmt = nir_cf_node_as_if(cur);
- bool then_ends_in_jump, else_ends_in_jump;
- progress |= dead_cf_list(&if_stmt->then_list, &then_ends_in_jump);
- progress |= dead_cf_list(&if_stmt->else_list, &else_ends_in_jump);
-
- if (then_ends_in_jump && else_ends_in_jump) {
- *list_ends_in_jump = true;
- nir_block *next = nir_cf_node_as_block(nir_cf_node_next(cur));
- if (!exec_list_is_empty(&next->instr_list) ||
- !exec_node_is_tail_sentinel(next->cf_node.node.next)) {
- remove_after_cf_node(cur);
- return true;
- }
- }
-
- break;
- }
-
- case nir_cf_node_loop: {
- nir_loop *loop = nir_cf_node_as_loop(cur);
- bool dummy;
- progress |= dead_cf_list(&loop->body, &dummy);
-
- break;
- }
-
- default:
- unreachable("unknown cf node type");
- }
-
- prev = cur;
- }
-
- return progress;
-}
-
-static bool
-opt_dead_cf_impl(nir_function_impl *impl)
-{
- bool dummy;
- bool progress = dead_cf_list(&impl->body, &dummy);
-
- if (progress)
- nir_metadata_preserve(impl, nir_metadata_none);
-
- return progress;
-}
-
-bool
-nir_opt_dead_cf(nir_shader *shader)
-{
- bool progress = false;
-
- nir_foreach_function(shader, function)
- if (function->impl)
- progress |= opt_dead_cf_impl(function->impl);
-
- return progress;
-}
diff --git a/src/glsl/nir/nir_opt_gcm.c b/src/glsl/nir/nir_opt_gcm.c
deleted file mode 100644
index a8779ce5b84..00000000000
--- a/src/glsl/nir/nir_opt_gcm.c
+++ /dev/null
@@ -1,494 +0,0 @@
-/*
- * Copyright © 2014 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- *
- * Authors:
- * Jason Ekstrand ([email protected])
- *
- */
-
-#include "nir.h"
-
-/*
- * Implements Global Code Motion. A description of GCM can be found in
- * "Global Code Motion; Global Value Numbering" by Cliff Click.
- * Unfortunately, the algorithm presented in the paper is broken in a
- * number of ways. The algorithm used here differs substantially from the
- * one in the paper but it is, in my opinion, much easier to read and
- * verify correcness.
- */
-
-struct gcm_block_info {
- /* Number of loops this block is inside */
- unsigned loop_depth;
-
- /* The last instruction inserted into this block. This is used as we
- * traverse the instructions and insert them back into the program to
- * put them in the right order.
- */
- nir_instr *last_instr;
-};
-
-/* Flags used in the instr->pass_flags field for various instruction states */
-enum {
- GCM_INSTR_PINNED = (1 << 0),
- GCM_INSTR_SCHEDULED_EARLY = (1 << 1),
- GCM_INSTR_SCHEDULED_LATE = (1 << 2),
- GCM_INSTR_PLACED = (1 << 3),
-};
-
-struct gcm_state {
- nir_function_impl *impl;
- nir_instr *instr;
-
- /* The list of non-pinned instructions. As we do the late scheduling,
- * we pull non-pinned instructions out of their blocks and place them in
- * this list. This saves us from having linked-list problems when we go
- * to put instructions back in their blocks.
- */
- struct exec_list instrs;
-
- struct gcm_block_info *blocks;
-};
-
-/* Recursively walks the CFG and builds the block_info structure */
-static void
-gcm_build_block_info(struct exec_list *cf_list, struct gcm_state *state,
- unsigned loop_depth)
-{
- foreach_list_typed(nir_cf_node, node, node, cf_list) {
- switch (node->type) {
- case nir_cf_node_block: {
- nir_block *block = nir_cf_node_as_block(node);
- state->blocks[block->index].loop_depth = loop_depth;
- break;
- }
- case nir_cf_node_if: {
- nir_if *if_stmt = nir_cf_node_as_if(node);
- gcm_build_block_info(&if_stmt->then_list, state, loop_depth);
- gcm_build_block_info(&if_stmt->else_list, state, loop_depth);
- break;
- }
- case nir_cf_node_loop: {
- nir_loop *loop = nir_cf_node_as_loop(node);
- gcm_build_block_info(&loop->body, state, loop_depth + 1);
- break;
- }
- default:
- unreachable("Invalid CF node type");
- }
- }
-}
-
-/* Walks the instruction list and marks immovable instructions as pinned
- *
- * This function also serves to initialize the instr->pass_flags field.
- * After this is completed, all instructions' pass_flags fields will be set
- * to either GCM_INSTR_PINNED or 0.
- */
-static bool
-gcm_pin_instructions_block(nir_block *block, void *void_state)
-{
- struct gcm_state *state = void_state;
-
- nir_foreach_instr_safe(block, instr) {
- switch (instr->type) {
- case nir_instr_type_alu:
- switch (nir_instr_as_alu(instr)->op) {
- case nir_op_fddx:
- case nir_op_fddy:
- case nir_op_fddx_fine:
- case nir_op_fddy_fine:
- case nir_op_fddx_coarse:
- case nir_op_fddy_coarse:
- /* These can only go in uniform control flow; pin them for now */
- instr->pass_flags = GCM_INSTR_PINNED;
- break;
-
- default:
- instr->pass_flags = 0;
- break;
- }
- break;
-
- case nir_instr_type_tex:
- switch (nir_instr_as_tex(instr)->op) {
- case nir_texop_tex:
- case nir_texop_txb:
- case nir_texop_lod:
- /* These two take implicit derivatives so they need to be pinned */
- instr->pass_flags = GCM_INSTR_PINNED;
- break;
-
- default:
- instr->pass_flags = 0;
- break;
- }
- break;
-
- case nir_instr_type_load_const:
- instr->pass_flags = 0;
- break;
-
- case nir_instr_type_intrinsic: {
- const nir_intrinsic_info *info =
- &nir_intrinsic_infos[nir_instr_as_intrinsic(instr)->intrinsic];
-
- if ((info->flags & NIR_INTRINSIC_CAN_ELIMINATE) &&
- (info->flags & NIR_INTRINSIC_CAN_REORDER)) {
- instr->pass_flags = 0;
- } else {
- instr->pass_flags = GCM_INSTR_PINNED;
- }
- break;
- }
-
- case nir_instr_type_jump:
- case nir_instr_type_ssa_undef:
- case nir_instr_type_phi:
- instr->pass_flags = GCM_INSTR_PINNED;
- break;
-
- default:
- unreachable("Invalid instruction type in GCM");
- }
-
- if (!(instr->pass_flags & GCM_INSTR_PINNED)) {
- /* If this is an unpinned instruction, go ahead and pull it out of
- * the program and put it on the instrs list. This has a couple
- * of benifits. First, it makes the scheduling algorithm more
- * efficient because we can avoid walking over basic blocks and
- * pinned instructions. Second, it keeps us from causing linked
- * list confusion when we're trying to put everything in its
- * proper place at the end of the pass.
- *
- * Note that we don't use nir_instr_remove here because that also
- * cleans up uses and defs and we want to keep that information.
- */
- exec_node_remove(&instr->node);
- exec_list_push_tail(&state->instrs, &instr->node);
- }
- }
-
- return true;
-}
-
-static void
-gcm_schedule_early_instr(nir_instr *instr, struct gcm_state *state);
-
-/** Update an instructions schedule for the given source
- *
- * This function is called iteratively as we walk the sources of an
- * instruction. It ensures that the given source instruction has been
- * scheduled and then update this instruction's block if the source
- * instruction is lower down the tree.
- */
-static bool
-gcm_schedule_early_src(nir_src *src, void *void_state)
-{
- struct gcm_state *state = void_state;
- nir_instr *instr = state->instr;
-
- assert(src->is_ssa);
-
- gcm_schedule_early_instr(src->ssa->parent_instr, void_state);
-
- /* While the index isn't a proper dominance depth, it does have the
- * property that if A dominates B then A->index <= B->index. Since we
- * know that this instruction must have been dominated by all of its
- * sources at some point (even if it's gone through value-numbering),
- * all of the sources must lie on the same branch of the dominance tree.
- * Therefore, we can just go ahead and just compare indices.
- */
- if (instr->block->index < src->ssa->parent_instr->block->index)
- instr->block = src->ssa->parent_instr->block;
-
- /* We need to restore the state instruction because it may have been
- * changed through the gcm_schedule_early_instr call above. Since we
- * may still be iterating through sources and future calls to
- * gcm_schedule_early_src for the same instruction will still need it.
- */
- state->instr = instr;
-
- return true;
-}
-
-/** Schedules an instruction early
- *
- * This function performs a recursive depth-first search starting at the
- * given instruction and proceeding through the sources to schedule
- * instructions as early as they can possibly go in the dominance tree.
- * The instructions are "scheduled" by updating their instr->block field.
- */
-static void
-gcm_schedule_early_instr(nir_instr *instr, struct gcm_state *state)
-{
- if (instr->pass_flags & GCM_INSTR_SCHEDULED_EARLY)
- return;
-
- instr->pass_flags |= GCM_INSTR_SCHEDULED_EARLY;
-
- /* Pinned instructions are already scheduled so we don't need to do
- * anything. Also, bailing here keeps us from ever following the
- * sources of phi nodes which can be back-edges.
- */
- if (instr->pass_flags & GCM_INSTR_PINNED)
- return;
-
- /* Start with the instruction at the top. As we iterate over the
- * sources, it will get moved down as needed.
- */
- instr->block = nir_start_block(state->impl);
- state->instr = instr;
-
- nir_foreach_src(instr, gcm_schedule_early_src, state);
-}
-
-static void
-gcm_schedule_late_instr(nir_instr *instr, struct gcm_state *state);
-
-/** Schedules the instruction associated with the given SSA def late
- *
- * This function works by first walking all of the uses of the given SSA
- * definition, ensuring that they are scheduled, and then computing the LCA
- * (least common ancestor) of its uses. It then schedules this instruction
- * as close to the LCA as possible while trying to stay out of loops.
- */
-static bool
-gcm_schedule_late_def(nir_ssa_def *def, void *void_state)
-{
- struct gcm_state *state = void_state;
-
- nir_block *lca = NULL;
-
- nir_foreach_use(def, use_src) {
- nir_instr *use_instr = use_src->parent_instr;
-
- gcm_schedule_late_instr(use_instr, state);
-
- /* Phi instructions are a bit special. SSA definitions don't have to
- * dominate the sources of the phi nodes that use them; instead, they
- * have to dominate the predecessor block corresponding to the phi
- * source. We handle this by looking through the sources, finding
- * any that are usingg this SSA def, and using those blocks instead
- * of the one the phi lives in.
- */
- if (use_instr->type == nir_instr_type_phi) {
- nir_phi_instr *phi = nir_instr_as_phi(use_instr);
-
- nir_foreach_phi_src(phi, phi_src) {
- if (phi_src->src.ssa == def)
- lca = nir_dominance_lca(lca, phi_src->pred);
- }
- } else {
- lca = nir_dominance_lca(lca, use_instr->block);
- }
- }
-
- nir_foreach_if_use(def, use_src) {
- nir_if *if_stmt = use_src->parent_if;
-
- /* For if statements, we consider the block to be the one immediately
- * preceding the if CF node.
- */
- nir_block *pred_block =
- nir_cf_node_as_block(nir_cf_node_prev(&if_stmt->cf_node));
-
- lca = nir_dominance_lca(lca, pred_block);
- }
-
- /* Some instructions may never be used. We'll just leave them scheduled
- * early and let dead code clean them up.
- */
- if (lca == NULL)
- return true;
-
- /* We know have the LCA of all of the uses. If our invariants hold,
- * this is dominated by the block that we chose when scheduling early.
- * We now walk up the dominance tree and pick the lowest block that is
- * as far outside loops as we can get.
- */
- nir_block *best = lca;
- while (lca != def->parent_instr->block) {
- assert(lca);
- if (state->blocks[lca->index].loop_depth <
- state->blocks[best->index].loop_depth)
- best = lca;
- lca = lca->imm_dom;
- }
- def->parent_instr->block = best;
-
- return true;
-}
-
-/** Schedules an instruction late
- *
- * This function performs a depth-first search starting at the given
- * instruction and proceeding through its uses to schedule instructions as
- * late as they can reasonably go in the dominance tree. The instructions
- * are "scheduled" by updating their instr->block field.
- *
- * The name of this function is actually a bit of a misnomer as it doesn't
- * schedule them "as late as possible" as the paper implies. Instead, it
- * first finds the lates possible place it can schedule the instruction and
- * then possibly schedules it earlier than that. The actual location is as
- * far down the tree as we can go while trying to stay out of loops.
- */
-static void
-gcm_schedule_late_instr(nir_instr *instr, struct gcm_state *state)
-{
- if (instr->pass_flags & GCM_INSTR_SCHEDULED_LATE)
- return;
-
- instr->pass_flags |= GCM_INSTR_SCHEDULED_LATE;
-
- /* Pinned instructions are already scheduled so we don't need to do
- * anything. Also, bailing here keeps us from ever following phi nodes
- * which can be back-edges.
- */
- if (instr->pass_flags & GCM_INSTR_PINNED)
- return;
-
- nir_foreach_ssa_def(instr, gcm_schedule_late_def, state);
-}
-
-static void
-gcm_place_instr(nir_instr *instr, struct gcm_state *state);
-
-static bool
-gcm_place_instr_def(nir_ssa_def *def, void *state)
-{
- nir_foreach_use(def, use_src)
- gcm_place_instr(use_src->parent_instr, state);
-
- return false;
-}
-
-/** Places an instrution back into the program
- *
- * The earlier passes of GCM simply choose blocks for each instruction and
- * otherwise leave them alone. This pass actually places the instructions
- * into their chosen blocks.
- *
- * To do so, we use a standard post-order depth-first search linearization
- * algorithm. We walk over the uses of the given instruction and ensure
- * that they are placed and then place this instruction. Because we are
- * working on multiple blocks at a time, we keep track of the last inserted
- * instruction per-block in the state structure's block_info array. When
- * we insert an instruction in a block we insert it before the last
- * instruction inserted in that block rather than the last instruction
- * inserted globally.
- */
-static void
-gcm_place_instr(nir_instr *instr, struct gcm_state *state)
-{
- if (instr->pass_flags & GCM_INSTR_PLACED)
- return;
-
- instr->pass_flags |= GCM_INSTR_PLACED;
-
- /* Phi nodes are our once source of back-edges. Since right now we are
- * only doing scheduling within blocks, we don't need to worry about
- * them since they are always at the top. Just skip them completely.
- */
- if (instr->type == nir_instr_type_phi) {
- assert(instr->pass_flags & GCM_INSTR_PINNED);
- return;
- }
-
- nir_foreach_ssa_def(instr, gcm_place_instr_def, state);
-
- if (instr->pass_flags & GCM_INSTR_PINNED) {
- /* Pinned instructions have an implicit dependence on the pinned
- * instructions that come after them in the block. Since the pinned
- * instructions will naturally "chain" together, we only need to
- * explicitly visit one of them.
- */
- for (nir_instr *after = nir_instr_next(instr);
- after;
- after = nir_instr_next(after)) {
- if (after->pass_flags & GCM_INSTR_PINNED) {
- gcm_place_instr(after, state);
- break;
- }
- }
- }
-
- struct gcm_block_info *block_info = &state->blocks[instr->block->index];
- if (!(instr->pass_flags & GCM_INSTR_PINNED)) {
- exec_node_remove(&instr->node);
-
- if (block_info->last_instr) {
- exec_node_insert_node_before(&block_info->last_instr->node,
- &instr->node);
- } else {
- /* Schedule it at the end of the block */
- nir_instr *jump_instr = nir_block_last_instr(instr->block);
- if (jump_instr && jump_instr->type == nir_instr_type_jump) {
- exec_node_insert_node_before(&jump_instr->node, &instr->node);
- } else {
- exec_list_push_tail(&instr->block->instr_list, &instr->node);
- }
- }
- }
-
- block_info->last_instr = instr;
-}
-
-static void
-opt_gcm_impl(nir_function_impl *impl)
-{
- struct gcm_state state;
-
- state.impl = impl;
- state.instr = NULL;
- exec_list_make_empty(&state.instrs);
- state.blocks = rzalloc_array(NULL, struct gcm_block_info, impl->num_blocks);
-
- nir_metadata_require(impl, nir_metadata_block_index |
- nir_metadata_dominance);
-
- gcm_build_block_info(&impl->body, &state, 0);
- nir_foreach_block(impl, gcm_pin_instructions_block, &state);
-
- foreach_list_typed(nir_instr, instr, node, &state.instrs)
- gcm_schedule_early_instr(instr, &state);
-
- foreach_list_typed(nir_instr, instr, node, &state.instrs)
- gcm_schedule_late_instr(instr, &state);
-
- while (!exec_list_is_empty(&state.instrs)) {
- nir_instr *instr = exec_node_data(nir_instr,
- state.instrs.tail_pred, node);
- gcm_place_instr(instr, &state);
- }
-
- ralloc_free(state.blocks);
-}
-
-void
-nir_opt_gcm(nir_shader *shader)
-{
- nir_foreach_function(shader, function) {
- if (function->impl)
- opt_gcm_impl(function->impl);
- }
-}
diff --git a/src/glsl/nir/nir_opt_global_to_local.c b/src/glsl/nir/nir_opt_global_to_local.c
deleted file mode 100644
index bccb45b6237..00000000000
--- a/src/glsl/nir/nir_opt_global_to_local.c
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright © 2014 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- *
- * Authors:
- * Connor Abbott ([email protected])
- *
- */
-
-#include "nir.h"
-
-static bool
-global_to_local(nir_register *reg)
-{
- nir_function_impl *impl = NULL;
-
- assert(reg->is_global);
-
- nir_foreach_def(reg, def_dest) {
- nir_instr *instr = def_dest->reg.parent_instr;
- nir_function_impl *instr_impl =
- nir_cf_node_get_function(&instr->block->cf_node);
- if (impl != NULL) {
- if (impl != instr_impl)
- return false;
- } else {
- impl = instr_impl;
- }
- }
-
- nir_foreach_use(reg, use_src) {
- nir_instr *instr = use_src->parent_instr;
- nir_function_impl *instr_impl =
- nir_cf_node_get_function(&instr->block->cf_node);
- if (impl != NULL) {
- if (impl != instr_impl)
- return false;
- } else {
- impl = instr_impl;
- }
- }
-
- nir_foreach_if_use(reg, use_src) {
- nir_if *if_stmt = use_src->parent_if;
- nir_function_impl *if_impl = nir_cf_node_get_function(&if_stmt->cf_node);
- if (impl != NULL) {
- if (impl != if_impl)
- return false;
- } else {
- impl = if_impl;
- }
- }
-
- if (impl == NULL) {
- /* this instruction is never used/defined, delete it */
- nir_reg_remove(reg);
- return true;
- }
-
- /*
- * if we've gotten to this point, the register is always used/defined in
- * the same implementation so we can move it to be local to that
- * implementation.
- */
-
- exec_node_remove(&reg->node);
- exec_list_push_tail(&impl->registers, &reg->node);
- reg->index = impl->reg_alloc++;
- reg->is_global = false;
- return true;
-}
-
-bool
-nir_opt_global_to_local(nir_shader *shader)
-{
- bool progress = false;
-
- foreach_list_typed_safe(nir_register, reg, node, &shader->registers) {
- if (global_to_local(reg))
- progress = true;
- }
-
- return progress;
-}
diff --git a/src/glsl/nir/nir_opt_peephole_select.c b/src/glsl/nir/nir_opt_peephole_select.c
deleted file mode 100644
index 0fc658df861..00000000000
--- a/src/glsl/nir/nir_opt_peephole_select.c
+++ /dev/null
@@ -1,256 +0,0 @@
-/*
- * Copyright © 2014 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- *
- * Authors:
- * Jason Ekstrand ([email protected])
- *
- */
-
-#include "nir.h"
-#include "nir_control_flow.h"
-
-/*
- * Implements a small peephole optimization that looks for
- *
- * if (cond) {
- * <empty>
- * } else {
- * <empty>
- * }
- * phi
- * ...
- * phi
- *
- * and replaces it with a series of selects. It can also handle the case
- * where, instead of being empty, the if may contain some move operations
- * whose only use is one of the following phi nodes. This happens all the
- * time when the SSA form comes from a conditional assignment with a
- * swizzle.
- */
-
-struct peephole_select_state {
- void *mem_ctx;
- bool progress;
-};
-
-static bool
-block_check_for_allowed_instrs(nir_block *block)
-{
- nir_foreach_instr(block, instr) {
- 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;
- }
-
- break;
- }
-
- case nir_instr_type_load_const:
- break;
-
- case nir_instr_type_alu: {
- nir_alu_instr *mov = nir_instr_as_alu(instr);
- switch (mov->op) {
- case nir_op_fmov:
- case nir_op_imov:
- case nir_op_fneg:
- case nir_op_ineg:
- case nir_op_fabs:
- case nir_op_iabs:
- case nir_op_vec2:
- case nir_op_vec3:
- case nir_op_vec4:
- /* It must be a move-like operation. */
- break;
- default:
- return false;
- }
-
- /* Can't handle saturate */
- if (mov->dest.saturate)
- return false;
-
- /* It must be SSA */
- if (!mov->dest.dest.is_ssa)
- return false;
-
- /* It cannot have any if-uses */
- if (!list_empty(&mov->dest.dest.ssa.if_uses))
- return false;
-
- /* The only uses of this definition must be phi's in the successor */
- nir_foreach_use(&mov->dest.dest.ssa, use) {
- if (use->parent_instr->type != nir_instr_type_phi ||
- use->parent_instr->block != block->successors[0])
- return false;
- }
- break;
- }
-
- default:
- return false;
- }
- }
-
- return true;
-}
-
-static bool
-nir_opt_peephole_select_block(nir_block *block, void *void_state)
-{
- struct peephole_select_state *state = void_state;
-
- /* If the block is empty, then it certainly doesn't have any phi nodes,
- * so we can skip it. This also ensures that we do an early skip on the
- * end block of the function which isn't actually attached to the CFG.
- */
- if (exec_list_is_empty(&block->instr_list))
- return true;
-
- if (nir_cf_node_is_first(&block->cf_node))
- return true;
-
- nir_cf_node *prev_node = nir_cf_node_prev(&block->cf_node);
- if (prev_node->type != nir_cf_node_if)
- return true;
-
- nir_if *if_stmt = nir_cf_node_as_if(prev_node);
- nir_cf_node *then_node = nir_if_first_then_node(if_stmt);
- nir_cf_node *else_node = nir_if_first_else_node(if_stmt);
-
- /* We can only have one block in each side ... */
- if (nir_if_last_then_node(if_stmt) != then_node ||
- nir_if_last_else_node(if_stmt) != else_node)
- return true;
-
- 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 "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
- * statement containing only moves to phi nodes in this block. We can
- * just remove that entire CF node and replace all of the phi nodes with
- * 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;
-
- nir_phi_instr *phi = nir_instr_as_phi(instr);
- nir_alu_instr *sel = nir_alu_instr_create(state->mem_ctx, nir_op_bcsel);
- nir_src_copy(&sel->src[0].src, &if_stmt->condition, sel);
- /* Splat the condition to all channels */
- memset(sel->src[0].swizzle, 0, sizeof sel->src[0].swizzle);
-
- assert(exec_list_length(&phi->srcs) == 2);
- nir_foreach_phi_src(phi, src) {
- assert(src->pred == then_block || src->pred == else_block);
- assert(src->src.is_ssa);
-
- unsigned idx = src->pred == then_block ? 1 : 2;
- nir_src_copy(&sel->src[idx].src, &src->src, sel);
- }
-
- nir_ssa_dest_init(&sel->instr, &sel->dest.dest,
- phi->dest.ssa.num_components, phi->dest.ssa.name);
- sel->dest.write_mask = (1 << phi->dest.ssa.num_components) - 1;
-
- nir_ssa_def_rewrite_uses(&phi->dest.ssa,
- nir_src_for_ssa(&sel->dest.dest.ssa));
-
- nir_instr_insert_before(&phi->instr, &sel->instr);
- nir_instr_remove(&phi->instr);
- }
-
- nir_cf_node_remove(&if_stmt->cf_node);
- state->progress = true;
-
- return true;
-}
-
-static bool
-nir_opt_peephole_select_impl(nir_function_impl *impl)
-{
- struct peephole_select_state state;
-
- state.mem_ctx = ralloc_parent(impl);
- state.progress = false;
-
- nir_foreach_block(impl, nir_opt_peephole_select_block, &state);
-
- if (state.progress)
- nir_metadata_preserve(impl, nir_metadata_none);
-
- return state.progress;
-}
-
-bool
-nir_opt_peephole_select(nir_shader *shader)
-{
- bool progress = false;
-
- nir_foreach_function(shader, function) {
- if (function->impl)
- progress |= nir_opt_peephole_select_impl(function->impl);
- }
-
- return progress;
-}
diff --git a/src/glsl/nir/nir_opt_remove_phis.c b/src/glsl/nir/nir_opt_remove_phis.c
deleted file mode 100644
index 646183707bd..00000000000
--- a/src/glsl/nir/nir_opt_remove_phis.c
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright © 2015 Connor Abbott
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- *
- * Authors:
- * Connor Abbott ([email protected])
- *
- */
-
-#include "nir.h"
-
-/*
- * This is a pass for removing phi nodes that look like:
- * a = phi(b, b, b, ...)
- *
- * Note that we can't ignore undef sources here, or else we may create a
- * situation where the definition of b isn't dominated by its uses. We're
- * allowed to do this since the definition of b must dominate all of the
- * phi node's predecessors, which means it must dominate the phi node as well
- * as all of the phi node's uses. In essence, the phi node acts as a copy
- * instruction. b can't be another phi node in the same block, since the only
- * time when phi nodes can source other phi nodes defined in the same block is
- * at the loop header, and in that case one of the sources of the phi has to
- * be from before the loop and that source can't be b.
- */
-
-static bool
-remove_phis_block(nir_block *block, void *state)
-{
- bool *progress = state;
-
- nir_foreach_instr_safe(block, instr) {
- if (instr->type != nir_instr_type_phi)
- break;
-
- nir_phi_instr *phi = nir_instr_as_phi(instr);
-
- nir_ssa_def *def = NULL;
- bool srcs_same = true;
-
- nir_foreach_phi_src(phi, src) {
- assert(src->src.is_ssa);
-
- /* For phi nodes at the beginning of loops, we may encounter some
- * sources from backedges that point back to the destination of the
- * same phi, i.e. something like:
- *
- * a = phi(a, b, ...)
- *
- * We can safely ignore these sources, since if all of the normal
- * sources point to the same definition, then that definition must
- * still dominate the phi node, and the phi will still always take
- * the value of that definition.
- */
- if (src->src.ssa == &phi->dest.ssa)
- continue;
-
- if (def == NULL) {
- def = src->src.ssa;
- } else {
- if (src->src.ssa != def) {
- srcs_same = false;
- break;
- }
- }
- }
-
- if (!srcs_same)
- continue;
-
- /* We must have found at least one definition, since there must be at
- * least one forward edge.
- */
- assert(def != NULL);
-
- assert(phi->dest.is_ssa);
- nir_ssa_def_rewrite_uses(&phi->dest.ssa, nir_src_for_ssa(def));
- nir_instr_remove(instr);
-
- *progress = true;
- }
-
- return true;
-}
-
-static bool
-remove_phis_impl(nir_function_impl *impl)
-{
- bool progress = false;
-
- nir_foreach_block(impl, remove_phis_block, &progress);
-
- if (progress) {
- nir_metadata_preserve(impl, nir_metadata_block_index |
- nir_metadata_dominance);
- }
-
- return progress;
-}
-
-bool
-nir_opt_remove_phis(nir_shader *shader)
-{
- bool progress = false;
-
- nir_foreach_function(shader, function)
- if (function->impl)
- progress = remove_phis_impl(function->impl) || progress;
-
- return progress;
-}
-
diff --git a/src/glsl/nir/nir_opt_undef.c b/src/glsl/nir/nir_opt_undef.c
deleted file mode 100644
index 374564d34c5..00000000000
--- a/src/glsl/nir/nir_opt_undef.c
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright © 2015 Broadcom
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include "nir.h"
-
-/** @file nir_opt_undef.c
- *
- * Handles optimization of operations involving ssa_undef. For now, we just
- * make sure that csels between undef and some other value just give the other
- * value (on the assumption that the condition's going to be choosing the
- * defined value). This reduces work after if flattening when each side of
- * the if is defining a variable.
- *
- * Some day, we may find some use for making other operations consuming an
- * undef arg output undef, but I don't know of any cases currently.
- */
-
-static bool
-opt_undef_alu(nir_alu_instr *instr)
-{
- if (instr->op != nir_op_bcsel && instr->op != nir_op_fcsel)
- return false;
-
- assert(instr->dest.dest.is_ssa);
-
- for (int i = 1; i <= 2; i++) {
- if (!instr->src[i].src.is_ssa)
- continue;
-
- nir_instr *parent = instr->src[i].src.ssa->parent_instr;
- if (parent->type != nir_instr_type_ssa_undef)
- continue;
-
- /* We can't just use nir_alu_src_copy, because we need the def/use
- * updated.
- */
- nir_instr_rewrite_src(&instr->instr, &instr->src[0].src,
- instr->src[i == 1 ? 2 : 1].src);
- nir_alu_src_copy(&instr->src[0], &instr->src[i == 1 ? 2 : 1],
- ralloc_parent(instr));
-
- nir_src empty_src;
- memset(&empty_src, 0, sizeof(empty_src));
- nir_instr_rewrite_src(&instr->instr, &instr->src[1].src, empty_src);
- nir_instr_rewrite_src(&instr->instr, &instr->src[2].src, empty_src);
- instr->op = nir_op_imov;
-
- return true;
- }
-
- return false;
-}
-
-static bool
-opt_undef_block(nir_block *block, void *data)
-{
- bool *progress = data;
-
- nir_foreach_instr_safe(block, instr) {
- if (instr->type == nir_instr_type_alu)
- if (opt_undef_alu(nir_instr_as_alu(instr)))
- (*progress) = true;
- }
-
- return true;
-}
-
-bool
-nir_opt_undef(nir_shader *shader)
-{
- bool progress = false;
-
- nir_foreach_function(shader, function) {
- if (function->impl) {
- nir_foreach_block(function->impl, opt_undef_block, &progress);
- if (progress)
- nir_metadata_preserve(function->impl,
- nir_metadata_block_index |
- nir_metadata_dominance);
- }
- }
-
- return progress;
-}
diff --git a/src/glsl/nir/nir_phi_builder.c b/src/glsl/nir/nir_phi_builder.c
deleted file mode 100644
index 5429083e5c8..00000000000
--- a/src/glsl/nir/nir_phi_builder.c
+++ /dev/null
@@ -1,254 +0,0 @@
-/*
- * Copyright © 2016 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include "nir_phi_builder.h"
-#include "nir/nir_vla.h"
-
-struct nir_phi_builder {
- nir_shader *shader;
- nir_function_impl *impl;
-
- /* Copied from the impl for easy access */
- unsigned num_blocks;
-
- /* Array of all blocks indexed by block->index. */
- nir_block **blocks;
-
- /* Hold on to the values so we can easily iterate over them. */
- struct exec_list values;
-
- /* Worklist for phi adding */
- unsigned iter_count;
- unsigned *work;
- nir_block **W;
-};
-
-#define NEEDS_PHI ((nir_ssa_def *)(intptr_t)-1)
-
-struct nir_phi_builder_value {
- struct exec_node node;
-
- struct nir_phi_builder *builder;
-
- /* Needed so we can create phis and undefs */
- unsigned num_components;
-
- /* The list of phi nodes associated with this value. Phi nodes are not
- * added directly. Instead, they are created, the instr->block pointer
- * set, and then added to this list. Later, in phi_builder_finish, we
- * set up their sources and add them to the top of their respective
- * blocks.
- */
- struct exec_list phis;
-
- /* Array of SSA defs, indexed by block. If a phi needs to be inserted
- * in a given block, it will have the magic value NEEDS_PHI.
- */
- nir_ssa_def *defs[0];
-};
-
-static bool
-fill_block_array(nir_block *block, void *void_data)
-{
- nir_block **blocks = void_data;
- blocks[block->index] = block;
- return true;
-}
-
-struct nir_phi_builder *
-nir_phi_builder_create(nir_function_impl *impl)
-{
- struct nir_phi_builder *pb = ralloc(NULL, struct nir_phi_builder);
-
- pb->shader = impl->function->shader;
- pb->impl = impl;
-
- assert(impl->valid_metadata & (nir_metadata_block_index |
- nir_metadata_dominance));
-
- pb->num_blocks = impl->num_blocks;
- pb->blocks = ralloc_array(pb, nir_block *, pb->num_blocks);
- nir_foreach_block(impl, fill_block_array, pb->blocks);
-
- exec_list_make_empty(&pb->values);
-
- pb->iter_count = 0;
- pb->work = rzalloc_array(pb, unsigned, pb->num_blocks);
- pb->W = ralloc_array(pb, nir_block *, pb->num_blocks);
-
- return pb;
-}
-
-struct nir_phi_builder_value *
-nir_phi_builder_add_value(struct nir_phi_builder *pb, unsigned num_components,
- const BITSET_WORD *defs)
-{
- struct nir_phi_builder_value *val;
- unsigned i, w_start = 0, w_end = 0;
-
- val = rzalloc_size(pb, sizeof(*val) + sizeof(val->defs[0]) * pb->num_blocks);
- val->builder = pb;
- val->num_components = num_components;
- exec_list_make_empty(&val->phis);
- exec_list_push_tail(&pb->values, &val->node);
-
- pb->iter_count++;
-
- BITSET_WORD tmp;
- BITSET_FOREACH_SET(i, tmp, defs, pb->num_blocks) {
- if (pb->work[i] < pb->iter_count)
- pb->W[w_end++] = pb->blocks[i];
- pb->work[i] = pb->iter_count;
- }
-
- while (w_start != w_end) {
- nir_block *cur = pb->W[w_start++];
- struct set_entry *dom_entry;
- set_foreach(cur->dom_frontier, dom_entry) {
- nir_block *next = (nir_block *) dom_entry->key;
-
- /*
- * If there's more than one return statement, then the end block
- * can be a join point for some definitions. However, there are
- * no instructions in the end block, so nothing would use those
- * phi nodes. Of course, we couldn't place those phi nodes
- * anyways due to the restriction of having no instructions in the
- * end block...
- */
- if (next == pb->impl->end_block)
- continue;
-
- if (val->defs[next->index] == NULL) {
- val->defs[next->index] = NEEDS_PHI;
-
- if (pb->work[next->index] < pb->iter_count) {
- pb->work[next->index] = pb->iter_count;
- pb->W[w_end++] = next;
- }
- }
- }
- }
-
- return val;
-}
-
-void
-nir_phi_builder_value_set_block_def(struct nir_phi_builder_value *val,
- nir_block *block, nir_ssa_def *def)
-{
- val->defs[block->index] = def;
-}
-
-nir_ssa_def *
-nir_phi_builder_value_get_block_def(struct nir_phi_builder_value *val,
- nir_block *block)
-{
- if (val->defs[block->index] == NULL) {
- if (block->imm_dom) {
- /* Grab it from our immediate dominator. We'll stash it here for
- * easy access later.
- */
- val->defs[block->index] =
- nir_phi_builder_value_get_block_def(val, block->imm_dom);
- return val->defs[block->index];
- } else {
- /* No immediate dominator means that this block is either the
- * start block or unreachable. In either case, the value is
- * undefined so we need an SSA undef.
- */
- nir_ssa_undef_instr *undef =
- nir_ssa_undef_instr_create(val->builder->shader,
- val->num_components);
- nir_instr_insert(nir_before_cf_list(&val->builder->impl->body),
- &undef->instr);
- val->defs[block->index] = &undef->def;
- return &undef->def;
- }
- } else if (val->defs[block->index] == NEEDS_PHI) {
- /* If we need a phi instruction, go ahead and create one but don't
- * add it to the program yet. Later, we'll go through and set up phi
- * sources and add the instructions will be added at that time.
- */
- nir_phi_instr *phi = nir_phi_instr_create(val->builder->shader);
- nir_ssa_dest_init(&phi->instr, &phi->dest, val->num_components, NULL);
- phi->instr.block = block;
- exec_list_push_tail(&val->phis, &phi->instr.node);
- val->defs[block->index] = &phi->dest.ssa;
- return &phi->dest.ssa;
- } else {
- return val->defs[block->index];
- }
-}
-
-static int
-compare_blocks(const void *_a, const void *_b)
-{
- nir_block * const * a = _a;
- nir_block * const * b = _b;
-
- return (*a)->index - (*b)->index;
-}
-
-void
-nir_phi_builder_finish(struct nir_phi_builder *pb)
-{
- const unsigned num_blocks = pb->num_blocks;
- NIR_VLA(nir_block *, preds, num_blocks);
-
- foreach_list_typed(struct nir_phi_builder_value, val, node, &pb->values) {
- /* We can't iterate over the list of phis normally because we are
- * removing them as we go and, in some cases, adding new phis as we
- * build the source lists of others.
- */
- while (!exec_list_is_empty(&val->phis)) {
- struct exec_node *head = exec_list_get_head(&val->phis);
- nir_phi_instr *phi = exec_node_data(nir_phi_instr, head, instr.node);
- assert(phi->instr.type == nir_instr_type_phi);
-
- exec_node_remove(&phi->instr.node);
-
- /* Construct an array of predecessors. We sort it to ensure
- * determinism in the phi insertion algorithm.
- *
- * XXX: Calling qsort this many times seems expensive.
- */
- int num_preds = 0;
- struct set_entry *entry;
- set_foreach(phi->instr.block->predecessors, entry)
- preds[num_preds++] = (nir_block *)entry->key;
- qsort(preds, num_preds, sizeof(*preds), compare_blocks);
-
- for (unsigned i = 0; i < num_preds; i++) {
- nir_phi_src *src = ralloc(phi, nir_phi_src);
- src->pred = preds[i];
- src->src = nir_src_for_ssa(
- nir_phi_builder_value_get_block_def(val, preds[i]));
- exec_list_push_tail(&phi->srcs, &src->node);
- }
-
- nir_instr_insert(nir_before_block(phi->instr.block), &phi->instr);
- }
- }
-
- ralloc_free(pb);
-}
diff --git a/src/glsl/nir/nir_phi_builder.h b/src/glsl/nir/nir_phi_builder.h
deleted file mode 100644
index 50251bf1ba3..00000000000
--- a/src/glsl/nir/nir_phi_builder.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright © 2016 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#pragma once
-
-#include "nir.h"
-
-struct nir_phi_builder;
-struct nir_phi_builder_value;
-
-/* Create a new phi builder.
- *
- * While this is fairly cheap, it does allocate some memory and walk the list
- * of blocks so it's recommended that you only call it once and use it to
- * build phis for several values.
- */
-struct nir_phi_builder *nir_phi_builder_create(nir_function_impl *impl);
-
-/* Register a value with the builder.
- *
- * The 'defs' parameter specifies a bitset of blocks in which the given value
- * is defined. This is used to determine where to place the phi nodes.
- */
-struct nir_phi_builder_value *
-nir_phi_builder_add_value(struct nir_phi_builder *pb, unsigned num_components,
- const BITSET_WORD *defs);
-
-/* Register a definition for the given value and block.
- *
- * It is safe to call this function as many times as you wish for any given
- * block/value pair. However, it always replaces whatever was there
- * previously even if that definition is from a phi node. The phi builder
- * always uses the latest information it has, so you must be careful about the
- * order in which you register definitions. The final value at the end of the
- * block must be the last value registered.
- */
-void
-nir_phi_builder_value_set_block_def(struct nir_phi_builder_value *val,
- nir_block *block, nir_ssa_def *def);
-
-/* Get the definition for the given value in the given block.
- *
- * This definition will always be the latest definition known for the given
- * block. If no definition is immediately available, it will crawl up the
- * dominance tree and insert phi nodes as needed until it finds one. In the
- * case that no suitable definition is found, it will return the result of a
- * nir_ssa_undef_instr with the correct number of components.
- *
- * Because this function only uses the latest available information for any
- * given block, you must have already finished registering definitions for any
- * blocks that dominate the current block in order to get the correct result.
- */
-nir_ssa_def *
-nir_phi_builder_value_get_block_def(struct nir_phi_builder_value *val,
- nir_block *block);
-
-/* Finish building phi nodes and free the builder.
- *
- * This function does far more than just free memory. Prior to calling
- * nir_phi_builder_finish, no phi nodes have actually been inserted in the
- * program. This function is what finishes setting up phi node sources and
- * adds the phi nodes to the program.
- */
-void nir_phi_builder_finish(struct nir_phi_builder *pb);
diff --git a/src/glsl/nir/nir_print.c b/src/glsl/nir/nir_print.c
deleted file mode 100644
index a137706b15b..00000000000
--- a/src/glsl/nir/nir_print.c
+++ /dev/null
@@ -1,1089 +0,0 @@
-/*
- * Copyright © 2014 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- *
- * Authors:
- * Connor Abbott ([email protected])
- *
- */
-
-#include "nir.h"
-#include "shader_enums.h"
-#include <stdio.h>
-#include <stdlib.h>
-
-static void
-print_tabs(unsigned num_tabs, FILE *fp)
-{
- for (unsigned i = 0; i < num_tabs; i++)
- fprintf(fp, "\t");
-}
-
-typedef struct {
- FILE *fp;
- nir_shader *shader;
- /** map from nir_variable -> printable name */
- struct hash_table *ht;
-
- /** set of names used so far for nir_variables */
- struct set *syms;
-
- /* an index used to make new non-conflicting names */
- unsigned index;
-} print_state;
-
-static void
-print_register(nir_register *reg, print_state *state)
-{
- FILE *fp = state->fp;
- if (reg->name != NULL)
- fprintf(fp, "/* %s */ ", reg->name);
- if (reg->is_global)
- fprintf(fp, "gr%u", reg->index);
- else
- fprintf(fp, "r%u", reg->index);
-}
-
-static const char *sizes[] = { "error", "vec1", "vec2", "vec3", "vec4" };
-
-static void
-print_register_decl(nir_register *reg, print_state *state)
-{
- FILE *fp = state->fp;
- fprintf(fp, "decl_reg %s ", sizes[reg->num_components]);
- if (reg->is_packed)
- fprintf(fp, "(packed) ");
- print_register(reg, state);
- if (reg->num_array_elems != 0)
- fprintf(fp, "[%u]", reg->num_array_elems);
- fprintf(fp, "\n");
-}
-
-static void
-print_ssa_def(nir_ssa_def *def, print_state *state)
-{
- FILE *fp = state->fp;
- if (def->name != NULL)
- fprintf(fp, "/* %s */ ", def->name);
- fprintf(fp, "%s ssa_%u", sizes[def->num_components], def->index);
-}
-
-static void
-print_ssa_use(nir_ssa_def *def, print_state *state)
-{
- FILE *fp = state->fp;
- if (def->name != NULL)
- fprintf(fp, "/* %s */ ", def->name);
- fprintf(fp, "ssa_%u", def->index);
-}
-
-static void print_src(nir_src *src, print_state *state);
-
-static void
-print_reg_src(nir_reg_src *src, print_state *state)
-{
- FILE *fp = state->fp;
- print_register(src->reg, state);
- if (src->reg->num_array_elems != 0) {
- fprintf(fp, "[%u", src->base_offset);
- if (src->indirect != NULL) {
- fprintf(fp, " + ");
- print_src(src->indirect, state);
- }
- fprintf(fp, "]");
- }
-}
-
-static void
-print_reg_dest(nir_reg_dest *dest, print_state *state)
-{
- FILE *fp = state->fp;
- print_register(dest->reg, state);
- if (dest->reg->num_array_elems != 0) {
- fprintf(fp, "[%u", dest->base_offset);
- if (dest->indirect != NULL) {
- fprintf(fp, " + ");
- print_src(dest->indirect, state);
- }
- fprintf(fp, "]");
- }
-}
-
-static void
-print_src(nir_src *src, print_state *state)
-{
- if (src->is_ssa)
- print_ssa_use(src->ssa, state);
- else
- print_reg_src(&src->reg, state);
-}
-
-static void
-print_dest(nir_dest *dest, print_state *state)
-{
- if (dest->is_ssa)
- print_ssa_def(&dest->ssa, state);
- else
- print_reg_dest(&dest->reg, state);
-}
-
-static void
-print_alu_src(nir_alu_instr *instr, unsigned src, print_state *state)
-{
- FILE *fp = state->fp;
-
- if (instr->src[src].negate)
- fprintf(fp, "-");
- if (instr->src[src].abs)
- fprintf(fp, "abs(");
-
- print_src(&instr->src[src].src, state);
-
- bool print_swizzle = false;
- for (unsigned i = 0; i < 4; i++) {
- if (!nir_alu_instr_channel_used(instr, src, i))
- continue;
-
- if (instr->src[src].swizzle[i] != i) {
- print_swizzle = true;
- break;
- }
- }
-
- if (print_swizzle) {
- fprintf(fp, ".");
- for (unsigned i = 0; i < 4; i++) {
- if (!nir_alu_instr_channel_used(instr, src, i))
- continue;
-
- fprintf(fp, "%c", "xyzw"[instr->src[src].swizzle[i]]);
- }
- }
-
- if (instr->src[src].abs)
- fprintf(fp, ")");
-}
-
-static void
-print_alu_dest(nir_alu_dest *dest, print_state *state)
-{
- FILE *fp = state->fp;
- /* we're going to print the saturate modifier later, after the opcode */
-
- print_dest(&dest->dest, state);
-
- if (!dest->dest.is_ssa &&
- dest->write_mask != (1 << dest->dest.reg.reg->num_components) - 1) {
- fprintf(fp, ".");
- for (unsigned i = 0; i < 4; i++)
- if ((dest->write_mask >> i) & 1)
- fprintf(fp, "%c", "xyzw"[i]);
- }
-}
-
-static void
-print_alu_instr(nir_alu_instr *instr, print_state *state)
-{
- FILE *fp = state->fp;
-
- print_alu_dest(&instr->dest, state);
-
- fprintf(fp, " = %s", nir_op_infos[instr->op].name);
- if (instr->dest.saturate)
- fprintf(fp, ".sat");
- fprintf(fp, " ");
-
- for (unsigned i = 0; i < nir_op_infos[instr->op].num_inputs; i++) {
- if (i != 0)
- fprintf(fp, ", ");
-
- print_alu_src(instr, i, state);
- }
-}
-
-static const char *
-get_var_name(nir_variable *var, print_state *state)
-{
- if (state->ht == NULL)
- return var->name;
-
- assert(state->syms);
-
- struct hash_entry *entry = _mesa_hash_table_search(state->ht, var);
- if (entry)
- return entry->data;
-
- char *name;
- if (var->name == NULL) {
- name = ralloc_asprintf(state->syms, "@%u", state->index++);
- } else {
- struct set_entry *set_entry = _mesa_set_search(state->syms, var->name);
- if (set_entry != NULL) {
- /* we have a collision with another name, append an @ + a unique
- * index */
- name = ralloc_asprintf(state->syms, "%s@%u", var->name,
- state->index++);
- } else {
- /* Mark this one as seen */
- _mesa_set_add(state->syms, var->name);
- name = var->name;
- }
- }
-
- _mesa_hash_table_insert(state->ht, var, name);
-
- return name;
-}
-
-static void
-print_constant(nir_constant *c, const struct glsl_type *type, print_state *state)
-{
- FILE *fp = state->fp;
- unsigned total_elems = glsl_get_components(type);
- unsigned i;
-
- switch (glsl_get_base_type(type)) {
- case GLSL_TYPE_UINT:
- case GLSL_TYPE_INT:
- case GLSL_TYPE_BOOL:
- for (i = 0; i < total_elems; i++) {
- if (i > 0) fprintf(fp, ", ");
- fprintf(fp, "0x%08x", c->value.u[i]);
- }
- break;
-
- case GLSL_TYPE_FLOAT:
- for (i = 0; i < total_elems; i++) {
- if (i > 0) fprintf(fp, ", ");
- fprintf(fp, "%f", c->value.f[i]);
- }
- break;
-
- case GLSL_TYPE_STRUCT:
- for (i = 0; i < c->num_elements; i++) {
- if (i > 0) fprintf(fp, ", ");
- fprintf(fp, "{ ");
- print_constant(c->elements[i], glsl_get_struct_field(type, i), state);
- fprintf(fp, " }");
- }
- break;
-
- case GLSL_TYPE_ARRAY:
- for (i = 0; i < c->num_elements; i++) {
- if (i > 0) fprintf(fp, ", ");
- fprintf(fp, "{ ");
- print_constant(c->elements[i], glsl_get_array_element(type), state);
- fprintf(fp, " }");
- }
- break;
-
- default:
- unreachable("not reached");
- }
-}
-
-static void
-print_var_decl(nir_variable *var, print_state *state)
-{
- FILE *fp = state->fp;
-
- fprintf(fp, "decl_var ");
-
- const char *const cent = (var->data.centroid) ? "centroid " : "";
- const char *const samp = (var->data.sample) ? "sample " : "";
- const char *const patch = (var->data.patch) ? "patch " : "";
- const char *const inv = (var->data.invariant) ? "invariant " : "";
- const char *const mode[] = { "shader_in ", "shader_out ", "", "",
- "uniform ", "shader_storage ", "shared ",
- "system "};
-
- fprintf(fp, "%s%s%s%s%s%s ",
- cent, samp, patch, inv, mode[var->data.mode],
- glsl_interp_qualifier_name(var->data.interpolation));
-
- glsl_print_type(var->type, fp);
-
- fprintf(fp, " %s", get_var_name(var, state));
-
- if (var->data.mode == nir_var_shader_in ||
- var->data.mode == nir_var_shader_out ||
- var->data.mode == nir_var_uniform ||
- var->data.mode == nir_var_shader_storage) {
- const char *loc = NULL;
- char buf[4];
-
- switch (state->shader->stage) {
- case MESA_SHADER_VERTEX:
- if (var->data.mode == nir_var_shader_in)
- loc = gl_vert_attrib_name(var->data.location);
- else if (var->data.mode == nir_var_shader_out)
- loc = gl_varying_slot_name(var->data.location);
- break;
- case MESA_SHADER_GEOMETRY:
- if ((var->data.mode == nir_var_shader_in) ||
- (var->data.mode == nir_var_shader_out))
- loc = gl_varying_slot_name(var->data.location);
- break;
- case MESA_SHADER_FRAGMENT:
- if (var->data.mode == nir_var_shader_in)
- loc = gl_varying_slot_name(var->data.location);
- else if (var->data.mode == nir_var_shader_out)
- loc = gl_frag_result_name(var->data.location);
- break;
- case MESA_SHADER_TESS_CTRL:
- case MESA_SHADER_TESS_EVAL:
- case MESA_SHADER_COMPUTE:
- default:
- /* TODO */
- break;
- }
-
- if (!loc) {
- snprintf(buf, sizeof(buf), "%u", var->data.location);
- loc = buf;
- }
-
- fprintf(fp, " (%s, %u)", loc, var->data.driver_location);
- }
-
- if (var->constant_initializer) {
- fprintf(fp, " = { ");
- print_constant(var->constant_initializer, var->type, state);
- fprintf(fp, " }");
- }
-
- fprintf(fp, "\n");
-}
-
-static void
-print_var(nir_variable *var, print_state *state)
-{
- FILE *fp = state->fp;
- fprintf(fp, "%s", get_var_name(var, state));
-}
-
-static void
-print_deref_var(nir_deref_var *deref, print_state *state)
-{
- print_var(deref->var, state);
-}
-
-static void
-print_deref_array(nir_deref_array *deref, print_state *state)
-{
- FILE *fp = state->fp;
- fprintf(fp, "[");
- switch (deref->deref_array_type) {
- case nir_deref_array_type_direct:
- fprintf(fp, "%u", deref->base_offset);
- break;
- case nir_deref_array_type_indirect:
- if (deref->base_offset != 0)
- fprintf(fp, "%u + ", deref->base_offset);
- print_src(&deref->indirect, state);
- break;
- case nir_deref_array_type_wildcard:
- fprintf(fp, "*");
- break;
- }
- fprintf(fp, "]");
-}
-
-static void
-print_deref_struct(nir_deref_struct *deref, const struct glsl_type *parent_type,
- print_state *state)
-{
- FILE *fp = state->fp;
- fprintf(fp, ".%s", glsl_get_struct_elem_name(parent_type, deref->index));
-}
-
-static void
-print_deref(nir_deref_var *deref, print_state *state)
-{
- nir_deref *tail = &deref->deref;
- nir_deref *pretail = NULL;
- while (tail != NULL) {
- switch (tail->deref_type) {
- case nir_deref_type_var:
- assert(pretail == NULL);
- assert(tail == &deref->deref);
- print_deref_var(deref, state);
- break;
-
- case nir_deref_type_array:
- assert(pretail != NULL);
- print_deref_array(nir_deref_as_array(tail), state);
- break;
-
- case nir_deref_type_struct:
- assert(pretail != NULL);
- print_deref_struct(nir_deref_as_struct(tail),
- pretail->type, state);
- break;
-
- default:
- unreachable("Invalid deref type");
- }
-
- pretail = tail;
- tail = pretail->child;
- }
-}
-
-static void
-print_intrinsic_instr(nir_intrinsic_instr *instr, print_state *state)
-{
- unsigned num_srcs = nir_intrinsic_infos[instr->intrinsic].num_srcs;
- FILE *fp = state->fp;
-
- if (nir_intrinsic_infos[instr->intrinsic].has_dest) {
- print_dest(&instr->dest, state);
- fprintf(fp, " = ");
- }
-
- fprintf(fp, "intrinsic %s (", nir_intrinsic_infos[instr->intrinsic].name);
-
- for (unsigned i = 0; i < num_srcs; i++) {
- if (i != 0)
- fprintf(fp, ", ");
-
- print_src(&instr->src[i], state);
- }
-
- fprintf(fp, ") (");
-
- unsigned num_vars = nir_intrinsic_infos[instr->intrinsic].num_variables;
-
- for (unsigned i = 0; i < num_vars; i++) {
- if (i != 0)
- fprintf(fp, ", ");
-
- print_deref(instr->variables[i], state);
- }
-
- fprintf(fp, ") (");
-
- unsigned num_indices = nir_intrinsic_infos[instr->intrinsic].num_indices;
-
- for (unsigned i = 0; i < num_indices; i++) {
- if (i != 0)
- fprintf(fp, ", ");
-
- fprintf(fp, "%d", instr->const_index[i]);
- }
-
- fprintf(fp, ")");
-
- if (!state->shader)
- return;
-
- struct exec_list *var_list = NULL;
-
- switch (instr->intrinsic) {
- case nir_intrinsic_load_uniform:
- var_list = &state->shader->uniforms;
- break;
- case nir_intrinsic_load_input:
- case nir_intrinsic_load_per_vertex_input:
- var_list = &state->shader->inputs;
- break;
- case nir_intrinsic_load_output:
- case nir_intrinsic_store_output:
- case nir_intrinsic_store_per_vertex_output:
- var_list = &state->shader->outputs;
- break;
- default:
- return;
- }
-
- nir_foreach_variable(var, var_list) {
- if ((var->data.driver_location == instr->const_index[0]) &&
- var->name) {
- fprintf(fp, "\t/* %s */", var->name);
- break;
- }
- }
-}
-
-static void
-print_tex_instr(nir_tex_instr *instr, print_state *state)
-{
- FILE *fp = state->fp;
-
- print_dest(&instr->dest, state);
-
- fprintf(fp, " = ");
-
- switch (instr->op) {
- case nir_texop_tex:
- fprintf(fp, "tex ");
- break;
- case nir_texop_txb:
- fprintf(fp, "txb ");
- break;
- case nir_texop_txl:
- fprintf(fp, "txl ");
- break;
- case nir_texop_txd:
- fprintf(fp, "txd ");
- break;
- case nir_texop_txf:
- fprintf(fp, "txf ");
- break;
- case nir_texop_txf_ms:
- fprintf(fp, "txf_ms ");
- break;
- case nir_texop_txs:
- fprintf(fp, "txs ");
- break;
- case nir_texop_lod:
- fprintf(fp, "lod ");
- break;
- case nir_texop_tg4:
- fprintf(fp, "tg4 ");
- break;
- case nir_texop_query_levels:
- fprintf(fp, "query_levels ");
- break;
- case nir_texop_texture_samples:
- fprintf(fp, "texture_samples ");
- break;
- case nir_texop_samples_identical:
- fprintf(fp, "samples_identical ");
- break;
- default:
- unreachable("Invalid texture operation");
- break;
- }
-
- for (unsigned i = 0; i < instr->num_srcs; i++) {
- print_src(&instr->src[i].src, state);
-
- fprintf(fp, " ");
-
- switch(instr->src[i].src_type) {
- case nir_tex_src_coord:
- fprintf(fp, "(coord)");
- break;
- case nir_tex_src_projector:
- fprintf(fp, "(projector)");
- break;
- case nir_tex_src_comparitor:
- fprintf(fp, "(comparitor)");
- break;
- case nir_tex_src_offset:
- fprintf(fp, "(offset)");
- break;
- case nir_tex_src_bias:
- fprintf(fp, "(bias)");
- break;
- case nir_tex_src_lod:
- fprintf(fp, "(lod)");
- break;
- case nir_tex_src_ms_index:
- fprintf(fp, "(ms_index)");
- break;
- case nir_tex_src_ddx:
- fprintf(fp, "(ddx)");
- break;
- case nir_tex_src_ddy:
- fprintf(fp, "(ddy)");
- break;
- case nir_tex_src_texture_offset:
- fprintf(fp, "(texture_offset)");
- break;
- case nir_tex_src_sampler_offset:
- fprintf(fp, "(sampler_offset)");
- break;
-
- default:
- unreachable("Invalid texture source type");
- break;
- }
-
- fprintf(fp, ", ");
- }
-
- bool has_nonzero_offset = false;
- for (unsigned i = 0; i < 4; i++) {
- if (instr->const_offset[i] != 0) {
- has_nonzero_offset = true;
- break;
- }
- }
-
- if (has_nonzero_offset) {
- fprintf(fp, "[%i %i %i %i] (offset), ",
- instr->const_offset[0], instr->const_offset[1],
- instr->const_offset[2], instr->const_offset[3]);
- }
-
- if (instr->op == nir_texop_tg4) {
- fprintf(fp, "%u (gather_component), ", instr->component);
- }
-
- if (instr->texture) {
- assert(instr->sampler);
- fprintf(fp, " (texture)");
- }
- if (instr->sampler) {
- print_deref(instr->sampler, state);
- fprintf(fp, " (sampler)");
- } else {
- assert(instr->texture == NULL);
- fprintf(fp, "%u (texture) %u (sampler)",
- instr->texture_index, instr->sampler_index);
- }
-}
-
-static void
-print_call_instr(nir_call_instr *instr, print_state *state)
-{
- FILE *fp = state->fp;
-
- fprintf(fp, "call %s ", instr->callee->name);
-
- for (unsigned i = 0; i < instr->num_params; i++) {
- if (i != 0)
- fprintf(fp, ", ");
-
- print_deref(instr->params[i], state);
- }
-
- if (instr->return_deref != NULL) {
- if (instr->num_params != 0)
- fprintf(fp, ", ");
- fprintf(fp, "returning ");
- print_deref(instr->return_deref, state);
- }
-}
-
-static void
-print_load_const_instr(nir_load_const_instr *instr, print_state *state)
-{
- FILE *fp = state->fp;
-
- print_ssa_def(&instr->def, state);
-
- fprintf(fp, " = load_const (");
-
- for (unsigned i = 0; i < instr->def.num_components; i++) {
- if (i != 0)
- fprintf(fp, ", ");
-
- /*
- * we don't really know the type of the constant (if it will be used as a
- * float or an int), so just print the raw constant in hex for fidelity
- * and then print the float in a comment for readability.
- */
-
- fprintf(fp, "0x%08x /* %f */", instr->value.u[i], instr->value.f[i]);
- }
-
- fprintf(fp, ")");
-}
-
-static void
-print_jump_instr(nir_jump_instr *instr, print_state *state)
-{
- FILE *fp = state->fp;
-
- switch (instr->type) {
- case nir_jump_break:
- fprintf(fp, "break");
- break;
-
- case nir_jump_continue:
- fprintf(fp, "continue");
- break;
-
- case nir_jump_return:
- fprintf(fp, "return");
- break;
- }
-}
-
-static void
-print_ssa_undef_instr(nir_ssa_undef_instr* instr, print_state *state)
-{
- FILE *fp = state->fp;
- print_ssa_def(&instr->def, state);
- fprintf(fp, " = undefined");
-}
-
-static void
-print_phi_instr(nir_phi_instr *instr, print_state *state)
-{
- FILE *fp = state->fp;
- print_dest(&instr->dest, state);
- fprintf(fp, " = phi ");
- nir_foreach_phi_src(instr, src) {
- if (&src->node != exec_list_get_head(&instr->srcs))
- fprintf(fp, ", ");
-
- fprintf(fp, "block_%u: ", src->pred->index);
- print_src(&src->src, state);
- }
-}
-
-static void
-print_parallel_copy_instr(nir_parallel_copy_instr *instr, print_state *state)
-{
- FILE *fp = state->fp;
- nir_foreach_parallel_copy_entry(instr, entry) {
- if (&entry->node != exec_list_get_head(&instr->entries))
- fprintf(fp, "; ");
-
- print_dest(&entry->dest, state);
- fprintf(fp, " = ");
- print_src(&entry->src, state);
- }
-}
-
-static void
-print_instr(const nir_instr *instr, print_state *state, unsigned tabs)
-{
- FILE *fp = state->fp;
- print_tabs(tabs, fp);
-
- switch (instr->type) {
- case nir_instr_type_alu:
- print_alu_instr(nir_instr_as_alu(instr), state);
- break;
-
- case nir_instr_type_call:
- print_call_instr(nir_instr_as_call(instr), state);
- break;
-
- case nir_instr_type_intrinsic:
- print_intrinsic_instr(nir_instr_as_intrinsic(instr), state);
- break;
-
- case nir_instr_type_tex:
- print_tex_instr(nir_instr_as_tex(instr), state);
- break;
-
- case nir_instr_type_load_const:
- print_load_const_instr(nir_instr_as_load_const(instr), state);
- break;
-
- case nir_instr_type_jump:
- print_jump_instr(nir_instr_as_jump(instr), state);
- break;
-
- case nir_instr_type_ssa_undef:
- print_ssa_undef_instr(nir_instr_as_ssa_undef(instr), state);
- break;
-
- case nir_instr_type_phi:
- print_phi_instr(nir_instr_as_phi(instr), state);
- break;
-
- case nir_instr_type_parallel_copy:
- print_parallel_copy_instr(nir_instr_as_parallel_copy(instr), state);
- break;
-
- default:
- unreachable("Invalid instruction type");
- break;
- }
-}
-
-static int
-compare_block_index(const void *p1, const void *p2)
-{
- const nir_block *block1 = *((const nir_block **) p1);
- const nir_block *block2 = *((const nir_block **) p2);
-
- return (int) block1->index - (int) block2->index;
-}
-
-static void print_cf_node(nir_cf_node *node, print_state *state,
- unsigned tabs);
-
-static void
-print_block(nir_block *block, print_state *state, unsigned tabs)
-{
- FILE *fp = state->fp;
-
- print_tabs(tabs, fp);
- fprintf(fp, "block block_%u:\n", block->index);
-
- /* sort the predecessors by index so we consistently print the same thing */
-
- nir_block **preds =
- malloc(block->predecessors->entries * sizeof(nir_block *));
-
- struct set_entry *entry;
- unsigned i = 0;
- set_foreach(block->predecessors, entry) {
- preds[i++] = (nir_block *) entry->key;
- }
-
- qsort(preds, block->predecessors->entries, sizeof(nir_block *),
- compare_block_index);
-
- print_tabs(tabs, fp);
- fprintf(fp, "/* preds: ");
- for (unsigned i = 0; i < block->predecessors->entries; i++) {
- fprintf(fp, "block_%u ", preds[i]->index);
- }
- fprintf(fp, "*/\n");
-
- free(preds);
-
- nir_foreach_instr(block, instr) {
- print_instr(instr, state, tabs);
- fprintf(fp, "\n");
- }
-
- print_tabs(tabs, fp);
- fprintf(fp, "/* succs: ");
- for (unsigned i = 0; i < 2; i++)
- if (block->successors[i]) {
- fprintf(fp, "block_%u ", block->successors[i]->index);
- }
- fprintf(fp, "*/\n");
-}
-
-static void
-print_if(nir_if *if_stmt, print_state *state, unsigned tabs)
-{
- FILE *fp = state->fp;
-
- print_tabs(tabs, fp);
- fprintf(fp, "if ");
- print_src(&if_stmt->condition, state);
- fprintf(fp, " {\n");
- foreach_list_typed(nir_cf_node, node, node, &if_stmt->then_list) {
- print_cf_node(node, state, tabs + 1);
- }
- print_tabs(tabs, fp);
- fprintf(fp, "} else {\n");
- foreach_list_typed(nir_cf_node, node, node, &if_stmt->else_list) {
- print_cf_node(node, state, tabs + 1);
- }
- print_tabs(tabs, fp);
- fprintf(fp, "}\n");
-}
-
-static void
-print_loop(nir_loop *loop, print_state *state, unsigned tabs)
-{
- FILE *fp = state->fp;
-
- print_tabs(tabs, fp);
- fprintf(fp, "loop {\n");
- foreach_list_typed(nir_cf_node, node, node, &loop->body) {
- print_cf_node(node, state, tabs + 1);
- }
- print_tabs(tabs, fp);
- fprintf(fp, "}\n");
-}
-
-static void
-print_cf_node(nir_cf_node *node, print_state *state, unsigned int tabs)
-{
- switch (node->type) {
- case nir_cf_node_block:
- print_block(nir_cf_node_as_block(node), state, tabs);
- break;
-
- case nir_cf_node_if:
- print_if(nir_cf_node_as_if(node), state, tabs);
- break;
-
- case nir_cf_node_loop:
- print_loop(nir_cf_node_as_loop(node), state, tabs);
- break;
-
- default:
- unreachable("Invalid CFG node type");
- }
-}
-
-static void
-print_function_impl(nir_function_impl *impl, print_state *state)
-{
- FILE *fp = state->fp;
-
- fprintf(fp, "\nimpl %s ", impl->function->name);
-
- for (unsigned i = 0; i < impl->num_params; i++) {
- if (i != 0)
- fprintf(fp, ", ");
-
- print_var(impl->params[i], state);
- }
-
- if (impl->return_var != NULL) {
- if (impl->num_params != 0)
- fprintf(fp, ", ");
- fprintf(fp, "returning ");
- print_var(impl->return_var, state);
- }
-
- fprintf(fp, "{\n");
-
- nir_foreach_variable(var, &impl->locals) {
- fprintf(fp, "\t");
- print_var_decl(var, state);
- }
-
- foreach_list_typed(nir_register, reg, node, &impl->registers) {
- fprintf(fp, "\t");
- print_register_decl(reg, state);
- }
-
- nir_index_blocks(impl);
-
- foreach_list_typed(nir_cf_node, node, node, &impl->body) {
- print_cf_node(node, state, 1);
- }
-
- fprintf(fp, "\tblock block_%u:\n}\n\n", impl->end_block->index);
-}
-
-static void
-print_function(nir_function *function, print_state *state)
-{
- FILE *fp = state->fp;
-
- fprintf(fp, "decl_function %s ", function->name);
-
- for (unsigned i = 0; i < function->num_params; i++) {
- if (i != 0)
- fprintf(fp, ", ");
-
- switch (function->params[i].param_type) {
- case nir_parameter_in:
- fprintf(fp, "in ");
- break;
- case nir_parameter_out:
- fprintf(fp, "out ");
- break;
- case nir_parameter_inout:
- fprintf(fp, "inout ");
- break;
- default:
- unreachable("Invalid parameter type");
- }
-
- glsl_print_type(function->params[i].type, fp);
- }
-
- if (function->return_type != NULL) {
- if (function->num_params != 0)
- fprintf(fp, ", ");
- fprintf(fp, "returning ");
- glsl_print_type(function->return_type, fp);
- }
-
- fprintf(fp, "\n");
-
- if (function->impl != NULL) {
- print_function_impl(function->impl, state);
- return;
- }
-}
-
-static void
-init_print_state(print_state *state, nir_shader *shader, FILE *fp)
-{
- state->fp = fp;
- state->shader = shader;
- state->ht = _mesa_hash_table_create(NULL, _mesa_hash_pointer,
- _mesa_key_pointer_equal);
- state->syms = _mesa_set_create(NULL, _mesa_key_hash_string,
- _mesa_key_string_equal);
- state->index = 0;
-}
-
-static void
-destroy_print_state(print_state *state)
-{
- _mesa_hash_table_destroy(state->ht, NULL);
- _mesa_set_destroy(state->syms, NULL);
-}
-
-void
-nir_print_shader(nir_shader *shader, FILE *fp)
-{
- print_state state;
- init_print_state(&state, shader, fp);
-
- fprintf(fp, "shader: %s\n", gl_shader_stage_name(shader->stage));
-
- if (shader->info.name)
- fprintf(fp, "name: %s\n", shader->info.name);
-
- if (shader->info.label)
- fprintf(fp, "label: %s\n", shader->info.label);
-
- fprintf(fp, "inputs: %u\n", shader->num_inputs);
- fprintf(fp, "outputs: %u\n", shader->num_outputs);
- fprintf(fp, "uniforms: %u\n", shader->num_uniforms);
- fprintf(fp, "shared: %u\n", shader->num_shared);
-
- nir_foreach_variable(var, &shader->uniforms) {
- print_var_decl(var, &state);
- }
-
- nir_foreach_variable(var, &shader->inputs) {
- print_var_decl(var, &state);
- }
-
- nir_foreach_variable(var, &shader->outputs) {
- print_var_decl(var, &state);
- }
-
- nir_foreach_variable(var, &shader->shared) {
- print_var_decl(var, &state);
- }
-
- nir_foreach_variable(var, &shader->globals) {
- print_var_decl(var, &state);
- }
-
- nir_foreach_variable(var, &shader->system_values) {
- print_var_decl(var, &state);
- }
-
- foreach_list_typed(nir_register, reg, node, &shader->registers) {
- print_register_decl(reg, &state);
- }
-
- foreach_list_typed(nir_function, func, node, &shader->functions) {
- print_function(func, &state);
- }
-
- destroy_print_state(&state);
-}
-
-void
-nir_print_instr(const nir_instr *instr, FILE *fp)
-{
- print_state state = {
- .fp = fp,
- };
- print_instr(instr, &state, 0);
-
-}
diff --git a/src/glsl/nir/nir_remove_dead_variables.c b/src/glsl/nir/nir_remove_dead_variables.c
deleted file mode 100644
index 792c5d4aae6..00000000000
--- a/src/glsl/nir/nir_remove_dead_variables.c
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * Copyright © 2014 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- *
- * Authors:
- * Connor Abbott ([email protected])
- *
- */
-
-#include "nir.h"
-
-static void
-add_var_use_intrinsic(nir_intrinsic_instr *instr, struct set *live)
-{
- unsigned num_vars = nir_intrinsic_infos[instr->intrinsic].num_variables;
- for (unsigned i = 0; i < num_vars; i++) {
- nir_variable *var = instr->variables[i]->var;
- _mesa_set_add(live, var);
- }
-}
-
-static void
-add_var_use_call(nir_call_instr *instr, struct set *live)
-{
- if (instr->return_deref != NULL) {
- nir_variable *var = instr->return_deref->var;
- _mesa_set_add(live, var);
- }
-
- for (unsigned i = 0; i < instr->num_params; i++) {
- nir_variable *var = instr->params[i]->var;
- _mesa_set_add(live, var);
- }
-}
-
-static void
-add_var_use_tex(nir_tex_instr *instr, struct set *live)
-{
- if (instr->sampler != NULL) {
- nir_variable *var = instr->sampler->var;
- _mesa_set_add(live, var);
- }
-}
-
-static bool
-add_var_use_block(nir_block *block, void *state)
-{
- struct set *live = state;
-
- nir_foreach_instr(block, instr) {
- switch(instr->type) {
- case nir_instr_type_intrinsic:
- add_var_use_intrinsic(nir_instr_as_intrinsic(instr), live);
- break;
-
- case nir_instr_type_call:
- add_var_use_call(nir_instr_as_call(instr), live);
- break;
-
- case nir_instr_type_tex:
- add_var_use_tex(nir_instr_as_tex(instr), live);
- break;
-
- default:
- break;
- }
- }
-
- return true;
-}
-
-static void
-add_var_use_shader(nir_shader *shader, struct set *live)
-{
- nir_foreach_function(shader, function) {
- if (function->impl) {
- nir_foreach_block(function->impl, add_var_use_block, live);
- }
- }
-}
-
-static bool
-remove_dead_vars(struct exec_list *var_list, struct set *live)
-{
- bool progress = false;
-
- foreach_list_typed_safe(nir_variable, var, node, var_list) {
- struct set_entry *entry = _mesa_set_search(live, var);
- if (entry == NULL) {
- exec_node_remove(&var->node);
- ralloc_free(var);
- progress = true;
- }
- }
-
- return progress;
-}
-
-bool
-nir_remove_dead_variables(nir_shader *shader, nir_variable_mode mode)
-{
- bool progress = false;
- struct set *live =
- _mesa_set_create(NULL, _mesa_hash_pointer, _mesa_key_pointer_equal);
-
- add_var_use_shader(shader, live);
-
- if (mode == nir_var_uniform || mode == nir_var_all)
- progress = remove_dead_vars(&shader->uniforms, live) || progress;
-
- if (mode == nir_var_shader_in || mode == nir_var_all)
- progress = remove_dead_vars(&shader->inputs, live) || progress;
-
- if (mode == nir_var_shader_out || mode == nir_var_all)
- progress = remove_dead_vars(&shader->outputs, live) || progress;
-
- if (mode == nir_var_global || mode == nir_var_all)
- progress = remove_dead_vars(&shader->globals, live) || progress;
-
- if (mode == nir_var_system_value || mode == nir_var_all)
- progress = remove_dead_vars(&shader->system_values, live) || progress;
-
- if (mode == nir_var_local || mode == nir_var_all) {
- nir_foreach_function(shader, function) {
- if (function->impl) {
- if (remove_dead_vars(&function->impl->locals, live)) {
- nir_metadata_preserve(function->impl, nir_metadata_block_index |
- nir_metadata_dominance |
- nir_metadata_live_ssa_defs);
- progress = true;
- }
- }
- }
- }
-
- _mesa_set_destroy(live, NULL);
- return progress;
-}
diff --git a/src/glsl/nir/nir_repair_ssa.c b/src/glsl/nir/nir_repair_ssa.c
deleted file mode 100644
index 3ab4f0f6db7..00000000000
--- a/src/glsl/nir/nir_repair_ssa.c
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * Copyright © 2016 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include "nir.h"
-#include "nir_phi_builder.h"
-
-struct repair_ssa_state {
- nir_function_impl *impl;
-
- BITSET_WORD *def_set;
- struct nir_phi_builder *phi_builder;
-
- bool progress;
-};
-
-/* Get ready to build a phi and return the builder */
-static struct nir_phi_builder *
-prep_build_phi(struct repair_ssa_state *state)
-{
- const unsigned num_words = BITSET_WORDS(state->impl->num_blocks);
-
- /* We create the phi builder on-demand. */
- if (state->phi_builder == NULL) {
- state->phi_builder = nir_phi_builder_create(state->impl);
- state->def_set = ralloc_array(NULL, BITSET_WORD, num_words);
- }
-
- /* We're going to build a phi. That's progress. */
- state->progress = true;
-
- /* Set the defs set to empty */
- memset(state->def_set, 0, num_words * sizeof(*state->def_set));
-
- return state->phi_builder;
-}
-
-static nir_block *
-get_src_block(nir_src *src)
-{
- if (src->parent_instr->type == nir_instr_type_phi) {
- return exec_node_data(nir_phi_src, src, src)->pred;
- } else {
- return src->parent_instr->block;
- }
-}
-
-static bool
-repair_ssa_def(nir_ssa_def *def, void *void_state)
-{
- struct repair_ssa_state *state = void_state;
-
- bool is_valid = true;
- nir_foreach_use(def, src) {
- if (!nir_block_dominates(def->parent_instr->block, get_src_block(src))) {
- is_valid = false;
- break;
- }
- }
-
- if (is_valid)
- return true;
-
- struct nir_phi_builder *pb = prep_build_phi(state);
-
- BITSET_SET(state->def_set, def->parent_instr->block->index);
-
- struct nir_phi_builder_value *val =
- nir_phi_builder_add_value(pb, def->num_components, state->def_set);
-
- nir_phi_builder_value_set_block_def(val, def->parent_instr->block, def);
-
- nir_foreach_use_safe(def, src) {
- nir_block *src_block = get_src_block(src);
- if (!nir_block_dominates(def->parent_instr->block, src_block)) {
- nir_instr_rewrite_src(src->parent_instr, src, nir_src_for_ssa(
- nir_phi_builder_value_get_block_def(val, src_block)));
- }
- }
-
- return true;
-}
-
-static bool
-repair_ssa_block(nir_block *block, void *state)
-{
- nir_foreach_instr_safe(block, instr) {
- nir_foreach_ssa_def(instr, repair_ssa_def, state);
- }
-
- return true;
-}
-
-bool
-nir_repair_ssa_impl(nir_function_impl *impl)
-{
- struct repair_ssa_state state;
-
- state.impl = impl;
- state.phi_builder = NULL;
- state.progress = false;
-
- nir_metadata_require(impl, nir_metadata_block_index |
- nir_metadata_dominance);
-
- nir_foreach_block(impl, repair_ssa_block, &state);
-
- if (state.progress)
- nir_metadata_preserve(impl, nir_metadata_block_index |
- nir_metadata_dominance);
-
- if (state.phi_builder) {
- nir_phi_builder_finish(state.phi_builder);
- ralloc_free(state.def_set);
- }
-
- return state.progress;
-}
-
-/** This pass can be used to repair SSA form in a shader.
- *
- * Sometimes a transformation (such as return lowering) will have to make
- * changes to a shader which, while still correct, break some of NIR's SSA
- * invariants. This pass will insert ssa_undefs and phi nodes as needed to
- * get the shader back into SSA that the validator will like.
- */
-bool
-nir_repair_ssa(nir_shader *shader)
-{
- bool progress = false;
-
- nir_foreach_function(shader, function) {
- if (function->impl)
- progress = nir_repair_ssa_impl(function->impl) || progress;
- }
-
- return progress;
-}
diff --git a/src/glsl/nir/nir_search.c b/src/glsl/nir/nir_search.c
deleted file mode 100644
index 56d7e8162f3..00000000000
--- a/src/glsl/nir/nir_search.c
+++ /dev/null
@@ -1,379 +0,0 @@
-/*
- * Copyright © 2014 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- *
- * Authors:
- * Jason Ekstrand ([email protected])
- *
- */
-
-#include "nir_search.h"
-
-struct match_state {
- unsigned variables_seen;
- nir_alu_src variables[NIR_SEARCH_MAX_VARIABLES];
-};
-
-static bool
-match_expression(const nir_search_expression *expr, nir_alu_instr *instr,
- unsigned num_components, const uint8_t *swizzle,
- struct match_state *state);
-
-static const uint8_t identity_swizzle[] = { 0, 1, 2, 3 };
-
-static bool alu_instr_is_bool(nir_alu_instr *instr);
-
-static bool
-src_is_bool(nir_src src)
-{
- if (!src.is_ssa)
- return false;
- if (src.ssa->parent_instr->type != nir_instr_type_alu)
- return false;
- return alu_instr_is_bool(nir_instr_as_alu(src.ssa->parent_instr));
-}
-
-static bool
-alu_instr_is_bool(nir_alu_instr *instr)
-{
- switch (instr->op) {
- case nir_op_iand:
- case nir_op_ior:
- case nir_op_ixor:
- return src_is_bool(instr->src[0].src) && src_is_bool(instr->src[1].src);
- case nir_op_inot:
- return src_is_bool(instr->src[0].src);
- default:
- return nir_op_infos[instr->op].output_type == nir_type_bool;
- }
-}
-
-static bool
-match_value(const nir_search_value *value, nir_alu_instr *instr, unsigned src,
- unsigned num_components, const uint8_t *swizzle,
- struct match_state *state)
-{
- uint8_t new_swizzle[4];
-
- /* If the source is an explicitly sized source, then we need to reset
- * both the number of components and the swizzle.
- */
- if (nir_op_infos[instr->op].input_sizes[src] != 0) {
- num_components = nir_op_infos[instr->op].input_sizes[src];
- swizzle = identity_swizzle;
- }
-
- for (unsigned i = 0; i < num_components; ++i)
- new_swizzle[i] = instr->src[src].swizzle[swizzle[i]];
-
- switch (value->type) {
- case nir_search_value_expression:
- if (!instr->src[src].src.is_ssa)
- return false;
-
- if (instr->src[src].src.ssa->parent_instr->type != nir_instr_type_alu)
- return false;
-
- return match_expression(nir_search_value_as_expression(value),
- nir_instr_as_alu(instr->src[src].src.ssa->parent_instr),
- num_components, new_swizzle, state);
-
- case nir_search_value_variable: {
- nir_search_variable *var = nir_search_value_as_variable(value);
- assert(var->variable < NIR_SEARCH_MAX_VARIABLES);
-
- if (state->variables_seen & (1 << var->variable)) {
- if (!nir_srcs_equal(state->variables[var->variable].src,
- instr->src[src].src))
- return false;
-
- assert(!instr->src[src].abs && !instr->src[src].negate);
-
- for (unsigned i = 0; i < num_components; ++i) {
- if (state->variables[var->variable].swizzle[i] != new_swizzle[i])
- return false;
- }
-
- return true;
- } else {
- if (var->is_constant &&
- instr->src[src].src.ssa->parent_instr->type != nir_instr_type_load_const)
- return false;
-
- if (var->type != nir_type_invalid) {
- if (instr->src[src].src.ssa->parent_instr->type != nir_instr_type_alu)
- return false;
-
- nir_alu_instr *src_alu =
- nir_instr_as_alu(instr->src[src].src.ssa->parent_instr);
-
- if (nir_op_infos[src_alu->op].output_type != var->type &&
- !(var->type == nir_type_bool && alu_instr_is_bool(src_alu)))
- return false;
- }
-
- state->variables_seen |= (1 << var->variable);
- state->variables[var->variable].src = instr->src[src].src;
- state->variables[var->variable].abs = false;
- state->variables[var->variable].negate = false;
-
- for (unsigned i = 0; i < 4; ++i) {
- if (i < num_components)
- state->variables[var->variable].swizzle[i] = new_swizzle[i];
- else
- state->variables[var->variable].swizzle[i] = 0;
- }
-
- return true;
- }
- }
-
- case nir_search_value_constant: {
- nir_search_constant *const_val = nir_search_value_as_constant(value);
-
- if (!instr->src[src].src.is_ssa)
- return false;
-
- if (instr->src[src].src.ssa->parent_instr->type != nir_instr_type_load_const)
- return false;
-
- nir_load_const_instr *load =
- nir_instr_as_load_const(instr->src[src].src.ssa->parent_instr);
-
- switch (nir_op_infos[instr->op].input_types[src]) {
- case nir_type_float:
- for (unsigned i = 0; i < num_components; ++i) {
- if (load->value.f[new_swizzle[i]] != const_val->data.f)
- return false;
- }
- return true;
- case nir_type_int:
- case nir_type_uint:
- case nir_type_bool:
- for (unsigned i = 0; i < num_components; ++i) {
- if (load->value.i[new_swizzle[i]] != const_val->data.i)
- return false;
- }
- return true;
- default:
- unreachable("Invalid alu source type");
- }
- }
-
- default:
- unreachable("Invalid search value type");
- }
-}
-
-static bool
-match_expression(const nir_search_expression *expr, nir_alu_instr *instr,
- unsigned num_components, const uint8_t *swizzle,
- struct match_state *state)
-{
- if (instr->op != expr->opcode)
- return false;
-
- assert(!instr->dest.saturate);
- assert(nir_op_infos[instr->op].num_inputs > 0);
-
- /* If we have an explicitly sized destination, we can only handle the
- * identity swizzle. While dot(vec3(a, b, c).zxy) is a valid
- * expression, we don't have the information right now to propagate that
- * swizzle through. We can only properly propagate swizzles if the
- * instruction is vectorized.
- */
- if (nir_op_infos[instr->op].output_size != 0) {
- for (unsigned i = 0; i < num_components; i++) {
- if (swizzle[i] != i)
- return false;
- }
- }
-
- /* Stash off the current variables_seen bitmask. This way we can
- * restore it prior to matching in the commutative case below.
- */
- unsigned variables_seen_stash = state->variables_seen;
-
- bool matched = true;
- for (unsigned i = 0; i < nir_op_infos[instr->op].num_inputs; i++) {
- if (!match_value(expr->srcs[i], instr, i, num_components,
- swizzle, state)) {
- matched = false;
- break;
- }
- }
-
- if (matched)
- return true;
-
- if (nir_op_infos[instr->op].algebraic_properties & NIR_OP_IS_COMMUTATIVE) {
- assert(nir_op_infos[instr->op].num_inputs == 2);
-
- /* Restore the variables_seen bitmask. If we don't do this, then we
- * could end up with an erroneous failure due to variables found in the
- * first match attempt above not matching those in the second.
- */
- state->variables_seen = variables_seen_stash;
-
- if (!match_value(expr->srcs[0], instr, 1, num_components,
- swizzle, state))
- return false;
-
- return match_value(expr->srcs[1], instr, 0, num_components,
- swizzle, state);
- } else {
- return false;
- }
-}
-
-static nir_alu_src
-construct_value(const nir_search_value *value, nir_alu_type type,
- unsigned num_components, struct match_state *state,
- nir_instr *instr, void *mem_ctx)
-{
- switch (value->type) {
- case nir_search_value_expression: {
- const nir_search_expression *expr = nir_search_value_as_expression(value);
-
- if (nir_op_infos[expr->opcode].output_size != 0)
- num_components = nir_op_infos[expr->opcode].output_size;
-
- nir_alu_instr *alu = nir_alu_instr_create(mem_ctx, expr->opcode);
- nir_ssa_dest_init(&alu->instr, &alu->dest.dest, num_components, NULL);
- alu->dest.write_mask = (1 << num_components) - 1;
- alu->dest.saturate = false;
-
- for (unsigned i = 0; i < nir_op_infos[expr->opcode].num_inputs; i++) {
- /* If the source is an explicitly sized source, then we need to reset
- * the number of components to match.
- */
- if (nir_op_infos[alu->op].input_sizes[i] != 0)
- num_components = nir_op_infos[alu->op].input_sizes[i];
-
- alu->src[i] = construct_value(expr->srcs[i],
- nir_op_infos[alu->op].input_types[i],
- num_components,
- state, instr, mem_ctx);
- }
-
- nir_instr_insert_before(instr, &alu->instr);
-
- nir_alu_src val;
- val.src = nir_src_for_ssa(&alu->dest.dest.ssa);
- val.negate = false;
- val.abs = false,
- memcpy(val.swizzle, identity_swizzle, sizeof val.swizzle);
-
- return val;
- }
-
- case nir_search_value_variable: {
- const nir_search_variable *var = nir_search_value_as_variable(value);
- assert(state->variables_seen & (1 << var->variable));
-
- nir_alu_src val = { NIR_SRC_INIT };
- nir_alu_src_copy(&val, &state->variables[var->variable], mem_ctx);
-
- assert(!var->is_constant);
-
- return val;
- }
-
- case nir_search_value_constant: {
- const nir_search_constant *c = nir_search_value_as_constant(value);
- nir_load_const_instr *load = nir_load_const_instr_create(mem_ctx, 1);
-
- switch (type) {
- case nir_type_float:
- load->def.name = ralloc_asprintf(mem_ctx, "%f", c->data.f);
- load->value.f[0] = c->data.f;
- break;
- case nir_type_int:
- load->def.name = ralloc_asprintf(mem_ctx, "%d", c->data.i);
- load->value.i[0] = c->data.i;
- break;
- case nir_type_uint:
- case nir_type_bool:
- load->value.u[0] = c->data.u;
- break;
- default:
- unreachable("Invalid alu source type");
- }
-
- nir_instr_insert_before(instr, &load->instr);
-
- nir_alu_src val;
- val.src = nir_src_for_ssa(&load->def);
- val.negate = false;
- val.abs = false,
- memset(val.swizzle, 0, sizeof val.swizzle);
-
- return val;
- }
-
- default:
- unreachable("Invalid search value type");
- }
-}
-
-nir_alu_instr *
-nir_replace_instr(nir_alu_instr *instr, const nir_search_expression *search,
- const nir_search_value *replace, void *mem_ctx)
-{
- uint8_t swizzle[4] = { 0, 0, 0, 0 };
-
- for (unsigned i = 0; i < instr->dest.dest.ssa.num_components; ++i)
- swizzle[i] = i;
-
- assert(instr->dest.dest.is_ssa);
-
- struct match_state state;
- state.variables_seen = 0;
-
- if (!match_expression(search, instr, instr->dest.dest.ssa.num_components,
- swizzle, &state))
- return NULL;
-
- /* Inserting a mov may be unnecessary. However, it's much easier to
- * simply let copy propagation clean this up than to try to go through
- * and rewrite swizzles ourselves.
- */
- nir_alu_instr *mov = nir_alu_instr_create(mem_ctx, nir_op_imov);
- mov->dest.write_mask = instr->dest.write_mask;
- nir_ssa_dest_init(&mov->instr, &mov->dest.dest,
- instr->dest.dest.ssa.num_components, NULL);
-
- mov->src[0] = construct_value(replace, nir_op_infos[instr->op].output_type,
- instr->dest.dest.ssa.num_components, &state,
- &instr->instr, mem_ctx);
- nir_instr_insert_before(&instr->instr, &mov->instr);
-
- nir_ssa_def_rewrite_uses(&instr->dest.dest.ssa,
- nir_src_for_ssa(&mov->dest.dest.ssa));
-
- /* We know this one has no more uses because we just rewrote them all,
- * so we can remove it. The rest of the matched expression, however, we
- * don't know so much about. We'll just let dead code clean them up.
- */
- nir_instr_remove(&instr->instr);
-
- return mov;
-}
diff --git a/src/glsl/nir/nir_search.h b/src/glsl/nir/nir_search.h
deleted file mode 100644
index 7d47792945e..00000000000
--- a/src/glsl/nir/nir_search.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright © 2014 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- *
- * Authors:
- * Jason Ekstrand ([email protected])
- *
- */
-
-#ifndef _NIR_SEARCH_
-#define _NIR_SEARCH_
-
-#include "nir.h"
-
-#define NIR_SEARCH_MAX_VARIABLES 16
-
-typedef enum {
- nir_search_value_expression,
- nir_search_value_variable,
- nir_search_value_constant,
-} nir_search_value_type;
-
-typedef struct {
- nir_search_value_type type;
-} nir_search_value;
-
-typedef struct {
- nir_search_value value;
-
- /** The variable index; Must be less than NIR_SEARCH_MAX_VARIABLES */
- unsigned variable;
-
- /** Indicates that the given variable must be a constant
- *
- * This is only alloed in search expressions and indicates that the
- * given variable is only allowed to match constant values.
- */
- bool is_constant;
-
- /** Indicates that the given variable must have a certain type
- *
- * This is only allowed in search expressions and indicates that the
- * given variable is only allowed to match values that come from an ALU
- * instruction with the given output type. A type of nir_type_void
- * means it can match any type.
- *
- * Note: A variable that is both constant and has a non-void type will
- * never match anything.
- */
- nir_alu_type type;
-} nir_search_variable;
-
-typedef struct {
- nir_search_value value;
-
- union {
- uint32_t u;
- int32_t i;
- float f;
- } data;
-} nir_search_constant;
-
-typedef struct {
- nir_search_value value;
-
- nir_op opcode;
- const nir_search_value *srcs[4];
-} nir_search_expression;
-
-NIR_DEFINE_CAST(nir_search_value_as_variable, nir_search_value,
- nir_search_variable, value)
-NIR_DEFINE_CAST(nir_search_value_as_constant, nir_search_value,
- nir_search_constant, value)
-NIR_DEFINE_CAST(nir_search_value_as_expression, nir_search_value,
- nir_search_expression, value)
-
-nir_alu_instr *
-nir_replace_instr(nir_alu_instr *instr, const nir_search_expression *search,
- const nir_search_value *replace, void *mem_ctx);
-
-#endif /* _NIR_SEARCH_ */
diff --git a/src/glsl/nir/nir_split_var_copies.c b/src/glsl/nir/nir_split_var_copies.c
deleted file mode 100644
index 6fdaefa32c8..00000000000
--- a/src/glsl/nir/nir_split_var_copies.c
+++ /dev/null
@@ -1,285 +0,0 @@
-/*
- * Copyright © 2014 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- *
- * Authors:
- * Jason Ekstrand ([email protected])
- *
- */
-
-#include "nir.h"
-
-/*
- * Implements "copy splitting" which is similar to structure splitting only
- * it works on copy operations rather than the datatypes themselves. The
- * GLSL language allows you to copy one variable to another an entire
- * structure (which may contain arrays or other structures) at a time.
- * Normally, in a language such as C this would be handled by a "structure
- * splitting" pass that breaks up the structures. Unfortunately for us,
- * structures used in inputs or outputs can't be split. Therefore,
- * regardlesss of what we do, we have to be able to copy to/from
- * structures.
- *
- * The primary purpose of structure splitting is to allow you to better
- * optimize variable access and lower things to registers where you can.
- * The primary issue here is that, if you lower the copy to a bunch of
- * loads and stores, you loose a lot of information about the copy
- * operation that you would like to keep around. To solve this problem, we
- * have a "copy splitting" pass that, instead of splitting the structures
- * or lowering the copy into loads and storres, splits the copy operation
- * into a bunch of copy operations one for each leaf of the structure tree.
- * If an intermediate array is encountered, it is referenced with a
- * wildcard reference to indicate that the entire array is to be copied.
- *
- * As things become direct, array copies may be able to be losslessly
- * lowered to having fewer and fewer wildcards. However, until that
- * happens we want to keep the information about the arrays intact.
- *
- * Prior to the copy splitting pass, there are no wildcard references but
- * there may be incomplete references where the tail of the deref chain is
- * an array or a structure and not a specific element. After the copy
- * splitting pass has completed, every variable deref will be a full-length
- * dereference pointing to a single leaf in the structure type tree with
- * possibly a few wildcard array dereferences.
- */
-
-struct split_var_copies_state {
- void *mem_ctx;
- void *dead_ctx;
- bool progress;
-};
-
-/* Recursively constructs deref chains to split a copy instruction into
- * multiple (if needed) copy instructions with full-length deref chains.
- * External callers of this function should pass the tail and head of the
- * deref chains found as the source and destination of the copy instruction
- * into this function.
- *
- * \param old_copy The copy instruction we are splitting
- * \param dest_head The head of the destination deref chain we are building
- * \param src_head The head of the source deref chain we are building
- * \param dest_tail The tail of the destination deref chain we are building
- * \param src_tail The tail of the source deref chain we are building
- * \param state The current split_var_copies_state object
- */
-static void
-split_var_copy_instr(nir_intrinsic_instr *old_copy,
- nir_deref *dest_head, nir_deref *src_head,
- nir_deref *dest_tail, nir_deref *src_tail,
- struct split_var_copies_state *state)
-{
- assert(src_tail->type == dest_tail->type);
-
- /* Make sure these really are the tails of the deref chains */
- assert(dest_tail->child == NULL);
- assert(src_tail->child == NULL);
-
- switch (glsl_get_base_type(src_tail->type)) {
- case GLSL_TYPE_ARRAY: {
- /* Make a wildcard dereference */
- nir_deref_array *deref = nir_deref_array_create(state->dead_ctx);
- deref->deref.type = glsl_get_array_element(src_tail->type);
- deref->deref_array_type = nir_deref_array_type_wildcard;
-
- /* Set the tail of both as the newly created wildcard deref. It is
- * safe to use the same wildcard in both places because a) we will be
- * copying it before we put it in an actual instruction and b)
- * everything that will potentially add another link in the deref
- * chain will also add the same thing to both chains.
- */
- src_tail->child = &deref->deref;
- dest_tail->child = &deref->deref;
-
- split_var_copy_instr(old_copy, dest_head, src_head,
- dest_tail->child, src_tail->child, state);
-
- /* Set it back to the way we found it */
- src_tail->child = NULL;
- dest_tail->child = NULL;
- break;
- }
-
- case GLSL_TYPE_STRUCT:
- /* This is the only part that actually does any interesting
- * splitting. For array types, we just use wildcards and resolve
- * them later. For structure types, we need to emit one copy
- * instruction for every structure element. Because we may have
- * structs inside structs, we just recurse and let the next level
- * take care of any additional structures.
- */
- for (unsigned i = 0; i < glsl_get_length(src_tail->type); i++) {
- nir_deref_struct *deref = nir_deref_struct_create(state->dead_ctx, i);
- deref->deref.type = glsl_get_struct_field(src_tail->type, i);
-
- /* Set the tail of both as the newly created structure deref. It
- * is safe to use the same wildcard in both places because a) we
- * will be copying it before we put it in an actual instruction
- * and b) everything that will potentially add another link in the
- * deref chain will also add the same thing to both chains.
- */
- src_tail->child = &deref->deref;
- dest_tail->child = &deref->deref;
-
- split_var_copy_instr(old_copy, dest_head, src_head,
- dest_tail->child, src_tail->child, state);
- }
- /* Set it back to the way we found it */
- src_tail->child = NULL;
- dest_tail->child = NULL;
- break;
-
- case GLSL_TYPE_UINT:
- case GLSL_TYPE_INT:
- case GLSL_TYPE_FLOAT:
- case GLSL_TYPE_BOOL:
- if (glsl_type_is_matrix(src_tail->type)) {
- nir_deref_array *deref = nir_deref_array_create(state->dead_ctx);
- deref->deref.type = glsl_get_column_type(src_tail->type);
- deref->deref_array_type = nir_deref_array_type_wildcard;
-
- /* Set the tail of both as the newly created wildcard deref. It
- * is safe to use the same wildcard in both places because a) we
- * will be copying it before we put it in an actual instruction
- * and b) everything that will potentially add another link in the
- * deref chain will also add the same thing to both chains.
- */
- src_tail->child = &deref->deref;
- dest_tail->child = &deref->deref;
-
- split_var_copy_instr(old_copy, dest_head, src_head,
- dest_tail->child, src_tail->child, state);
-
- /* Set it back to the way we found it */
- src_tail->child = NULL;
- dest_tail->child = NULL;
- } else {
- /* At this point, we have fully built our deref chains and can
- * actually add the new copy instruction.
- */
- nir_intrinsic_instr *new_copy =
- nir_intrinsic_instr_create(state->mem_ctx, nir_intrinsic_copy_var);
-
- /* We need to make copies because a) this deref chain actually
- * belongs to the copy instruction and b) the deref chains may
- * have some of the same links due to the way we constructed them
- */
- nir_deref *src = nir_copy_deref(new_copy, src_head);
- nir_deref *dest = nir_copy_deref(new_copy, dest_head);
-
- new_copy->variables[0] = nir_deref_as_var(dest);
- new_copy->variables[1] = nir_deref_as_var(src);
-
- /* Emit the copy instruction after the old instruction. We'll
- * remove the old one later.
- */
- nir_instr_insert_after(&old_copy->instr, &new_copy->instr);
- state->progress = true;
- }
- break;
-
- case GLSL_TYPE_SAMPLER:
- case GLSL_TYPE_IMAGE:
- case GLSL_TYPE_ATOMIC_UINT:
- case GLSL_TYPE_INTERFACE:
- default:
- unreachable("Cannot copy these types");
- }
-}
-
-static bool
-split_var_copies_block(nir_block *block, void *void_state)
-{
- struct split_var_copies_state *state = void_state;
-
- nir_foreach_instr_safe(block, instr) {
- if (instr->type != nir_instr_type_intrinsic)
- continue;
-
- nir_intrinsic_instr *intrinsic = nir_instr_as_intrinsic(instr);
- if (intrinsic->intrinsic != nir_intrinsic_copy_var)
- continue;
-
- nir_deref *dest_head = &intrinsic->variables[0]->deref;
- nir_deref *src_head = &intrinsic->variables[1]->deref;
- nir_deref *dest_tail = nir_deref_tail(dest_head);
- nir_deref *src_tail = nir_deref_tail(src_head);
-
- switch (glsl_get_base_type(src_tail->type)) {
- case GLSL_TYPE_ARRAY:
- case GLSL_TYPE_STRUCT:
- split_var_copy_instr(intrinsic, dest_head, src_head,
- dest_tail, src_tail, state);
- nir_instr_remove(&intrinsic->instr);
- ralloc_steal(state->dead_ctx, instr);
- break;
- case GLSL_TYPE_FLOAT:
- case GLSL_TYPE_INT:
- case GLSL_TYPE_UINT:
- case GLSL_TYPE_BOOL:
- if (glsl_type_is_matrix(src_tail->type)) {
- split_var_copy_instr(intrinsic, dest_head, src_head,
- dest_tail, src_tail, state);
- nir_instr_remove(&intrinsic->instr);
- ralloc_steal(state->dead_ctx, instr);
- }
- break;
- default:
- unreachable("Invalid type");
- break;
- }
- }
-
- return true;
-}
-
-static bool
-split_var_copies_impl(nir_function_impl *impl)
-{
- struct split_var_copies_state state;
-
- state.mem_ctx = ralloc_parent(impl);
- state.dead_ctx = ralloc_context(NULL);
- state.progress = false;
-
- nir_foreach_block(impl, split_var_copies_block, &state);
-
- ralloc_free(state.dead_ctx);
-
- if (state.progress) {
- nir_metadata_preserve(impl, nir_metadata_block_index |
- nir_metadata_dominance);
- }
-
- return state.progress;
-}
-
-bool
-nir_split_var_copies(nir_shader *shader)
-{
- bool progress = false;
-
- nir_foreach_function(shader, function) {
- if (function->impl)
- progress = split_var_copies_impl(function->impl) || progress;
- }
-
- return progress;
-}
diff --git a/src/glsl/nir/nir_sweep.c b/src/glsl/nir/nir_sweep.c
deleted file mode 100644
index 5c62154ec7f..00000000000
--- a/src/glsl/nir/nir_sweep.c
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * Copyright © 2015 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include "nir.h"
-
-/**
- * \file nir_sweep.c
- *
- * The nir_sweep() pass performs a mark and sweep pass over a nir_shader's associated
- * memory - anything still connected to the program will be kept, and any dead memory
- * we dropped on the floor will be freed.
- *
- * The expectation is that drivers should call this when finished compiling the shader
- * (after any optimization, lowering, and so on). However, it's also fine to call it
- * earlier, and even many times, trading CPU cycles for memory savings.
- */
-
-#define steal_list(mem_ctx, type, list) \
- foreach_list_typed(type, obj, node, list) { ralloc_steal(mem_ctx, obj); }
-
-static void sweep_cf_node(nir_shader *nir, nir_cf_node *cf_node);
-
-static bool
-sweep_src_indirect(nir_src *src, void *nir)
-{
- if (!src->is_ssa && src->reg.indirect)
- ralloc_steal(nir, src->reg.indirect);
-
- return true;
-}
-
-static bool
-sweep_dest_indirect(nir_dest *dest, void *nir)
-{
- if (!dest->is_ssa && dest->reg.indirect)
- ralloc_steal(nir, dest->reg.indirect);
-
- return true;
-}
-
-static void
-sweep_block(nir_shader *nir, nir_block *block)
-{
- ralloc_steal(nir, block);
-
- nir_foreach_instr(block, instr) {
- ralloc_steal(nir, instr);
-
- nir_foreach_src(instr, sweep_src_indirect, nir);
- nir_foreach_dest(instr, sweep_dest_indirect, nir);
- }
-}
-
-static void
-sweep_if(nir_shader *nir, nir_if *iff)
-{
- ralloc_steal(nir, iff);
-
- foreach_list_typed(nir_cf_node, cf_node, node, &iff->then_list) {
- sweep_cf_node(nir, cf_node);
- }
-
- foreach_list_typed(nir_cf_node, cf_node, node, &iff->else_list) {
- sweep_cf_node(nir, cf_node);
- }
-}
-
-static void
-sweep_loop(nir_shader *nir, nir_loop *loop)
-{
- ralloc_steal(nir, loop);
-
- foreach_list_typed(nir_cf_node, cf_node, node, &loop->body) {
- sweep_cf_node(nir, cf_node);
- }
-}
-
-static void
-sweep_cf_node(nir_shader *nir, nir_cf_node *cf_node)
-{
- switch (cf_node->type) {
- case nir_cf_node_block:
- sweep_block(nir, nir_cf_node_as_block(cf_node));
- break;
- case nir_cf_node_if:
- sweep_if(nir, nir_cf_node_as_if(cf_node));
- break;
- case nir_cf_node_loop:
- sweep_loop(nir, nir_cf_node_as_loop(cf_node));
- break;
- default:
- unreachable("Invalid CF node type");
- }
-}
-
-static void
-sweep_impl(nir_shader *nir, nir_function_impl *impl)
-{
- ralloc_steal(nir, impl);
-
- ralloc_steal(nir, impl->params);
- ralloc_steal(nir, impl->return_var);
- steal_list(nir, nir_variable, &impl->locals);
- steal_list(nir, nir_register, &impl->registers);
-
- foreach_list_typed(nir_cf_node, cf_node, node, &impl->body) {
- sweep_cf_node(nir, cf_node);
- }
-
- sweep_block(nir, impl->end_block);
-
- /* Wipe out all the metadata, if any. */
- nir_metadata_preserve(impl, nir_metadata_none);
-}
-
-static void
-sweep_function(nir_shader *nir, nir_function *f)
-{
- ralloc_steal(nir, f);
- ralloc_steal(nir, f->params);
-
- if (f->impl)
- sweep_impl(nir, f->impl);
-}
-
-void
-nir_sweep(nir_shader *nir)
-{
- void *rubbish = ralloc_context(NULL);
-
- /* First, move ownership of all the memory to a temporary context; assume dead. */
- ralloc_adopt(rubbish, nir);
-
- ralloc_steal(nir, (char *)nir->info.name);
- if (nir->info.label)
- ralloc_steal(nir, (char *)nir->info.label);
-
- /* Variables and registers are not dead. Steal them back. */
- steal_list(nir, nir_variable, &nir->uniforms);
- steal_list(nir, nir_variable, &nir->inputs);
- steal_list(nir, nir_variable, &nir->outputs);
- steal_list(nir, nir_variable, &nir->shared);
- steal_list(nir, nir_variable, &nir->globals);
- steal_list(nir, nir_variable, &nir->system_values);
- steal_list(nir, nir_register, &nir->registers);
-
- /* Recurse into functions, stealing their contents back. */
- foreach_list_typed(nir_function, func, node, &nir->functions) {
- sweep_function(nir, func);
- }
-
- /* Free everything we didn't steal back. */
- ralloc_free(rubbish);
-}
diff --git a/src/glsl/nir/nir_to_ssa.c b/src/glsl/nir/nir_to_ssa.c
deleted file mode 100644
index 44a50547738..00000000000
--- a/src/glsl/nir/nir_to_ssa.c
+++ /dev/null
@@ -1,536 +0,0 @@
-/*
- * Copyright © 2014 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- *
- * Authors:
- * Connor Abbott ([email protected])
- *
- */
-
-#include "nir.h"
-#include <stdlib.h>
-#include <unistd.h>
-
-/*
- * Implements the classic to-SSA algorithm described by Cytron et. al. in
- * "Efficiently Computing Static Single Assignment Form and the Control
- * Dependence Graph."
- */
-
-/* inserts a phi node of the form reg = phi(reg, reg, reg, ...) */
-
-static void
-insert_trivial_phi(nir_register *reg, nir_block *block, void *mem_ctx)
-{
- nir_phi_instr *instr = nir_phi_instr_create(mem_ctx);
-
- instr->dest.reg.reg = reg;
- struct set_entry *entry;
- set_foreach(block->predecessors, entry) {
- nir_block *pred = (nir_block *) entry->key;
-
- nir_phi_src *src = ralloc(instr, nir_phi_src);
- src->pred = pred;
- src->src.is_ssa = false;
- src->src.reg.base_offset = 0;
- src->src.reg.indirect = NULL;
- src->src.reg.reg = reg;
- exec_list_push_tail(&instr->srcs, &src->node);
- }
-
- nir_instr_insert_before_block(block, &instr->instr);
-}
-
-static void
-insert_phi_nodes(nir_function_impl *impl)
-{
- void *mem_ctx = ralloc_parent(impl);
-
- unsigned *work = calloc(impl->num_blocks, sizeof(unsigned));
- unsigned *has_already = calloc(impl->num_blocks, sizeof(unsigned));
-
- /*
- * Since the work flags already prevent us from inserting a node that has
- * ever been inserted into W, we don't need to use a set to represent W.
- * Also, since no block can ever be inserted into W more than once, we know
- * that the maximum size of W is the number of basic blocks in the
- * function. So all we need to handle W is an array and a pointer to the
- * next element to be inserted and the next element to be removed.
- */
- nir_block **W = malloc(impl->num_blocks * sizeof(nir_block *));
- unsigned w_start, w_end;
-
- unsigned iter_count = 0;
-
- nir_index_blocks(impl);
-
- foreach_list_typed(nir_register, reg, node, &impl->registers) {
- if (reg->num_array_elems != 0)
- continue;
-
- w_start = w_end = 0;
- iter_count++;
-
- nir_foreach_def(reg, dest) {
- nir_instr *def = dest->reg.parent_instr;
- if (work[def->block->index] < iter_count)
- W[w_end++] = def->block;
- work[def->block->index] = iter_count;
- }
-
- while (w_start != w_end) {
- nir_block *cur = W[w_start++];
- struct set_entry *entry;
- set_foreach(cur->dom_frontier, entry) {
- nir_block *next = (nir_block *) entry->key;
-
- /*
- * If there's more than one return statement, then the end block
- * can be a join point for some definitions. However, there are
- * no instructions in the end block, so nothing would use those
- * phi nodes. Of course, we couldn't place those phi nodes
- * anyways due to the restriction of having no instructions in the
- * end block...
- */
- if (next == impl->end_block)
- continue;
-
- if (has_already[next->index] < iter_count) {
- insert_trivial_phi(reg, next, mem_ctx);
- has_already[next->index] = iter_count;
- if (work[next->index] < iter_count) {
- work[next->index] = iter_count;
- W[w_end++] = next;
- }
- }
- }
- }
- }
-
- free(work);
- free(has_already);
- free(W);
-}
-
-typedef struct {
- nir_ssa_def **stack;
- int index;
- unsigned num_defs; /** < used to add indices to debug names */
-#ifndef NDEBUG
- unsigned stack_size;
-#endif
-} reg_state;
-
-typedef struct {
- reg_state *states;
- void *mem_ctx;
- nir_instr *parent_instr;
- nir_if *parent_if;
- nir_function_impl *impl;
-
- /* map from SSA value -> original register */
- struct hash_table *ssa_map;
-} rewrite_state;
-
-static nir_ssa_def *get_ssa_src(nir_register *reg, rewrite_state *state)
-{
- unsigned index = reg->index;
-
- if (state->states[index].index == -1) {
- /*
- * We're using an undefined register, create a new undefined SSA value
- * to preserve the information that this source is undefined
- */
- nir_ssa_undef_instr *instr =
- nir_ssa_undef_instr_create(state->mem_ctx, reg->num_components);
-
- /*
- * We could just insert the undefined instruction before the instruction
- * we're rewriting, but we could be rewriting a phi source in which case
- * we can't do that, so do the next easiest thing - insert it at the
- * beginning of the program. In the end, it doesn't really matter where
- * the undefined instructions are because they're going to be ignored
- * in the backend.
- */
- nir_instr_insert_before_cf_list(&state->impl->body, &instr->instr);
- return &instr->def;
- }
-
- return state->states[index].stack[state->states[index].index];
-}
-
-static bool
-rewrite_use(nir_src *src, void *_state)
-{
- rewrite_state *state = (rewrite_state *) _state;
-
- if (src->is_ssa)
- return true;
-
- unsigned index = src->reg.reg->index;
-
- if (state->states[index].stack == NULL)
- return true;
-
- nir_ssa_def *def = get_ssa_src(src->reg.reg, state);
- if (state->parent_instr)
- nir_instr_rewrite_src(state->parent_instr, src, nir_src_for_ssa(def));
- else
- nir_if_rewrite_condition(state->parent_if, nir_src_for_ssa(def));
-
- return true;
-}
-
-static bool
-rewrite_def_forwards(nir_dest *dest, void *_state)
-{
- rewrite_state *state = (rewrite_state *) _state;
-
- if (dest->is_ssa)
- return true;
-
- nir_register *reg = dest->reg.reg;
- unsigned index = reg->index;
-
- if (state->states[index].stack == NULL)
- return true;
-
- char *name = NULL;
- if (dest->reg.reg->name)
- name = ralloc_asprintf(state->mem_ctx, "%s_%u", dest->reg.reg->name,
- state->states[index].num_defs);
-
- list_del(&dest->reg.def_link);
- nir_ssa_dest_init(state->parent_instr, dest, reg->num_components, name);
-
- /* push our SSA destination on the stack */
- state->states[index].index++;
- assert(state->states[index].index < state->states[index].stack_size);
- state->states[index].stack[state->states[index].index] = &dest->ssa;
- state->states[index].num_defs++;
-
- _mesa_hash_table_insert(state->ssa_map, &dest->ssa, reg);
-
- return true;
-}
-
-static void
-rewrite_alu_instr_forward(nir_alu_instr *instr, rewrite_state *state)
-{
- state->parent_instr = &instr->instr;
-
- nir_foreach_src(&instr->instr, rewrite_use, state);
-
- if (instr->dest.dest.is_ssa)
- return;
-
- nir_register *reg = instr->dest.dest.reg.reg;
- unsigned index = reg->index;
-
- if (state->states[index].stack == NULL)
- return;
-
- unsigned write_mask = instr->dest.write_mask;
- if (write_mask != (1 << instr->dest.dest.reg.reg->num_components) - 1) {
- /*
- * Calculate the number of components the final instruction, which for
- * per-component things is the number of output components of the
- * instruction and non-per-component things is the number of enabled
- * channels in the write mask.
- */
- unsigned num_components;
- if (nir_op_infos[instr->op].output_size == 0) {
- unsigned temp = (write_mask & 0x5) + ((write_mask >> 1) & 0x5);
- num_components = (temp & 0x3) + ((temp >> 2) & 0x3);
- } else {
- num_components = nir_op_infos[instr->op].output_size;
- }
-
- char *name = NULL;
- if (instr->dest.dest.reg.reg->name)
- name = ralloc_asprintf(state->mem_ctx, "%s_%u",
- reg->name, state->states[index].num_defs);
-
- instr->dest.write_mask = (1 << num_components) - 1;
- list_del(&instr->dest.dest.reg.def_link);
- nir_ssa_dest_init(&instr->instr, &instr->dest.dest, num_components, name);
-
- if (nir_op_infos[instr->op].output_size == 0) {
- /*
- * When we change the output writemask, we need to change the
- * swizzles for per-component inputs too
- */
- for (unsigned i = 0; i < nir_op_infos[instr->op].num_inputs; i++) {
- if (nir_op_infos[instr->op].input_sizes[i] != 0)
- continue;
-
- unsigned new_swizzle[4] = {0, 0, 0, 0};
-
- /*
- * We keep two indices:
- * 1. The index of the original (non-SSA) component
- * 2. The index of the post-SSA, compacted, component
- *
- * We need to map the swizzle component at index 1 to the swizzle
- * component at index 2.
- */
-
- unsigned ssa_index = 0;
- for (unsigned index = 0; index < 4; index++) {
- if (!((write_mask >> index) & 1))
- continue;
-
- new_swizzle[ssa_index] = instr->src[i].swizzle[index];
- ssa_index++;
- }
-
- for (unsigned j = 0; j < 4; j++)
- instr->src[i].swizzle[j] = new_swizzle[j];
- }
- }
-
- nir_op op;
- switch (reg->num_components) {
- case 2: op = nir_op_vec2; break;
- case 3: op = nir_op_vec3; break;
- case 4: op = nir_op_vec4; break;
- default: unreachable("not reached");
- }
-
- nir_alu_instr *vec = nir_alu_instr_create(state->mem_ctx, op);
-
- vec->dest.dest.reg.reg = reg;
- vec->dest.write_mask = (1 << reg->num_components) - 1;
-
- nir_ssa_def *old_src = get_ssa_src(reg, state);
- nir_ssa_def *new_src = &instr->dest.dest.ssa;
-
- unsigned ssa_index = 0;
- for (unsigned i = 0; i < reg->num_components; i++) {
- vec->src[i].src.is_ssa = true;
- if ((write_mask >> i) & 1) {
- vec->src[i].src.ssa = new_src;
- if (nir_op_infos[instr->op].output_size == 0)
- vec->src[i].swizzle[0] = ssa_index;
- else
- vec->src[i].swizzle[0] = i;
- ssa_index++;
- } else {
- vec->src[i].src.ssa = old_src;
- vec->src[i].swizzle[0] = i;
- }
- }
-
- nir_instr_insert_after(&instr->instr, &vec->instr);
-
- state->parent_instr = &vec->instr;
- rewrite_def_forwards(&vec->dest.dest, state);
- } else {
- rewrite_def_forwards(&instr->dest.dest, state);
- }
-}
-
-static void
-rewrite_phi_instr(nir_phi_instr *instr, rewrite_state *state)
-{
- state->parent_instr = &instr->instr;
- rewrite_def_forwards(&instr->dest, state);
-}
-
-static void
-rewrite_instr_forward(nir_instr *instr, rewrite_state *state)
-{
- if (instr->type == nir_instr_type_alu) {
- rewrite_alu_instr_forward(nir_instr_as_alu(instr), state);
- return;
- }
-
- if (instr->type == nir_instr_type_phi) {
- rewrite_phi_instr(nir_instr_as_phi(instr), state);
- return;
- }
-
- state->parent_instr = instr;
-
- nir_foreach_src(instr, rewrite_use, state);
- nir_foreach_dest(instr, rewrite_def_forwards, state);
-}
-
-static void
-rewrite_phi_sources(nir_block *block, nir_block *pred, rewrite_state *state)
-{
- nir_foreach_instr(block, instr) {
- if (instr->type != nir_instr_type_phi)
- break;
-
- nir_phi_instr *phi_instr = nir_instr_as_phi(instr);
-
- state->parent_instr = instr;
-
- nir_foreach_phi_src(phi_instr, src) {
- if (src->pred == pred) {
- rewrite_use(&src->src, state);
- break;
- }
- }
- }
-}
-
-static bool
-rewrite_def_backwards(nir_dest *dest, void *_state)
-{
- rewrite_state *state = (rewrite_state *) _state;
-
- if (!dest->is_ssa)
- return true;
-
- struct hash_entry *entry =
- _mesa_hash_table_search(state->ssa_map, &dest->ssa);
-
- if (!entry)
- return true;
-
- nir_register *reg = (nir_register *) entry->data;
- unsigned index = reg->index;
-
- state->states[index].index--;
- assert(state->states[index].index >= -1);
-
- return true;
-}
-
-static void
-rewrite_instr_backwards(nir_instr *instr, rewrite_state *state)
-{
- nir_foreach_dest(instr, rewrite_def_backwards, state);
-}
-
-static void
-rewrite_block(nir_block *block, rewrite_state *state)
-{
- /* This will skip over any instructions after the current one, which is
- * what we want because those instructions (vector gather, conditional
- * select) will already be in SSA form.
- */
- nir_foreach_instr_safe(block, instr) {
- rewrite_instr_forward(instr, state);
- }
-
- if (block != state->impl->end_block &&
- !nir_cf_node_is_last(&block->cf_node) &&
- nir_cf_node_next(&block->cf_node)->type == nir_cf_node_if) {
- nir_if *if_stmt = nir_cf_node_as_if(nir_cf_node_next(&block->cf_node));
- state->parent_instr = NULL;
- state->parent_if = if_stmt;
- rewrite_use(&if_stmt->condition, state);
- }
-
- if (block->successors[0])
- rewrite_phi_sources(block->successors[0], block, state);
- if (block->successors[1])
- rewrite_phi_sources(block->successors[1], block, state);
-
- for (unsigned i = 0; i < block->num_dom_children; i++)
- rewrite_block(block->dom_children[i], state);
-
- nir_foreach_instr_reverse(block, instr) {
- rewrite_instr_backwards(instr, state);
- }
-}
-
-static void
-remove_unused_regs(nir_function_impl *impl, rewrite_state *state)
-{
- foreach_list_typed_safe(nir_register, reg, node, &impl->registers) {
- if (state->states[reg->index].stack != NULL)
- exec_node_remove(&reg->node);
- }
-}
-
-static void
-init_rewrite_state(nir_function_impl *impl, rewrite_state *state)
-{
- state->impl = impl;
- state->mem_ctx = ralloc_parent(impl);
- state->ssa_map = _mesa_hash_table_create(NULL, _mesa_hash_pointer,
- _mesa_key_pointer_equal);
- state->states = ralloc_array(NULL, reg_state, impl->reg_alloc);
-
- foreach_list_typed(nir_register, reg, node, &impl->registers) {
- assert(reg->index < impl->reg_alloc);
- if (reg->num_array_elems > 0) {
- state->states[reg->index].stack = NULL;
- } else {
- /*
- * Calculate a conservative estimate of the stack size based on the
- * number of definitions there are. Note that this function *must* be
- * called after phi nodes are inserted so we can count phi node
- * definitions too.
- */
- unsigned stack_size = list_length(&reg->defs);
-
- state->states[reg->index].stack = ralloc_array(state->states,
- nir_ssa_def *,
- stack_size);
-#ifndef NDEBUG
- state->states[reg->index].stack_size = stack_size;
-#endif
- state->states[reg->index].index = -1;
- state->states[reg->index].num_defs = 0;
- }
- }
-}
-
-static void
-destroy_rewrite_state(rewrite_state *state)
-{
- _mesa_hash_table_destroy(state->ssa_map, NULL);
- ralloc_free(state->states);
-}
-
-void
-nir_convert_to_ssa_impl(nir_function_impl *impl)
-{
- nir_metadata_require(impl, nir_metadata_dominance);
-
- insert_phi_nodes(impl);
-
- rewrite_state state;
- init_rewrite_state(impl, &state);
-
- rewrite_block(nir_start_block(impl), &state);
-
- remove_unused_regs(impl, &state);
-
- nir_metadata_preserve(impl, nir_metadata_block_index |
- nir_metadata_dominance);
-
- destroy_rewrite_state(&state);
-}
-
-void
-nir_convert_to_ssa(nir_shader *shader)
-{
- nir_foreach_function(shader, function) {
- if (function->impl)
- nir_convert_to_ssa_impl(function->impl);
- }
-}
diff --git a/src/glsl/nir/nir_types.cpp b/src/glsl/nir/nir_types.cpp
deleted file mode 100644
index f4408def9a0..00000000000
--- a/src/glsl/nir/nir_types.cpp
+++ /dev/null
@@ -1,336 +0,0 @@
-/*
- * Copyright © 2014 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- *
- * Authors:
- * Connor Abbott ([email protected])
- *
- */
-
-#include "nir_types.h"
-#include "ir.h"
-
-void
-glsl_print_type(const glsl_type *type, FILE *fp)
-{
- if (type->base_type == GLSL_TYPE_ARRAY) {
- glsl_print_type(type->fields.array, fp);
- fprintf(fp, "[%u]", type->length);
- } else if ((type->base_type == GLSL_TYPE_STRUCT)
- && !is_gl_identifier(type->name)) {
- fprintf(fp, "%s@%p", type->name, (void *) type);
- } else {
- fprintf(fp, "%s", type->name);
- }
-}
-
-void
-glsl_print_struct(const glsl_type *type, FILE *fp)
-{
- assert(type->base_type == GLSL_TYPE_STRUCT);
-
- fprintf(fp, "struct {\n");
- for (unsigned i = 0; i < type->length; i++) {
- fprintf(fp, "\t");
- glsl_print_type(type->fields.structure[i].type, fp);
- fprintf(fp, " %s;\n", type->fields.structure[i].name);
- }
- fprintf(fp, "}\n");
-}
-
-const glsl_type *
-glsl_get_array_element(const glsl_type* type)
-{
- if (type->is_matrix())
- return type->column_type();
- return type->fields.array;
-}
-
-const glsl_type *
-glsl_get_struct_field(const glsl_type *type, unsigned index)
-{
- return type->fields.structure[index].type;
-}
-
-const glsl_type *
-glsl_get_function_return_type(const glsl_type *type)
-{
- return type->fields.parameters[0].type;
-}
-
-const glsl_function_param *
-glsl_get_function_param(const glsl_type *type, unsigned index)
-{
- return &type->fields.parameters[index + 1];
-}
-
-const struct glsl_type *
-glsl_get_column_type(const struct glsl_type *type)
-{
- return type->column_type();
-}
-
-enum glsl_base_type
-glsl_get_base_type(const struct glsl_type *type)
-{
- return type->base_type;
-}
-
-unsigned
-glsl_get_vector_elements(const struct glsl_type *type)
-{
- return type->vector_elements;
-}
-
-unsigned
-glsl_get_components(const struct glsl_type *type)
-{
- return type->components();
-}
-
-unsigned
-glsl_get_matrix_columns(const struct glsl_type *type)
-{
- return type->matrix_columns;
-}
-
-unsigned
-glsl_get_length(const struct glsl_type *type)
-{
- return type->is_matrix() ? type->matrix_columns : type->length;
-}
-
-unsigned
-glsl_get_aoa_size(const struct glsl_type *type)
-{
- return type->arrays_of_arrays_size();
-}
-
-unsigned
-glsl_count_attribute_slots(const struct glsl_type *type,
- bool vertex_input_slots)
-{
- return type->count_attribute_slots(vertex_input_slots);
-}
-
-const char *
-glsl_get_struct_elem_name(const struct glsl_type *type, unsigned index)
-{
- return type->fields.structure[index].name;
-}
-
-glsl_sampler_dim
-glsl_get_sampler_dim(const struct glsl_type *type)
-{
- assert(glsl_type_is_sampler(type) || glsl_type_is_image(type));
- return (glsl_sampler_dim)type->sampler_dimensionality;
-}
-
-glsl_base_type
-glsl_get_sampler_result_type(const struct glsl_type *type)
-{
- assert(glsl_type_is_sampler(type) || glsl_type_is_image(type));
- return (glsl_base_type)type->sampler_type;
-}
-
-unsigned
-glsl_get_record_location_offset(const struct glsl_type *type,
- unsigned length)
-{
- return type->record_location_offset(length);
-}
-
-bool
-glsl_type_is_void(const glsl_type *type)
-{
- return type->is_void();
-}
-
-bool
-glsl_type_is_error(const glsl_type *type)
-{
- return type->is_error();
-}
-
-bool
-glsl_type_is_vector(const struct glsl_type *type)
-{
- return type->is_vector();
-}
-
-bool
-glsl_type_is_scalar(const struct glsl_type *type)
-{
- return type->is_scalar();
-}
-
-bool
-glsl_type_is_vector_or_scalar(const struct glsl_type *type)
-{
- return type->is_vector() || type->is_scalar();
-}
-
-bool
-glsl_type_is_matrix(const struct glsl_type *type)
-{
- return type->is_matrix();
-}
-
-bool
-glsl_type_is_array(const struct glsl_type *type)
-{
- return type->is_array();
-}
-
-bool
-glsl_type_is_struct(const struct glsl_type *type)
-{
- return type->is_record() || type->is_interface();
-}
-
-bool
-glsl_type_is_sampler(const struct glsl_type *type)
-{
- return type->is_sampler();
-}
-
-bool
-glsl_type_is_image(const struct glsl_type *type)
-{
- return type->is_image();
-}
-
-bool
-glsl_sampler_type_is_shadow(const struct glsl_type *type)
-{
- assert(glsl_type_is_sampler(type));
- return type->sampler_shadow;
-}
-
-bool
-glsl_sampler_type_is_array(const struct glsl_type *type)
-{
- assert(glsl_type_is_sampler(type) || glsl_type_is_image(type));
- return type->sampler_array;
-}
-
-const glsl_type *
-glsl_void_type(void)
-{
- return glsl_type::void_type;
-}
-
-const glsl_type *
-glsl_float_type(void)
-{
- return glsl_type::float_type;
-}
-
-const glsl_type *
-glsl_vec_type(unsigned n)
-{
- return glsl_type::vec(n);
-}
-
-const glsl_type *
-glsl_vec4_type(void)
-{
- return glsl_type::vec4_type;
-}
-
-const glsl_type *
-glsl_int_type(void)
-{
- return glsl_type::int_type;
-}
-
-const glsl_type *
-glsl_uint_type(void)
-{
- return glsl_type::uint_type;
-}
-
-const glsl_type *
-glsl_bool_type(void)
-{
- return glsl_type::bool_type;
-}
-
-const glsl_type *
-glsl_scalar_type(enum glsl_base_type base_type)
-{
- return glsl_type::get_instance(base_type, 1, 1);
-}
-
-const glsl_type *
-glsl_vector_type(enum glsl_base_type base_type, unsigned components)
-{
- assert(components > 1 && components <= 4);
- return glsl_type::get_instance(base_type, components, 1);
-}
-
-const glsl_type *
-glsl_matrix_type(enum glsl_base_type base_type, unsigned rows, unsigned columns)
-{
- assert(rows > 1 && rows <= 4 && columns >= 1 && columns <= 4);
- return glsl_type::get_instance(base_type, rows, columns);
-}
-
-const glsl_type *
-glsl_array_type(const glsl_type *base, unsigned elements)
-{
- return glsl_type::get_array_instance(base, elements);
-}
-
-const glsl_type *
-glsl_struct_type(const glsl_struct_field *fields,
- unsigned num_fields, const char *name)
-{
- return glsl_type::get_record_instance(fields, num_fields, name);
-}
-
-const struct glsl_type *
-glsl_sampler_type(enum glsl_sampler_dim dim, bool is_shadow, bool is_array,
- enum glsl_base_type base_type)
-{
- return glsl_type::get_sampler_instance(dim, is_shadow, is_array, base_type);
-}
-
-const struct glsl_type *
-glsl_image_type(enum glsl_sampler_dim dim, bool is_array,
- enum glsl_base_type base_type)
-{
- return glsl_type::get_image_instance(dim, is_array, base_type);
-}
-
-const glsl_type *
-glsl_function_type(const glsl_type *return_type,
- const glsl_function_param *params, unsigned num_params)
-{
- return glsl_type::get_function_instance(return_type, params, num_params);
-}
-
-const glsl_type *
-glsl_transposed_type(const struct glsl_type *type)
-{
- return glsl_type::get_instance(type->base_type, type->matrix_columns,
- type->vector_elements);
-}
diff --git a/src/glsl/nir/nir_types.h b/src/glsl/nir/nir_types.h
deleted file mode 100644
index 8cb7ec16ce3..00000000000
--- a/src/glsl/nir/nir_types.h
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright © 2014 Connor Abbott
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- *
- * Authors:
- * Connor Abbott ([email protected])
- *
- */
-
-#pragma once
-
-#include <stdio.h>
-
-/* C wrapper around glsl_types.h */
-
-#include "glsl_types.h"
-
-#ifdef __cplusplus
-extern "C" {
-#else
-struct glsl_type;
-#endif
-
-void glsl_print_type(const struct glsl_type *type, FILE *fp);
-void glsl_print_struct(const struct glsl_type *type, FILE *fp);
-
-const struct glsl_type *glsl_get_struct_field(const struct glsl_type *type,
- unsigned index);
-
-const struct glsl_type *glsl_get_array_element(const struct glsl_type *type);
-
-const struct glsl_type *glsl_get_column_type(const struct glsl_type *type);
-
-const struct glsl_type *
-glsl_get_function_return_type(const struct glsl_type *type);
-
-const struct glsl_function_param *
-glsl_get_function_param(const struct glsl_type *type, unsigned index);
-
-enum glsl_base_type glsl_get_base_type(const struct glsl_type *type);
-
-unsigned glsl_get_vector_elements(const struct glsl_type *type);
-
-unsigned glsl_get_components(const struct glsl_type *type);
-
-unsigned glsl_get_matrix_columns(const struct glsl_type *type);
-
-unsigned glsl_get_length(const struct glsl_type *type);
-
-unsigned glsl_get_aoa_size(const struct glsl_type *type);
-
-unsigned glsl_count_attribute_slots(const struct glsl_type *type,
- bool vertex_input_slots);
-
-const char *glsl_get_struct_elem_name(const struct glsl_type *type,
- unsigned index);
-
-enum glsl_sampler_dim glsl_get_sampler_dim(const struct glsl_type *type);
-enum glsl_base_type glsl_get_sampler_result_type(const struct glsl_type *type);
-
-unsigned glsl_get_record_location_offset(const struct glsl_type *type,
- unsigned length);
-
-bool glsl_type_is_void(const struct glsl_type *type);
-bool glsl_type_is_error(const struct glsl_type *type);
-bool glsl_type_is_vector(const struct glsl_type *type);
-bool glsl_type_is_scalar(const struct glsl_type *type);
-bool glsl_type_is_vector_or_scalar(const struct glsl_type *type);
-bool glsl_type_is_matrix(const struct glsl_type *type);
-bool glsl_type_is_array(const struct glsl_type *type);
-bool glsl_type_is_struct(const struct glsl_type *type);
-bool glsl_type_is_sampler(const struct glsl_type *type);
-bool glsl_type_is_image(const struct glsl_type *type);
-bool glsl_sampler_type_is_shadow(const struct glsl_type *type);
-bool glsl_sampler_type_is_array(const struct glsl_type *type);
-
-const struct glsl_type *glsl_void_type(void);
-const struct glsl_type *glsl_float_type(void);
-const struct glsl_type *glsl_vec_type(unsigned n);
-const struct glsl_type *glsl_vec4_type(void);
-const struct glsl_type *glsl_int_type(void);
-const struct glsl_type *glsl_uint_type(void);
-const struct glsl_type *glsl_bool_type(void);
-
-const struct glsl_type *glsl_scalar_type(enum glsl_base_type base_type);
-const struct glsl_type *glsl_vector_type(enum glsl_base_type base_type,
- unsigned components);
-const struct glsl_type *glsl_matrix_type(enum glsl_base_type base_type,
- unsigned rows, unsigned columns);
-const struct glsl_type *glsl_array_type(const struct glsl_type *base,
- unsigned elements);
-const struct glsl_type *glsl_struct_type(const struct glsl_struct_field *fields,
- unsigned num_fields, const char *name);
-const struct glsl_type *glsl_sampler_type(enum glsl_sampler_dim dim,
- bool is_shadow, bool is_array,
- enum glsl_base_type base_type);
-const struct glsl_type *glsl_image_type(enum glsl_sampler_dim dim,
- bool is_array,
- enum glsl_base_type base_type);
-const struct glsl_type * glsl_function_type(const struct glsl_type *return_type,
- const struct glsl_function_param *params,
- unsigned num_params);
-
-const struct glsl_type *glsl_transposed_type(const struct glsl_type *type);
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/src/glsl/nir/nir_validate.c b/src/glsl/nir/nir_validate.c
deleted file mode 100644
index 1a943d76314..00000000000
--- a/src/glsl/nir/nir_validate.c
+++ /dev/null
@@ -1,1076 +0,0 @@
-/*
- * Copyright © 2014 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- *
- * Authors:
- * Connor Abbott ([email protected])
- *
- */
-
-#include "nir.h"
-#include <assert.h>
-
-/*
- * This file checks for invalid IR indicating a bug somewhere in the compiler.
- */
-
-/* Since this file is just a pile of asserts, don't bother compiling it if
- * we're not building a debug build.
- */
-#ifdef DEBUG
-
-/*
- * Per-register validation state.
- */
-
-typedef struct {
- /*
- * equivalent to the uses and defs in nir_register, but built up by the
- * validator. At the end, we verify that the sets have the same entries.
- */
- struct set *uses, *if_uses, *defs;
- nir_function_impl *where_defined; /* NULL for global registers */
-} reg_validate_state;
-
-typedef struct {
- /*
- * equivalent to the uses in nir_ssa_def, but built up by the validator.
- * At the end, we verify that the sets have the same entries.
- */
- struct set *uses, *if_uses;
- nir_function_impl *where_defined;
-} ssa_def_validate_state;
-
-typedef struct {
- /* map of register -> validation state (struct above) */
- struct hash_table *regs;
-
- /* the current shader being validated */
- nir_shader *shader;
-
- /* the current instruction being validated */
- nir_instr *instr;
-
- /* the current basic block being validated */
- nir_block *block;
-
- /* the current if statement being validated */
- nir_if *if_stmt;
-
- /* the current loop being visited */
- nir_loop *loop;
-
- /* the parent of the current cf node being visited */
- nir_cf_node *parent_node;
-
- /* the current function implementation being validated */
- nir_function_impl *impl;
-
- /* map of SSA value -> function implementation where it is defined */
- struct hash_table *ssa_defs;
-
- /* bitset of ssa definitions we have found; used to check uniqueness */
- BITSET_WORD *ssa_defs_found;
-
- /* bitset of registers we have currently found; used to check uniqueness */
- BITSET_WORD *regs_found;
-
- /* map of local variable -> function implementation where it is defined */
- struct hash_table *var_defs;
-} validate_state;
-
-static void validate_src(nir_src *src, validate_state *state);
-
-static void
-validate_reg_src(nir_src *src, validate_state *state)
-{
- assert(src->reg.reg != NULL);
-
- struct hash_entry *entry;
- entry = _mesa_hash_table_search(state->regs, src->reg.reg);
- assert(entry);
-
- reg_validate_state *reg_state = (reg_validate_state *) entry->data;
-
- if (state->instr) {
- _mesa_set_add(reg_state->uses, src);
- } else {
- assert(state->if_stmt);
- _mesa_set_add(reg_state->if_uses, src);
- }
-
- if (!src->reg.reg->is_global) {
- assert(reg_state->where_defined == state->impl &&
- "using a register declared in a different function");
- }
-
- assert((src->reg.reg->num_array_elems == 0 ||
- src->reg.base_offset < src->reg.reg->num_array_elems) &&
- "definitely out-of-bounds array access");
-
- if (src->reg.indirect) {
- assert(src->reg.reg->num_array_elems != 0);
- assert((src->reg.indirect->is_ssa ||
- src->reg.indirect->reg.indirect == NULL) &&
- "only one level of indirection allowed");
- validate_src(src->reg.indirect, state);
- }
-}
-
-static void
-validate_ssa_src(nir_src *src, validate_state *state)
-{
- assert(src->ssa != NULL);
-
- struct hash_entry *entry = _mesa_hash_table_search(state->ssa_defs, src->ssa);
-
- assert(entry);
-
- ssa_def_validate_state *def_state = (ssa_def_validate_state *)entry->data;
-
- assert(def_state->where_defined == state->impl &&
- "using an SSA value defined in a different function");
-
- if (state->instr) {
- _mesa_set_add(def_state->uses, src);
- } else {
- assert(state->if_stmt);
- _mesa_set_add(def_state->if_uses, src);
- }
-
- /* TODO validate that the use is dominated by the definition */
-}
-
-static void
-validate_src(nir_src *src, validate_state *state)
-{
- if (state->instr)
- assert(src->parent_instr == state->instr);
- else
- assert(src->parent_if == state->if_stmt);
-
- if (src->is_ssa)
- validate_ssa_src(src, state);
- else
- validate_reg_src(src, state);
-}
-
-static void
-validate_alu_src(nir_alu_instr *instr, unsigned index, validate_state *state)
-{
- nir_alu_src *src = &instr->src[index];
-
- unsigned num_components;
- if (src->src.is_ssa)
- num_components = src->src.ssa->num_components;
- else {
- if (src->src.reg.reg->is_packed)
- num_components = 4; /* can't check anything */
- else
- num_components = src->src.reg.reg->num_components;
- }
- for (unsigned i = 0; i < 4; i++) {
- assert(src->swizzle[i] < 4);
-
- if (nir_alu_instr_channel_used(instr, index, i))
- assert(src->swizzle[i] < num_components);
- }
-
- validate_src(&src->src, state);
-}
-
-static void
-validate_reg_dest(nir_reg_dest *dest, validate_state *state)
-{
- assert(dest->reg != NULL);
-
- assert(dest->parent_instr == state->instr);
-
- struct hash_entry *entry2;
- entry2 = _mesa_hash_table_search(state->regs, dest->reg);
-
- assert(entry2);
-
- reg_validate_state *reg_state = (reg_validate_state *) entry2->data;
- _mesa_set_add(reg_state->defs, dest);
-
- if (!dest->reg->is_global) {
- assert(reg_state->where_defined == state->impl &&
- "writing to a register declared in a different function");
- }
-
- assert((dest->reg->num_array_elems == 0 ||
- dest->base_offset < dest->reg->num_array_elems) &&
- "definitely out-of-bounds array access");
-
- if (dest->indirect) {
- assert(dest->reg->num_array_elems != 0);
- assert((dest->indirect->is_ssa || dest->indirect->reg.indirect == NULL) &&
- "only one level of indirection allowed");
- validate_src(dest->indirect, state);
- }
-}
-
-static void
-validate_ssa_def(nir_ssa_def *def, validate_state *state)
-{
- assert(def->index < state->impl->ssa_alloc);
- assert(!BITSET_TEST(state->ssa_defs_found, def->index));
- BITSET_SET(state->ssa_defs_found, def->index);
-
- assert(def->parent_instr == state->instr);
-
- assert(def->num_components <= 4);
-
- list_validate(&def->uses);
- list_validate(&def->if_uses);
-
- ssa_def_validate_state *def_state = ralloc(state->ssa_defs,
- ssa_def_validate_state);
- def_state->where_defined = state->impl;
- def_state->uses = _mesa_set_create(def_state, _mesa_hash_pointer,
- _mesa_key_pointer_equal);
- def_state->if_uses = _mesa_set_create(def_state, _mesa_hash_pointer,
- _mesa_key_pointer_equal);
- _mesa_hash_table_insert(state->ssa_defs, def, def_state);
-}
-
-static void
-validate_dest(nir_dest *dest, validate_state *state)
-{
- if (dest->is_ssa)
- validate_ssa_def(&dest->ssa, state);
- else
- validate_reg_dest(&dest->reg, state);
-}
-
-static void
-validate_alu_dest(nir_alu_dest *dest, validate_state *state)
-{
- unsigned dest_size =
- dest->dest.is_ssa ? dest->dest.ssa.num_components
- : dest->dest.reg.reg->num_components;
- bool is_packed = !dest->dest.is_ssa && dest->dest.reg.reg->is_packed;
- /*
- * validate that the instruction doesn't write to components not in the
- * register/SSA value
- */
- assert(is_packed || !(dest->write_mask & ~((1 << dest_size) - 1)));
-
- /* validate that saturate is only ever used on instructions with
- * destinations of type float
- */
- nir_alu_instr *alu = nir_instr_as_alu(state->instr);
- assert(nir_op_infos[alu->op].output_type == nir_type_float ||
- !dest->saturate);
-
- validate_dest(&dest->dest, state);
-}
-
-static void
-validate_alu_instr(nir_alu_instr *instr, validate_state *state)
-{
- assert(instr->op < nir_num_opcodes);
-
- for (unsigned i = 0; i < nir_op_infos[instr->op].num_inputs; i++) {
- validate_alu_src(instr, i, state);
- }
-
- validate_alu_dest(&instr->dest, state);
-}
-
-static void
-validate_deref_chain(nir_deref *deref, validate_state *state)
-{
- assert(deref->child == NULL || ralloc_parent(deref->child) == deref);
-
- nir_deref *parent = NULL;
- while (deref != NULL) {
- switch (deref->deref_type) {
- case nir_deref_type_array:
- assert(deref->type == glsl_get_array_element(parent->type));
- if (nir_deref_as_array(deref)->deref_array_type ==
- nir_deref_array_type_indirect)
- validate_src(&nir_deref_as_array(deref)->indirect, state);
- break;
-
- case nir_deref_type_struct:
- assert(deref->type ==
- glsl_get_struct_field(parent->type,
- nir_deref_as_struct(deref)->index));
- break;
-
- case nir_deref_type_var:
- break;
-
- default:
- assert(!"Invalid deref type");
- break;
- }
-
- parent = deref;
- deref = deref->child;
- }
-}
-
-static void
-validate_var_use(nir_variable *var, validate_state *state)
-{
- if (var->data.mode == nir_var_local) {
- struct hash_entry *entry = _mesa_hash_table_search(state->var_defs, var);
-
- assert(entry);
- assert((nir_function_impl *) entry->data == state->impl);
- }
-}
-
-static void
-validate_deref_var(void *parent_mem_ctx, nir_deref_var *deref, validate_state *state)
-{
- assert(deref != NULL);
- assert(ralloc_parent(deref) == parent_mem_ctx);
- assert(deref->deref.type == deref->var->type);
-
- validate_var_use(deref->var, state);
-
- validate_deref_chain(&deref->deref, state);
-}
-
-static void
-validate_intrinsic_instr(nir_intrinsic_instr *instr, validate_state *state)
-{
- unsigned num_srcs = nir_intrinsic_infos[instr->intrinsic].num_srcs;
- for (unsigned i = 0; i < num_srcs; i++) {
- unsigned components_read =
- nir_intrinsic_infos[instr->intrinsic].src_components[i];
- if (components_read == 0)
- components_read = instr->num_components;
-
- assert(components_read > 0);
-
- if (instr->src[i].is_ssa) {
- assert(components_read <= instr->src[i].ssa->num_components);
- } else if (!instr->src[i].reg.reg->is_packed) {
- assert(components_read <= instr->src[i].reg.reg->num_components);
- }
-
- validate_src(&instr->src[i], state);
- }
-
- unsigned num_vars = nir_intrinsic_infos[instr->intrinsic].num_variables;
- for (unsigned i = 0; i < num_vars; i++) {
- validate_deref_var(instr, instr->variables[i], state);
- }
-
- if (nir_intrinsic_infos[instr->intrinsic].has_dest) {
- unsigned components_written =
- nir_intrinsic_infos[instr->intrinsic].dest_components;
- if (components_written == 0)
- components_written = instr->num_components;
-
- assert(components_written > 0);
-
- if (instr->dest.is_ssa) {
- assert(components_written <= instr->dest.ssa.num_components);
- } else if (!instr->dest.reg.reg->is_packed) {
- assert(components_written <= instr->dest.reg.reg->num_components);
- }
-
- validate_dest(&instr->dest, state);
- }
-
- switch (instr->intrinsic) {
- case nir_intrinsic_load_var: {
- const struct glsl_type *type =
- nir_deref_tail(&instr->variables[0]->deref)->type;
- assert(glsl_type_is_vector_or_scalar(type) ||
- (instr->variables[0]->var->data.mode == nir_var_uniform &&
- glsl_get_base_type(type) == GLSL_TYPE_SUBROUTINE));
- assert(instr->num_components == glsl_get_vector_elements(type));
- break;
- }
- case nir_intrinsic_store_var: {
- const struct glsl_type *type =
- nir_deref_tail(&instr->variables[0]->deref)->type;
- assert(glsl_type_is_vector_or_scalar(type) ||
- (instr->variables[0]->var->data.mode == nir_var_uniform &&
- glsl_get_base_type(type) == GLSL_TYPE_SUBROUTINE));
- assert(instr->num_components == glsl_get_vector_elements(type));
- assert(instr->variables[0]->var->data.mode != nir_var_shader_in &&
- instr->variables[0]->var->data.mode != nir_var_uniform &&
- instr->variables[0]->var->data.mode != nir_var_shader_storage);
- assert((instr->const_index[0] & ~((1 << instr->num_components) - 1)) == 0);
- break;
- }
- case nir_intrinsic_copy_var:
- assert(nir_deref_tail(&instr->variables[0]->deref)->type ==
- nir_deref_tail(&instr->variables[1]->deref)->type);
- assert(instr->variables[0]->var->data.mode != nir_var_shader_in &&
- instr->variables[0]->var->data.mode != nir_var_uniform &&
- instr->variables[0]->var->data.mode != nir_var_shader_storage);
- break;
- default:
- break;
- }
-}
-
-static void
-validate_tex_instr(nir_tex_instr *instr, validate_state *state)
-{
- bool src_type_seen[nir_num_tex_src_types];
- for (unsigned i = 0; i < nir_num_tex_src_types; i++)
- src_type_seen[i] = false;
-
- for (unsigned i = 0; i < instr->num_srcs; i++) {
- assert(!src_type_seen[instr->src[i].src_type]);
- src_type_seen[instr->src[i].src_type] = true;
- validate_src(&instr->src[i].src, state);
- }
-
- if (instr->sampler != NULL)
- validate_deref_var(instr, instr->sampler, state);
-
- validate_dest(&instr->dest, state);
-}
-
-static void
-validate_call_instr(nir_call_instr *instr, validate_state *state)
-{
- if (instr->return_deref == NULL) {
- assert(glsl_type_is_void(instr->callee->return_type));
- } else {
- assert(instr->return_deref->deref.type == instr->callee->return_type);
- validate_deref_var(instr, instr->return_deref, state);
- }
-
- assert(instr->num_params == instr->callee->num_params);
-
- for (unsigned i = 0; i < instr->num_params; i++) {
- assert(instr->callee->params[i].type == instr->params[i]->deref.type);
- validate_deref_var(instr, instr->params[i], state);
- }
-}
-
-static void
-validate_load_const_instr(nir_load_const_instr *instr, validate_state *state)
-{
- validate_ssa_def(&instr->def, state);
-}
-
-static void
-validate_ssa_undef_instr(nir_ssa_undef_instr *instr, validate_state *state)
-{
- validate_ssa_def(&instr->def, state);
-}
-
-static void
-validate_phi_instr(nir_phi_instr *instr, validate_state *state)
-{
- /*
- * don't validate the sources until we get to them from their predecessor
- * basic blocks, to avoid validating an SSA use before its definition.
- */
-
- validate_dest(&instr->dest, state);
-
- exec_list_validate(&instr->srcs);
- assert(exec_list_length(&instr->srcs) ==
- state->block->predecessors->entries);
-}
-
-static void
-validate_instr(nir_instr *instr, validate_state *state)
-{
- assert(instr->block == state->block);
-
- state->instr = instr;
-
- switch (instr->type) {
- case nir_instr_type_alu:
- validate_alu_instr(nir_instr_as_alu(instr), state);
- break;
-
- case nir_instr_type_call:
- validate_call_instr(nir_instr_as_call(instr), state);
- break;
-
- case nir_instr_type_intrinsic:
- validate_intrinsic_instr(nir_instr_as_intrinsic(instr), state);
- break;
-
- case nir_instr_type_tex:
- validate_tex_instr(nir_instr_as_tex(instr), state);
- break;
-
- case nir_instr_type_load_const:
- validate_load_const_instr(nir_instr_as_load_const(instr), state);
- break;
-
- case nir_instr_type_phi:
- validate_phi_instr(nir_instr_as_phi(instr), state);
- break;
-
- case nir_instr_type_ssa_undef:
- validate_ssa_undef_instr(nir_instr_as_ssa_undef(instr), state);
- break;
-
- case nir_instr_type_jump:
- break;
-
- default:
- assert(!"Invalid ALU instruction type");
- break;
- }
-
- state->instr = NULL;
-}
-
-static void
-validate_phi_src(nir_phi_instr *instr, nir_block *pred, validate_state *state)
-{
- state->instr = &instr->instr;
-
- assert(instr->dest.is_ssa);
-
- exec_list_validate(&instr->srcs);
- nir_foreach_phi_src(instr, src) {
- if (src->pred == pred) {
- assert(src->src.is_ssa);
- assert(src->src.ssa->num_components ==
- instr->dest.ssa.num_components);
-
- validate_src(&src->src, state);
- state->instr = NULL;
- return;
- }
- }
-
- abort();
-}
-
-static void
-validate_phi_srcs(nir_block *block, nir_block *succ, validate_state *state)
-{
- nir_foreach_instr(succ, instr) {
- if (instr->type != nir_instr_type_phi)
- break;
-
- validate_phi_src(nir_instr_as_phi(instr), block, state);
- }
-}
-
-static void validate_cf_node(nir_cf_node *node, validate_state *state);
-
-static void
-validate_block(nir_block *block, validate_state *state)
-{
- assert(block->cf_node.parent == state->parent_node);
-
- state->block = block;
-
- exec_list_validate(&block->instr_list);
- nir_foreach_instr(block, instr) {
- if (instr->type == nir_instr_type_phi) {
- assert(instr == nir_block_first_instr(block) ||
- nir_instr_prev(instr)->type == nir_instr_type_phi);
- }
-
- if (instr->type == nir_instr_type_jump) {
- assert(instr == nir_block_last_instr(block));
- }
-
- validate_instr(instr, state);
- }
-
- assert(block->successors[0] != NULL);
- assert(block->successors[0] != block->successors[1]);
-
- for (unsigned i = 0; i < 2; i++) {
- if (block->successors[i] != NULL) {
- struct set_entry *entry =
- _mesa_set_search(block->successors[i]->predecessors, block);
- assert(entry);
-
- validate_phi_srcs(block, block->successors[i], state);
- }
- }
-
- struct set_entry *entry;
- set_foreach(block->predecessors, entry) {
- const nir_block *pred = entry->key;
- assert(pred->successors[0] == block ||
- pred->successors[1] == block);
- }
-
- if (!exec_list_is_empty(&block->instr_list) &&
- nir_block_last_instr(block)->type == nir_instr_type_jump) {
- assert(block->successors[1] == NULL);
- nir_jump_instr *jump = nir_instr_as_jump(nir_block_last_instr(block));
- switch (jump->type) {
- case nir_jump_break: {
- nir_block *after =
- nir_cf_node_as_block(nir_cf_node_next(&state->loop->cf_node));
- assert(block->successors[0] == after);
- break;
- }
-
- case nir_jump_continue: {
- nir_block *first =
- nir_cf_node_as_block(nir_loop_first_cf_node(state->loop));
- assert(block->successors[0] == first);
- break;
- }
-
- case nir_jump_return:
- assert(block->successors[0] == state->impl->end_block);
- break;
-
- default:
- unreachable("bad jump type");
- }
- } else {
- nir_cf_node *next = nir_cf_node_next(&block->cf_node);
- if (next == NULL) {
- switch (state->parent_node->type) {
- case nir_cf_node_loop: {
- nir_block *first =
- nir_cf_node_as_block(nir_loop_first_cf_node(state->loop));
- assert(block->successors[0] == first);
- /* due to the hack for infinite loops, block->successors[1] may
- * point to the block after the loop.
- */
- break;
- }
-
- case nir_cf_node_if: {
- nir_block *after =
- nir_cf_node_as_block(nir_cf_node_next(state->parent_node));
- assert(block->successors[0] == after);
- assert(block->successors[1] == NULL);
- break;
- }
-
- case nir_cf_node_function:
- assert(block->successors[0] == state->impl->end_block);
- assert(block->successors[1] == NULL);
- break;
-
- default:
- unreachable("unknown control flow node type");
- }
- } else {
- if (next->type == nir_cf_node_if) {
- nir_if *if_stmt = nir_cf_node_as_if(next);
- assert(&block->successors[0]->cf_node ==
- nir_if_first_then_node(if_stmt));
- assert(&block->successors[1]->cf_node ==
- nir_if_first_else_node(if_stmt));
- } else {
- assert(next->type == nir_cf_node_loop);
- nir_loop *loop = nir_cf_node_as_loop(next);
- assert(&block->successors[0]->cf_node ==
- nir_loop_first_cf_node(loop));
- assert(block->successors[1] == NULL);
- }
- }
- }
-}
-
-static void
-validate_if(nir_if *if_stmt, validate_state *state)
-{
- state->if_stmt = if_stmt;
-
- assert(!exec_node_is_head_sentinel(if_stmt->cf_node.node.prev));
- nir_cf_node *prev_node = nir_cf_node_prev(&if_stmt->cf_node);
- assert(prev_node->type == nir_cf_node_block);
-
- assert(!exec_node_is_tail_sentinel(if_stmt->cf_node.node.next));
- nir_cf_node *next_node = nir_cf_node_next(&if_stmt->cf_node);
- assert(next_node->type == nir_cf_node_block);
-
- validate_src(&if_stmt->condition, state);
-
- assert(!exec_list_is_empty(&if_stmt->then_list));
- assert(!exec_list_is_empty(&if_stmt->else_list));
-
- nir_cf_node *old_parent = state->parent_node;
- state->parent_node = &if_stmt->cf_node;
-
- exec_list_validate(&if_stmt->then_list);
- foreach_list_typed(nir_cf_node, cf_node, node, &if_stmt->then_list) {
- validate_cf_node(cf_node, state);
- }
-
- exec_list_validate(&if_stmt->else_list);
- foreach_list_typed(nir_cf_node, cf_node, node, &if_stmt->else_list) {
- validate_cf_node(cf_node, state);
- }
-
- state->parent_node = old_parent;
- state->if_stmt = NULL;
-}
-
-static void
-validate_loop(nir_loop *loop, validate_state *state)
-{
- assert(!exec_node_is_head_sentinel(loop->cf_node.node.prev));
- nir_cf_node *prev_node = nir_cf_node_prev(&loop->cf_node);
- assert(prev_node->type == nir_cf_node_block);
-
- assert(!exec_node_is_tail_sentinel(loop->cf_node.node.next));
- nir_cf_node *next_node = nir_cf_node_next(&loop->cf_node);
- assert(next_node->type == nir_cf_node_block);
-
- assert(!exec_list_is_empty(&loop->body));
-
- nir_cf_node *old_parent = state->parent_node;
- state->parent_node = &loop->cf_node;
- nir_loop *old_loop = state->loop;
- state->loop = loop;
-
- exec_list_validate(&loop->body);
- foreach_list_typed(nir_cf_node, cf_node, node, &loop->body) {
- validate_cf_node(cf_node, state);
- }
-
- state->parent_node = old_parent;
- state->loop = old_loop;
-}
-
-static void
-validate_cf_node(nir_cf_node *node, validate_state *state)
-{
- assert(node->parent == state->parent_node);
-
- switch (node->type) {
- case nir_cf_node_block:
- validate_block(nir_cf_node_as_block(node), state);
- break;
-
- case nir_cf_node_if:
- validate_if(nir_cf_node_as_if(node), state);
- break;
-
- case nir_cf_node_loop:
- validate_loop(nir_cf_node_as_loop(node), state);
- break;
-
- default:
- unreachable("Invalid CF node type");
- }
-}
-
-static void
-prevalidate_reg_decl(nir_register *reg, bool is_global, validate_state *state)
-{
- assert(reg->is_global == is_global);
-
- if (is_global)
- assert(reg->index < state->shader->reg_alloc);
- else
- assert(reg->index < state->impl->reg_alloc);
- assert(!BITSET_TEST(state->regs_found, reg->index));
- BITSET_SET(state->regs_found, reg->index);
-
- list_validate(&reg->uses);
- list_validate(&reg->defs);
- list_validate(&reg->if_uses);
-
- reg_validate_state *reg_state = ralloc(state->regs, reg_validate_state);
- reg_state->uses = _mesa_set_create(reg_state, _mesa_hash_pointer,
- _mesa_key_pointer_equal);
- reg_state->if_uses = _mesa_set_create(reg_state, _mesa_hash_pointer,
- _mesa_key_pointer_equal);
- reg_state->defs = _mesa_set_create(reg_state, _mesa_hash_pointer,
- _mesa_key_pointer_equal);
-
- reg_state->where_defined = is_global ? NULL : state->impl;
-
- _mesa_hash_table_insert(state->regs, reg, reg_state);
-}
-
-static void
-postvalidate_reg_decl(nir_register *reg, validate_state *state)
-{
- struct hash_entry *entry = _mesa_hash_table_search(state->regs, reg);
-
- reg_validate_state *reg_state = (reg_validate_state *) entry->data;
-
- nir_foreach_use(reg, src) {
- struct set_entry *entry = _mesa_set_search(reg_state->uses, src);
- assert(entry);
- _mesa_set_remove(reg_state->uses, entry);
- }
-
- if (reg_state->uses->entries != 0) {
- printf("extra entries in register uses:\n");
- struct set_entry *entry;
- set_foreach(reg_state->uses, entry)
- printf("%p\n", entry->key);
-
- abort();
- }
-
- nir_foreach_if_use(reg, src) {
- struct set_entry *entry = _mesa_set_search(reg_state->if_uses, src);
- assert(entry);
- _mesa_set_remove(reg_state->if_uses, entry);
- }
-
- if (reg_state->if_uses->entries != 0) {
- printf("extra entries in register if_uses:\n");
- struct set_entry *entry;
- set_foreach(reg_state->if_uses, entry)
- printf("%p\n", entry->key);
-
- abort();
- }
-
- nir_foreach_def(reg, src) {
- struct set_entry *entry = _mesa_set_search(reg_state->defs, src);
- assert(entry);
- _mesa_set_remove(reg_state->defs, entry);
- }
-
- if (reg_state->defs->entries != 0) {
- printf("extra entries in register defs:\n");
- struct set_entry *entry;
- set_foreach(reg_state->defs, entry)
- printf("%p\n", entry->key);
-
- abort();
- }
-}
-
-static void
-validate_var_decl(nir_variable *var, bool is_global, validate_state *state)
-{
- assert(is_global != (var->data.mode == nir_var_local));
-
- /*
- * TODO validate some things ir_validate.cpp does (requires more GLSL type
- * support)
- */
-
- if (!is_global) {
- _mesa_hash_table_insert(state->var_defs, var, state->impl);
- }
-}
-
-static bool
-postvalidate_ssa_def(nir_ssa_def *def, void *void_state)
-{
- validate_state *state = void_state;
-
- struct hash_entry *entry = _mesa_hash_table_search(state->ssa_defs, def);
- ssa_def_validate_state *def_state = (ssa_def_validate_state *)entry->data;
-
- nir_foreach_use(def, src) {
- struct set_entry *entry = _mesa_set_search(def_state->uses, src);
- assert(entry);
- _mesa_set_remove(def_state->uses, entry);
- }
-
- if (def_state->uses->entries != 0) {
- printf("extra entries in register uses:\n");
- struct set_entry *entry;
- set_foreach(def_state->uses, entry)
- printf("%p\n", entry->key);
-
- abort();
- }
-
- nir_foreach_if_use(def, src) {
- struct set_entry *entry = _mesa_set_search(def_state->if_uses, src);
- assert(entry);
- _mesa_set_remove(def_state->if_uses, entry);
- }
-
- if (def_state->if_uses->entries != 0) {
- printf("extra entries in register uses:\n");
- struct set_entry *entry;
- set_foreach(def_state->if_uses, entry)
- printf("%p\n", entry->key);
-
- abort();
- }
-
- return true;
-}
-
-static bool
-postvalidate_ssa_defs_block(nir_block *block, void *state)
-{
- nir_foreach_instr(block, instr)
- nir_foreach_ssa_def(instr, postvalidate_ssa_def, state);
-
- return true;
-}
-
-static void
-validate_function_impl(nir_function_impl *impl, validate_state *state)
-{
- assert(impl->function->impl == impl);
- assert(impl->cf_node.parent == NULL);
-
- assert(impl->num_params == impl->function->num_params);
- for (unsigned i = 0; i < impl->num_params; i++)
- assert(impl->params[i]->type == impl->function->params[i].type);
-
- if (glsl_type_is_void(impl->function->return_type))
- assert(impl->return_var == NULL);
- else
- assert(impl->return_var->type == impl->function->return_type);
-
- assert(exec_list_is_empty(&impl->end_block->instr_list));
- assert(impl->end_block->successors[0] == NULL);
- assert(impl->end_block->successors[1] == NULL);
-
- state->impl = impl;
- state->parent_node = &impl->cf_node;
-
- exec_list_validate(&impl->locals);
- nir_foreach_variable(var, &impl->locals) {
- validate_var_decl(var, false, state);
- }
-
- state->regs_found = realloc(state->regs_found,
- BITSET_WORDS(impl->reg_alloc) *
- sizeof(BITSET_WORD));
- memset(state->regs_found, 0, BITSET_WORDS(impl->reg_alloc) *
- sizeof(BITSET_WORD));
- exec_list_validate(&impl->registers);
- foreach_list_typed(nir_register, reg, node, &impl->registers) {
- prevalidate_reg_decl(reg, false, state);
- }
-
- state->ssa_defs_found = realloc(state->ssa_defs_found,
- BITSET_WORDS(impl->ssa_alloc) *
- sizeof(BITSET_WORD));
- memset(state->ssa_defs_found, 0, BITSET_WORDS(impl->ssa_alloc) *
- sizeof(BITSET_WORD));
- exec_list_validate(&impl->body);
- foreach_list_typed(nir_cf_node, node, node, &impl->body) {
- validate_cf_node(node, state);
- }
-
- foreach_list_typed(nir_register, reg, node, &impl->registers) {
- postvalidate_reg_decl(reg, state);
- }
-
- nir_foreach_block(impl, postvalidate_ssa_defs_block, state);
-}
-
-static void
-validate_function(nir_function *func, validate_state *state)
-{
- if (func->impl != NULL) {
- assert(func->impl->function == func);
- validate_function_impl(func->impl, state);
- }
-}
-
-static void
-init_validate_state(validate_state *state)
-{
- state->regs = _mesa_hash_table_create(NULL, _mesa_hash_pointer,
- _mesa_key_pointer_equal);
- state->ssa_defs = _mesa_hash_table_create(NULL, _mesa_hash_pointer,
- _mesa_key_pointer_equal);
- state->ssa_defs_found = NULL;
- state->regs_found = NULL;
- state->var_defs = _mesa_hash_table_create(NULL, _mesa_hash_pointer,
- _mesa_key_pointer_equal);
- state->loop = NULL;
-}
-
-static void
-destroy_validate_state(validate_state *state)
-{
- _mesa_hash_table_destroy(state->regs, NULL);
- _mesa_hash_table_destroy(state->ssa_defs, NULL);
- free(state->ssa_defs_found);
- free(state->regs_found);
- _mesa_hash_table_destroy(state->var_defs, NULL);
-}
-
-void
-nir_validate_shader(nir_shader *shader)
-{
- validate_state state;
- init_validate_state(&state);
-
- state.shader = shader;
-
- exec_list_validate(&shader->uniforms);
- nir_foreach_variable(var, &shader->uniforms) {
- validate_var_decl(var, true, &state);
- }
-
- exec_list_validate(&shader->inputs);
- nir_foreach_variable(var, &shader->inputs) {
- validate_var_decl(var, true, &state);
- }
-
- exec_list_validate(&shader->outputs);
- nir_foreach_variable(var, &shader->outputs) {
- validate_var_decl(var, true, &state);
- }
-
- exec_list_validate(&shader->shared);
- nir_foreach_variable(var, &shader->shared) {
- validate_var_decl(var, true, &state);
- }
-
- exec_list_validate(&shader->globals);
- nir_foreach_variable(var, &shader->globals) {
- validate_var_decl(var, true, &state);
- }
-
- exec_list_validate(&shader->system_values);
- nir_foreach_variable(var, &shader->system_values) {
- validate_var_decl(var, true, &state);
- }
-
- state.regs_found = realloc(state.regs_found,
- BITSET_WORDS(shader->reg_alloc) *
- sizeof(BITSET_WORD));
- memset(state.regs_found, 0, BITSET_WORDS(shader->reg_alloc) *
- sizeof(BITSET_WORD));
- exec_list_validate(&shader->registers);
- foreach_list_typed(nir_register, reg, node, &shader->registers) {
- prevalidate_reg_decl(reg, true, &state);
- }
-
- exec_list_validate(&shader->functions);
- foreach_list_typed(nir_function, func, node, &shader->functions) {
- validate_function(func, &state);
- }
-
- foreach_list_typed(nir_register, reg, node, &shader->registers) {
- postvalidate_reg_decl(reg, &state);
- }
-
- destroy_validate_state(&state);
-}
-
-#endif /* NDEBUG */
diff --git a/src/glsl/nir/nir_vla.h b/src/glsl/nir/nir_vla.h
deleted file mode 100644
index 753783316a2..00000000000
--- a/src/glsl/nir/nir_vla.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/**************************************************************************
- *
- * Copyright 2015 VMware, Inc.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- **************************************************************************/
-
-#pragma once
-
-
-#include "c99_alloca.h"
-
-
-/* Declare a variable length array, with no initialization */
-#define NIR_VLA(_type, _name, _length) \
- _type *_name = alloca((_length) * sizeof *_name)
-
-
-/* Declare a variable length array, and initialize it with the given byte.
- *
- * _length is evaluated twice, so expressions with side-effects must be
- * avoided.
- */
-#define NIR_VLA_FILL(_type, _name, _length, _byte) \
- _type *_name = memset(alloca((_length) * sizeof *_name), _byte, (_length) * sizeof *_name)
-
-
-/* Declare a variable length array, and zero it.
- *
- * Just like NIR_VLA_FILL, _length is evaluated twice, so expressions with
- * side-effects must be avoided.
- */
-#define NIR_VLA_ZERO(_type, _name, _length) \
- NIR_VLA_FILL(_type, _name, _length, 0)
diff --git a/src/glsl/nir/nir_worklist.c b/src/glsl/nir/nir_worklist.c
deleted file mode 100644
index 3087a1d2354..00000000000
--- a/src/glsl/nir/nir_worklist.c
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Copyright © 2014 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- *
- * Authors:
- * Jason Ekstrand ([email protected])
- *
- */
-
-#include "nir_worklist.h"
-
-void
-nir_block_worklist_init(nir_block_worklist *w, unsigned num_blocks,
- void *mem_ctx)
-{
- w->size = num_blocks;
- w->count = 0;
- w->start = 0;
-
- w->blocks_present = rzalloc_array(mem_ctx, BITSET_WORD,
- BITSET_WORDS(num_blocks));
- w->blocks = ralloc_array(mem_ctx, nir_block *, num_blocks);
-}
-
-void
-nir_block_worklist_fini(nir_block_worklist *w)
-{
- ralloc_free(w->blocks_present);
- ralloc_free(w->blocks);
-}
-
-static bool
-worklist_add_block(nir_block *block, void *w)
-{
- nir_block_worklist_push_tail(w, block);
-
- return true;
-}
-
-void
-nir_block_worklist_add_all(nir_block_worklist *w, nir_function_impl *impl)
-{
- nir_foreach_block(impl, worklist_add_block, w);
-}
-
-void
-nir_block_worklist_push_head(nir_block_worklist *w, nir_block *block)
-{
- /* Pushing a block we already have is a no-op */
- if (BITSET_TEST(w->blocks_present, block->index))
- return;
-
- assert(w->count < w->size);
-
- if (w->start == 0)
- w->start = w->size - 1;
- else
- w->start--;
-
- w->count++;
-
- w->blocks[w->start] = block;
- BITSET_SET(w->blocks_present, block->index);
-}
-
-nir_block *
-nir_block_worklist_peek_head(const nir_block_worklist *w)
-{
- assert(w->count > 0);
-
- return w->blocks[w->start];
-}
-
-nir_block *
-nir_block_worklist_pop_head(nir_block_worklist *w)
-{
- assert(w->count > 0);
-
- unsigned head = w->start;
-
- w->start = (w->start + 1) % w->size;
- w->count--;
-
- BITSET_CLEAR(w->blocks_present, w->blocks[head]->index);
- return w->blocks[head];
-}
-
-void
-nir_block_worklist_push_tail(nir_block_worklist *w, nir_block *block)
-{
- /* Pushing a block we already have is a no-op */
- if (BITSET_TEST(w->blocks_present, block->index))
- return;
-
- assert(w->count < w->size);
-
- w->count++;
-
- 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(const nir_block_worklist *w)
-{
- assert(w->count > 0);
-
- unsigned tail = (w->start + w->count - 1) % w->size;
-
- return w->blocks[tail];
-}
-
-nir_block *
-nir_block_worklist_pop_tail(nir_block_worklist *w)
-{
- assert(w->count > 0);
-
- unsigned tail = (w->start + w->count - 1) % w->size;
-
- w->count--;
-
- BITSET_CLEAR(w->blocks_present, w->blocks[tail]->index);
- return w->blocks[tail];
-}
diff --git a/src/glsl/nir/nir_worklist.h b/src/glsl/nir/nir_worklist.h
deleted file mode 100644
index 829bff24a55..00000000000
--- a/src/glsl/nir/nir_worklist.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright © 2014 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- *
- * Authors:
- * Jason Ekstrand ([email protected])
- *
- */
-
-#pragma once
-
-#ifndef _NIR_WORKLIST_
-#define _NIR_WORKLIST_
-
-#include "nir.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/** Represents a double-ended queue of unique blocks
- *
- * The worklist datastructure guarantees that eacy block is in the queue at
- * most once. Pushing a block onto either end of the queue is a no-op if
- * the block is already in the queue. In order for this to work, the
- * caller must ensure that the blocks are properly indexed.
- */
-typedef struct {
- /* The total size of the worklist */
- unsigned size;
-
- /* The number of blocks currently in the worklist */
- unsigned count;
-
- /* The offset in the array of blocks at which the list starts */
- unsigned start;
-
- /* A bitset of all of the blocks currently present in the worklist */
- BITSET_WORD *blocks_present;
-
- /* The actual worklist */
- nir_block **blocks;
-} nir_block_worklist;
-
-void nir_block_worklist_init(nir_block_worklist *w, unsigned num_blocks,
- void *mem_ctx);
-void nir_block_worklist_fini(nir_block_worklist *w);
-
-void nir_block_worklist_add_all(nir_block_worklist *w, nir_function_impl *impl);
-
-static inline bool
-nir_block_worklist_is_empty(const nir_block_worklist *w)
-{
- return w->count == 0;
-}
-
-void nir_block_worklist_push_head(nir_block_worklist *w, nir_block *block);
-
-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(const nir_block_worklist *w);
-
-nir_block *nir_block_worklist_pop_tail(nir_block_worklist *w);
-
-#ifdef __cplusplus
-} /* extern "C" */
-#endif
-
-#endif /* _NIR_WORKLIST_ */
diff --git a/src/glsl/nir/shader_enums.c b/src/glsl/nir/shader_enums.c
deleted file mode 100644
index ff2f564dc98..00000000000
--- a/src/glsl/nir/shader_enums.c
+++ /dev/null
@@ -1,260 +0,0 @@
-/*
- * Mesa 3-D graphics library
- *
- * Copyright © 2015 Red Hat
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- *
- * Authors:
- * Rob Clark <[email protected]>
- */
-
-#include "shader_enums.h"
-#include "util/macros.h"
-#include "mesa/main/config.h"
-
-#define ENUM(x) [x] = #x
-#define NAME(val) ((((val) < ARRAY_SIZE(names)) && names[(val)]) ? names[(val)] : "UNKNOWN")
-
-const char *
-gl_shader_stage_name(gl_shader_stage stage)
-{
- static const char *names[] = {
- ENUM(MESA_SHADER_VERTEX),
- ENUM(MESA_SHADER_TESS_CTRL),
- ENUM(MESA_SHADER_TESS_EVAL),
- ENUM(MESA_SHADER_GEOMETRY),
- ENUM(MESA_SHADER_FRAGMENT),
- ENUM(MESA_SHADER_COMPUTE),
- };
- STATIC_ASSERT(ARRAY_SIZE(names) == MESA_SHADER_STAGES);
- return NAME(stage);
-}
-
-/**
- * Translate a gl_shader_stage to a short shader stage name for debug
- * printouts and error messages.
- */
-const char *
-_mesa_shader_stage_to_string(unsigned stage)
-{
- switch (stage) {
- case MESA_SHADER_VERTEX: return "vertex";
- case MESA_SHADER_FRAGMENT: return "fragment";
- case MESA_SHADER_GEOMETRY: return "geometry";
- case MESA_SHADER_COMPUTE: return "compute";
- case MESA_SHADER_TESS_CTRL: return "tessellation control";
- case MESA_SHADER_TESS_EVAL: return "tessellation evaluation";
- }
-
- unreachable("Unknown shader stage.");
-}
-
-/**
- * Translate a gl_shader_stage to a shader stage abbreviation (VS, GS, FS)
- * for debug printouts and error messages.
- */
-const char *
-_mesa_shader_stage_to_abbrev(unsigned stage)
-{
- switch (stage) {
- case MESA_SHADER_VERTEX: return "VS";
- case MESA_SHADER_FRAGMENT: return "FS";
- case MESA_SHADER_GEOMETRY: return "GS";
- case MESA_SHADER_COMPUTE: return "CS";
- case MESA_SHADER_TESS_CTRL: return "TCS";
- case MESA_SHADER_TESS_EVAL: return "TES";
- }
-
- unreachable("Unknown shader stage.");
-}
-
-const char *
-gl_vert_attrib_name(gl_vert_attrib attrib)
-{
- static const char *names[] = {
- ENUM(VERT_ATTRIB_POS),
- ENUM(VERT_ATTRIB_WEIGHT),
- ENUM(VERT_ATTRIB_NORMAL),
- ENUM(VERT_ATTRIB_COLOR0),
- ENUM(VERT_ATTRIB_COLOR1),
- ENUM(VERT_ATTRIB_FOG),
- ENUM(VERT_ATTRIB_COLOR_INDEX),
- ENUM(VERT_ATTRIB_EDGEFLAG),
- ENUM(VERT_ATTRIB_TEX0),
- ENUM(VERT_ATTRIB_TEX1),
- ENUM(VERT_ATTRIB_TEX2),
- ENUM(VERT_ATTRIB_TEX3),
- ENUM(VERT_ATTRIB_TEX4),
- ENUM(VERT_ATTRIB_TEX5),
- ENUM(VERT_ATTRIB_TEX6),
- ENUM(VERT_ATTRIB_TEX7),
- ENUM(VERT_ATTRIB_POINT_SIZE),
- ENUM(VERT_ATTRIB_GENERIC0),
- ENUM(VERT_ATTRIB_GENERIC1),
- ENUM(VERT_ATTRIB_GENERIC2),
- ENUM(VERT_ATTRIB_GENERIC3),
- ENUM(VERT_ATTRIB_GENERIC4),
- ENUM(VERT_ATTRIB_GENERIC5),
- ENUM(VERT_ATTRIB_GENERIC6),
- ENUM(VERT_ATTRIB_GENERIC7),
- ENUM(VERT_ATTRIB_GENERIC8),
- ENUM(VERT_ATTRIB_GENERIC9),
- ENUM(VERT_ATTRIB_GENERIC10),
- ENUM(VERT_ATTRIB_GENERIC11),
- ENUM(VERT_ATTRIB_GENERIC12),
- ENUM(VERT_ATTRIB_GENERIC13),
- ENUM(VERT_ATTRIB_GENERIC14),
- ENUM(VERT_ATTRIB_GENERIC15),
- };
- STATIC_ASSERT(ARRAY_SIZE(names) == VERT_ATTRIB_MAX);
- return NAME(attrib);
-}
-
-const char *
-gl_varying_slot_name(gl_varying_slot slot)
-{
- static const char *names[] = {
- ENUM(VARYING_SLOT_POS),
- ENUM(VARYING_SLOT_COL0),
- ENUM(VARYING_SLOT_COL1),
- ENUM(VARYING_SLOT_FOGC),
- ENUM(VARYING_SLOT_TEX0),
- ENUM(VARYING_SLOT_TEX1),
- ENUM(VARYING_SLOT_TEX2),
- ENUM(VARYING_SLOT_TEX3),
- ENUM(VARYING_SLOT_TEX4),
- ENUM(VARYING_SLOT_TEX5),
- ENUM(VARYING_SLOT_TEX6),
- ENUM(VARYING_SLOT_TEX7),
- ENUM(VARYING_SLOT_PSIZ),
- ENUM(VARYING_SLOT_BFC0),
- ENUM(VARYING_SLOT_BFC1),
- ENUM(VARYING_SLOT_EDGE),
- ENUM(VARYING_SLOT_CLIP_VERTEX),
- ENUM(VARYING_SLOT_CLIP_DIST0),
- ENUM(VARYING_SLOT_CLIP_DIST1),
- ENUM(VARYING_SLOT_PRIMITIVE_ID),
- ENUM(VARYING_SLOT_LAYER),
- ENUM(VARYING_SLOT_VIEWPORT),
- ENUM(VARYING_SLOT_FACE),
- ENUM(VARYING_SLOT_PNTC),
- ENUM(VARYING_SLOT_TESS_LEVEL_OUTER),
- ENUM(VARYING_SLOT_TESS_LEVEL_INNER),
- ENUM(VARYING_SLOT_VAR0),
- ENUM(VARYING_SLOT_VAR1),
- ENUM(VARYING_SLOT_VAR2),
- ENUM(VARYING_SLOT_VAR3),
- ENUM(VARYING_SLOT_VAR4),
- ENUM(VARYING_SLOT_VAR5),
- ENUM(VARYING_SLOT_VAR6),
- ENUM(VARYING_SLOT_VAR7),
- ENUM(VARYING_SLOT_VAR8),
- ENUM(VARYING_SLOT_VAR9),
- ENUM(VARYING_SLOT_VAR10),
- ENUM(VARYING_SLOT_VAR11),
- ENUM(VARYING_SLOT_VAR12),
- ENUM(VARYING_SLOT_VAR13),
- ENUM(VARYING_SLOT_VAR14),
- ENUM(VARYING_SLOT_VAR15),
- ENUM(VARYING_SLOT_VAR16),
- ENUM(VARYING_SLOT_VAR17),
- ENUM(VARYING_SLOT_VAR18),
- ENUM(VARYING_SLOT_VAR19),
- ENUM(VARYING_SLOT_VAR20),
- ENUM(VARYING_SLOT_VAR21),
- ENUM(VARYING_SLOT_VAR22),
- ENUM(VARYING_SLOT_VAR23),
- ENUM(VARYING_SLOT_VAR24),
- ENUM(VARYING_SLOT_VAR25),
- ENUM(VARYING_SLOT_VAR26),
- ENUM(VARYING_SLOT_VAR27),
- ENUM(VARYING_SLOT_VAR28),
- ENUM(VARYING_SLOT_VAR29),
- ENUM(VARYING_SLOT_VAR30),
- ENUM(VARYING_SLOT_VAR31),
- };
- STATIC_ASSERT(ARRAY_SIZE(names) == VARYING_SLOT_MAX);
- return NAME(slot);
-}
-
-const char *
-gl_system_value_name(gl_system_value sysval)
-{
- static const char *names[] = {
- ENUM(SYSTEM_VALUE_VERTEX_ID),
- ENUM(SYSTEM_VALUE_INSTANCE_ID),
- ENUM(SYSTEM_VALUE_INSTANCE_INDEX),
- ENUM(SYSTEM_VALUE_VERTEX_ID_ZERO_BASE),
- ENUM(SYSTEM_VALUE_BASE_VERTEX),
- ENUM(SYSTEM_VALUE_INVOCATION_ID),
- ENUM(SYSTEM_VALUE_FRONT_FACE),
- ENUM(SYSTEM_VALUE_SAMPLE_ID),
- ENUM(SYSTEM_VALUE_SAMPLE_POS),
- ENUM(SYSTEM_VALUE_SAMPLE_MASK_IN),
- ENUM(SYSTEM_VALUE_TESS_COORD),
- ENUM(SYSTEM_VALUE_VERTICES_IN),
- ENUM(SYSTEM_VALUE_PRIMITIVE_ID),
- ENUM(SYSTEM_VALUE_TESS_LEVEL_OUTER),
- ENUM(SYSTEM_VALUE_TESS_LEVEL_INNER),
- ENUM(SYSTEM_VALUE_LOCAL_INVOCATION_ID),
- ENUM(SYSTEM_VALUE_LOCAL_INVOCATION_INDEX),
- ENUM(SYSTEM_VALUE_GLOBAL_INVOCATION_ID),
- ENUM(SYSTEM_VALUE_WORK_GROUP_ID),
- ENUM(SYSTEM_VALUE_NUM_WORK_GROUPS),
- ENUM(SYSTEM_VALUE_VERTEX_CNT),
- };
- STATIC_ASSERT(ARRAY_SIZE(names) == SYSTEM_VALUE_MAX);
- return NAME(sysval);
-}
-
-const char *
-glsl_interp_qualifier_name(enum glsl_interp_qualifier qual)
-{
- static const char *names[] = {
- ENUM(INTERP_QUALIFIER_NONE),
- ENUM(INTERP_QUALIFIER_SMOOTH),
- ENUM(INTERP_QUALIFIER_FLAT),
- ENUM(INTERP_QUALIFIER_NOPERSPECTIVE),
- };
- STATIC_ASSERT(ARRAY_SIZE(names) == INTERP_QUALIFIER_COUNT);
- return NAME(qual);
-}
-
-const char *
-gl_frag_result_name(gl_frag_result result)
-{
- static const char *names[] = {
- ENUM(FRAG_RESULT_DEPTH),
- ENUM(FRAG_RESULT_STENCIL),
- ENUM(FRAG_RESULT_COLOR),
- ENUM(FRAG_RESULT_SAMPLE_MASK),
- ENUM(FRAG_RESULT_DATA0),
- ENUM(FRAG_RESULT_DATA1),
- ENUM(FRAG_RESULT_DATA2),
- ENUM(FRAG_RESULT_DATA3),
- ENUM(FRAG_RESULT_DATA4),
- ENUM(FRAG_RESULT_DATA5),
- ENUM(FRAG_RESULT_DATA6),
- ENUM(FRAG_RESULT_DATA7),
- };
- STATIC_ASSERT(ARRAY_SIZE(names) == FRAG_RESULT_MAX);
- return NAME(result);
-}
diff --git a/src/glsl/nir/shader_enums.h b/src/glsl/nir/shader_enums.h
deleted file mode 100644
index e3f46e3d739..00000000000
--- a/src/glsl/nir/shader_enums.h
+++ /dev/null
@@ -1,551 +0,0 @@
-/*
- * Mesa 3-D graphics library
- *
- * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
- * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef SHADER_ENUMS_H
-#define SHADER_ENUMS_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * Shader stages. Note that these will become 5 with tessellation.
- *
- * The order must match how shaders are ordered in the pipeline.
- * The GLSL linker assumes that if i<j, then the j-th shader is
- * executed later than the i-th shader.
- */
-typedef enum
-{
- MESA_SHADER_VERTEX = 0,
- MESA_SHADER_TESS_CTRL = 1,
- MESA_SHADER_TESS_EVAL = 2,
- MESA_SHADER_GEOMETRY = 3,
- MESA_SHADER_FRAGMENT = 4,
- MESA_SHADER_COMPUTE = 5,
-} gl_shader_stage;
-
-const char *gl_shader_stage_name(gl_shader_stage stage);
-
-/**
- * Translate a gl_shader_stage to a short shader stage name for debug
- * printouts and error messages.
- */
-const char *_mesa_shader_stage_to_string(unsigned stage);
-
-/**
- * Translate a gl_shader_stage to a shader stage abbreviation (VS, GS, FS)
- * for debug printouts and error messages.
- */
-const char *_mesa_shader_stage_to_abbrev(unsigned stage);
-
-#define MESA_SHADER_STAGES (MESA_SHADER_COMPUTE + 1)
-
-
-/**
- * Indexes for vertex program attributes.
- * GL_NV_vertex_program aliases generic attributes over the conventional
- * attributes. In GL_ARB_vertex_program shader the aliasing is optional.
- * In GL_ARB_vertex_shader / OpenGL 2.0 the aliasing is disallowed (the
- * generic attributes are distinct/separate).
- */
-typedef enum
-{
- VERT_ATTRIB_POS = 0,
- VERT_ATTRIB_WEIGHT = 1,
- VERT_ATTRIB_NORMAL = 2,
- VERT_ATTRIB_COLOR0 = 3,
- VERT_ATTRIB_COLOR1 = 4,
- VERT_ATTRIB_FOG = 5,
- VERT_ATTRIB_COLOR_INDEX = 6,
- VERT_ATTRIB_EDGEFLAG = 7,
- VERT_ATTRIB_TEX0 = 8,
- VERT_ATTRIB_TEX1 = 9,
- VERT_ATTRIB_TEX2 = 10,
- VERT_ATTRIB_TEX3 = 11,
- VERT_ATTRIB_TEX4 = 12,
- VERT_ATTRIB_TEX5 = 13,
- VERT_ATTRIB_TEX6 = 14,
- VERT_ATTRIB_TEX7 = 15,
- VERT_ATTRIB_POINT_SIZE = 16,
- VERT_ATTRIB_GENERIC0 = 17,
- VERT_ATTRIB_GENERIC1 = 18,
- VERT_ATTRIB_GENERIC2 = 19,
- VERT_ATTRIB_GENERIC3 = 20,
- VERT_ATTRIB_GENERIC4 = 21,
- VERT_ATTRIB_GENERIC5 = 22,
- VERT_ATTRIB_GENERIC6 = 23,
- VERT_ATTRIB_GENERIC7 = 24,
- VERT_ATTRIB_GENERIC8 = 25,
- VERT_ATTRIB_GENERIC9 = 26,
- VERT_ATTRIB_GENERIC10 = 27,
- VERT_ATTRIB_GENERIC11 = 28,
- VERT_ATTRIB_GENERIC12 = 29,
- VERT_ATTRIB_GENERIC13 = 30,
- VERT_ATTRIB_GENERIC14 = 31,
- VERT_ATTRIB_GENERIC15 = 32,
- VERT_ATTRIB_MAX = 33
-} gl_vert_attrib;
-
-const char *gl_vert_attrib_name(gl_vert_attrib attrib);
-
-/**
- * Symbolic constats to help iterating over
- * specific blocks of vertex attributes.
- *
- * VERT_ATTRIB_FF
- * includes all fixed function attributes as well as
- * the aliased GL_NV_vertex_program shader attributes.
- * VERT_ATTRIB_TEX
- * include the classic texture coordinate attributes.
- * Is a subset of VERT_ATTRIB_FF.
- * VERT_ATTRIB_GENERIC
- * include the OpenGL 2.0+ GLSL generic shader attributes.
- * These alias the generic GL_ARB_vertex_shader attributes.
- */
-#define VERT_ATTRIB_FF(i) (VERT_ATTRIB_POS + (i))
-#define VERT_ATTRIB_FF_MAX VERT_ATTRIB_GENERIC0
-
-#define VERT_ATTRIB_TEX(i) (VERT_ATTRIB_TEX0 + (i))
-#define VERT_ATTRIB_TEX_MAX MAX_TEXTURE_COORD_UNITS
-
-#define VERT_ATTRIB_GENERIC(i) (VERT_ATTRIB_GENERIC0 + (i))
-#define VERT_ATTRIB_GENERIC_MAX MAX_VERTEX_GENERIC_ATTRIBS
-
-/**
- * Bitflags for vertex attributes.
- * These are used in bitfields in many places.
- */
-/*@{*/
-#define VERT_BIT_POS BITFIELD64_BIT(VERT_ATTRIB_POS)
-#define VERT_BIT_WEIGHT BITFIELD64_BIT(VERT_ATTRIB_WEIGHT)
-#define VERT_BIT_NORMAL BITFIELD64_BIT(VERT_ATTRIB_NORMAL)
-#define VERT_BIT_COLOR0 BITFIELD64_BIT(VERT_ATTRIB_COLOR0)
-#define VERT_BIT_COLOR1 BITFIELD64_BIT(VERT_ATTRIB_COLOR1)
-#define VERT_BIT_FOG BITFIELD64_BIT(VERT_ATTRIB_FOG)
-#define VERT_BIT_COLOR_INDEX BITFIELD64_BIT(VERT_ATTRIB_COLOR_INDEX)
-#define VERT_BIT_EDGEFLAG BITFIELD64_BIT(VERT_ATTRIB_EDGEFLAG)
-#define VERT_BIT_TEX0 BITFIELD64_BIT(VERT_ATTRIB_TEX0)
-#define VERT_BIT_TEX1 BITFIELD64_BIT(VERT_ATTRIB_TEX1)
-#define VERT_BIT_TEX2 BITFIELD64_BIT(VERT_ATTRIB_TEX2)
-#define VERT_BIT_TEX3 BITFIELD64_BIT(VERT_ATTRIB_TEX3)
-#define VERT_BIT_TEX4 BITFIELD64_BIT(VERT_ATTRIB_TEX4)
-#define VERT_BIT_TEX5 BITFIELD64_BIT(VERT_ATTRIB_TEX5)
-#define VERT_BIT_TEX6 BITFIELD64_BIT(VERT_ATTRIB_TEX6)
-#define VERT_BIT_TEX7 BITFIELD64_BIT(VERT_ATTRIB_TEX7)
-#define VERT_BIT_POINT_SIZE BITFIELD64_BIT(VERT_ATTRIB_POINT_SIZE)
-#define VERT_BIT_GENERIC0 BITFIELD64_BIT(VERT_ATTRIB_GENERIC0)
-
-#define VERT_BIT(i) BITFIELD64_BIT(i)
-#define VERT_BIT_ALL BITFIELD64_RANGE(0, VERT_ATTRIB_MAX)
-
-#define VERT_BIT_FF(i) VERT_BIT(i)
-#define VERT_BIT_FF_ALL BITFIELD64_RANGE(0, VERT_ATTRIB_FF_MAX)
-#define VERT_BIT_TEX(i) VERT_BIT(VERT_ATTRIB_TEX(i))
-#define VERT_BIT_TEX_ALL \
- BITFIELD64_RANGE(VERT_ATTRIB_TEX(0), VERT_ATTRIB_TEX_MAX)
-
-#define VERT_BIT_GENERIC(i) VERT_BIT(VERT_ATTRIB_GENERIC(i))
-#define VERT_BIT_GENERIC_ALL \
- BITFIELD64_RANGE(VERT_ATTRIB_GENERIC(0), VERT_ATTRIB_GENERIC_MAX)
-/*@}*/
-
-
-/**
- * Indexes for vertex shader outputs, geometry shader inputs/outputs, and
- * fragment shader inputs.
- *
- * Note that some of these values are not available to all pipeline stages.
- *
- * When this enum is updated, the following code must be updated too:
- * - vertResults (in prog_print.c's arb_output_attrib_string())
- * - fragAttribs (in prog_print.c's arb_input_attrib_string())
- * - _mesa_varying_slot_in_fs()
- */
-typedef enum
-{
- VARYING_SLOT_POS,
- VARYING_SLOT_COL0, /* COL0 and COL1 must be contiguous */
- VARYING_SLOT_COL1,
- VARYING_SLOT_FOGC,
- VARYING_SLOT_TEX0, /* TEX0-TEX7 must be contiguous */
- VARYING_SLOT_TEX1,
- VARYING_SLOT_TEX2,
- VARYING_SLOT_TEX3,
- VARYING_SLOT_TEX4,
- VARYING_SLOT_TEX5,
- VARYING_SLOT_TEX6,
- VARYING_SLOT_TEX7,
- VARYING_SLOT_PSIZ, /* Does not appear in FS */
- VARYING_SLOT_BFC0, /* Does not appear in FS */
- VARYING_SLOT_BFC1, /* Does not appear in FS */
- VARYING_SLOT_EDGE, /* Does not appear in FS */
- VARYING_SLOT_CLIP_VERTEX, /* Does not appear in FS */
- VARYING_SLOT_CLIP_DIST0,
- VARYING_SLOT_CLIP_DIST1,
- VARYING_SLOT_PRIMITIVE_ID, /* Does not appear in VS */
- VARYING_SLOT_LAYER, /* Appears as VS or GS output */
- VARYING_SLOT_VIEWPORT, /* Appears as VS or GS output */
- VARYING_SLOT_FACE, /* FS only */
- VARYING_SLOT_PNTC, /* FS only */
- VARYING_SLOT_TESS_LEVEL_OUTER, /* Only appears as TCS output. */
- VARYING_SLOT_TESS_LEVEL_INNER, /* Only appears as TCS output. */
- VARYING_SLOT_VAR0, /* First generic varying slot */
- /* the remaining are simply for the benefit of gl_varying_slot_name()
- * and not to be construed as an upper bound:
- */
- VARYING_SLOT_VAR1,
- VARYING_SLOT_VAR2,
- VARYING_SLOT_VAR3,
- VARYING_SLOT_VAR4,
- VARYING_SLOT_VAR5,
- VARYING_SLOT_VAR6,
- VARYING_SLOT_VAR7,
- VARYING_SLOT_VAR8,
- VARYING_SLOT_VAR9,
- VARYING_SLOT_VAR10,
- VARYING_SLOT_VAR11,
- VARYING_SLOT_VAR12,
- VARYING_SLOT_VAR13,
- VARYING_SLOT_VAR14,
- VARYING_SLOT_VAR15,
- VARYING_SLOT_VAR16,
- VARYING_SLOT_VAR17,
- VARYING_SLOT_VAR18,
- VARYING_SLOT_VAR19,
- VARYING_SLOT_VAR20,
- VARYING_SLOT_VAR21,
- VARYING_SLOT_VAR22,
- VARYING_SLOT_VAR23,
- VARYING_SLOT_VAR24,
- VARYING_SLOT_VAR25,
- VARYING_SLOT_VAR26,
- VARYING_SLOT_VAR27,
- VARYING_SLOT_VAR28,
- VARYING_SLOT_VAR29,
- VARYING_SLOT_VAR30,
- VARYING_SLOT_VAR31,
-} gl_varying_slot;
-
-
-#define VARYING_SLOT_MAX (VARYING_SLOT_VAR0 + MAX_VARYING)
-#define VARYING_SLOT_PATCH0 (VARYING_SLOT_MAX)
-#define VARYING_SLOT_TESS_MAX (VARYING_SLOT_PATCH0 + MAX_VARYING)
-
-const char *gl_varying_slot_name(gl_varying_slot slot);
-
-/**
- * Bitflags for varying slots.
- */
-/*@{*/
-#define VARYING_BIT_POS BITFIELD64_BIT(VARYING_SLOT_POS)
-#define VARYING_BIT_COL0 BITFIELD64_BIT(VARYING_SLOT_COL0)
-#define VARYING_BIT_COL1 BITFIELD64_BIT(VARYING_SLOT_COL1)
-#define VARYING_BIT_FOGC BITFIELD64_BIT(VARYING_SLOT_FOGC)
-#define VARYING_BIT_TEX0 BITFIELD64_BIT(VARYING_SLOT_TEX0)
-#define VARYING_BIT_TEX1 BITFIELD64_BIT(VARYING_SLOT_TEX1)
-#define VARYING_BIT_TEX2 BITFIELD64_BIT(VARYING_SLOT_TEX2)
-#define VARYING_BIT_TEX3 BITFIELD64_BIT(VARYING_SLOT_TEX3)
-#define VARYING_BIT_TEX4 BITFIELD64_BIT(VARYING_SLOT_TEX4)
-#define VARYING_BIT_TEX5 BITFIELD64_BIT(VARYING_SLOT_TEX5)
-#define VARYING_BIT_TEX6 BITFIELD64_BIT(VARYING_SLOT_TEX6)
-#define VARYING_BIT_TEX7 BITFIELD64_BIT(VARYING_SLOT_TEX7)
-#define VARYING_BIT_TEX(U) BITFIELD64_BIT(VARYING_SLOT_TEX0 + (U))
-#define VARYING_BITS_TEX_ANY BITFIELD64_RANGE(VARYING_SLOT_TEX0, \
- MAX_TEXTURE_COORD_UNITS)
-#define VARYING_BIT_PSIZ BITFIELD64_BIT(VARYING_SLOT_PSIZ)
-#define VARYING_BIT_BFC0 BITFIELD64_BIT(VARYING_SLOT_BFC0)
-#define VARYING_BIT_BFC1 BITFIELD64_BIT(VARYING_SLOT_BFC1)
-#define VARYING_BIT_EDGE BITFIELD64_BIT(VARYING_SLOT_EDGE)
-#define VARYING_BIT_CLIP_VERTEX BITFIELD64_BIT(VARYING_SLOT_CLIP_VERTEX)
-#define VARYING_BIT_CLIP_DIST0 BITFIELD64_BIT(VARYING_SLOT_CLIP_DIST0)
-#define VARYING_BIT_CLIP_DIST1 BITFIELD64_BIT(VARYING_SLOT_CLIP_DIST1)
-#define VARYING_BIT_PRIMITIVE_ID BITFIELD64_BIT(VARYING_SLOT_PRIMITIVE_ID)
-#define VARYING_BIT_LAYER BITFIELD64_BIT(VARYING_SLOT_LAYER)
-#define VARYING_BIT_VIEWPORT BITFIELD64_BIT(VARYING_SLOT_VIEWPORT)
-#define VARYING_BIT_FACE BITFIELD64_BIT(VARYING_SLOT_FACE)
-#define VARYING_BIT_PNTC BITFIELD64_BIT(VARYING_SLOT_PNTC)
-#define VARYING_BIT_TESS_LEVEL_OUTER BITFIELD64_BIT(VARYING_SLOT_TESS_LEVEL_OUTER)
-#define VARYING_BIT_TESS_LEVEL_INNER BITFIELD64_BIT(VARYING_SLOT_TESS_LEVEL_INNER)
-#define VARYING_BIT_VAR(V) BITFIELD64_BIT(VARYING_SLOT_VAR0 + (V))
-/*@}*/
-
-/**
- * Bitflags for system values.
- */
-#define SYSTEM_BIT_SAMPLE_ID ((uint64_t)1 << SYSTEM_VALUE_SAMPLE_ID)
-#define SYSTEM_BIT_SAMPLE_POS ((uint64_t)1 << SYSTEM_VALUE_SAMPLE_POS)
-#define SYSTEM_BIT_SAMPLE_MASK_IN ((uint64_t)1 << SYSTEM_VALUE_SAMPLE_MASK_IN)
-#define SYSTEM_BIT_LOCAL_INVOCATION_ID ((uint64_t)1 << SYSTEM_VALUE_LOCAL_INVOCATION_ID)
-
-/**
- * If the gl_register_file is PROGRAM_SYSTEM_VALUE, the register index will be
- * one of these values. If a NIR variable's mode is nir_var_system_value, it
- * will be one of these values.
- */
-typedef enum
-{
- /**
- * \name Vertex shader system values
- */
- /*@{*/
- /**
- * OpenGL-style vertex ID.
- *
- * Section 2.11.7 (Shader Execution), subsection Shader Inputs, of the
- * OpenGL 3.3 core profile spec says:
- *
- * "gl_VertexID holds the integer index i implicitly passed by
- * DrawArrays or one of the other drawing commands defined in section
- * 2.8.3."
- *
- * Section 2.8.3 (Drawing Commands) of the same spec says:
- *
- * "The commands....are equivalent to the commands with the same base
- * name (without the BaseVertex suffix), except that the ith element
- * transferred by the corresponding draw call will be taken from
- * element indices[i] + basevertex of each enabled array."
- *
- * Additionally, the overview in the GL_ARB_shader_draw_parameters spec
- * says:
- *
- * "In unextended GL, vertex shaders have inputs named gl_VertexID and
- * gl_InstanceID, which contain, respectively the index of the vertex
- * and instance. The value of gl_VertexID is the implicitly passed
- * index of the vertex being processed, which includes the value of
- * baseVertex, for those commands that accept it."
- *
- * gl_VertexID gets basevertex added in. This differs from DirectX where
- * SV_VertexID does \b not get basevertex added in.
- *
- * \note
- * If all system values are available, \c SYSTEM_VALUE_VERTEX_ID will be
- * equal to \c SYSTEM_VALUE_VERTEX_ID_ZERO_BASE plus
- * \c SYSTEM_VALUE_BASE_VERTEX.
- *
- * \sa SYSTEM_VALUE_VERTEX_ID_ZERO_BASE, SYSTEM_VALUE_BASE_VERTEX
- */
- SYSTEM_VALUE_VERTEX_ID,
-
- /**
- * Instanced ID as supplied to gl_InstanceID
- *
- * Values assigned to gl_InstanceID always begin with zero, regardless of
- * the value of baseinstance.
- *
- * Section 11.1.3.9 (Shader Inputs) of the OpenGL 4.4 core profile spec
- * says:
- *
- * "gl_InstanceID holds the integer instance number of the current
- * primitive in an instanced draw call (see section 10.5)."
- *
- * Through a big chain of pseudocode, section 10.5 describes that
- * baseinstance is not counted by gl_InstanceID. In that section, notice
- *
- * "If an enabled vertex attribute array is instanced (it has a
- * non-zero divisor as specified by VertexAttribDivisor), the element
- * index that is transferred to the GL, for all vertices, is given by
- *
- * floor(instance/divisor) + baseinstance
- *
- * If an array corresponding to an attribute required by a vertex
- * shader is not enabled, then the corresponding element is taken from
- * the current attribute state (see section 10.2)."
- *
- * Note that baseinstance is \b not included in the value of instance.
- */
- SYSTEM_VALUE_INSTANCE_ID,
-
- /**
- * Vulkan InstanceIndex.
- *
- * InstanceIndex = gl_InstanceID + gl_BaseInstance
- */
- SYSTEM_VALUE_INSTANCE_INDEX,
-
- /**
- * DirectX-style vertex ID.
- *
- * Unlike \c SYSTEM_VALUE_VERTEX_ID, this system value does \b not include
- * the value of basevertex.
- *
- * \sa SYSTEM_VALUE_VERTEX_ID, SYSTEM_VALUE_BASE_VERTEX
- */
- SYSTEM_VALUE_VERTEX_ID_ZERO_BASE,
-
- /**
- * Value of \c basevertex passed to \c glDrawElementsBaseVertex and similar
- * functions.
- *
- * \sa SYSTEM_VALUE_VERTEX_ID, SYSTEM_VALUE_VERTEX_ID_ZERO_BASE
- */
- SYSTEM_VALUE_BASE_VERTEX,
-
- /**
- * Value of \c baseinstance passed to instanced draw entry points
- *
- * \sa SYSTEM_VALUE_INSTANCE_ID
- */
- SYSTEM_VALUE_BASE_INSTANCE,
-
- /**
- * From _ARB_shader_draw_parameters:
- *
- * "Additionally, this extension adds a further built-in variable,
- * gl_DrawID to the shading language. This variable contains the index
- * of the draw currently being processed by a Multi* variant of a
- * drawing command (such as MultiDrawElements or
- * MultiDrawArraysIndirect)."
- *
- * If GL_ARB_multi_draw_indirect is not supported, this is always 0.
- */
- SYSTEM_VALUE_DRAW_ID,
- /*@}*/
-
- /**
- * \name Geometry shader system values
- */
- /*@{*/
- SYSTEM_VALUE_INVOCATION_ID, /**< (Also in Tessellation Control shader) */
- /*@}*/
-
- /**
- * \name Fragment shader system values
- */
- /*@{*/
- SYSTEM_VALUE_FRAG_COORD,
- SYSTEM_VALUE_FRONT_FACE,
- SYSTEM_VALUE_SAMPLE_ID,
- SYSTEM_VALUE_SAMPLE_POS,
- SYSTEM_VALUE_SAMPLE_MASK_IN,
- SYSTEM_VALUE_HELPER_INVOCATION,
- /*@}*/
-
- /**
- * \name Tessellation Evaluation shader system values
- */
- /*@{*/
- SYSTEM_VALUE_TESS_COORD,
- SYSTEM_VALUE_VERTICES_IN, /**< Tessellation vertices in input patch */
- SYSTEM_VALUE_PRIMITIVE_ID,
- SYSTEM_VALUE_TESS_LEVEL_OUTER, /**< TES input */
- SYSTEM_VALUE_TESS_LEVEL_INNER, /**< TES input */
- /*@}*/
-
- /**
- * \name Compute shader system values
- */
- /*@{*/
- SYSTEM_VALUE_LOCAL_INVOCATION_ID,
- SYSTEM_VALUE_LOCAL_INVOCATION_INDEX,
- SYSTEM_VALUE_GLOBAL_INVOCATION_ID,
- SYSTEM_VALUE_WORK_GROUP_ID,
- SYSTEM_VALUE_NUM_WORK_GROUPS,
- /*@}*/
-
- /**
- * Driver internal vertex-count, used (for example) for drivers to
- * calculate stride for stream-out outputs. Not externally visible.
- */
- SYSTEM_VALUE_VERTEX_CNT,
-
- SYSTEM_VALUE_MAX /**< Number of values */
-} gl_system_value;
-
-const char *gl_system_value_name(gl_system_value sysval);
-
-/**
- * The possible interpolation qualifiers that can be applied to a fragment
- * shader input in GLSL.
- *
- * Note: INTERP_QUALIFIER_NONE must be 0 so that memsetting the
- * gl_fragment_program data structure to 0 causes the default behavior.
- */
-enum glsl_interp_qualifier
-{
- INTERP_QUALIFIER_NONE = 0,
- INTERP_QUALIFIER_SMOOTH,
- INTERP_QUALIFIER_FLAT,
- INTERP_QUALIFIER_NOPERSPECTIVE,
- INTERP_QUALIFIER_COUNT /**< Number of interpolation qualifiers */
-};
-
-const char *glsl_interp_qualifier_name(enum glsl_interp_qualifier qual);
-
-/**
- * Fragment program results
- */
-typedef enum
-{
- FRAG_RESULT_DEPTH = 0,
- FRAG_RESULT_STENCIL = 1,
- /* If a single color should be written to all render targets, this
- * register is written. No FRAG_RESULT_DATAn will be written.
- */
- FRAG_RESULT_COLOR = 2,
- FRAG_RESULT_SAMPLE_MASK = 3,
-
- /* FRAG_RESULT_DATAn are the per-render-target (GLSL gl_FragData[n]
- * or ARB_fragment_program fragment.color[n]) color results. If
- * any are written, FRAG_RESULT_COLOR will not be written.
- * FRAG_RESULT_DATA1 and up are simply for the benefit of
- * gl_frag_result_name() and not to be construed as an upper bound
- */
- FRAG_RESULT_DATA0 = 4,
- FRAG_RESULT_DATA1,
- FRAG_RESULT_DATA2,
- FRAG_RESULT_DATA3,
- FRAG_RESULT_DATA4,
- FRAG_RESULT_DATA5,
- FRAG_RESULT_DATA6,
- FRAG_RESULT_DATA7,
-} gl_frag_result;
-
-const char *gl_frag_result_name(gl_frag_result result);
-
-#define FRAG_RESULT_MAX (FRAG_RESULT_DATA0 + MAX_DRAW_BUFFERS)
-
-/**
- * \brief Layout qualifiers for gl_FragDepth.
- *
- * Extension AMD_conservative_depth allows gl_FragDepth to be redeclared with
- * a layout qualifier.
- *
- * \see enum ir_depth_layout
- */
-enum gl_frag_depth_layout
-{
- FRAG_DEPTH_LAYOUT_NONE, /**< No layout is specified. */
- FRAG_DEPTH_LAYOUT_ANY,
- FRAG_DEPTH_LAYOUT_GREATER,
- FRAG_DEPTH_LAYOUT_LESS,
- FRAG_DEPTH_LAYOUT_UNCHANGED
-};
-
-#ifdef __cplusplus
-} /* extern "C" */
-#endif
-
-#endif /* SHADER_ENUMS_H */
diff --git a/src/glsl/nir/spirv/GLSL.std.450.h b/src/glsl/nir/spirv/GLSL.std.450.h
deleted file mode 100644
index d1c9b5c1d44..00000000000
--- a/src/glsl/nir/spirv/GLSL.std.450.h
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
-** Copyright (c) 2014-2015 The Khronos Group Inc.
-**
-** Permission is hereby granted, free of charge, to any person obtaining a copy
-** of this software and/or associated documentation files (the "Materials"),
-** to deal in the Materials without restriction, including without limitation
-** the rights to use, copy, modify, merge, publish, distribute, sublicense,
-** and/or sell copies of the Materials, and to permit persons to whom the
-** Materials are furnished to do so, subject to the following conditions:
-**
-** The above copyright notice and this permission notice shall be included in
-** all copies or substantial portions of the Materials.
-**
-** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS
-** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND
-** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/
-**
-** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS
-** IN THE MATERIALS.
-*/
-
-#ifndef GLSLstd450_H
-#define GLSLstd450_H
-
-const int GLSLstd450Version = 99;
-const int GLSLstd450Revision = 3;
-
-enum GLSLstd450 {
- GLSLstd450Bad = 0, // Don't use
-
- GLSLstd450Round = 1,
- GLSLstd450RoundEven = 2,
- GLSLstd450Trunc = 3,
- GLSLstd450FAbs = 4,
- GLSLstd450SAbs = 5,
- GLSLstd450FSign = 6,
- GLSLstd450SSign = 7,
- GLSLstd450Floor = 8,
- GLSLstd450Ceil = 9,
- GLSLstd450Fract = 10,
-
- GLSLstd450Radians = 11,
- GLSLstd450Degrees = 12,
- GLSLstd450Sin = 13,
- GLSLstd450Cos = 14,
- GLSLstd450Tan = 15,
- GLSLstd450Asin = 16,
- GLSLstd450Acos = 17,
- GLSLstd450Atan = 18,
- GLSLstd450Sinh = 19,
- GLSLstd450Cosh = 20,
- GLSLstd450Tanh = 21,
- GLSLstd450Asinh = 22,
- GLSLstd450Acosh = 23,
- GLSLstd450Atanh = 24,
- GLSLstd450Atan2 = 25,
-
- GLSLstd450Pow = 26,
- GLSLstd450Exp = 27,
- GLSLstd450Log = 28,
- GLSLstd450Exp2 = 29,
- GLSLstd450Log2 = 30,
- GLSLstd450Sqrt = 31,
- GLSLstd450InverseSqrt = 32,
-
- GLSLstd450Determinant = 33,
- GLSLstd450MatrixInverse = 34,
-
- GLSLstd450Modf = 35, // second operand needs an OpVariable to write to
- GLSLstd450ModfStruct = 36, // no OpVariable operand
- GLSLstd450FMin = 37,
- GLSLstd450UMin = 38,
- GLSLstd450SMin = 39,
- GLSLstd450FMax = 40,
- GLSLstd450UMax = 41,
- GLSLstd450SMax = 42,
- GLSLstd450FClamp = 43,
- GLSLstd450UClamp = 44,
- GLSLstd450SClamp = 45,
- GLSLstd450FMix = 46,
- GLSLstd450IMix = 47,
- GLSLstd450Step = 48,
- GLSLstd450SmoothStep = 49,
-
- GLSLstd450Fma = 50,
- GLSLstd450Frexp = 51, // second operand needs an OpVariable to write to
- GLSLstd450FrexpStruct = 52, // no OpVariable operand
- GLSLstd450Ldexp = 53,
-
- GLSLstd450PackSnorm4x8 = 54,
- GLSLstd450PackUnorm4x8 = 55,
- GLSLstd450PackSnorm2x16 = 56,
- GLSLstd450PackUnorm2x16 = 57,
- GLSLstd450PackHalf2x16 = 58,
- GLSLstd450PackDouble2x32 = 59,
- GLSLstd450UnpackSnorm2x16 = 60,
- GLSLstd450UnpackUnorm2x16 = 61,
- GLSLstd450UnpackHalf2x16 = 62,
- GLSLstd450UnpackSnorm4x8 = 63,
- GLSLstd450UnpackUnorm4x8 = 64,
- GLSLstd450UnpackDouble2x32 = 65,
-
- GLSLstd450Length = 66,
- GLSLstd450Distance = 67,
- GLSLstd450Cross = 68,
- GLSLstd450Normalize = 69,
- GLSLstd450FaceForward = 70,
- GLSLstd450Reflect = 71,
- GLSLstd450Refract = 72,
-
- GLSLstd450FindILsb = 73,
- GLSLstd450FindSMsb = 74,
- GLSLstd450FindUMsb = 75,
-
- GLSLstd450InterpolateAtCentroid = 76,
- GLSLstd450InterpolateAtSample = 77,
- GLSLstd450InterpolateAtOffset = 78,
-
- GLSLstd450Count
-};
-
-#endif // #ifndef GLSLstd450_H
diff --git a/src/glsl/nir/spirv/nir_spirv.h b/src/glsl/nir/spirv/nir_spirv.h
deleted file mode 100644
index 9c9c93d36c2..00000000000
--- a/src/glsl/nir/spirv/nir_spirv.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright © 2015 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- *
- * Authors:
- * Jason Ekstrand ([email protected])
- *
- */
-
-#pragma once
-
-#ifndef _NIR_SPIRV_H_
-#define _NIR_SPIRV_H_
-
-#include "nir.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct nir_spirv_specialization {
- uint32_t id;
- uint32_t data;
-};
-
-nir_function *spirv_to_nir(const uint32_t *words, size_t word_count,
- struct nir_spirv_specialization *specializations,
- unsigned num_specializations,
- gl_shader_stage stage, const char *entry_point_name,
- const nir_shader_compiler_options *options);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _NIR_SPIRV_H_ */
diff --git a/src/glsl/nir/spirv/spirv.h b/src/glsl/nir/spirv/spirv.h
deleted file mode 100644
index 63bcb2f88dd..00000000000
--- a/src/glsl/nir/spirv/spirv.h
+++ /dev/null
@@ -1,870 +0,0 @@
-/*
-** Copyright (c) 2014-2015 The Khronos Group Inc.
-**
-** Permission is hereby granted, free of charge, to any person obtaining a copy
-** of this software and/or associated documentation files (the "Materials"),
-** to deal in the Materials without restriction, including without limitation
-** the rights to use, copy, modify, merge, publish, distribute, sublicense,
-** and/or sell copies of the Materials, and to permit persons to whom the
-** Materials are furnished to do so, subject to the following conditions:
-**
-** The above copyright notice and this permission notice shall be included in
-** all copies or substantial portions of the Materials.
-**
-** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS
-** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND
-** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/
-**
-** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS
-** IN THE MATERIALS.
-*/
-
-/*
-** This header is automatically generated by the same tool that creates
-** the Binary Section of the SPIR-V specification.
-*/
-
-/*
-** Enumeration tokens for SPIR-V, in various styles:
-** C, C++, C++11, JSON, Lua, Python
-**
-** - C will have tokens with a "Spv" prefix, e.g.: SpvSourceLanguageGLSL
-** - C++ will have tokens in the "spv" name space, e.g.: spv::SourceLanguageGLSL
-** - C++11 will use enum classes in the spv namespace, e.g.: spv::SourceLanguage::GLSL
-** - Lua will use tables, e.g.: spv.SourceLanguage.GLSL
-** - Python will use dictionaries, e.g.: spv['SourceLanguage']['GLSL']
-**
-** Some tokens act like mask values, which can be OR'd together,
-** while others are mutually exclusive. The mask-like ones have
-** "Mask" in their name, and a parallel enum that has the shift
-** amount (1 << x) for each corresponding enumerant.
-*/
-
-#ifndef spirv_H
-#define spirv_H
-
-typedef unsigned int SpvId;
-
-#define SPV_VERSION 0x10000
-#define SPV_REVISION 2
-
-static const unsigned int SpvMagicNumber = 0x07230203;
-static const unsigned int SpvVersion = 0x00010000;
-static const unsigned int SpvRevision = 2;
-static const unsigned int SpvOpCodeMask = 0xffff;
-static const unsigned int SpvWordCountShift = 16;
-
-typedef enum SpvSourceLanguage_ {
- SpvSourceLanguageUnknown = 0,
- SpvSourceLanguageESSL = 1,
- SpvSourceLanguageGLSL = 2,
- SpvSourceLanguageOpenCL_C = 3,
- SpvSourceLanguageOpenCL_CPP = 4,
-} SpvSourceLanguage;
-
-typedef enum SpvExecutionModel_ {
- SpvExecutionModelVertex = 0,
- SpvExecutionModelTessellationControl = 1,
- SpvExecutionModelTessellationEvaluation = 2,
- SpvExecutionModelGeometry = 3,
- SpvExecutionModelFragment = 4,
- SpvExecutionModelGLCompute = 5,
- SpvExecutionModelKernel = 6,
-} SpvExecutionModel;
-
-typedef enum SpvAddressingModel_ {
- SpvAddressingModelLogical = 0,
- SpvAddressingModelPhysical32 = 1,
- SpvAddressingModelPhysical64 = 2,
-} SpvAddressingModel;
-
-typedef enum SpvMemoryModel_ {
- SpvMemoryModelSimple = 0,
- SpvMemoryModelGLSL450 = 1,
- SpvMemoryModelOpenCL = 2,
-} SpvMemoryModel;
-
-typedef enum SpvExecutionMode_ {
- SpvExecutionModeInvocations = 0,
- SpvExecutionModeSpacingEqual = 1,
- SpvExecutionModeSpacingFractionalEven = 2,
- SpvExecutionModeSpacingFractionalOdd = 3,
- SpvExecutionModeVertexOrderCw = 4,
- SpvExecutionModeVertexOrderCcw = 5,
- SpvExecutionModePixelCenterInteger = 6,
- SpvExecutionModeOriginUpperLeft = 7,
- SpvExecutionModeOriginLowerLeft = 8,
- SpvExecutionModeEarlyFragmentTests = 9,
- SpvExecutionModePointMode = 10,
- SpvExecutionModeXfb = 11,
- SpvExecutionModeDepthReplacing = 12,
- SpvExecutionModeDepthGreater = 14,
- SpvExecutionModeDepthLess = 15,
- SpvExecutionModeDepthUnchanged = 16,
- SpvExecutionModeLocalSize = 17,
- SpvExecutionModeLocalSizeHint = 18,
- SpvExecutionModeInputPoints = 19,
- SpvExecutionModeInputLines = 20,
- SpvExecutionModeInputLinesAdjacency = 21,
- SpvExecutionModeTriangles = 22,
- SpvExecutionModeInputTrianglesAdjacency = 23,
- SpvExecutionModeQuads = 24,
- SpvExecutionModeIsolines = 25,
- SpvExecutionModeOutputVertices = 26,
- SpvExecutionModeOutputPoints = 27,
- SpvExecutionModeOutputLineStrip = 28,
- SpvExecutionModeOutputTriangleStrip = 29,
- SpvExecutionModeVecTypeHint = 30,
- SpvExecutionModeContractionOff = 31,
-} SpvExecutionMode;
-
-typedef enum SpvStorageClass_ {
- SpvStorageClassUniformConstant = 0,
- SpvStorageClassInput = 1,
- SpvStorageClassUniform = 2,
- SpvStorageClassOutput = 3,
- SpvStorageClassWorkgroup = 4,
- SpvStorageClassCrossWorkgroup = 5,
- SpvStorageClassPrivate = 6,
- SpvStorageClassFunction = 7,
- SpvStorageClassGeneric = 8,
- SpvStorageClassPushConstant = 9,
- SpvStorageClassAtomicCounter = 10,
- SpvStorageClassImage = 11,
-} SpvStorageClass;
-
-typedef enum SpvDim_ {
- SpvDim1D = 0,
- SpvDim2D = 1,
- SpvDim3D = 2,
- SpvDimCube = 3,
- SpvDimRect = 4,
- SpvDimBuffer = 5,
- SpvDimSubpassData = 6,
-} SpvDim;
-
-typedef enum SpvSamplerAddressingMode_ {
- SpvSamplerAddressingModeNone = 0,
- SpvSamplerAddressingModeClampToEdge = 1,
- SpvSamplerAddressingModeClamp = 2,
- SpvSamplerAddressingModeRepeat = 3,
- SpvSamplerAddressingModeRepeatMirrored = 4,
-} SpvSamplerAddressingMode;
-
-typedef enum SpvSamplerFilterMode_ {
- SpvSamplerFilterModeNearest = 0,
- SpvSamplerFilterModeLinear = 1,
-} SpvSamplerFilterMode;
-
-typedef enum SpvImageFormat_ {
- SpvImageFormatUnknown = 0,
- SpvImageFormatRgba32f = 1,
- SpvImageFormatRgba16f = 2,
- SpvImageFormatR32f = 3,
- SpvImageFormatRgba8 = 4,
- SpvImageFormatRgba8Snorm = 5,
- SpvImageFormatRg32f = 6,
- SpvImageFormatRg16f = 7,
- SpvImageFormatR11fG11fB10f = 8,
- SpvImageFormatR16f = 9,
- SpvImageFormatRgba16 = 10,
- SpvImageFormatRgb10A2 = 11,
- SpvImageFormatRg16 = 12,
- SpvImageFormatRg8 = 13,
- SpvImageFormatR16 = 14,
- SpvImageFormatR8 = 15,
- SpvImageFormatRgba16Snorm = 16,
- SpvImageFormatRg16Snorm = 17,
- SpvImageFormatRg8Snorm = 18,
- SpvImageFormatR16Snorm = 19,
- SpvImageFormatR8Snorm = 20,
- SpvImageFormatRgba32i = 21,
- SpvImageFormatRgba16i = 22,
- SpvImageFormatRgba8i = 23,
- SpvImageFormatR32i = 24,
- SpvImageFormatRg32i = 25,
- SpvImageFormatRg16i = 26,
- SpvImageFormatRg8i = 27,
- SpvImageFormatR16i = 28,
- SpvImageFormatR8i = 29,
- SpvImageFormatRgba32ui = 30,
- SpvImageFormatRgba16ui = 31,
- SpvImageFormatRgba8ui = 32,
- SpvImageFormatR32ui = 33,
- SpvImageFormatRgb10a2ui = 34,
- SpvImageFormatRg32ui = 35,
- SpvImageFormatRg16ui = 36,
- SpvImageFormatRg8ui = 37,
- SpvImageFormatR16ui = 38,
- SpvImageFormatR8ui = 39,
-} SpvImageFormat;
-
-typedef enum SpvImageChannelOrder_ {
- SpvImageChannelOrderR = 0,
- SpvImageChannelOrderA = 1,
- SpvImageChannelOrderRG = 2,
- SpvImageChannelOrderRA = 3,
- SpvImageChannelOrderRGB = 4,
- SpvImageChannelOrderRGBA = 5,
- SpvImageChannelOrderBGRA = 6,
- SpvImageChannelOrderARGB = 7,
- SpvImageChannelOrderIntensity = 8,
- SpvImageChannelOrderLuminance = 9,
- SpvImageChannelOrderRx = 10,
- SpvImageChannelOrderRGx = 11,
- SpvImageChannelOrderRGBx = 12,
- SpvImageChannelOrderDepth = 13,
- SpvImageChannelOrderDepthStencil = 14,
- SpvImageChannelOrdersRGB = 15,
- SpvImageChannelOrdersRGBx = 16,
- SpvImageChannelOrdersRGBA = 17,
- SpvImageChannelOrdersBGRA = 18,
-} SpvImageChannelOrder;
-
-typedef enum SpvImageChannelDataType_ {
- SpvImageChannelDataTypeSnormInt8 = 0,
- SpvImageChannelDataTypeSnormInt16 = 1,
- SpvImageChannelDataTypeUnormInt8 = 2,
- SpvImageChannelDataTypeUnormInt16 = 3,
- SpvImageChannelDataTypeUnormShort565 = 4,
- SpvImageChannelDataTypeUnormShort555 = 5,
- SpvImageChannelDataTypeUnormInt101010 = 6,
- SpvImageChannelDataTypeSignedInt8 = 7,
- SpvImageChannelDataTypeSignedInt16 = 8,
- SpvImageChannelDataTypeSignedInt32 = 9,
- SpvImageChannelDataTypeUnsignedInt8 = 10,
- SpvImageChannelDataTypeUnsignedInt16 = 11,
- SpvImageChannelDataTypeUnsignedInt32 = 12,
- SpvImageChannelDataTypeHalfFloat = 13,
- SpvImageChannelDataTypeFloat = 14,
- SpvImageChannelDataTypeUnormInt24 = 15,
- SpvImageChannelDataTypeUnormInt101010_2 = 16,
-} SpvImageChannelDataType;
-
-typedef enum SpvImageOperandsShift_ {
- SpvImageOperandsBiasShift = 0,
- SpvImageOperandsLodShift = 1,
- SpvImageOperandsGradShift = 2,
- SpvImageOperandsConstOffsetShift = 3,
- SpvImageOperandsOffsetShift = 4,
- SpvImageOperandsConstOffsetsShift = 5,
- SpvImageOperandsSampleShift = 6,
- SpvImageOperandsMinLodShift = 7,
-} SpvImageOperandsShift;
-
-typedef enum SpvImageOperandsMask_ {
- SpvImageOperandsMaskNone = 0,
- SpvImageOperandsBiasMask = 0x00000001,
- SpvImageOperandsLodMask = 0x00000002,
- SpvImageOperandsGradMask = 0x00000004,
- SpvImageOperandsConstOffsetMask = 0x00000008,
- SpvImageOperandsOffsetMask = 0x00000010,
- SpvImageOperandsConstOffsetsMask = 0x00000020,
- SpvImageOperandsSampleMask = 0x00000040,
- SpvImageOperandsMinLodMask = 0x00000080,
-} SpvImageOperandsMask;
-
-typedef enum SpvFPFastMathModeShift_ {
- SpvFPFastMathModeNotNaNShift = 0,
- SpvFPFastMathModeNotInfShift = 1,
- SpvFPFastMathModeNSZShift = 2,
- SpvFPFastMathModeAllowRecipShift = 3,
- SpvFPFastMathModeFastShift = 4,
-} SpvFPFastMathModeShift;
-
-typedef enum SpvFPFastMathModeMask_ {
- SpvFPFastMathModeMaskNone = 0,
- SpvFPFastMathModeNotNaNMask = 0x00000001,
- SpvFPFastMathModeNotInfMask = 0x00000002,
- SpvFPFastMathModeNSZMask = 0x00000004,
- SpvFPFastMathModeAllowRecipMask = 0x00000008,
- SpvFPFastMathModeFastMask = 0x00000010,
-} SpvFPFastMathModeMask;
-
-typedef enum SpvFPRoundingMode_ {
- SpvFPRoundingModeRTE = 0,
- SpvFPRoundingModeRTZ = 1,
- SpvFPRoundingModeRTP = 2,
- SpvFPRoundingModeRTN = 3,
-} SpvFPRoundingMode;
-
-typedef enum SpvLinkageType_ {
- SpvLinkageTypeExport = 0,
- SpvLinkageTypeImport = 1,
-} SpvLinkageType;
-
-typedef enum SpvAccessQualifier_ {
- SpvAccessQualifierReadOnly = 0,
- SpvAccessQualifierWriteOnly = 1,
- SpvAccessQualifierReadWrite = 2,
-} SpvAccessQualifier;
-
-typedef enum SpvFunctionParameterAttribute_ {
- SpvFunctionParameterAttributeZext = 0,
- SpvFunctionParameterAttributeSext = 1,
- SpvFunctionParameterAttributeByVal = 2,
- SpvFunctionParameterAttributeSret = 3,
- SpvFunctionParameterAttributeNoAlias = 4,
- SpvFunctionParameterAttributeNoCapture = 5,
- SpvFunctionParameterAttributeNoWrite = 6,
- SpvFunctionParameterAttributeNoReadWrite = 7,
-} SpvFunctionParameterAttribute;
-
-typedef enum SpvDecoration_ {
- SpvDecorationRelaxedPrecision = 0,
- SpvDecorationSpecId = 1,
- SpvDecorationBlock = 2,
- SpvDecorationBufferBlock = 3,
- SpvDecorationRowMajor = 4,
- SpvDecorationColMajor = 5,
- SpvDecorationArrayStride = 6,
- SpvDecorationMatrixStride = 7,
- SpvDecorationGLSLShared = 8,
- SpvDecorationGLSLPacked = 9,
- SpvDecorationCPacked = 10,
- SpvDecorationBuiltIn = 11,
- SpvDecorationNoPerspective = 13,
- SpvDecorationFlat = 14,
- SpvDecorationPatch = 15,
- SpvDecorationCentroid = 16,
- SpvDecorationSample = 17,
- SpvDecorationInvariant = 18,
- SpvDecorationRestrict = 19,
- SpvDecorationAliased = 20,
- SpvDecorationVolatile = 21,
- SpvDecorationConstant = 22,
- SpvDecorationCoherent = 23,
- SpvDecorationNonWritable = 24,
- SpvDecorationNonReadable = 25,
- SpvDecorationUniform = 26,
- SpvDecorationSaturatedConversion = 28,
- SpvDecorationStream = 29,
- SpvDecorationLocation = 30,
- SpvDecorationComponent = 31,
- SpvDecorationIndex = 32,
- SpvDecorationBinding = 33,
- SpvDecorationDescriptorSet = 34,
- SpvDecorationOffset = 35,
- SpvDecorationXfbBuffer = 36,
- SpvDecorationXfbStride = 37,
- SpvDecorationFuncParamAttr = 38,
- SpvDecorationFPRoundingMode = 39,
- SpvDecorationFPFastMathMode = 40,
- SpvDecorationLinkageAttributes = 41,
- SpvDecorationNoContraction = 42,
- SpvDecorationInputAttachmentIndex = 43,
- SpvDecorationAlignment = 44,
-} SpvDecoration;
-
-typedef enum SpvBuiltIn_ {
- SpvBuiltInPosition = 0,
- SpvBuiltInPointSize = 1,
- SpvBuiltInClipDistance = 3,
- SpvBuiltInCullDistance = 4,
- SpvBuiltInVertexId = 5,
- SpvBuiltInInstanceId = 6,
- SpvBuiltInPrimitiveId = 7,
- SpvBuiltInInvocationId = 8,
- SpvBuiltInLayer = 9,
- SpvBuiltInViewportIndex = 10,
- SpvBuiltInTessLevelOuter = 11,
- SpvBuiltInTessLevelInner = 12,
- SpvBuiltInTessCoord = 13,
- SpvBuiltInPatchVertices = 14,
- SpvBuiltInFragCoord = 15,
- SpvBuiltInPointCoord = 16,
- SpvBuiltInFrontFacing = 17,
- SpvBuiltInSampleId = 18,
- SpvBuiltInSamplePosition = 19,
- SpvBuiltInSampleMask = 20,
- SpvBuiltInFragDepth = 22,
- SpvBuiltInHelperInvocation = 23,
- SpvBuiltInNumWorkgroups = 24,
- SpvBuiltInWorkgroupSize = 25,
- SpvBuiltInWorkgroupId = 26,
- SpvBuiltInLocalInvocationId = 27,
- SpvBuiltInGlobalInvocationId = 28,
- SpvBuiltInLocalInvocationIndex = 29,
- SpvBuiltInWorkDim = 30,
- SpvBuiltInGlobalSize = 31,
- SpvBuiltInEnqueuedWorkgroupSize = 32,
- SpvBuiltInGlobalOffset = 33,
- SpvBuiltInGlobalLinearId = 34,
- SpvBuiltInSubgroupSize = 36,
- SpvBuiltInSubgroupMaxSize = 37,
- SpvBuiltInNumSubgroups = 38,
- SpvBuiltInNumEnqueuedSubgroups = 39,
- SpvBuiltInSubgroupId = 40,
- SpvBuiltInSubgroupLocalInvocationId = 41,
- SpvBuiltInVertexIndex = 42,
- SpvBuiltInInstanceIndex = 43,
-} SpvBuiltIn;
-
-typedef enum SpvSelectionControlShift_ {
- SpvSelectionControlFlattenShift = 0,
- SpvSelectionControlDontFlattenShift = 1,
-} SpvSelectionControlShift;
-
-typedef enum SpvSelectionControlMask_ {
- SpvSelectionControlMaskNone = 0,
- SpvSelectionControlFlattenMask = 0x00000001,
- SpvSelectionControlDontFlattenMask = 0x00000002,
-} SpvSelectionControlMask;
-
-typedef enum SpvLoopControlShift_ {
- SpvLoopControlUnrollShift = 0,
- SpvLoopControlDontUnrollShift = 1,
-} SpvLoopControlShift;
-
-typedef enum SpvLoopControlMask_ {
- SpvLoopControlMaskNone = 0,
- SpvLoopControlUnrollMask = 0x00000001,
- SpvLoopControlDontUnrollMask = 0x00000002,
-} SpvLoopControlMask;
-
-typedef enum SpvFunctionControlShift_ {
- SpvFunctionControlInlineShift = 0,
- SpvFunctionControlDontInlineShift = 1,
- SpvFunctionControlPureShift = 2,
- SpvFunctionControlConstShift = 3,
-} SpvFunctionControlShift;
-
-typedef enum SpvFunctionControlMask_ {
- SpvFunctionControlMaskNone = 0,
- SpvFunctionControlInlineMask = 0x00000001,
- SpvFunctionControlDontInlineMask = 0x00000002,
- SpvFunctionControlPureMask = 0x00000004,
- SpvFunctionControlConstMask = 0x00000008,
-} SpvFunctionControlMask;
-
-typedef enum SpvMemorySemanticsShift_ {
- SpvMemorySemanticsAcquireShift = 1,
- SpvMemorySemanticsReleaseShift = 2,
- SpvMemorySemanticsAcquireReleaseShift = 3,
- SpvMemorySemanticsSequentiallyConsistentShift = 4,
- SpvMemorySemanticsUniformMemoryShift = 6,
- SpvMemorySemanticsSubgroupMemoryShift = 7,
- SpvMemorySemanticsWorkgroupMemoryShift = 8,
- SpvMemorySemanticsCrossWorkgroupMemoryShift = 9,
- SpvMemorySemanticsAtomicCounterMemoryShift = 10,
- SpvMemorySemanticsImageMemoryShift = 11,
-} SpvMemorySemanticsShift;
-
-typedef enum SpvMemorySemanticsMask_ {
- SpvMemorySemanticsMaskNone = 0,
- SpvMemorySemanticsAcquireMask = 0x00000002,
- SpvMemorySemanticsReleaseMask = 0x00000004,
- SpvMemorySemanticsAcquireReleaseMask = 0x00000008,
- SpvMemorySemanticsSequentiallyConsistentMask = 0x00000010,
- SpvMemorySemanticsUniformMemoryMask = 0x00000040,
- SpvMemorySemanticsSubgroupMemoryMask = 0x00000080,
- SpvMemorySemanticsWorkgroupMemoryMask = 0x00000100,
- SpvMemorySemanticsCrossWorkgroupMemoryMask = 0x00000200,
- SpvMemorySemanticsAtomicCounterMemoryMask = 0x00000400,
- SpvMemorySemanticsImageMemoryMask = 0x00000800,
-} SpvMemorySemanticsMask;
-
-typedef enum SpvMemoryAccessShift_ {
- SpvMemoryAccessVolatileShift = 0,
- SpvMemoryAccessAlignedShift = 1,
- SpvMemoryAccessNontemporalShift = 2,
-} SpvMemoryAccessShift;
-
-typedef enum SpvMemoryAccessMask_ {
- SpvMemoryAccessMaskNone = 0,
- SpvMemoryAccessVolatileMask = 0x00000001,
- SpvMemoryAccessAlignedMask = 0x00000002,
- SpvMemoryAccessNontemporalMask = 0x00000004,
-} SpvMemoryAccessMask;
-
-typedef enum SpvScope_ {
- SpvScopeCrossDevice = 0,
- SpvScopeDevice = 1,
- SpvScopeWorkgroup = 2,
- SpvScopeSubgroup = 3,
- SpvScopeInvocation = 4,
-} SpvScope;
-
-typedef enum SpvGroupOperation_ {
- SpvGroupOperationReduce = 0,
- SpvGroupOperationInclusiveScan = 1,
- SpvGroupOperationExclusiveScan = 2,
-} SpvGroupOperation;
-
-typedef enum SpvKernelEnqueueFlags_ {
- SpvKernelEnqueueFlagsNoWait = 0,
- SpvKernelEnqueueFlagsWaitKernel = 1,
- SpvKernelEnqueueFlagsWaitWorkGroup = 2,
-} SpvKernelEnqueueFlags;
-
-typedef enum SpvKernelProfilingInfoShift_ {
- SpvKernelProfilingInfoCmdExecTimeShift = 0,
-} SpvKernelProfilingInfoShift;
-
-typedef enum SpvKernelProfilingInfoMask_ {
- SpvKernelProfilingInfoMaskNone = 0,
- SpvKernelProfilingInfoCmdExecTimeMask = 0x00000001,
-} SpvKernelProfilingInfoMask;
-
-typedef enum SpvCapability_ {
- SpvCapabilityMatrix = 0,
- SpvCapabilityShader = 1,
- SpvCapabilityGeometry = 2,
- SpvCapabilityTessellation = 3,
- SpvCapabilityAddresses = 4,
- SpvCapabilityLinkage = 5,
- SpvCapabilityKernel = 6,
- SpvCapabilityVector16 = 7,
- SpvCapabilityFloat16Buffer = 8,
- SpvCapabilityFloat16 = 9,
- SpvCapabilityFloat64 = 10,
- SpvCapabilityInt64 = 11,
- SpvCapabilityInt64Atomics = 12,
- SpvCapabilityImageBasic = 13,
- SpvCapabilityImageReadWrite = 14,
- SpvCapabilityImageMipmap = 15,
- SpvCapabilityPipes = 17,
- SpvCapabilityGroups = 18,
- SpvCapabilityDeviceEnqueue = 19,
- SpvCapabilityLiteralSampler = 20,
- SpvCapabilityAtomicStorage = 21,
- SpvCapabilityInt16 = 22,
- SpvCapabilityTessellationPointSize = 23,
- SpvCapabilityGeometryPointSize = 24,
- SpvCapabilityImageGatherExtended = 25,
- SpvCapabilityStorageImageMultisample = 27,
- SpvCapabilityUniformBufferArrayDynamicIndexing = 28,
- SpvCapabilitySampledImageArrayDynamicIndexing = 29,
- SpvCapabilityStorageBufferArrayDynamicIndexing = 30,
- SpvCapabilityStorageImageArrayDynamicIndexing = 31,
- SpvCapabilityClipDistance = 32,
- SpvCapabilityCullDistance = 33,
- SpvCapabilityImageCubeArray = 34,
- SpvCapabilitySampleRateShading = 35,
- SpvCapabilityImageRect = 36,
- SpvCapabilitySampledRect = 37,
- SpvCapabilityGenericPointer = 38,
- SpvCapabilityInt8 = 39,
- SpvCapabilityInputAttachment = 40,
- SpvCapabilitySparseResidency = 41,
- SpvCapabilityMinLod = 42,
- SpvCapabilitySampled1D = 43,
- SpvCapabilityImage1D = 44,
- SpvCapabilitySampledCubeArray = 45,
- SpvCapabilitySampledBuffer = 46,
- SpvCapabilityImageBuffer = 47,
- SpvCapabilityImageMSArray = 48,
- SpvCapabilityStorageImageExtendedFormats = 49,
- SpvCapabilityImageQuery = 50,
- SpvCapabilityDerivativeControl = 51,
- SpvCapabilityInterpolationFunction = 52,
- SpvCapabilityTransformFeedback = 53,
- SpvCapabilityGeometryStreams = 54,
- SpvCapabilityStorageImageReadWithoutFormat = 55,
- SpvCapabilityStorageImageWriteWithoutFormat = 56,
- SpvCapabilityMultiViewport = 57,
-} SpvCapability;
-
-typedef enum SpvOp_ {
- SpvOpNop = 0,
- SpvOpUndef = 1,
- SpvOpSourceContinued = 2,
- SpvOpSource = 3,
- SpvOpSourceExtension = 4,
- SpvOpName = 5,
- SpvOpMemberName = 6,
- SpvOpString = 7,
- SpvOpLine = 8,
- SpvOpExtension = 10,
- SpvOpExtInstImport = 11,
- SpvOpExtInst = 12,
- SpvOpMemoryModel = 14,
- SpvOpEntryPoint = 15,
- SpvOpExecutionMode = 16,
- SpvOpCapability = 17,
- SpvOpTypeVoid = 19,
- SpvOpTypeBool = 20,
- SpvOpTypeInt = 21,
- SpvOpTypeFloat = 22,
- SpvOpTypeVector = 23,
- SpvOpTypeMatrix = 24,
- SpvOpTypeImage = 25,
- SpvOpTypeSampler = 26,
- SpvOpTypeSampledImage = 27,
- SpvOpTypeArray = 28,
- SpvOpTypeRuntimeArray = 29,
- SpvOpTypeStruct = 30,
- SpvOpTypeOpaque = 31,
- SpvOpTypePointer = 32,
- SpvOpTypeFunction = 33,
- SpvOpTypeEvent = 34,
- SpvOpTypeDeviceEvent = 35,
- SpvOpTypeReserveId = 36,
- SpvOpTypeQueue = 37,
- SpvOpTypePipe = 38,
- SpvOpTypeForwardPointer = 39,
- SpvOpConstantTrue = 41,
- SpvOpConstantFalse = 42,
- SpvOpConstant = 43,
- SpvOpConstantComposite = 44,
- SpvOpConstantSampler = 45,
- SpvOpConstantNull = 46,
- SpvOpSpecConstantTrue = 48,
- SpvOpSpecConstantFalse = 49,
- SpvOpSpecConstant = 50,
- SpvOpSpecConstantComposite = 51,
- SpvOpSpecConstantOp = 52,
- SpvOpFunction = 54,
- SpvOpFunctionParameter = 55,
- SpvOpFunctionEnd = 56,
- SpvOpFunctionCall = 57,
- SpvOpVariable = 59,
- SpvOpImageTexelPointer = 60,
- SpvOpLoad = 61,
- SpvOpStore = 62,
- SpvOpCopyMemory = 63,
- SpvOpCopyMemorySized = 64,
- SpvOpAccessChain = 65,
- SpvOpInBoundsAccessChain = 66,
- SpvOpPtrAccessChain = 67,
- SpvOpArrayLength = 68,
- SpvOpGenericPtrMemSemantics = 69,
- SpvOpInBoundsPtrAccessChain = 70,
- SpvOpDecorate = 71,
- SpvOpMemberDecorate = 72,
- SpvOpDecorationGroup = 73,
- SpvOpGroupDecorate = 74,
- SpvOpGroupMemberDecorate = 75,
- SpvOpVectorExtractDynamic = 77,
- SpvOpVectorInsertDynamic = 78,
- SpvOpVectorShuffle = 79,
- SpvOpCompositeConstruct = 80,
- SpvOpCompositeExtract = 81,
- SpvOpCompositeInsert = 82,
- SpvOpCopyObject = 83,
- SpvOpTranspose = 84,
- SpvOpSampledImage = 86,
- SpvOpImageSampleImplicitLod = 87,
- SpvOpImageSampleExplicitLod = 88,
- SpvOpImageSampleDrefImplicitLod = 89,
- SpvOpImageSampleDrefExplicitLod = 90,
- SpvOpImageSampleProjImplicitLod = 91,
- SpvOpImageSampleProjExplicitLod = 92,
- SpvOpImageSampleProjDrefImplicitLod = 93,
- SpvOpImageSampleProjDrefExplicitLod = 94,
- SpvOpImageFetch = 95,
- SpvOpImageGather = 96,
- SpvOpImageDrefGather = 97,
- SpvOpImageRead = 98,
- SpvOpImageWrite = 99,
- SpvOpImage = 100,
- SpvOpImageQueryFormat = 101,
- SpvOpImageQueryOrder = 102,
- SpvOpImageQuerySizeLod = 103,
- SpvOpImageQuerySize = 104,
- SpvOpImageQueryLod = 105,
- SpvOpImageQueryLevels = 106,
- SpvOpImageQuerySamples = 107,
- SpvOpConvertFToU = 109,
- SpvOpConvertFToS = 110,
- SpvOpConvertSToF = 111,
- SpvOpConvertUToF = 112,
- SpvOpUConvert = 113,
- SpvOpSConvert = 114,
- SpvOpFConvert = 115,
- SpvOpQuantizeToF16 = 116,
- SpvOpConvertPtrToU = 117,
- SpvOpSatConvertSToU = 118,
- SpvOpSatConvertUToS = 119,
- SpvOpConvertUToPtr = 120,
- SpvOpPtrCastToGeneric = 121,
- SpvOpGenericCastToPtr = 122,
- SpvOpGenericCastToPtrExplicit = 123,
- SpvOpBitcast = 124,
- SpvOpSNegate = 126,
- SpvOpFNegate = 127,
- SpvOpIAdd = 128,
- SpvOpFAdd = 129,
- SpvOpISub = 130,
- SpvOpFSub = 131,
- SpvOpIMul = 132,
- SpvOpFMul = 133,
- SpvOpUDiv = 134,
- SpvOpSDiv = 135,
- SpvOpFDiv = 136,
- SpvOpUMod = 137,
- SpvOpSRem = 138,
- SpvOpSMod = 139,
- SpvOpFRem = 140,
- SpvOpFMod = 141,
- SpvOpVectorTimesScalar = 142,
- SpvOpMatrixTimesScalar = 143,
- SpvOpVectorTimesMatrix = 144,
- SpvOpMatrixTimesVector = 145,
- SpvOpMatrixTimesMatrix = 146,
- SpvOpOuterProduct = 147,
- SpvOpDot = 148,
- SpvOpIAddCarry = 149,
- SpvOpISubBorrow = 150,
- SpvOpUMulExtended = 151,
- SpvOpSMulExtended = 152,
- SpvOpAny = 154,
- SpvOpAll = 155,
- SpvOpIsNan = 156,
- SpvOpIsInf = 157,
- SpvOpIsFinite = 158,
- SpvOpIsNormal = 159,
- SpvOpSignBitSet = 160,
- SpvOpLessOrGreater = 161,
- SpvOpOrdered = 162,
- SpvOpUnordered = 163,
- SpvOpLogicalEqual = 164,
- SpvOpLogicalNotEqual = 165,
- SpvOpLogicalOr = 166,
- SpvOpLogicalAnd = 167,
- SpvOpLogicalNot = 168,
- SpvOpSelect = 169,
- SpvOpIEqual = 170,
- SpvOpINotEqual = 171,
- SpvOpUGreaterThan = 172,
- SpvOpSGreaterThan = 173,
- SpvOpUGreaterThanEqual = 174,
- SpvOpSGreaterThanEqual = 175,
- SpvOpULessThan = 176,
- SpvOpSLessThan = 177,
- SpvOpULessThanEqual = 178,
- SpvOpSLessThanEqual = 179,
- SpvOpFOrdEqual = 180,
- SpvOpFUnordEqual = 181,
- SpvOpFOrdNotEqual = 182,
- SpvOpFUnordNotEqual = 183,
- SpvOpFOrdLessThan = 184,
- SpvOpFUnordLessThan = 185,
- SpvOpFOrdGreaterThan = 186,
- SpvOpFUnordGreaterThan = 187,
- SpvOpFOrdLessThanEqual = 188,
- SpvOpFUnordLessThanEqual = 189,
- SpvOpFOrdGreaterThanEqual = 190,
- SpvOpFUnordGreaterThanEqual = 191,
- SpvOpShiftRightLogical = 194,
- SpvOpShiftRightArithmetic = 195,
- SpvOpShiftLeftLogical = 196,
- SpvOpBitwiseOr = 197,
- SpvOpBitwiseXor = 198,
- SpvOpBitwiseAnd = 199,
- SpvOpNot = 200,
- SpvOpBitFieldInsert = 201,
- SpvOpBitFieldSExtract = 202,
- SpvOpBitFieldUExtract = 203,
- SpvOpBitReverse = 204,
- SpvOpBitCount = 205,
- SpvOpDPdx = 207,
- SpvOpDPdy = 208,
- SpvOpFwidth = 209,
- SpvOpDPdxFine = 210,
- SpvOpDPdyFine = 211,
- SpvOpFwidthFine = 212,
- SpvOpDPdxCoarse = 213,
- SpvOpDPdyCoarse = 214,
- SpvOpFwidthCoarse = 215,
- SpvOpEmitVertex = 218,
- SpvOpEndPrimitive = 219,
- SpvOpEmitStreamVertex = 220,
- SpvOpEndStreamPrimitive = 221,
- SpvOpControlBarrier = 224,
- SpvOpMemoryBarrier = 225,
- SpvOpAtomicLoad = 227,
- SpvOpAtomicStore = 228,
- SpvOpAtomicExchange = 229,
- SpvOpAtomicCompareExchange = 230,
- SpvOpAtomicCompareExchangeWeak = 231,
- SpvOpAtomicIIncrement = 232,
- SpvOpAtomicIDecrement = 233,
- SpvOpAtomicIAdd = 234,
- SpvOpAtomicISub = 235,
- SpvOpAtomicSMin = 236,
- SpvOpAtomicUMin = 237,
- SpvOpAtomicSMax = 238,
- SpvOpAtomicUMax = 239,
- SpvOpAtomicAnd = 240,
- SpvOpAtomicOr = 241,
- SpvOpAtomicXor = 242,
- SpvOpPhi = 245,
- SpvOpLoopMerge = 246,
- SpvOpSelectionMerge = 247,
- SpvOpLabel = 248,
- SpvOpBranch = 249,
- SpvOpBranchConditional = 250,
- SpvOpSwitch = 251,
- SpvOpKill = 252,
- SpvOpReturn = 253,
- SpvOpReturnValue = 254,
- SpvOpUnreachable = 255,
- SpvOpLifetimeStart = 256,
- SpvOpLifetimeStop = 257,
- SpvOpGroupAsyncCopy = 259,
- SpvOpGroupWaitEvents = 260,
- SpvOpGroupAll = 261,
- SpvOpGroupAny = 262,
- SpvOpGroupBroadcast = 263,
- SpvOpGroupIAdd = 264,
- SpvOpGroupFAdd = 265,
- SpvOpGroupFMin = 266,
- SpvOpGroupUMin = 267,
- SpvOpGroupSMin = 268,
- SpvOpGroupFMax = 269,
- SpvOpGroupUMax = 270,
- SpvOpGroupSMax = 271,
- SpvOpReadPipe = 274,
- SpvOpWritePipe = 275,
- SpvOpReservedReadPipe = 276,
- SpvOpReservedWritePipe = 277,
- SpvOpReserveReadPipePackets = 278,
- SpvOpReserveWritePipePackets = 279,
- SpvOpCommitReadPipe = 280,
- SpvOpCommitWritePipe = 281,
- SpvOpIsValidReserveId = 282,
- SpvOpGetNumPipePackets = 283,
- SpvOpGetMaxPipePackets = 284,
- SpvOpGroupReserveReadPipePackets = 285,
- SpvOpGroupReserveWritePipePackets = 286,
- SpvOpGroupCommitReadPipe = 287,
- SpvOpGroupCommitWritePipe = 288,
- SpvOpEnqueueMarker = 291,
- SpvOpEnqueueKernel = 292,
- SpvOpGetKernelNDrangeSubGroupCount = 293,
- SpvOpGetKernelNDrangeMaxSubGroupSize = 294,
- SpvOpGetKernelWorkGroupSize = 295,
- SpvOpGetKernelPreferredWorkGroupSizeMultiple = 296,
- SpvOpRetainEvent = 297,
- SpvOpReleaseEvent = 298,
- SpvOpCreateUserEvent = 299,
- SpvOpIsValidEvent = 300,
- SpvOpSetUserEventStatus = 301,
- SpvOpCaptureEventProfilingInfo = 302,
- SpvOpGetDefaultQueue = 303,
- SpvOpBuildNDRange = 304,
- SpvOpImageSparseSampleImplicitLod = 305,
- SpvOpImageSparseSampleExplicitLod = 306,
- SpvOpImageSparseSampleDrefImplicitLod = 307,
- SpvOpImageSparseSampleDrefExplicitLod = 308,
- SpvOpImageSparseSampleProjImplicitLod = 309,
- SpvOpImageSparseSampleProjExplicitLod = 310,
- SpvOpImageSparseSampleProjDrefImplicitLod = 311,
- SpvOpImageSparseSampleProjDrefExplicitLod = 312,
- SpvOpImageSparseFetch = 313,
- SpvOpImageSparseGather = 314,
- SpvOpImageSparseDrefGather = 315,
- SpvOpImageSparseTexelsResident = 316,
- SpvOpNoLine = 317,
- SpvOpAtomicFlagTestAndSet = 318,
- SpvOpAtomicFlagClear = 319,
-} SpvOp;
-
-#endif // #ifndef spirv_H
-
diff --git a/src/glsl/nir/spirv/spirv_to_nir.c b/src/glsl/nir/spirv/spirv_to_nir.c
deleted file mode 100644
index c002457ce12..00000000000
--- a/src/glsl/nir/spirv/spirv_to_nir.c
+++ /dev/null
@@ -1,2654 +0,0 @@
-/*
- * Copyright © 2015 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- *
- * Authors:
- * Jason Ekstrand ([email protected])
- *
- */
-
-#include "vtn_private.h"
-#include "nir/nir_vla.h"
-#include "nir/nir_control_flow.h"
-#include "nir/nir_constant_expressions.h"
-
-static struct vtn_ssa_value *
-vtn_undef_ssa_value(struct vtn_builder *b, const struct glsl_type *type)
-{
- struct vtn_ssa_value *val = rzalloc(b, struct vtn_ssa_value);
- val->type = type;
-
- if (glsl_type_is_vector_or_scalar(type)) {
- unsigned num_components = glsl_get_vector_elements(val->type);
- nir_ssa_undef_instr *undef =
- nir_ssa_undef_instr_create(b->shader, num_components);
-
- nir_instr_insert_before_cf_list(&b->impl->body, &undef->instr);
- val->def = &undef->def;
- } else {
- unsigned elems = glsl_get_length(val->type);
- val->elems = ralloc_array(b, struct vtn_ssa_value *, elems);
- if (glsl_type_is_matrix(type)) {
- const struct glsl_type *elem_type =
- glsl_vector_type(glsl_get_base_type(type),
- glsl_get_vector_elements(type));
-
- for (unsigned i = 0; i < elems; i++)
- val->elems[i] = vtn_undef_ssa_value(b, elem_type);
- } else if (glsl_type_is_array(type)) {
- const struct glsl_type *elem_type = glsl_get_array_element(type);
- for (unsigned i = 0; i < elems; i++)
- val->elems[i] = vtn_undef_ssa_value(b, elem_type);
- } else {
- for (unsigned i = 0; i < elems; i++) {
- const struct glsl_type *elem_type = glsl_get_struct_field(type, i);
- val->elems[i] = vtn_undef_ssa_value(b, elem_type);
- }
- }
- }
-
- return val;
-}
-
-static struct vtn_ssa_value *
-vtn_const_ssa_value(struct vtn_builder *b, nir_constant *constant,
- const struct glsl_type *type)
-{
- struct hash_entry *entry = _mesa_hash_table_search(b->const_table, constant);
-
- if (entry)
- return entry->data;
-
- struct vtn_ssa_value *val = rzalloc(b, struct vtn_ssa_value);
- val->type = type;
-
- switch (glsl_get_base_type(type)) {
- case GLSL_TYPE_INT:
- case GLSL_TYPE_UINT:
- case GLSL_TYPE_BOOL:
- case GLSL_TYPE_FLOAT:
- case GLSL_TYPE_DOUBLE:
- if (glsl_type_is_vector_or_scalar(type)) {
- unsigned num_components = glsl_get_vector_elements(val->type);
- nir_load_const_instr *load =
- nir_load_const_instr_create(b->shader, num_components);
-
- for (unsigned i = 0; i < num_components; i++)
- load->value.u[i] = constant->value.u[i];
-
- nir_instr_insert_before_cf_list(&b->impl->body, &load->instr);
- val->def = &load->def;
- } else {
- assert(glsl_type_is_matrix(type));
- unsigned rows = glsl_get_vector_elements(val->type);
- unsigned columns = glsl_get_matrix_columns(val->type);
- val->elems = ralloc_array(b, struct vtn_ssa_value *, columns);
-
- for (unsigned i = 0; i < columns; i++) {
- struct vtn_ssa_value *col_val = rzalloc(b, struct vtn_ssa_value);
- col_val->type = glsl_get_column_type(val->type);
- nir_load_const_instr *load =
- nir_load_const_instr_create(b->shader, rows);
-
- for (unsigned j = 0; j < rows; j++)
- load->value.u[j] = constant->value.u[rows * i + j];
-
- nir_instr_insert_before_cf_list(&b->impl->body, &load->instr);
- col_val->def = &load->def;
-
- val->elems[i] = col_val;
- }
- }
- break;
-
- case GLSL_TYPE_ARRAY: {
- unsigned elems = glsl_get_length(val->type);
- val->elems = ralloc_array(b, struct vtn_ssa_value *, elems);
- const struct glsl_type *elem_type = glsl_get_array_element(val->type);
- for (unsigned i = 0; i < elems; i++)
- val->elems[i] = vtn_const_ssa_value(b, constant->elements[i],
- elem_type);
- break;
- }
-
- case GLSL_TYPE_STRUCT: {
- unsigned elems = glsl_get_length(val->type);
- val->elems = ralloc_array(b, struct vtn_ssa_value *, elems);
- for (unsigned i = 0; i < elems; i++) {
- const struct glsl_type *elem_type =
- glsl_get_struct_field(val->type, i);
- val->elems[i] = vtn_const_ssa_value(b, constant->elements[i],
- elem_type);
- }
- break;
- }
-
- default:
- unreachable("bad constant type");
- }
-
- return val;
-}
-
-struct vtn_ssa_value *
-vtn_ssa_value(struct vtn_builder *b, uint32_t value_id)
-{
- struct vtn_value *val = vtn_untyped_value(b, value_id);
- switch (val->value_type) {
- case vtn_value_type_undef:
- return vtn_undef_ssa_value(b, val->type->type);
-
- case vtn_value_type_constant:
- return vtn_const_ssa_value(b, val->constant, val->const_type);
-
- case vtn_value_type_ssa:
- return val->ssa;
-
- case vtn_value_type_access_chain:
- /* This is needed for function parameters */
- return vtn_variable_load(b, val->access_chain);
-
- default:
- unreachable("Invalid type for an SSA value");
- }
-}
-
-static char *
-vtn_string_literal(struct vtn_builder *b, const uint32_t *words,
- unsigned word_count, unsigned *words_used)
-{
- char *dup = ralloc_strndup(b, (char *)words, word_count * sizeof(*words));
- if (words_used) {
- /* Ammount of space taken by the string (including the null) */
- unsigned len = strlen(dup) + 1;
- *words_used = DIV_ROUND_UP(len, sizeof(*words));
- }
- return dup;
-}
-
-const uint32_t *
-vtn_foreach_instruction(struct vtn_builder *b, const uint32_t *start,
- const uint32_t *end, vtn_instruction_handler handler)
-{
- b->file = NULL;
- b->line = -1;
- b->col = -1;
-
- const uint32_t *w = start;
- while (w < end) {
- SpvOp opcode = w[0] & SpvOpCodeMask;
- unsigned count = w[0] >> SpvWordCountShift;
- assert(count >= 1 && w + count <= end);
-
- switch (opcode) {
- case SpvOpNop:
- break; /* Do nothing */
-
- case SpvOpLine:
- b->file = vtn_value(b, w[1], vtn_value_type_string)->str;
- b->line = w[2];
- b->col = w[3];
- break;
-
- case SpvOpNoLine:
- b->file = NULL;
- b->line = -1;
- b->col = -1;
- break;
-
- default:
- if (!handler(b, opcode, w, count))
- return w;
- break;
- }
-
- w += count;
- }
- assert(w == end);
- return w;
-}
-
-static void
-vtn_handle_extension(struct vtn_builder *b, SpvOp opcode,
- const uint32_t *w, unsigned count)
-{
- switch (opcode) {
- case SpvOpExtInstImport: {
- struct vtn_value *val = vtn_push_value(b, w[1], vtn_value_type_extension);
- if (strcmp((const char *)&w[2], "GLSL.std.450") == 0) {
- val->ext_handler = vtn_handle_glsl450_instruction;
- } else {
- assert(!"Unsupported extension");
- }
- break;
- }
-
- case SpvOpExtInst: {
- struct vtn_value *val = vtn_value(b, w[3], vtn_value_type_extension);
- bool handled = val->ext_handler(b, w[4], w, count);
- (void)handled;
- assert(handled);
- break;
- }
-
- default:
- unreachable("Unhandled opcode");
- }
-}
-
-static void
-_foreach_decoration_helper(struct vtn_builder *b,
- struct vtn_value *base_value,
- int parent_member,
- struct vtn_value *value,
- vtn_decoration_foreach_cb cb, void *data)
-{
- for (struct vtn_decoration *dec = value->decoration; dec; dec = dec->next) {
- int member;
- if (dec->scope == VTN_DEC_DECORATION) {
- member = parent_member;
- } else if (dec->scope >= VTN_DEC_STRUCT_MEMBER0) {
- assert(parent_member == -1);
- member = dec->scope - VTN_DEC_STRUCT_MEMBER0;
- } else {
- /* Not a decoration */
- continue;
- }
-
- if (dec->group) {
- assert(dec->group->value_type == vtn_value_type_decoration_group);
- _foreach_decoration_helper(b, base_value, member, dec->group,
- cb, data);
- } else {
- cb(b, base_value, member, dec, data);
- }
- }
-}
-
-/** Iterates (recursively if needed) over all of the decorations on a value
- *
- * This function iterates over all of the decorations applied to a given
- * value. If it encounters a decoration group, it recurses into the group
- * and iterates over all of those decorations as well.
- */
-void
-vtn_foreach_decoration(struct vtn_builder *b, struct vtn_value *value,
- vtn_decoration_foreach_cb cb, void *data)
-{
- _foreach_decoration_helper(b, value, -1, value, cb, data);
-}
-
-void
-vtn_foreach_execution_mode(struct vtn_builder *b, struct vtn_value *value,
- vtn_execution_mode_foreach_cb cb, void *data)
-{
- for (struct vtn_decoration *dec = value->decoration; dec; dec = dec->next) {
- if (dec->scope != VTN_DEC_EXECUTION_MODE)
- continue;
-
- assert(dec->group == NULL);
- cb(b, value, dec, data);
- }
-}
-
-static void
-vtn_handle_decoration(struct vtn_builder *b, SpvOp opcode,
- const uint32_t *w, unsigned count)
-{
- const uint32_t *w_end = w + count;
- const uint32_t target = w[1];
- w += 2;
-
- switch (opcode) {
- case SpvOpDecorationGroup:
- vtn_push_value(b, target, vtn_value_type_decoration_group);
- break;
-
- case SpvOpDecorate:
- case SpvOpMemberDecorate:
- case SpvOpExecutionMode: {
- struct vtn_value *val = &b->values[target];
-
- struct vtn_decoration *dec = rzalloc(b, struct vtn_decoration);
- switch (opcode) {
- case SpvOpDecorate:
- dec->scope = VTN_DEC_DECORATION;
- break;
- case SpvOpMemberDecorate:
- dec->scope = VTN_DEC_STRUCT_MEMBER0 + *(w++);
- break;
- case SpvOpExecutionMode:
- dec->scope = VTN_DEC_EXECUTION_MODE;
- break;
- default:
- unreachable("Invalid decoration opcode");
- }
- dec->decoration = *(w++);
- dec->literals = w;
-
- /* Link into the list */
- dec->next = val->decoration;
- val->decoration = dec;
- break;
- }
-
- case SpvOpGroupMemberDecorate:
- case SpvOpGroupDecorate: {
- struct vtn_value *group =
- vtn_value(b, target, vtn_value_type_decoration_group);
-
- for (; w < w_end; w++) {
- struct vtn_value *val = vtn_untyped_value(b, *w);
- struct vtn_decoration *dec = rzalloc(b, struct vtn_decoration);
-
- dec->group = group;
- if (opcode == SpvOpGroupDecorate) {
- dec->scope = VTN_DEC_DECORATION;
- } else {
- dec->scope = VTN_DEC_STRUCT_MEMBER0 + *(w++);
- }
-
- /* Link into the list */
- dec->next = val->decoration;
- val->decoration = dec;
- }
- break;
- }
-
- default:
- unreachable("Unhandled opcode");
- }
-}
-
-struct member_decoration_ctx {
- struct glsl_struct_field *fields;
- struct vtn_type *type;
-};
-
-/* does a shallow copy of a vtn_type */
-
-static struct vtn_type *
-vtn_type_copy(struct vtn_builder *b, struct vtn_type *src)
-{
- struct vtn_type *dest = ralloc(b, struct vtn_type);
- dest->type = src->type;
- dest->is_builtin = src->is_builtin;
- if (src->is_builtin)
- dest->builtin = src->builtin;
-
- if (!glsl_type_is_scalar(src->type)) {
- switch (glsl_get_base_type(src->type)) {
- case GLSL_TYPE_INT:
- case GLSL_TYPE_UINT:
- case GLSL_TYPE_BOOL:
- case GLSL_TYPE_FLOAT:
- case GLSL_TYPE_DOUBLE:
- case GLSL_TYPE_ARRAY:
- dest->row_major = src->row_major;
- dest->stride = src->stride;
- dest->array_element = src->array_element;
- break;
-
- case GLSL_TYPE_STRUCT: {
- unsigned elems = glsl_get_length(src->type);
-
- dest->members = ralloc_array(b, struct vtn_type *, elems);
- memcpy(dest->members, src->members, elems * sizeof(struct vtn_type *));
-
- dest->offsets = ralloc_array(b, unsigned, elems);
- memcpy(dest->offsets, src->offsets, elems * sizeof(unsigned));
- break;
- }
-
- default:
- unreachable("unhandled type");
- }
- }
-
- return dest;
-}
-
-static struct vtn_type *
-mutable_matrix_member(struct vtn_builder *b, struct vtn_type *type, int member)
-{
- type->members[member] = vtn_type_copy(b, type->members[member]);
- type = type->members[member];
-
- /* We may have an array of matrices.... Oh, joy! */
- while (glsl_type_is_array(type->type)) {
- type->array_element = vtn_type_copy(b, type->array_element);
- type = type->array_element;
- }
-
- assert(glsl_type_is_matrix(type->type));
-
- return type;
-}
-
-static void
-struct_member_decoration_cb(struct vtn_builder *b,
- struct vtn_value *val, int member,
- const struct vtn_decoration *dec, void *void_ctx)
-{
- struct member_decoration_ctx *ctx = void_ctx;
-
- if (member < 0)
- return;
-
- switch (dec->decoration) {
- case SpvDecorationRelaxedPrecision:
- break; /* FIXME: Do nothing with this for now. */
- case SpvDecorationNoPerspective:
- ctx->fields[member].interpolation = INTERP_QUALIFIER_NOPERSPECTIVE;
- break;
- case SpvDecorationFlat:
- ctx->fields[member].interpolation = INTERP_QUALIFIER_FLAT;
- break;
- case SpvDecorationCentroid:
- ctx->fields[member].centroid = true;
- break;
- case SpvDecorationSample:
- ctx->fields[member].sample = true;
- break;
- case SpvDecorationLocation:
- ctx->fields[member].location = dec->literals[0];
- break;
- case SpvDecorationBuiltIn:
- ctx->type->members[member] = vtn_type_copy(b, ctx->type->members[member]);
- ctx->type->members[member]->is_builtin = true;
- ctx->type->members[member]->builtin = dec->literals[0];
- ctx->type->builtin_block = true;
- break;
- case SpvDecorationOffset:
- ctx->type->offsets[member] = dec->literals[0];
- break;
- case SpvDecorationMatrixStride:
- mutable_matrix_member(b, ctx->type, member)->stride = dec->literals[0];
- break;
- case SpvDecorationColMajor:
- break; /* Nothing to do here. Column-major is the default. */
- case SpvDecorationRowMajor:
- mutable_matrix_member(b, ctx->type, member)->row_major = true;
- break;
- default:
- unreachable("Unhandled member decoration");
- }
-}
-
-static void
-type_decoration_cb(struct vtn_builder *b,
- struct vtn_value *val, int member,
- const struct vtn_decoration *dec, void *ctx)
-{
- struct vtn_type *type = val->type;
-
- if (member != -1)
- return;
-
- switch (dec->decoration) {
- case SpvDecorationArrayStride:
- type->stride = dec->literals[0];
- break;
- case SpvDecorationBlock:
- type->block = true;
- break;
- case SpvDecorationBufferBlock:
- type->buffer_block = true;
- break;
- case SpvDecorationGLSLShared:
- case SpvDecorationGLSLPacked:
- /* Ignore these, since we get explicit offsets anyways */
- break;
-
- case SpvDecorationStream:
- assert(dec->literals[0] == 0);
- break;
-
- default:
- unreachable("Unhandled type decoration");
- }
-}
-
-static unsigned
-translate_image_format(SpvImageFormat format)
-{
- switch (format) {
- case SpvImageFormatUnknown: return 0; /* GL_NONE */
- case SpvImageFormatRgba32f: return 0x8814; /* GL_RGBA32F */
- case SpvImageFormatRgba16f: return 0x881A; /* GL_RGBA16F */
- case SpvImageFormatR32f: return 0x822E; /* GL_R32F */
- case SpvImageFormatRgba8: return 0x8058; /* GL_RGBA8 */
- case SpvImageFormatRgba8Snorm: return 0x8F97; /* GL_RGBA8_SNORM */
- case SpvImageFormatRg32f: return 0x8230; /* GL_RG32F */
- case SpvImageFormatRg16f: return 0x822F; /* GL_RG16F */
- case SpvImageFormatR11fG11fB10f: return 0x8C3A; /* GL_R11F_G11F_B10F */
- case SpvImageFormatR16f: return 0x822D; /* GL_R16F */
- case SpvImageFormatRgba16: return 0x805B; /* GL_RGBA16 */
- case SpvImageFormatRgb10A2: return 0x8059; /* GL_RGB10_A2 */
- case SpvImageFormatRg16: return 0x822C; /* GL_RG16 */
- case SpvImageFormatRg8: return 0x822B; /* GL_RG8 */
- case SpvImageFormatR16: return 0x822A; /* GL_R16 */
- case SpvImageFormatR8: return 0x8229; /* GL_R8 */
- case SpvImageFormatRgba16Snorm: return 0x8F9B; /* GL_RGBA16_SNORM */
- case SpvImageFormatRg16Snorm: return 0x8F99; /* GL_RG16_SNORM */
- case SpvImageFormatRg8Snorm: return 0x8F95; /* GL_RG8_SNORM */
- case SpvImageFormatR16Snorm: return 0x8F98; /* GL_R16_SNORM */
- case SpvImageFormatR8Snorm: return 0x8F94; /* GL_R8_SNORM */
- case SpvImageFormatRgba32i: return 0x8D82; /* GL_RGBA32I */
- case SpvImageFormatRgba16i: return 0x8D88; /* GL_RGBA16I */
- case SpvImageFormatRgba8i: return 0x8D8E; /* GL_RGBA8I */
- case SpvImageFormatR32i: return 0x8235; /* GL_R32I */
- case SpvImageFormatRg32i: return 0x823B; /* GL_RG32I */
- case SpvImageFormatRg16i: return 0x8239; /* GL_RG16I */
- case SpvImageFormatRg8i: return 0x8237; /* GL_RG8I */
- case SpvImageFormatR16i: return 0x8233; /* GL_R16I */
- case SpvImageFormatR8i: return 0x8231; /* GL_R8I */
- case SpvImageFormatRgba32ui: return 0x8D70; /* GL_RGBA32UI */
- case SpvImageFormatRgba16ui: return 0x8D76; /* GL_RGBA16UI */
- case SpvImageFormatRgba8ui: return 0x8D7C; /* GL_RGBA8UI */
- case SpvImageFormatR32ui: return 0x8236; /* GL_R32UI */
- case SpvImageFormatRgb10a2ui: return 0x906F; /* GL_RGB10_A2UI */
- case SpvImageFormatRg32ui: return 0x823C; /* GL_RG32UI */
- case SpvImageFormatRg16ui: return 0x823A; /* GL_RG16UI */
- case SpvImageFormatRg8ui: return 0x8238; /* GL_RG8UI */
- case SpvImageFormatR16ui: return 0x823A; /* GL_RG16UI */
- case SpvImageFormatR8ui: return 0x8232; /* GL_R8UI */
- default:
- assert(!"Invalid image format");
- return 0;
- }
-}
-
-static void
-vtn_handle_type(struct vtn_builder *b, SpvOp opcode,
- const uint32_t *w, unsigned count)
-{
- struct vtn_value *val = vtn_push_value(b, w[1], vtn_value_type_type);
-
- val->type = rzalloc(b, struct vtn_type);
- val->type->is_builtin = false;
- val->type->val = val;
-
- switch (opcode) {
- case SpvOpTypeVoid:
- val->type->type = glsl_void_type();
- break;
- case SpvOpTypeBool:
- val->type->type = glsl_bool_type();
- break;
- case SpvOpTypeInt:
- val->type->type = glsl_int_type();
- break;
- case SpvOpTypeFloat:
- val->type->type = glsl_float_type();
- break;
-
- case SpvOpTypeVector: {
- struct vtn_type *base = vtn_value(b, w[2], vtn_value_type_type)->type;
- unsigned elems = w[3];
-
- assert(glsl_type_is_scalar(base->type));
- val->type->type = glsl_vector_type(glsl_get_base_type(base->type), elems);
-
- /* Vectors implicitly have sizeof(base_type) stride. For now, this
- * is always 4 bytes. This will have to change if we want to start
- * supporting doubles or half-floats.
- */
- val->type->stride = 4;
- val->type->array_element = base;
- break;
- }
-
- case SpvOpTypeMatrix: {
- struct vtn_type *base = vtn_value(b, w[2], vtn_value_type_type)->type;
- unsigned columns = w[3];
-
- assert(glsl_type_is_vector(base->type));
- val->type->type = glsl_matrix_type(glsl_get_base_type(base->type),
- glsl_get_vector_elements(base->type),
- columns);
- assert(!glsl_type_is_error(val->type->type));
- val->type->array_element = base;
- val->type->row_major = false;
- val->type->stride = 0;
- break;
- }
-
- case SpvOpTypeRuntimeArray:
- case SpvOpTypeArray: {
- struct vtn_type *array_element =
- vtn_value(b, w[2], vtn_value_type_type)->type;
-
- unsigned length;
- if (opcode == SpvOpTypeRuntimeArray) {
- /* A length of 0 is used to denote unsized arrays */
- length = 0;
- } else {
- length =
- vtn_value(b, w[3], vtn_value_type_constant)->constant->value.u[0];
- }
-
- val->type->type = glsl_array_type(array_element->type, length);
- val->type->array_element = array_element;
- val->type->stride = 0;
- break;
- }
-
- case SpvOpTypeStruct: {
- unsigned num_fields = count - 2;
- val->type->members = ralloc_array(b, struct vtn_type *, num_fields);
- val->type->offsets = ralloc_array(b, unsigned, num_fields);
-
- NIR_VLA(struct glsl_struct_field, fields, count);
- for (unsigned i = 0; i < num_fields; i++) {
- val->type->members[i] =
- vtn_value(b, w[i + 2], vtn_value_type_type)->type;
- fields[i] = (struct glsl_struct_field) {
- .type = val->type->members[i]->type,
- .name = ralloc_asprintf(b, "field%d", i),
- .location = -1,
- };
- }
-
- struct member_decoration_ctx ctx = {
- .fields = fields,
- .type = val->type
- };
-
- vtn_foreach_decoration(b, val, struct_member_decoration_cb, &ctx);
-
- const char *name = val->name ? val->name : "struct";
-
- val->type->type = glsl_struct_type(fields, num_fields, name);
- break;
- }
-
- case SpvOpTypeFunction: {
- const struct glsl_type *return_type =
- vtn_value(b, w[2], vtn_value_type_type)->type->type;
- NIR_VLA(struct glsl_function_param, params, count - 3);
- for (unsigned i = 0; i < count - 3; i++) {
- params[i].type = vtn_value(b, w[i + 3], vtn_value_type_type)->type->type;
-
- /* FIXME: */
- params[i].in = true;
- params[i].out = true;
- }
- val->type->type = glsl_function_type(return_type, params, count - 3);
- break;
- }
-
- case SpvOpTypePointer:
- /* FIXME: For now, we'll just do the really lame thing and return
- * the same type. The validator should ensure that the proper number
- * of dereferences happen
- */
- val->type = vtn_value(b, w[3], vtn_value_type_type)->type;
- break;
-
- case SpvOpTypeImage: {
- const struct glsl_type *sampled_type =
- vtn_value(b, w[2], vtn_value_type_type)->type->type;
-
- assert(glsl_type_is_vector_or_scalar(sampled_type));
-
- enum glsl_sampler_dim dim;
- switch ((SpvDim)w[3]) {
- case SpvDim1D: dim = GLSL_SAMPLER_DIM_1D; break;
- case SpvDim2D: dim = GLSL_SAMPLER_DIM_2D; break;
- case SpvDim3D: dim = GLSL_SAMPLER_DIM_3D; break;
- case SpvDimCube: dim = GLSL_SAMPLER_DIM_CUBE; break;
- case SpvDimRect: dim = GLSL_SAMPLER_DIM_RECT; break;
- case SpvDimBuffer: dim = GLSL_SAMPLER_DIM_BUF; break;
- default:
- unreachable("Invalid SPIR-V Sampler dimension");
- }
-
- bool is_shadow = w[4];
- bool is_array = w[5];
- bool multisampled = w[6];
- unsigned sampled = w[7];
- SpvImageFormat format = w[8];
-
- if (count > 9)
- val->type->access_qualifier = w[9];
- else
- val->type->access_qualifier = SpvAccessQualifierReadWrite;
-
- assert(!multisampled && "FIXME: Handl multi-sampled textures");
-
- val->type->image_format = translate_image_format(format);
-
- if (sampled == 1) {
- val->type->type = glsl_sampler_type(dim, is_shadow, is_array,
- glsl_get_base_type(sampled_type));
- } else if (sampled == 2) {
- assert(format);
- assert(!is_shadow);
- val->type->type = glsl_image_type(dim, is_array,
- glsl_get_base_type(sampled_type));
- } else {
- assert(!"We need to know if the image will be sampled");
- }
- break;
- }
-
- case SpvOpTypeSampledImage:
- val->type = vtn_value(b, w[2], vtn_value_type_type)->type;
- break;
-
- case SpvOpTypeSampler:
- /* The actual sampler type here doesn't really matter. It gets
- * thrown away the moment you combine it with an image. What really
- * matters is that it's a sampler type as opposed to an integer type
- * so the backend knows what to do.
- *
- * TODO: Eventually we should consider adding a "bare sampler" type
- * to glsl_types.
- */
- val->type->type = glsl_sampler_type(GLSL_SAMPLER_DIM_2D, false, false,
- GLSL_TYPE_FLOAT);
- break;
-
- case SpvOpTypeOpaque:
- case SpvOpTypeEvent:
- case SpvOpTypeDeviceEvent:
- case SpvOpTypeReserveId:
- case SpvOpTypeQueue:
- case SpvOpTypePipe:
- default:
- unreachable("Unhandled opcode");
- }
-
- vtn_foreach_decoration(b, val, type_decoration_cb, NULL);
-}
-
-static nir_constant *
-vtn_null_constant(struct vtn_builder *b, const struct glsl_type *type)
-{
- nir_constant *c = rzalloc(b, nir_constant);
-
- switch (glsl_get_base_type(type)) {
- case GLSL_TYPE_INT:
- case GLSL_TYPE_UINT:
- case GLSL_TYPE_BOOL:
- case GLSL_TYPE_FLOAT:
- case GLSL_TYPE_DOUBLE:
- /* Nothing to do here. It's already initialized to zero */
- break;
-
- case GLSL_TYPE_ARRAY:
- assert(glsl_get_length(type) > 0);
- c->num_elements = glsl_get_length(type);
- c->elements = ralloc_array(b, nir_constant *, c->num_elements);
-
- c->elements[0] = vtn_null_constant(b, glsl_get_array_element(type));
- for (unsigned i = 1; i < c->num_elements; i++)
- c->elements[i] = c->elements[0];
- break;
-
- case GLSL_TYPE_STRUCT:
- c->num_elements = glsl_get_length(type);
- c->elements = ralloc_array(b, nir_constant *, c->num_elements);
-
- for (unsigned i = 0; i < c->num_elements; i++) {
- c->elements[i] = vtn_null_constant(b, glsl_get_struct_field(type, i));
- }
- break;
-
- default:
- unreachable("Invalid type for null constant");
- }
-
- return c;
-}
-
-static void
-spec_constant_deocoration_cb(struct vtn_builder *b, struct vtn_value *v,
- int member, const struct vtn_decoration *dec,
- void *data)
-{
- assert(member == -1);
- if (dec->decoration != SpvDecorationSpecId)
- return;
-
- uint32_t *const_value = data;
-
- for (unsigned i = 0; i < b->num_specializations; i++) {
- if (b->specializations[i].id == dec->literals[0]) {
- *const_value = b->specializations[i].data;
- return;
- }
- }
-}
-
-static uint32_t
-get_specialization(struct vtn_builder *b, struct vtn_value *val,
- uint32_t const_value)
-{
- vtn_foreach_decoration(b, val, spec_constant_deocoration_cb, &const_value);
- return const_value;
-}
-
-static void
-vtn_handle_constant(struct vtn_builder *b, SpvOp opcode,
- const uint32_t *w, unsigned count)
-{
- struct vtn_value *val = vtn_push_value(b, w[2], vtn_value_type_constant);
- val->const_type = vtn_value(b, w[1], vtn_value_type_type)->type->type;
- val->constant = rzalloc(b, nir_constant);
- switch (opcode) {
- case SpvOpConstantTrue:
- assert(val->const_type == glsl_bool_type());
- val->constant->value.u[0] = NIR_TRUE;
- break;
- case SpvOpConstantFalse:
- assert(val->const_type == glsl_bool_type());
- val->constant->value.u[0] = NIR_FALSE;
- break;
-
- case SpvOpSpecConstantTrue:
- case SpvOpSpecConstantFalse: {
- assert(val->const_type == glsl_bool_type());
- uint32_t int_val =
- get_specialization(b, val, (opcode == SpvOpSpecConstantTrue));
- val->constant->value.u[0] = int_val ? NIR_TRUE : NIR_FALSE;
- break;
- }
-
- case SpvOpConstant:
- assert(glsl_type_is_scalar(val->const_type));
- val->constant->value.u[0] = w[3];
- break;
- case SpvOpSpecConstant:
- assert(glsl_type_is_scalar(val->const_type));
- val->constant->value.u[0] = get_specialization(b, val, w[3]);
- break;
- case SpvOpSpecConstantComposite:
- case SpvOpConstantComposite: {
- unsigned elem_count = count - 3;
- nir_constant **elems = ralloc_array(b, nir_constant *, elem_count);
- for (unsigned i = 0; i < elem_count; i++)
- elems[i] = vtn_value(b, w[i + 3], vtn_value_type_constant)->constant;
-
- switch (glsl_get_base_type(val->const_type)) {
- case GLSL_TYPE_UINT:
- case GLSL_TYPE_INT:
- case GLSL_TYPE_FLOAT:
- case GLSL_TYPE_BOOL:
- if (glsl_type_is_matrix(val->const_type)) {
- unsigned rows = glsl_get_vector_elements(val->const_type);
- assert(glsl_get_matrix_columns(val->const_type) == elem_count);
- for (unsigned i = 0; i < elem_count; i++)
- for (unsigned j = 0; j < rows; j++)
- val->constant->value.u[rows * i + j] = elems[i]->value.u[j];
- } else {
- assert(glsl_type_is_vector(val->const_type));
- assert(glsl_get_vector_elements(val->const_type) == elem_count);
- for (unsigned i = 0; i < elem_count; i++)
- val->constant->value.u[i] = elems[i]->value.u[0];
- }
- ralloc_free(elems);
- break;
-
- case GLSL_TYPE_STRUCT:
- case GLSL_TYPE_ARRAY:
- ralloc_steal(val->constant, elems);
- val->constant->num_elements = elem_count;
- val->constant->elements = elems;
- break;
-
- default:
- unreachable("Unsupported type for constants");
- }
- break;
- }
-
- case SpvOpSpecConstantOp: {
- SpvOp opcode = get_specialization(b, val, w[3]);
- switch (opcode) {
- case SpvOpVectorShuffle: {
- struct vtn_value *v0 = vtn_value(b, w[4], vtn_value_type_constant);
- struct vtn_value *v1 = vtn_value(b, w[5], vtn_value_type_constant);
- unsigned len0 = glsl_get_vector_elements(v0->const_type);
- unsigned len1 = glsl_get_vector_elements(v1->const_type);
-
- uint32_t u[8];
- for (unsigned i = 0; i < len0; i++)
- u[i] = v0->constant->value.u[i];
- for (unsigned i = 0; i < len1; i++)
- u[len0 + i] = v1->constant->value.u[i];
-
- for (unsigned i = 0; i < count - 6; i++) {
- uint32_t comp = w[i + 6];
- if (comp == (uint32_t)-1) {
- val->constant->value.u[i] = 0xdeadbeef;
- } else {
- val->constant->value.u[i] = u[comp];
- }
- }
- return;
- }
-
- case SpvOpCompositeExtract:
- case SpvOpCompositeInsert: {
- struct vtn_value *comp;
- unsigned deref_start;
- struct nir_constant **c;
- if (opcode == SpvOpCompositeExtract) {
- comp = vtn_value(b, w[4], vtn_value_type_constant);
- deref_start = 5;
- c = &comp->constant;
- } else {
- comp = vtn_value(b, w[5], vtn_value_type_constant);
- deref_start = 6;
- val->constant = nir_constant_clone(comp->constant,
- (nir_variable *)b);
- c = &val->constant;
- }
-
- int elem = -1;
- const struct glsl_type *type = comp->const_type;
- for (unsigned i = deref_start; i < count; i++) {
- switch (glsl_get_base_type(type)) {
- case GLSL_TYPE_UINT:
- case GLSL_TYPE_INT:
- case GLSL_TYPE_FLOAT:
- case GLSL_TYPE_BOOL:
- /* If we hit this granularity, we're picking off an element */
- if (elem < 0)
- elem = 0;
-
- if (glsl_type_is_matrix(type)) {
- elem += w[i] * glsl_get_vector_elements(type);
- type = glsl_get_column_type(type);
- } else {
- assert(glsl_type_is_vector(type));
- elem += w[i];
- type = glsl_scalar_type(glsl_get_base_type(type));
- }
- continue;
-
- case GLSL_TYPE_ARRAY:
- c = &(*c)->elements[w[i]];
- type = glsl_get_array_element(type);
- continue;
-
- case GLSL_TYPE_STRUCT:
- c = &(*c)->elements[w[i]];
- type = glsl_get_struct_field(type, w[i]);
- continue;
-
- default:
- unreachable("Invalid constant type");
- }
- }
-
- if (opcode == SpvOpCompositeExtract) {
- if (elem == -1) {
- val->constant = *c;
- } else {
- unsigned num_components = glsl_get_vector_elements(type);
- for (unsigned i = 0; i < num_components; i++)
- val->constant->value.u[i] = (*c)->value.u[elem + i];
- }
- } else {
- struct vtn_value *insert =
- vtn_value(b, w[4], vtn_value_type_constant);
- assert(insert->const_type == type);
- if (elem == -1) {
- *c = insert->constant;
- } else {
- unsigned num_components = glsl_get_vector_elements(type);
- for (unsigned i = 0; i < num_components; i++)
- (*c)->value.u[elem + i] = insert->constant->value.u[i];
- }
- }
- return;
- }
-
- default: {
- bool swap;
- nir_op op = vtn_nir_alu_op_for_spirv_opcode(opcode, &swap);
-
- unsigned num_components = glsl_get_vector_elements(val->const_type);
-
- nir_const_value src[3];
- assert(count <= 7);
- for (unsigned i = 0; i < count - 4; i++) {
- nir_constant *c =
- vtn_value(b, w[4 + i], vtn_value_type_constant)->constant;
-
- unsigned j = swap ? 1 - i : i;
- for (unsigned k = 0; k < num_components; k++)
- src[j].u[k] = c->value.u[k];
- }
-
- nir_const_value res = nir_eval_const_opcode(op, num_components, src);
-
- for (unsigned k = 0; k < num_components; k++)
- val->constant->value.u[k] = res.u[k];
-
- return;
- } /* default */
- }
- }
-
- case SpvOpConstantNull:
- val->constant = vtn_null_constant(b, val->const_type);
- break;
-
- case SpvOpConstantSampler:
- assert(!"OpConstantSampler requires Kernel Capability");
- break;
-
- default:
- unreachable("Unhandled opcode");
- }
-}
-
-static void
-vtn_handle_function_call(struct vtn_builder *b, SpvOp opcode,
- const uint32_t *w, unsigned count)
-{
- struct nir_function *callee =
- vtn_value(b, w[3], vtn_value_type_function)->func->impl->function;
-
- nir_call_instr *call = nir_call_instr_create(b->nb.shader, callee);
- for (unsigned i = 0; i < call->num_params; i++) {
- unsigned arg_id = w[4 + i];
- struct vtn_value *arg = vtn_untyped_value(b, arg_id);
- if (arg->value_type == vtn_value_type_access_chain) {
- nir_deref_var *d = vtn_access_chain_to_deref(b, arg->access_chain);
- call->params[i] = nir_deref_as_var(nir_copy_deref(call, &d->deref));
- } else {
- struct vtn_ssa_value *arg_ssa = vtn_ssa_value(b, arg_id);
-
- /* Make a temporary to store the argument in */
- nir_variable *tmp =
- nir_local_variable_create(b->impl, arg_ssa->type, "arg_tmp");
- call->params[i] = nir_deref_var_create(call, tmp);
-
- vtn_local_store(b, arg_ssa, call->params[i]);
- }
- }
-
- nir_variable *out_tmp = NULL;
- if (!glsl_type_is_void(callee->return_type)) {
- out_tmp = nir_local_variable_create(b->impl, callee->return_type,
- "out_tmp");
- call->return_deref = nir_deref_var_create(call, out_tmp);
- }
-
- nir_builder_instr_insert(&b->nb, &call->instr);
-
- if (glsl_type_is_void(callee->return_type)) {
- vtn_push_value(b, w[2], vtn_value_type_undef);
- } else {
- struct vtn_value *retval = vtn_push_value(b, w[2], vtn_value_type_ssa);
- retval->ssa = vtn_local_load(b, call->return_deref);
- }
-}
-
-struct vtn_ssa_value *
-vtn_create_ssa_value(struct vtn_builder *b, const struct glsl_type *type)
-{
- struct vtn_ssa_value *val = rzalloc(b, struct vtn_ssa_value);
- val->type = type;
-
- if (!glsl_type_is_vector_or_scalar(type)) {
- unsigned elems = glsl_get_length(type);
- val->elems = ralloc_array(b, struct vtn_ssa_value *, elems);
- for (unsigned i = 0; i < elems; i++) {
- const struct glsl_type *child_type;
-
- switch (glsl_get_base_type(type)) {
- case GLSL_TYPE_INT:
- case GLSL_TYPE_UINT:
- case GLSL_TYPE_BOOL:
- case GLSL_TYPE_FLOAT:
- case GLSL_TYPE_DOUBLE:
- child_type = glsl_get_column_type(type);
- break;
- case GLSL_TYPE_ARRAY:
- child_type = glsl_get_array_element(type);
- break;
- case GLSL_TYPE_STRUCT:
- child_type = glsl_get_struct_field(type, i);
- break;
- default:
- unreachable("unkown base type");
- }
-
- val->elems[i] = vtn_create_ssa_value(b, child_type);
- }
- }
-
- return val;
-}
-
-static nir_tex_src
-vtn_tex_src(struct vtn_builder *b, unsigned index, nir_tex_src_type type)
-{
- nir_tex_src src;
- src.src = nir_src_for_ssa(vtn_ssa_value(b, index)->def);
- src.src_type = type;
- return src;
-}
-
-static void
-vtn_handle_texture(struct vtn_builder *b, SpvOp opcode,
- const uint32_t *w, unsigned count)
-{
- if (opcode == SpvOpSampledImage) {
- struct vtn_value *val =
- vtn_push_value(b, w[2], vtn_value_type_sampled_image);
- val->sampled_image = ralloc(b, struct vtn_sampled_image);
- val->sampled_image->image =
- vtn_value(b, w[3], vtn_value_type_access_chain)->access_chain;
- val->sampled_image->sampler =
- vtn_value(b, w[4], vtn_value_type_access_chain)->access_chain;
- return;
- } else if (opcode == SpvOpImage) {
- struct vtn_value *val =
- vtn_push_value(b, w[2], vtn_value_type_access_chain);
- struct vtn_value *src_val = vtn_untyped_value(b, w[3]);
- if (src_val->value_type == vtn_value_type_sampled_image) {
- val->access_chain = src_val->sampled_image->image;
- } else {
- assert(src_val->value_type == vtn_value_type_access_chain);
- val->access_chain = src_val->access_chain;
- }
- return;
- }
-
- struct vtn_type *ret_type = vtn_value(b, w[1], vtn_value_type_type)->type;
- struct vtn_value *val = vtn_push_value(b, w[2], vtn_value_type_ssa);
-
- struct vtn_sampled_image sampled;
- struct vtn_value *sampled_val = vtn_untyped_value(b, w[3]);
- if (sampled_val->value_type == vtn_value_type_sampled_image) {
- sampled = *sampled_val->sampled_image;
- } else {
- assert(sampled_val->value_type == vtn_value_type_access_chain);
- sampled.image = NULL;
- sampled.sampler = sampled_val->access_chain;
- }
-
- nir_tex_src srcs[8]; /* 8 should be enough */
- nir_tex_src *p = srcs;
-
- unsigned idx = 4;
-
- bool has_coord = false;
- switch (opcode) {
- case SpvOpImageSampleImplicitLod:
- case SpvOpImageSampleExplicitLod:
- case SpvOpImageSampleDrefImplicitLod:
- case SpvOpImageSampleDrefExplicitLod:
- case SpvOpImageSampleProjImplicitLod:
- case SpvOpImageSampleProjExplicitLod:
- case SpvOpImageSampleProjDrefImplicitLod:
- case SpvOpImageSampleProjDrefExplicitLod:
- case SpvOpImageFetch:
- case SpvOpImageGather:
- case SpvOpImageDrefGather:
- case SpvOpImageQueryLod: {
- /* All these types have the coordinate as their first real argument */
- struct vtn_ssa_value *coord = vtn_ssa_value(b, w[idx++]);
- has_coord = true;
- p->src = nir_src_for_ssa(coord->def);
- p->src_type = nir_tex_src_coord;
- p++;
- break;
- }
-
- default:
- break;
- }
-
- /* These all have an explicit depth value as their next source */
- switch (opcode) {
- case SpvOpImageSampleDrefImplicitLod:
- case SpvOpImageSampleDrefExplicitLod:
- case SpvOpImageSampleProjDrefImplicitLod:
- case SpvOpImageSampleProjDrefExplicitLod:
- (*p++) = vtn_tex_src(b, w[idx++], nir_tex_src_comparitor);
- break;
- default:
- break;
- }
-
- /* For OpImageQuerySizeLod, we always have an LOD */
- if (opcode == SpvOpImageQuerySizeLod)
- (*p++) = vtn_tex_src(b, w[idx++], nir_tex_src_lod);
-
- /* Figure out the base texture operation */
- nir_texop texop;
- switch (opcode) {
- case SpvOpImageSampleImplicitLod:
- case SpvOpImageSampleDrefImplicitLod:
- case SpvOpImageSampleProjImplicitLod:
- case SpvOpImageSampleProjDrefImplicitLod:
- texop = nir_texop_tex;
- break;
-
- case SpvOpImageSampleExplicitLod:
- case SpvOpImageSampleDrefExplicitLod:
- case SpvOpImageSampleProjExplicitLod:
- case SpvOpImageSampleProjDrefExplicitLod:
- texop = nir_texop_txl;
- break;
-
- case SpvOpImageFetch:
- texop = nir_texop_txf;
- break;
-
- case SpvOpImageGather:
- case SpvOpImageDrefGather:
- texop = nir_texop_tg4;
- break;
-
- case SpvOpImageQuerySizeLod:
- case SpvOpImageQuerySize:
- texop = nir_texop_txs;
- break;
-
- case SpvOpImageQueryLod:
- texop = nir_texop_lod;
- break;
-
- case SpvOpImageQueryLevels:
- texop = nir_texop_query_levels;
- break;
-
- case SpvOpImageQuerySamples:
- default:
- unreachable("Unhandled opcode");
- }
-
- /* Now we need to handle some number of optional arguments */
- if (idx < count) {
- uint32_t operands = w[idx++];
-
- if (operands & SpvImageOperandsBiasMask) {
- assert(texop == nir_texop_tex);
- texop = nir_texop_txb;
- (*p++) = vtn_tex_src(b, w[idx++], nir_tex_src_bias);
- }
-
- if (operands & SpvImageOperandsLodMask) {
- assert(texop == nir_texop_txl || texop == nir_texop_txf ||
- texop == nir_texop_txs);
- (*p++) = vtn_tex_src(b, w[idx++], nir_tex_src_lod);
- }
-
- if (operands & SpvImageOperandsGradMask) {
- assert(texop == nir_texop_tex);
- texop = nir_texop_txd;
- (*p++) = vtn_tex_src(b, w[idx++], nir_tex_src_ddx);
- (*p++) = vtn_tex_src(b, w[idx++], nir_tex_src_ddy);
- }
-
- if (operands & SpvImageOperandsOffsetMask ||
- operands & SpvImageOperandsConstOffsetMask)
- (*p++) = vtn_tex_src(b, w[idx++], nir_tex_src_offset);
-
- if (operands & SpvImageOperandsConstOffsetsMask)
- assert(!"Constant offsets to texture gather not yet implemented");
-
- if (operands & SpvImageOperandsSampleMask) {
- assert(texop == nir_texop_txf);
- texop = nir_texop_txf_ms;
- (*p++) = vtn_tex_src(b, w[idx++], nir_tex_src_ms_index);
- }
- }
- /* We should have now consumed exactly all of the arguments */
- assert(idx == count);
-
- nir_tex_instr *instr = nir_tex_instr_create(b->shader, p - srcs);
- instr->op = texop;
-
- memcpy(instr->src, srcs, instr->num_srcs * sizeof(*instr->src));
-
- const struct glsl_type *image_type;
- if (sampled.image) {
- image_type = sampled.image->var->var->interface_type;
- } else {
- image_type = sampled.sampler->var->var->interface_type;
- }
-
- instr->sampler_dim = glsl_get_sampler_dim(image_type);
- instr->is_array = glsl_sampler_type_is_array(image_type);
- instr->is_shadow = glsl_sampler_type_is_shadow(image_type);
- instr->is_new_style_shadow = instr->is_shadow;
-
- if (has_coord) {
- switch (instr->sampler_dim) {
- case GLSL_SAMPLER_DIM_1D:
- case GLSL_SAMPLER_DIM_BUF:
- instr->coord_components = 1;
- break;
- case GLSL_SAMPLER_DIM_2D:
- case GLSL_SAMPLER_DIM_RECT:
- instr->coord_components = 2;
- break;
- case GLSL_SAMPLER_DIM_3D:
- case GLSL_SAMPLER_DIM_CUBE:
- case GLSL_SAMPLER_DIM_MS:
- instr->coord_components = 3;
- break;
- default:
- assert("Invalid sampler type");
- }
-
- if (instr->is_array)
- instr->coord_components++;
- } else {
- instr->coord_components = 0;
- }
-
- switch (glsl_get_sampler_result_type(image_type)) {
- case GLSL_TYPE_FLOAT: instr->dest_type = nir_type_float; break;
- case GLSL_TYPE_INT: instr->dest_type = nir_type_int; break;
- case GLSL_TYPE_UINT: instr->dest_type = nir_type_uint; break;
- case GLSL_TYPE_BOOL: instr->dest_type = nir_type_bool; break;
- default:
- unreachable("Invalid base type for sampler result");
- }
-
- nir_deref_var *sampler = vtn_access_chain_to_deref(b, sampled.sampler);
- instr->sampler = nir_deref_as_var(nir_copy_deref(instr, &sampler->deref));
- if (sampled.image) {
- nir_deref_var *image = vtn_access_chain_to_deref(b, sampled.image);
- instr->texture = nir_deref_as_var(nir_copy_deref(instr, &image->deref));
- } else {
- instr->texture = NULL;
- }
-
- nir_ssa_dest_init(&instr->instr, &instr->dest,
- nir_tex_instr_dest_size(instr), NULL);
-
- assert(glsl_get_vector_elements(ret_type->type) ==
- nir_tex_instr_dest_size(instr));
-
- val->ssa = vtn_create_ssa_value(b, ret_type->type);
- val->ssa->def = &instr->dest.ssa;
-
- nir_builder_instr_insert(&b->nb, &instr->instr);
-}
-
-static nir_ssa_def *
-get_image_coord(struct vtn_builder *b, uint32_t value)
-{
- struct vtn_ssa_value *coord = vtn_ssa_value(b, value);
-
- /* The image_load_store intrinsics assume a 4-dim coordinate */
- unsigned dim = glsl_get_vector_elements(coord->type);
- unsigned swizzle[4];
- for (unsigned i = 0; i < 4; i++)
- swizzle[i] = MIN2(i, dim - 1);
-
- return nir_swizzle(&b->nb, coord->def, swizzle, 4, false);
-}
-
-static void
-vtn_handle_image(struct vtn_builder *b, SpvOp opcode,
- const uint32_t *w, unsigned count)
-{
- /* Just get this one out of the way */
- if (opcode == SpvOpImageTexelPointer) {
- struct vtn_value *val =
- vtn_push_value(b, w[2], vtn_value_type_image_pointer);
- val->image = ralloc(b, struct vtn_image_pointer);
-
- val->image->image =
- vtn_value(b, w[3], vtn_value_type_access_chain)->access_chain;
- val->image->coord = get_image_coord(b, w[4]);
- val->image->sample = vtn_ssa_value(b, w[5])->def;
- return;
- }
-
- struct vtn_image_pointer image;
-
- switch (opcode) {
- case SpvOpAtomicExchange:
- case SpvOpAtomicCompareExchange:
- case SpvOpAtomicCompareExchangeWeak:
- case SpvOpAtomicIIncrement:
- case SpvOpAtomicIDecrement:
- case SpvOpAtomicIAdd:
- case SpvOpAtomicISub:
- case SpvOpAtomicSMin:
- case SpvOpAtomicUMin:
- case SpvOpAtomicSMax:
- case SpvOpAtomicUMax:
- case SpvOpAtomicAnd:
- case SpvOpAtomicOr:
- case SpvOpAtomicXor:
- image = *vtn_value(b, w[3], vtn_value_type_image_pointer)->image;
- break;
-
- case SpvOpImageQuerySize:
- image.image =
- vtn_value(b, w[3], vtn_value_type_access_chain)->access_chain;
- image.coord = NULL;
- image.sample = NULL;
- break;
-
- case SpvOpImageRead:
- image.image =
- vtn_value(b, w[3], vtn_value_type_access_chain)->access_chain;
- image.coord = get_image_coord(b, w[4]);
-
- if (count > 5 && (w[5] & SpvImageOperandsSampleMask)) {
- assert(w[5] == SpvImageOperandsSampleMask);
- image.sample = vtn_ssa_value(b, w[6])->def;
- } else {
- image.sample = nir_ssa_undef(&b->nb, 1);
- }
- break;
-
- case SpvOpImageWrite:
- image.image =
- vtn_value(b, w[1], vtn_value_type_access_chain)->access_chain;
- image.coord = get_image_coord(b, w[2]);
-
- /* texel = w[3] */
-
- if (count > 4 && (w[4] & SpvImageOperandsSampleMask)) {
- assert(w[4] == SpvImageOperandsSampleMask);
- image.sample = vtn_ssa_value(b, w[5])->def;
- } else {
- image.sample = nir_ssa_undef(&b->nb, 1);
- }
- break;
-
- default:
- unreachable("Invalid image opcode");
- }
-
- nir_intrinsic_op op;
- switch (opcode) {
-#define OP(S, N) case SpvOp##S: op = nir_intrinsic_image_##N; break;
- OP(ImageQuerySize, size)
- OP(ImageRead, load)
- OP(ImageWrite, store)
- OP(AtomicExchange, atomic_exchange)
- OP(AtomicCompareExchange, atomic_comp_swap)
- OP(AtomicIIncrement, atomic_add)
- OP(AtomicIDecrement, atomic_add)
- OP(AtomicIAdd, atomic_add)
- OP(AtomicISub, atomic_add)
- OP(AtomicSMin, atomic_min)
- OP(AtomicUMin, atomic_min)
- OP(AtomicSMax, atomic_max)
- OP(AtomicUMax, atomic_max)
- OP(AtomicAnd, atomic_and)
- OP(AtomicOr, atomic_or)
- OP(AtomicXor, atomic_xor)
-#undef OP
- default:
- unreachable("Invalid image opcode");
- }
-
- nir_intrinsic_instr *intrin = nir_intrinsic_instr_create(b->shader, op);
-
- nir_deref_var *image_deref = vtn_access_chain_to_deref(b, image.image);
- intrin->variables[0] =
- nir_deref_as_var(nir_copy_deref(&intrin->instr, &image_deref->deref));
-
- /* ImageQuerySize doesn't take any extra parameters */
- if (opcode != SpvOpImageQuerySize) {
- /* The image coordinate is always 4 components but we may not have that
- * many. Swizzle to compensate.
- */
- unsigned swiz[4];
- for (unsigned i = 0; i < 4; i++)
- swiz[i] = i < image.coord->num_components ? i : 0;
- intrin->src[0] = nir_src_for_ssa(nir_swizzle(&b->nb, image.coord,
- swiz, 4, false));
- intrin->src[1] = nir_src_for_ssa(image.sample);
- }
-
- switch (opcode) {
- case SpvOpImageQuerySize:
- case SpvOpImageRead:
- break;
- case SpvOpImageWrite:
- intrin->src[2] = nir_src_for_ssa(vtn_ssa_value(b, w[3])->def);
- break;
- case SpvOpAtomicIIncrement:
- intrin->src[2] = nir_src_for_ssa(nir_imm_int(&b->nb, 1));
- break;
- case SpvOpAtomicIDecrement:
- intrin->src[2] = nir_src_for_ssa(nir_imm_int(&b->nb, -1));
- break;
-
- case SpvOpAtomicExchange:
- case SpvOpAtomicIAdd:
- case SpvOpAtomicSMin:
- case SpvOpAtomicUMin:
- case SpvOpAtomicSMax:
- case SpvOpAtomicUMax:
- case SpvOpAtomicAnd:
- case SpvOpAtomicOr:
- case SpvOpAtomicXor:
- intrin->src[2] = nir_src_for_ssa(vtn_ssa_value(b, w[6])->def);
- break;
-
- case SpvOpAtomicCompareExchange:
- intrin->src[2] = nir_src_for_ssa(vtn_ssa_value(b, w[7])->def);
- intrin->src[3] = nir_src_for_ssa(vtn_ssa_value(b, w[6])->def);
- break;
-
- case SpvOpAtomicISub:
- intrin->src[2] = nir_src_for_ssa(nir_ineg(&b->nb, vtn_ssa_value(b, w[6])->def));
- break;
-
- default:
- unreachable("Invalid image opcode");
- }
-
- if (opcode != SpvOpImageWrite) {
- struct vtn_value *val = vtn_push_value(b, w[2], vtn_value_type_ssa);
- struct vtn_type *type = vtn_value(b, w[1], vtn_value_type_type)->type;
- nir_ssa_dest_init(&intrin->instr, &intrin->dest, 4, NULL);
-
- nir_builder_instr_insert(&b->nb, &intrin->instr);
-
- /* The image intrinsics always return 4 channels but we may not want
- * that many. Emit a mov to trim it down.
- */
- unsigned swiz[4] = {0, 1, 2, 3};
- val->ssa = vtn_create_ssa_value(b, type->type);
- val->ssa->def = nir_swizzle(&b->nb, &intrin->dest.ssa, swiz,
- glsl_get_vector_elements(type->type), false);
- } else {
- nir_builder_instr_insert(&b->nb, &intrin->instr);
- }
-}
-
-static nir_intrinsic_op
-get_ssbo_nir_atomic_op(SpvOp opcode)
-{
- switch (opcode) {
-#define OP(S, N) case SpvOp##S: return nir_intrinsic_ssbo_##N;
- OP(AtomicExchange, atomic_exchange)
- OP(AtomicCompareExchange, atomic_comp_swap)
- OP(AtomicIIncrement, atomic_add)
- OP(AtomicIDecrement, atomic_add)
- OP(AtomicIAdd, atomic_add)
- OP(AtomicISub, atomic_add)
- OP(AtomicSMin, atomic_imin)
- OP(AtomicUMin, atomic_umin)
- OP(AtomicSMax, atomic_imax)
- OP(AtomicUMax, atomic_umax)
- OP(AtomicAnd, atomic_and)
- OP(AtomicOr, atomic_or)
- OP(AtomicXor, atomic_xor)
-#undef OP
- default:
- unreachable("Invalid SSBO atomic");
- }
-}
-
-static nir_intrinsic_op
-get_shared_nir_atomic_op(SpvOp opcode)
-{
- switch (opcode) {
-#define OP(S, N) case SpvOp##S: return nir_intrinsic_var_##N;
- OP(AtomicExchange, atomic_exchange)
- OP(AtomicCompareExchange, atomic_comp_swap)
- OP(AtomicIIncrement, atomic_add)
- OP(AtomicIDecrement, atomic_add)
- OP(AtomicIAdd, atomic_add)
- OP(AtomicISub, atomic_add)
- OP(AtomicSMin, atomic_imin)
- OP(AtomicUMin, atomic_umin)
- OP(AtomicSMax, atomic_imax)
- OP(AtomicUMax, atomic_umax)
- OP(AtomicAnd, atomic_and)
- OP(AtomicOr, atomic_or)
- OP(AtomicXor, atomic_xor)
-#undef OP
- default:
- unreachable("Invalid shared atomic");
- }
-}
-
-static void
-fill_common_atomic_sources(struct vtn_builder *b, SpvOp opcode,
- const uint32_t *w, nir_src *src)
-{
- switch (opcode) {
- case SpvOpAtomicIIncrement:
- src[0] = nir_src_for_ssa(nir_imm_int(&b->nb, 1));
- break;
-
- case SpvOpAtomicIDecrement:
- src[0] = nir_src_for_ssa(nir_imm_int(&b->nb, -1));
- break;
-
- case SpvOpAtomicISub:
- src[0] =
- nir_src_for_ssa(nir_ineg(&b->nb, vtn_ssa_value(b, w[6])->def));
- break;
-
- case SpvOpAtomicCompareExchange:
- src[0] = nir_src_for_ssa(vtn_ssa_value(b, w[7])->def);
- src[1] = nir_src_for_ssa(vtn_ssa_value(b, w[8])->def);
- break;
- /* Fall through */
-
- case SpvOpAtomicExchange:
- case SpvOpAtomicIAdd:
- case SpvOpAtomicSMin:
- case SpvOpAtomicUMin:
- case SpvOpAtomicSMax:
- case SpvOpAtomicUMax:
- case SpvOpAtomicAnd:
- case SpvOpAtomicOr:
- case SpvOpAtomicXor:
- src[0] = nir_src_for_ssa(vtn_ssa_value(b, w[6])->def);
- break;
-
- default:
- unreachable("Invalid SPIR-V atomic");
- }
-}
-
-static void
-vtn_handle_ssbo_or_shared_atomic(struct vtn_builder *b, SpvOp opcode,
- const uint32_t *w, unsigned count)
-{
- struct vtn_access_chain *chain =
- vtn_value(b, w[3], vtn_value_type_access_chain)->access_chain;
- nir_intrinsic_instr *atomic;
-
- /*
- SpvScope scope = w[4];
- SpvMemorySemanticsMask semantics = w[5];
- */
-
- if (chain->var->mode == vtn_variable_mode_workgroup) {
- nir_deref *deref = &vtn_access_chain_to_deref(b, chain)->deref;
- nir_intrinsic_op op = get_shared_nir_atomic_op(opcode);
- atomic = nir_intrinsic_instr_create(b->nb.shader, op);
- atomic->variables[0] = nir_deref_as_var(nir_copy_deref(atomic, deref));
- fill_common_atomic_sources(b, opcode, w, &atomic->src[0]);
- } else {
- assert(chain->var->mode == vtn_variable_mode_ssbo);
- struct vtn_type *type;
- nir_ssa_def *offset, *index;
- offset = vtn_access_chain_to_offset(b, chain, &index, &type, NULL, false);
-
- nir_intrinsic_op op = get_ssbo_nir_atomic_op(opcode);
-
- atomic = nir_intrinsic_instr_create(b->nb.shader, op);
- atomic->src[0] = nir_src_for_ssa(index);
- atomic->src[1] = nir_src_for_ssa(offset);
- fill_common_atomic_sources(b, opcode, w, &atomic->src[2]);
- }
-
- nir_ssa_dest_init(&atomic->instr, &atomic->dest, 1, NULL);
-
- struct vtn_type *type = vtn_value(b, w[1], vtn_value_type_type)->type;
- struct vtn_value *val = vtn_push_value(b, w[2], vtn_value_type_ssa);
- val->ssa = rzalloc(b, struct vtn_ssa_value);
- val->ssa->def = &atomic->dest.ssa;
- val->ssa->type = type->type;
-
- nir_builder_instr_insert(&b->nb, &atomic->instr);
-}
-
-static nir_alu_instr *
-create_vec(nir_shader *shader, unsigned num_components)
-{
- nir_op op;
- switch (num_components) {
- case 1: op = nir_op_fmov; break;
- case 2: op = nir_op_vec2; break;
- case 3: op = nir_op_vec3; break;
- case 4: op = nir_op_vec4; break;
- default: unreachable("bad vector size");
- }
-
- nir_alu_instr *vec = nir_alu_instr_create(shader, op);
- nir_ssa_dest_init(&vec->instr, &vec->dest.dest, num_components, NULL);
- vec->dest.write_mask = (1 << num_components) - 1;
-
- return vec;
-}
-
-struct vtn_ssa_value *
-vtn_ssa_transpose(struct vtn_builder *b, struct vtn_ssa_value *src)
-{
- if (src->transposed)
- return src->transposed;
-
- struct vtn_ssa_value *dest =
- vtn_create_ssa_value(b, glsl_transposed_type(src->type));
-
- for (unsigned i = 0; i < glsl_get_matrix_columns(dest->type); i++) {
- nir_alu_instr *vec = create_vec(b->shader,
- glsl_get_matrix_columns(src->type));
- if (glsl_type_is_vector_or_scalar(src->type)) {
- vec->src[0].src = nir_src_for_ssa(src->def);
- vec->src[0].swizzle[0] = i;
- } else {
- for (unsigned j = 0; j < glsl_get_matrix_columns(src->type); j++) {
- vec->src[j].src = nir_src_for_ssa(src->elems[j]->def);
- vec->src[j].swizzle[0] = i;
- }
- }
- nir_builder_instr_insert(&b->nb, &vec->instr);
- dest->elems[i]->def = &vec->dest.dest.ssa;
- }
-
- dest->transposed = src;
-
- return dest;
-}
-
-nir_ssa_def *
-vtn_vector_extract(struct vtn_builder *b, nir_ssa_def *src, unsigned index)
-{
- unsigned swiz[4] = { index };
- return nir_swizzle(&b->nb, src, swiz, 1, true);
-}
-
-nir_ssa_def *
-vtn_vector_insert(struct vtn_builder *b, nir_ssa_def *src, nir_ssa_def *insert,
- unsigned index)
-{
- nir_alu_instr *vec = create_vec(b->shader, src->num_components);
-
- for (unsigned i = 0; i < src->num_components; i++) {
- if (i == index) {
- vec->src[i].src = nir_src_for_ssa(insert);
- } else {
- vec->src[i].src = nir_src_for_ssa(src);
- vec->src[i].swizzle[0] = i;
- }
- }
-
- nir_builder_instr_insert(&b->nb, &vec->instr);
-
- return &vec->dest.dest.ssa;
-}
-
-nir_ssa_def *
-vtn_vector_extract_dynamic(struct vtn_builder *b, nir_ssa_def *src,
- nir_ssa_def *index)
-{
- nir_ssa_def *dest = vtn_vector_extract(b, src, 0);
- for (unsigned i = 1; i < src->num_components; i++)
- dest = nir_bcsel(&b->nb, nir_ieq(&b->nb, index, nir_imm_int(&b->nb, i)),
- vtn_vector_extract(b, src, i), dest);
-
- return dest;
-}
-
-nir_ssa_def *
-vtn_vector_insert_dynamic(struct vtn_builder *b, nir_ssa_def *src,
- nir_ssa_def *insert, nir_ssa_def *index)
-{
- nir_ssa_def *dest = vtn_vector_insert(b, src, insert, 0);
- for (unsigned i = 1; i < src->num_components; i++)
- dest = nir_bcsel(&b->nb, nir_ieq(&b->nb, index, nir_imm_int(&b->nb, i)),
- vtn_vector_insert(b, src, insert, i), dest);
-
- return dest;
-}
-
-static nir_ssa_def *
-vtn_vector_shuffle(struct vtn_builder *b, unsigned num_components,
- nir_ssa_def *src0, nir_ssa_def *src1,
- const uint32_t *indices)
-{
- nir_alu_instr *vec = create_vec(b->shader, num_components);
-
- nir_ssa_undef_instr *undef = nir_ssa_undef_instr_create(b->shader, 1);
- nir_builder_instr_insert(&b->nb, &undef->instr);
-
- for (unsigned i = 0; i < num_components; i++) {
- uint32_t index = indices[i];
- if (index == 0xffffffff) {
- vec->src[i].src = nir_src_for_ssa(&undef->def);
- } else if (index < src0->num_components) {
- vec->src[i].src = nir_src_for_ssa(src0);
- vec->src[i].swizzle[0] = index;
- } else {
- vec->src[i].src = nir_src_for_ssa(src1);
- vec->src[i].swizzle[0] = index - src0->num_components;
- }
- }
-
- nir_builder_instr_insert(&b->nb, &vec->instr);
-
- return &vec->dest.dest.ssa;
-}
-
-/*
- * Concatentates a number of vectors/scalars together to produce a vector
- */
-static nir_ssa_def *
-vtn_vector_construct(struct vtn_builder *b, unsigned num_components,
- unsigned num_srcs, nir_ssa_def **srcs)
-{
- nir_alu_instr *vec = create_vec(b->shader, num_components);
-
- unsigned dest_idx = 0;
- for (unsigned i = 0; i < num_srcs; i++) {
- nir_ssa_def *src = srcs[i];
- for (unsigned j = 0; j < src->num_components; j++) {
- vec->src[dest_idx].src = nir_src_for_ssa(src);
- vec->src[dest_idx].swizzle[0] = j;
- dest_idx++;
- }
- }
-
- nir_builder_instr_insert(&b->nb, &vec->instr);
-
- return &vec->dest.dest.ssa;
-}
-
-static struct vtn_ssa_value *
-vtn_composite_copy(void *mem_ctx, struct vtn_ssa_value *src)
-{
- struct vtn_ssa_value *dest = rzalloc(mem_ctx, struct vtn_ssa_value);
- dest->type = src->type;
-
- if (glsl_type_is_vector_or_scalar(src->type)) {
- dest->def = src->def;
- } else {
- unsigned elems = glsl_get_length(src->type);
-
- dest->elems = ralloc_array(mem_ctx, struct vtn_ssa_value *, elems);
- for (unsigned i = 0; i < elems; i++)
- dest->elems[i] = vtn_composite_copy(mem_ctx, src->elems[i]);
- }
-
- return dest;
-}
-
-static struct vtn_ssa_value *
-vtn_composite_insert(struct vtn_builder *b, struct vtn_ssa_value *src,
- struct vtn_ssa_value *insert, const uint32_t *indices,
- unsigned num_indices)
-{
- struct vtn_ssa_value *dest = vtn_composite_copy(b, src);
-
- struct vtn_ssa_value *cur = dest;
- unsigned i;
- for (i = 0; i < num_indices - 1; i++) {
- cur = cur->elems[indices[i]];
- }
-
- if (glsl_type_is_vector_or_scalar(cur->type)) {
- /* According to the SPIR-V spec, OpCompositeInsert may work down to
- * the component granularity. In that case, the last index will be
- * the index to insert the scalar into the vector.
- */
-
- cur->def = vtn_vector_insert(b, cur->def, insert->def, indices[i]);
- } else {
- cur->elems[indices[i]] = insert;
- }
-
- return dest;
-}
-
-static struct vtn_ssa_value *
-vtn_composite_extract(struct vtn_builder *b, struct vtn_ssa_value *src,
- const uint32_t *indices, unsigned num_indices)
-{
- struct vtn_ssa_value *cur = src;
- for (unsigned i = 0; i < num_indices; i++) {
- if (glsl_type_is_vector_or_scalar(cur->type)) {
- assert(i == num_indices - 1);
- /* According to the SPIR-V spec, OpCompositeExtract may work down to
- * the component granularity. The last index will be the index of the
- * vector to extract.
- */
-
- struct vtn_ssa_value *ret = rzalloc(b, struct vtn_ssa_value);
- ret->type = glsl_scalar_type(glsl_get_base_type(cur->type));
- ret->def = vtn_vector_extract(b, cur->def, indices[i]);
- return ret;
- } else {
- cur = cur->elems[indices[i]];
- }
- }
-
- return cur;
-}
-
-static void
-vtn_handle_composite(struct vtn_builder *b, SpvOp opcode,
- const uint32_t *w, unsigned count)
-{
- struct vtn_value *val = vtn_push_value(b, w[2], vtn_value_type_ssa);
- const struct glsl_type *type =
- vtn_value(b, w[1], vtn_value_type_type)->type->type;
- val->ssa = vtn_create_ssa_value(b, type);
-
- switch (opcode) {
- case SpvOpVectorExtractDynamic:
- val->ssa->def = vtn_vector_extract_dynamic(b, vtn_ssa_value(b, w[3])->def,
- vtn_ssa_value(b, w[4])->def);
- break;
-
- case SpvOpVectorInsertDynamic:
- val->ssa->def = vtn_vector_insert_dynamic(b, vtn_ssa_value(b, w[3])->def,
- vtn_ssa_value(b, w[4])->def,
- vtn_ssa_value(b, w[5])->def);
- break;
-
- case SpvOpVectorShuffle:
- val->ssa->def = vtn_vector_shuffle(b, glsl_get_vector_elements(type),
- vtn_ssa_value(b, w[3])->def,
- vtn_ssa_value(b, w[4])->def,
- w + 5);
- break;
-
- case SpvOpCompositeConstruct: {
- unsigned elems = count - 3;
- if (glsl_type_is_vector_or_scalar(type)) {
- nir_ssa_def *srcs[4];
- for (unsigned i = 0; i < elems; i++)
- srcs[i] = vtn_ssa_value(b, w[3 + i])->def;
- val->ssa->def =
- vtn_vector_construct(b, glsl_get_vector_elements(type),
- elems, srcs);
- } else {
- val->ssa->elems = ralloc_array(b, struct vtn_ssa_value *, elems);
- for (unsigned i = 0; i < elems; i++)
- val->ssa->elems[i] = vtn_ssa_value(b, w[3 + i]);
- }
- break;
- }
- case SpvOpCompositeExtract:
- val->ssa = vtn_composite_extract(b, vtn_ssa_value(b, w[3]),
- w + 4, count - 4);
- break;
-
- case SpvOpCompositeInsert:
- val->ssa = vtn_composite_insert(b, vtn_ssa_value(b, w[4]),
- vtn_ssa_value(b, w[3]),
- w + 5, count - 5);
- break;
-
- case SpvOpCopyObject:
- val->ssa = vtn_composite_copy(b, vtn_ssa_value(b, w[3]));
- break;
-
- default:
- unreachable("unknown composite operation");
- }
-}
-
-static void
-vtn_handle_barrier(struct vtn_builder *b, SpvOp opcode,
- const uint32_t *w, unsigned count)
-{
- nir_intrinsic_op intrinsic_op;
- switch (opcode) {
- case SpvOpEmitVertex:
- case SpvOpEmitStreamVertex:
- intrinsic_op = nir_intrinsic_emit_vertex;
- break;
- case SpvOpEndPrimitive:
- case SpvOpEndStreamPrimitive:
- intrinsic_op = nir_intrinsic_end_primitive;
- break;
- case SpvOpMemoryBarrier:
- intrinsic_op = nir_intrinsic_memory_barrier;
- break;
- case SpvOpControlBarrier:
- intrinsic_op = nir_intrinsic_barrier;
- break;
- default:
- unreachable("unknown barrier instruction");
- }
-
- nir_intrinsic_instr *intrin =
- nir_intrinsic_instr_create(b->shader, intrinsic_op);
-
- if (opcode == SpvOpEmitStreamVertex || opcode == SpvOpEndStreamPrimitive)
- intrin->const_index[0] = w[1];
-
- nir_builder_instr_insert(&b->nb, &intrin->instr);
-}
-
-static unsigned
-gl_primitive_from_spv_execution_mode(SpvExecutionMode mode)
-{
- switch (mode) {
- case SpvExecutionModeInputPoints:
- case SpvExecutionModeOutputPoints:
- return 0; /* GL_POINTS */
- case SpvExecutionModeInputLines:
- return 1; /* GL_LINES */
- case SpvExecutionModeInputLinesAdjacency:
- return 0x000A; /* GL_LINE_STRIP_ADJACENCY_ARB */
- case SpvExecutionModeTriangles:
- return 4; /* GL_TRIANGLES */
- case SpvExecutionModeInputTrianglesAdjacency:
- return 0x000C; /* GL_TRIANGLES_ADJACENCY_ARB */
- case SpvExecutionModeQuads:
- return 7; /* GL_QUADS */
- case SpvExecutionModeIsolines:
- return 0x8E7A; /* GL_ISOLINES */
- case SpvExecutionModeOutputLineStrip:
- return 3; /* GL_LINE_STRIP */
- case SpvExecutionModeOutputTriangleStrip:
- return 5; /* GL_TRIANGLE_STRIP */
- default:
- assert(!"Invalid primitive type");
- return 4;
- }
-}
-
-static unsigned
-vertices_in_from_spv_execution_mode(SpvExecutionMode mode)
-{
- switch (mode) {
- case SpvExecutionModeInputPoints:
- return 1;
- case SpvExecutionModeInputLines:
- return 2;
- case SpvExecutionModeInputLinesAdjacency:
- return 4;
- case SpvExecutionModeTriangles:
- return 3;
- case SpvExecutionModeInputTrianglesAdjacency:
- return 6;
- default:
- assert(!"Invalid GS input mode");
- return 0;
- }
-}
-
-static gl_shader_stage
-stage_for_execution_model(SpvExecutionModel model)
-{
- switch (model) {
- case SpvExecutionModelVertex:
- return MESA_SHADER_VERTEX;
- case SpvExecutionModelTessellationControl:
- return MESA_SHADER_TESS_CTRL;
- case SpvExecutionModelTessellationEvaluation:
- return MESA_SHADER_TESS_EVAL;
- case SpvExecutionModelGeometry:
- return MESA_SHADER_GEOMETRY;
- case SpvExecutionModelFragment:
- return MESA_SHADER_FRAGMENT;
- case SpvExecutionModelGLCompute:
- return MESA_SHADER_COMPUTE;
- default:
- unreachable("Unsupported execution model");
- }
-}
-
-static bool
-vtn_handle_preamble_instruction(struct vtn_builder *b, SpvOp opcode,
- const uint32_t *w, unsigned count)
-{
- switch (opcode) {
- case SpvOpSource:
- case SpvOpSourceExtension:
- case SpvOpSourceContinued:
- case SpvOpExtension:
- /* Unhandled, but these are for debug so that's ok. */
- break;
-
- case SpvOpCapability:
- switch ((SpvCapability)w[1]) {
- case SpvCapabilityMatrix:
- case SpvCapabilityShader:
- case SpvCapabilityGeometry:
- break;
- default:
- assert(!"Unsupported capability");
- }
- break;
-
- case SpvOpExtInstImport:
- vtn_handle_extension(b, opcode, w, count);
- break;
-
- case SpvOpMemoryModel:
- assert(w[1] == SpvAddressingModelLogical);
- assert(w[2] == SpvMemoryModelGLSL450);
- break;
-
- case SpvOpEntryPoint: {
- struct vtn_value *entry_point = &b->values[w[2]];
- /* Let this be a name label regardless */
- unsigned name_words;
- entry_point->name = vtn_string_literal(b, &w[3], count - 3, &name_words);
-
- if (strcmp(entry_point->name, b->entry_point_name) != 0 ||
- stage_for_execution_model(w[1]) != b->entry_point_stage)
- break;
-
- assert(b->entry_point == NULL);
- b->entry_point = entry_point;
- break;
- }
-
- case SpvOpString:
- vtn_push_value(b, w[1], vtn_value_type_string)->str =
- vtn_string_literal(b, &w[2], count - 2, NULL);
- break;
-
- case SpvOpName:
- b->values[w[1]].name = vtn_string_literal(b, &w[2], count - 2, NULL);
- break;
-
- case SpvOpMemberName:
- /* TODO */
- break;
-
- case SpvOpExecutionMode:
- case SpvOpDecorationGroup:
- case SpvOpDecorate:
- case SpvOpMemberDecorate:
- case SpvOpGroupDecorate:
- case SpvOpGroupMemberDecorate:
- vtn_handle_decoration(b, opcode, w, count);
- break;
-
- default:
- return false; /* End of preamble */
- }
-
- return true;
-}
-
-static void
-vtn_handle_execution_mode(struct vtn_builder *b, struct vtn_value *entry_point,
- const struct vtn_decoration *mode, void *data)
-{
- assert(b->entry_point == entry_point);
-
- switch(mode->exec_mode) {
- case SpvExecutionModeOriginUpperLeft:
- case SpvExecutionModeOriginLowerLeft:
- b->origin_upper_left =
- (mode->exec_mode == SpvExecutionModeOriginUpperLeft);
- break;
-
- case SpvExecutionModeEarlyFragmentTests:
- assert(b->shader->stage == MESA_SHADER_FRAGMENT);
- b->shader->info.fs.early_fragment_tests = true;
- break;
-
- case SpvExecutionModeInvocations:
- assert(b->shader->stage == MESA_SHADER_GEOMETRY);
- b->shader->info.gs.invocations = MAX2(1, mode->literals[0]);
- break;
-
- case SpvExecutionModeDepthReplacing:
- assert(b->shader->stage == MESA_SHADER_FRAGMENT);
- b->shader->info.fs.depth_layout = FRAG_DEPTH_LAYOUT_ANY;
- break;
- case SpvExecutionModeDepthGreater:
- assert(b->shader->stage == MESA_SHADER_FRAGMENT);
- b->shader->info.fs.depth_layout = FRAG_DEPTH_LAYOUT_GREATER;
- break;
- case SpvExecutionModeDepthLess:
- assert(b->shader->stage == MESA_SHADER_FRAGMENT);
- b->shader->info.fs.depth_layout = FRAG_DEPTH_LAYOUT_LESS;
- break;
- case SpvExecutionModeDepthUnchanged:
- assert(b->shader->stage == MESA_SHADER_FRAGMENT);
- b->shader->info.fs.depth_layout = FRAG_DEPTH_LAYOUT_UNCHANGED;
- break;
-
- case SpvExecutionModeLocalSize:
- assert(b->shader->stage == MESA_SHADER_COMPUTE);
- b->shader->info.cs.local_size[0] = mode->literals[0];
- b->shader->info.cs.local_size[1] = mode->literals[1];
- b->shader->info.cs.local_size[2] = mode->literals[2];
- break;
- case SpvExecutionModeLocalSizeHint:
- break; /* Nothing do do with this */
-
- case SpvExecutionModeOutputVertices:
- assert(b->shader->stage == MESA_SHADER_GEOMETRY);
- b->shader->info.gs.vertices_out = mode->literals[0];
- break;
-
- case SpvExecutionModeInputPoints:
- case SpvExecutionModeInputLines:
- case SpvExecutionModeInputLinesAdjacency:
- case SpvExecutionModeTriangles:
- case SpvExecutionModeInputTrianglesAdjacency:
- case SpvExecutionModeQuads:
- case SpvExecutionModeIsolines:
- if (b->shader->stage == MESA_SHADER_GEOMETRY) {
- b->shader->info.gs.vertices_in =
- vertices_in_from_spv_execution_mode(mode->exec_mode);
- } else {
- assert(!"Tesselation shaders not yet supported");
- }
- break;
-
- case SpvExecutionModeOutputPoints:
- case SpvExecutionModeOutputLineStrip:
- case SpvExecutionModeOutputTriangleStrip:
- assert(b->shader->stage == MESA_SHADER_GEOMETRY);
- b->shader->info.gs.output_primitive =
- gl_primitive_from_spv_execution_mode(mode->exec_mode);
- break;
-
- case SpvExecutionModeSpacingEqual:
- case SpvExecutionModeSpacingFractionalEven:
- case SpvExecutionModeSpacingFractionalOdd:
- case SpvExecutionModeVertexOrderCw:
- case SpvExecutionModeVertexOrderCcw:
- case SpvExecutionModePointMode:
- assert(!"TODO: Add tessellation metadata");
- break;
-
- case SpvExecutionModePixelCenterInteger:
- case SpvExecutionModeXfb:
- assert(!"Unhandled execution mode");
- break;
-
- case SpvExecutionModeVecTypeHint:
- case SpvExecutionModeContractionOff:
- break; /* OpenCL */
- }
-}
-
-static bool
-vtn_handle_variable_or_type_instruction(struct vtn_builder *b, SpvOp opcode,
- const uint32_t *w, unsigned count)
-{
- switch (opcode) {
- case SpvOpSource:
- case SpvOpSourceContinued:
- case SpvOpSourceExtension:
- case SpvOpExtension:
- case SpvOpCapability:
- case SpvOpExtInstImport:
- case SpvOpMemoryModel:
- case SpvOpEntryPoint:
- case SpvOpExecutionMode:
- case SpvOpString:
- case SpvOpName:
- case SpvOpMemberName:
- case SpvOpDecorationGroup:
- case SpvOpDecorate:
- case SpvOpMemberDecorate:
- case SpvOpGroupDecorate:
- case SpvOpGroupMemberDecorate:
- assert(!"Invalid opcode types and variables section");
- break;
-
- case SpvOpTypeVoid:
- case SpvOpTypeBool:
- case SpvOpTypeInt:
- case SpvOpTypeFloat:
- case SpvOpTypeVector:
- case SpvOpTypeMatrix:
- case SpvOpTypeImage:
- case SpvOpTypeSampler:
- case SpvOpTypeSampledImage:
- case SpvOpTypeArray:
- case SpvOpTypeRuntimeArray:
- case SpvOpTypeStruct:
- case SpvOpTypeOpaque:
- case SpvOpTypePointer:
- case SpvOpTypeFunction:
- case SpvOpTypeEvent:
- case SpvOpTypeDeviceEvent:
- case SpvOpTypeReserveId:
- case SpvOpTypeQueue:
- case SpvOpTypePipe:
- vtn_handle_type(b, opcode, w, count);
- break;
-
- case SpvOpConstantTrue:
- case SpvOpConstantFalse:
- case SpvOpConstant:
- case SpvOpConstantComposite:
- case SpvOpConstantSampler:
- case SpvOpConstantNull:
- case SpvOpSpecConstantTrue:
- case SpvOpSpecConstantFalse:
- case SpvOpSpecConstant:
- case SpvOpSpecConstantComposite:
- case SpvOpSpecConstantOp:
- vtn_handle_constant(b, opcode, w, count);
- break;
-
- case SpvOpVariable:
- vtn_handle_variables(b, opcode, w, count);
- break;
-
- default:
- return false; /* End of preamble */
- }
-
- return true;
-}
-
-static bool
-vtn_handle_body_instruction(struct vtn_builder *b, SpvOp opcode,
- const uint32_t *w, unsigned count)
-{
- switch (opcode) {
- case SpvOpLabel:
- break;
-
- case SpvOpLoopMerge:
- case SpvOpSelectionMerge:
- /* This is handled by cfg pre-pass and walk_blocks */
- break;
-
- case SpvOpUndef: {
- struct vtn_value *val = vtn_push_value(b, w[2], vtn_value_type_undef);
- val->type = vtn_value(b, w[1], vtn_value_type_type)->type;
- break;
- }
-
- case SpvOpExtInst:
- vtn_handle_extension(b, opcode, w, count);
- break;
-
- case SpvOpVariable:
- case SpvOpLoad:
- case SpvOpStore:
- case SpvOpCopyMemory:
- case SpvOpCopyMemorySized:
- case SpvOpAccessChain:
- case SpvOpInBoundsAccessChain:
- case SpvOpArrayLength:
- vtn_handle_variables(b, opcode, w, count);
- break;
-
- case SpvOpFunctionCall:
- vtn_handle_function_call(b, opcode, w, count);
- break;
-
- case SpvOpSampledImage:
- case SpvOpImage:
- case SpvOpImageSampleImplicitLod:
- case SpvOpImageSampleExplicitLod:
- case SpvOpImageSampleDrefImplicitLod:
- case SpvOpImageSampleDrefExplicitLod:
- case SpvOpImageSampleProjImplicitLod:
- case SpvOpImageSampleProjExplicitLod:
- case SpvOpImageSampleProjDrefImplicitLod:
- case SpvOpImageSampleProjDrefExplicitLod:
- case SpvOpImageFetch:
- case SpvOpImageGather:
- case SpvOpImageDrefGather:
- case SpvOpImageQuerySizeLod:
- case SpvOpImageQueryLod:
- case SpvOpImageQueryLevels:
- case SpvOpImageQuerySamples:
- vtn_handle_texture(b, opcode, w, count);
- break;
-
- case SpvOpImageRead:
- case SpvOpImageWrite:
- case SpvOpImageTexelPointer:
- vtn_handle_image(b, opcode, w, count);
- break;
-
- case SpvOpImageQuerySize: {
- struct vtn_access_chain *image =
- vtn_value(b, w[3], vtn_value_type_access_chain)->access_chain;
- if (glsl_type_is_image(image->var->var->interface_type)) {
- vtn_handle_image(b, opcode, w, count);
- } else {
- vtn_handle_texture(b, opcode, w, count);
- }
- break;
- }
-
- case SpvOpAtomicExchange:
- case SpvOpAtomicCompareExchange:
- case SpvOpAtomicCompareExchangeWeak:
- case SpvOpAtomicIIncrement:
- case SpvOpAtomicIDecrement:
- case SpvOpAtomicIAdd:
- case SpvOpAtomicISub:
- case SpvOpAtomicSMin:
- case SpvOpAtomicUMin:
- case SpvOpAtomicSMax:
- case SpvOpAtomicUMax:
- case SpvOpAtomicAnd:
- case SpvOpAtomicOr:
- case SpvOpAtomicXor: {
- struct vtn_value *pointer = vtn_untyped_value(b, w[3]);
- if (pointer->value_type == vtn_value_type_image_pointer) {
- vtn_handle_image(b, opcode, w, count);
- } else {
- assert(pointer->value_type == vtn_value_type_access_chain);
- vtn_handle_ssbo_or_shared_atomic(b, opcode, w, count);
- }
- break;
- }
-
- case SpvOpSNegate:
- case SpvOpFNegate:
- case SpvOpNot:
- case SpvOpAny:
- case SpvOpAll:
- case SpvOpConvertFToU:
- case SpvOpConvertFToS:
- case SpvOpConvertSToF:
- case SpvOpConvertUToF:
- case SpvOpUConvert:
- case SpvOpSConvert:
- case SpvOpFConvert:
- case SpvOpQuantizeToF16:
- case SpvOpConvertPtrToU:
- case SpvOpConvertUToPtr:
- case SpvOpPtrCastToGeneric:
- case SpvOpGenericCastToPtr:
- case SpvOpBitcast:
- case SpvOpIsNan:
- case SpvOpIsInf:
- case SpvOpIsFinite:
- case SpvOpIsNormal:
- case SpvOpSignBitSet:
- case SpvOpLessOrGreater:
- case SpvOpOrdered:
- case SpvOpUnordered:
- case SpvOpIAdd:
- case SpvOpFAdd:
- case SpvOpISub:
- case SpvOpFSub:
- case SpvOpIMul:
- case SpvOpFMul:
- case SpvOpUDiv:
- case SpvOpSDiv:
- case SpvOpFDiv:
- case SpvOpUMod:
- case SpvOpSRem:
- case SpvOpSMod:
- case SpvOpFRem:
- case SpvOpFMod:
- case SpvOpVectorTimesScalar:
- case SpvOpDot:
- case SpvOpIAddCarry:
- case SpvOpISubBorrow:
- case SpvOpUMulExtended:
- case SpvOpSMulExtended:
- case SpvOpShiftRightLogical:
- case SpvOpShiftRightArithmetic:
- case SpvOpShiftLeftLogical:
- case SpvOpLogicalEqual:
- case SpvOpLogicalNotEqual:
- case SpvOpLogicalOr:
- case SpvOpLogicalAnd:
- case SpvOpLogicalNot:
- case SpvOpBitwiseOr:
- case SpvOpBitwiseXor:
- case SpvOpBitwiseAnd:
- case SpvOpSelect:
- case SpvOpIEqual:
- case SpvOpFOrdEqual:
- case SpvOpFUnordEqual:
- case SpvOpINotEqual:
- case SpvOpFOrdNotEqual:
- case SpvOpFUnordNotEqual:
- case SpvOpULessThan:
- case SpvOpSLessThan:
- case SpvOpFOrdLessThan:
- case SpvOpFUnordLessThan:
- case SpvOpUGreaterThan:
- case SpvOpSGreaterThan:
- case SpvOpFOrdGreaterThan:
- case SpvOpFUnordGreaterThan:
- case SpvOpULessThanEqual:
- case SpvOpSLessThanEqual:
- case SpvOpFOrdLessThanEqual:
- case SpvOpFUnordLessThanEqual:
- case SpvOpUGreaterThanEqual:
- case SpvOpSGreaterThanEqual:
- case SpvOpFOrdGreaterThanEqual:
- case SpvOpFUnordGreaterThanEqual:
- case SpvOpDPdx:
- case SpvOpDPdy:
- case SpvOpFwidth:
- case SpvOpDPdxFine:
- case SpvOpDPdyFine:
- case SpvOpFwidthFine:
- case SpvOpDPdxCoarse:
- case SpvOpDPdyCoarse:
- case SpvOpFwidthCoarse:
- case SpvOpBitFieldInsert:
- case SpvOpBitFieldSExtract:
- case SpvOpBitFieldUExtract:
- case SpvOpBitReverse:
- case SpvOpBitCount:
- case SpvOpTranspose:
- case SpvOpOuterProduct:
- case SpvOpMatrixTimesScalar:
- case SpvOpVectorTimesMatrix:
- case SpvOpMatrixTimesVector:
- case SpvOpMatrixTimesMatrix:
- vtn_handle_alu(b, opcode, w, count);
- break;
-
- case SpvOpVectorExtractDynamic:
- case SpvOpVectorInsertDynamic:
- case SpvOpVectorShuffle:
- case SpvOpCompositeConstruct:
- case SpvOpCompositeExtract:
- case SpvOpCompositeInsert:
- case SpvOpCopyObject:
- vtn_handle_composite(b, opcode, w, count);
- break;
-
- case SpvOpEmitVertex:
- case SpvOpEndPrimitive:
- case SpvOpEmitStreamVertex:
- case SpvOpEndStreamPrimitive:
- case SpvOpControlBarrier:
- case SpvOpMemoryBarrier:
- vtn_handle_barrier(b, opcode, w, count);
- break;
-
- default:
- unreachable("Unhandled opcode");
- }
-
- return true;
-}
-
-nir_function *
-spirv_to_nir(const uint32_t *words, size_t word_count,
- struct nir_spirv_specialization *spec, unsigned num_spec,
- gl_shader_stage stage, const char *entry_point_name,
- const nir_shader_compiler_options *options)
-{
- const uint32_t *word_end = words + word_count;
-
- /* Handle the SPIR-V header (first 4 dwords) */
- assert(word_count > 5);
-
- assert(words[0] == SpvMagicNumber);
- assert(words[1] >= 0x10000);
- /* words[2] == generator magic */
- unsigned value_id_bound = words[3];
- assert(words[4] == 0);
-
- words+= 5;
-
- /* Initialize the stn_builder object */
- struct vtn_builder *b = rzalloc(NULL, struct vtn_builder);
- b->value_id_bound = value_id_bound;
- b->values = rzalloc_array(b, struct vtn_value, value_id_bound);
- exec_list_make_empty(&b->functions);
- b->entry_point_stage = stage;
- b->entry_point_name = entry_point_name;
-
- /* Handle all the preamble instructions */
- words = vtn_foreach_instruction(b, words, word_end,
- vtn_handle_preamble_instruction);
-
- if (b->entry_point == NULL) {
- assert(!"Entry point not found");
- ralloc_free(b);
- return NULL;
- }
-
- b->shader = nir_shader_create(NULL, stage, options);
-
- /* Parse execution modes */
- vtn_foreach_execution_mode(b, b->entry_point,
- vtn_handle_execution_mode, NULL);
-
- b->specializations = spec;
- b->num_specializations = num_spec;
-
- /* Handle all variable, type, and constant instructions */
- words = vtn_foreach_instruction(b, words, word_end,
- vtn_handle_variable_or_type_instruction);
-
- vtn_build_cfg(b, words, word_end);
-
- foreach_list_typed(struct vtn_function, func, node, &b->functions) {
- b->impl = func->impl;
- b->const_table = _mesa_hash_table_create(b, _mesa_hash_pointer,
- _mesa_key_pointer_equal);
-
- vtn_function_emit(b, func, vtn_handle_body_instruction);
- }
-
- assert(b->entry_point->value_type == vtn_value_type_function);
- nir_function *entry_point = b->entry_point->func->impl->function;
- assert(entry_point);
-
- ralloc_free(b);
-
- return entry_point;
-}
diff --git a/src/glsl/nir/spirv/vtn_alu.c b/src/glsl/nir/spirv/vtn_alu.c
deleted file mode 100644
index d866da7445e..00000000000
--- a/src/glsl/nir/spirv/vtn_alu.c
+++ /dev/null
@@ -1,448 +0,0 @@
-/*
- * Copyright © 2016 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include "vtn_private.h"
-
-/*
- * Normally, column vectors in SPIR-V correspond to a single NIR SSA
- * definition. But for matrix multiplies, we want to do one routine for
- * multiplying a matrix by a matrix and then pretend that vectors are matrices
- * with one column. So we "wrap" these things, and unwrap the result before we
- * send it off.
- */
-
-static struct vtn_ssa_value *
-wrap_matrix(struct vtn_builder *b, struct vtn_ssa_value *val)
-{
- if (val == NULL)
- return NULL;
-
- if (glsl_type_is_matrix(val->type))
- return val;
-
- struct vtn_ssa_value *dest = rzalloc(b, struct vtn_ssa_value);
- dest->type = val->type;
- dest->elems = ralloc_array(b, struct vtn_ssa_value *, 1);
- dest->elems[0] = val;
-
- return dest;
-}
-
-static struct vtn_ssa_value *
-unwrap_matrix(struct vtn_ssa_value *val)
-{
- if (glsl_type_is_matrix(val->type))
- return val;
-
- return val->elems[0];
-}
-
-static struct vtn_ssa_value *
-matrix_multiply(struct vtn_builder *b,
- struct vtn_ssa_value *_src0, struct vtn_ssa_value *_src1)
-{
-
- struct vtn_ssa_value *src0 = wrap_matrix(b, _src0);
- struct vtn_ssa_value *src1 = wrap_matrix(b, _src1);
- struct vtn_ssa_value *src0_transpose = wrap_matrix(b, _src0->transposed);
- struct vtn_ssa_value *src1_transpose = wrap_matrix(b, _src1->transposed);
-
- unsigned src0_rows = glsl_get_vector_elements(src0->type);
- unsigned src0_columns = glsl_get_matrix_columns(src0->type);
- unsigned src1_columns = glsl_get_matrix_columns(src1->type);
-
- const struct glsl_type *dest_type;
- if (src1_columns > 1) {
- dest_type = glsl_matrix_type(glsl_get_base_type(src0->type),
- src0_rows, src1_columns);
- } else {
- dest_type = glsl_vector_type(glsl_get_base_type(src0->type), src0_rows);
- }
- struct vtn_ssa_value *dest = vtn_create_ssa_value(b, dest_type);
-
- dest = wrap_matrix(b, dest);
-
- bool transpose_result = false;
- if (src0_transpose && src1_transpose) {
- /* transpose(A) * transpose(B) = transpose(B * A) */
- src1 = src0_transpose;
- src0 = src1_transpose;
- src0_transpose = NULL;
- src1_transpose = NULL;
- transpose_result = true;
- }
-
- if (src0_transpose && !src1_transpose &&
- glsl_get_base_type(src0->type) == GLSL_TYPE_FLOAT) {
- /* We already have the rows of src0 and the columns of src1 available,
- * so we can just take the dot product of each row with each column to
- * get the result.
- */
-
- for (unsigned i = 0; i < src1_columns; i++) {
- nir_ssa_def *vec_src[4];
- for (unsigned j = 0; j < src0_rows; j++) {
- vec_src[j] = nir_fdot(&b->nb, src0_transpose->elems[j]->def,
- src1->elems[i]->def);
- }
- dest->elems[i]->def = nir_vec(&b->nb, vec_src, src0_rows);
- }
- } else {
- /* We don't handle the case where src1 is transposed but not src0, since
- * the general case only uses individual components of src1 so the
- * optimizer should chew through the transpose we emitted for src1.
- */
-
- for (unsigned i = 0; i < src1_columns; i++) {
- /* dest[i] = sum(src0[j] * src1[i][j] for all j) */
- dest->elems[i]->def =
- nir_fmul(&b->nb, src0->elems[0]->def,
- nir_channel(&b->nb, src1->elems[i]->def, 0));
- for (unsigned j = 1; j < src0_columns; j++) {
- dest->elems[i]->def =
- nir_fadd(&b->nb, dest->elems[i]->def,
- nir_fmul(&b->nb, src0->elems[j]->def,
- nir_channel(&b->nb, src1->elems[i]->def, j)));
- }
- }
- }
-
- dest = unwrap_matrix(dest);
-
- if (transpose_result)
- dest = vtn_ssa_transpose(b, dest);
-
- return dest;
-}
-
-static struct vtn_ssa_value *
-mat_times_scalar(struct vtn_builder *b,
- struct vtn_ssa_value *mat,
- nir_ssa_def *scalar)
-{
- struct vtn_ssa_value *dest = vtn_create_ssa_value(b, mat->type);
- for (unsigned i = 0; i < glsl_get_matrix_columns(mat->type); i++) {
- if (glsl_get_base_type(mat->type) == GLSL_TYPE_FLOAT)
- dest->elems[i]->def = nir_fmul(&b->nb, mat->elems[i]->def, scalar);
- else
- dest->elems[i]->def = nir_imul(&b->nb, mat->elems[i]->def, scalar);
- }
-
- return dest;
-}
-
-static void
-vtn_handle_matrix_alu(struct vtn_builder *b, SpvOp opcode,
- struct vtn_value *dest,
- struct vtn_ssa_value *src0, struct vtn_ssa_value *src1)
-{
- switch (opcode) {
- case SpvOpFNegate: {
- dest->ssa = vtn_create_ssa_value(b, src0->type);
- unsigned cols = glsl_get_matrix_columns(src0->type);
- for (unsigned i = 0; i < cols; i++)
- dest->ssa->elems[i]->def = nir_fneg(&b->nb, src0->elems[i]->def);
- break;
- }
-
- case SpvOpFAdd: {
- dest->ssa = vtn_create_ssa_value(b, src0->type);
- unsigned cols = glsl_get_matrix_columns(src0->type);
- for (unsigned i = 0; i < cols; i++)
- dest->ssa->elems[i]->def =
- nir_fadd(&b->nb, src0->elems[i]->def, src1->elems[i]->def);
- break;
- }
-
- case SpvOpFSub: {
- dest->ssa = vtn_create_ssa_value(b, src0->type);
- unsigned cols = glsl_get_matrix_columns(src0->type);
- for (unsigned i = 0; i < cols; i++)
- dest->ssa->elems[i]->def =
- nir_fsub(&b->nb, src0->elems[i]->def, src1->elems[i]->def);
- break;
- }
-
- case SpvOpTranspose:
- dest->ssa = vtn_ssa_transpose(b, src0);
- break;
-
- case SpvOpMatrixTimesScalar:
- if (src0->transposed) {
- dest->ssa = vtn_ssa_transpose(b, mat_times_scalar(b, src0->transposed,
- src1->def));
- } else {
- dest->ssa = mat_times_scalar(b, src0, src1->def);
- }
- break;
-
- case SpvOpVectorTimesMatrix:
- case SpvOpMatrixTimesVector:
- case SpvOpMatrixTimesMatrix:
- if (opcode == SpvOpVectorTimesMatrix) {
- dest->ssa = matrix_multiply(b, vtn_ssa_transpose(b, src1), src0);
- } else {
- dest->ssa = matrix_multiply(b, src0, src1);
- }
- break;
-
- default: unreachable("unknown matrix opcode");
- }
-}
-
-nir_op
-vtn_nir_alu_op_for_spirv_opcode(SpvOp opcode, bool *swap)
-{
- /* Indicates that the first two arguments should be swapped. This is
- * used for implementing greater-than and less-than-or-equal.
- */
- *swap = false;
-
- switch (opcode) {
- case SpvOpSNegate: return nir_op_ineg;
- case SpvOpFNegate: return nir_op_fneg;
- case SpvOpNot: return nir_op_inot;
- case SpvOpIAdd: return nir_op_iadd;
- case SpvOpFAdd: return nir_op_fadd;
- case SpvOpISub: return nir_op_isub;
- case SpvOpFSub: return nir_op_fsub;
- case SpvOpIMul: return nir_op_imul;
- case SpvOpFMul: return nir_op_fmul;
- case SpvOpUDiv: return nir_op_udiv;
- case SpvOpSDiv: return nir_op_idiv;
- case SpvOpFDiv: return nir_op_fdiv;
- case SpvOpUMod: return nir_op_umod;
- case SpvOpSMod: return nir_op_imod;
- case SpvOpFMod: return nir_op_fmod;
- case SpvOpSRem: return nir_op_irem;
- case SpvOpFRem: return nir_op_frem;
-
- case SpvOpShiftRightLogical: return nir_op_ushr;
- case SpvOpShiftRightArithmetic: return nir_op_ishr;
- case SpvOpShiftLeftLogical: return nir_op_ishl;
- case SpvOpLogicalOr: return nir_op_ior;
- case SpvOpLogicalEqual: return nir_op_ieq;
- case SpvOpLogicalNotEqual: return nir_op_ine;
- case SpvOpLogicalAnd: return nir_op_iand;
- case SpvOpLogicalNot: return nir_op_inot;
- case SpvOpBitwiseOr: return nir_op_ior;
- case SpvOpBitwiseXor: return nir_op_ixor;
- case SpvOpBitwiseAnd: return nir_op_iand;
- case SpvOpSelect: return nir_op_bcsel;
- case SpvOpIEqual: return nir_op_ieq;
-
- case SpvOpBitFieldInsert: return nir_op_bitfield_insert;
- case SpvOpBitFieldSExtract: return nir_op_ibitfield_extract;
- case SpvOpBitFieldUExtract: return nir_op_ubitfield_extract;
- case SpvOpBitReverse: return nir_op_bitfield_reverse;
- case SpvOpBitCount: return nir_op_bit_count;
-
- /* Comparisons: (TODO: How do we want to handled ordered/unordered?) */
- case SpvOpFOrdEqual: return nir_op_feq;
- case SpvOpFUnordEqual: return nir_op_feq;
- case SpvOpINotEqual: return nir_op_ine;
- case SpvOpFOrdNotEqual: return nir_op_fne;
- case SpvOpFUnordNotEqual: return nir_op_fne;
- case SpvOpULessThan: return nir_op_ult;
- case SpvOpSLessThan: return nir_op_ilt;
- case SpvOpFOrdLessThan: return nir_op_flt;
- case SpvOpFUnordLessThan: return nir_op_flt;
- case SpvOpUGreaterThan: *swap = true; return nir_op_ult;
- case SpvOpSGreaterThan: *swap = true; return nir_op_ilt;
- case SpvOpFOrdGreaterThan: *swap = true; return nir_op_flt;
- case SpvOpFUnordGreaterThan: *swap = true; return nir_op_flt;
- case SpvOpULessThanEqual: *swap = true; return nir_op_uge;
- case SpvOpSLessThanEqual: *swap = true; return nir_op_ige;
- case SpvOpFOrdLessThanEqual: *swap = true; return nir_op_fge;
- case SpvOpFUnordLessThanEqual: *swap = true; return nir_op_fge;
- case SpvOpUGreaterThanEqual: return nir_op_uge;
- case SpvOpSGreaterThanEqual: return nir_op_ige;
- case SpvOpFOrdGreaterThanEqual: return nir_op_fge;
- case SpvOpFUnordGreaterThanEqual: return nir_op_fge;
-
- /* Conversions: */
- case SpvOpConvertFToU: return nir_op_f2u;
- case SpvOpConvertFToS: return nir_op_f2i;
- case SpvOpConvertSToF: return nir_op_i2f;
- case SpvOpConvertUToF: return nir_op_u2f;
- case SpvOpBitcast: return nir_op_imov;
- case SpvOpUConvert:
- case SpvOpQuantizeToF16: return nir_op_fquantize2f16;
- /* TODO: NIR is 32-bit only; these are no-ops. */
- case SpvOpSConvert: return nir_op_imov;
- case SpvOpFConvert: return nir_op_fmov;
-
- /* Derivatives: */
- case SpvOpDPdx: return nir_op_fddx;
- case SpvOpDPdy: return nir_op_fddy;
- case SpvOpDPdxFine: return nir_op_fddx_fine;
- case SpvOpDPdyFine: return nir_op_fddy_fine;
- case SpvOpDPdxCoarse: return nir_op_fddx_coarse;
- case SpvOpDPdyCoarse: return nir_op_fddy_coarse;
-
- default:
- unreachable("No NIR equivalent");
- }
-}
-
-void
-vtn_handle_alu(struct vtn_builder *b, SpvOp opcode,
- const uint32_t *w, unsigned count)
-{
- struct vtn_value *val = vtn_push_value(b, w[2], vtn_value_type_ssa);
- const struct glsl_type *type =
- vtn_value(b, w[1], vtn_value_type_type)->type->type;
-
- /* Collect the various SSA sources */
- const unsigned num_inputs = count - 3;
- struct vtn_ssa_value *vtn_src[4] = { NULL, };
- for (unsigned i = 0; i < num_inputs; i++)
- vtn_src[i] = vtn_ssa_value(b, w[i + 3]);
-
- if (glsl_type_is_matrix(vtn_src[0]->type) ||
- (num_inputs >= 2 && glsl_type_is_matrix(vtn_src[1]->type))) {
- vtn_handle_matrix_alu(b, opcode, val, vtn_src[0], vtn_src[1]);
- return;
- }
-
- val->ssa = vtn_create_ssa_value(b, type);
- nir_ssa_def *src[4] = { NULL, };
- for (unsigned i = 0; i < num_inputs; i++) {
- assert(glsl_type_is_vector_or_scalar(vtn_src[i]->type));
- src[i] = vtn_src[i]->def;
- }
-
- switch (opcode) {
- case SpvOpAny:
- if (src[0]->num_components == 1) {
- val->ssa->def = nir_imov(&b->nb, src[0]);
- } else {
- nir_op op;
- switch (src[0]->num_components) {
- case 2: op = nir_op_bany_inequal2; break;
- case 3: op = nir_op_bany_inequal3; break;
- case 4: op = nir_op_bany_inequal4; break;
- }
- val->ssa->def = nir_build_alu(&b->nb, op, src[0],
- nir_imm_int(&b->nb, NIR_FALSE),
- NULL, NULL);
- }
- return;
-
- case SpvOpAll:
- if (src[0]->num_components == 1) {
- val->ssa->def = nir_imov(&b->nb, src[0]);
- } else {
- nir_op op;
- switch (src[0]->num_components) {
- case 2: op = nir_op_ball_iequal2; break;
- case 3: op = nir_op_ball_iequal3; break;
- case 4: op = nir_op_ball_iequal4; break;
- }
- val->ssa->def = nir_build_alu(&b->nb, op, src[0],
- nir_imm_int(&b->nb, NIR_TRUE),
- NULL, NULL);
- }
- return;
-
- case SpvOpOuterProduct: {
- for (unsigned i = 0; i < src[1]->num_components; i++) {
- val->ssa->elems[i]->def =
- nir_fmul(&b->nb, src[0], nir_channel(&b->nb, src[1], i));
- }
- return;
- }
-
- case SpvOpDot:
- val->ssa->def = nir_fdot(&b->nb, src[0], src[1]);
- return;
-
- case SpvOpIAddCarry:
- assert(glsl_type_is_struct(val->ssa->type));
- val->ssa->elems[0]->def = nir_iadd(&b->nb, src[0], src[1]);
- val->ssa->elems[1]->def = nir_uadd_carry(&b->nb, src[0], src[1]);
- return;
-
- case SpvOpISubBorrow:
- assert(glsl_type_is_struct(val->ssa->type));
- val->ssa->elems[0]->def = nir_isub(&b->nb, src[0], src[1]);
- val->ssa->elems[1]->def = nir_usub_borrow(&b->nb, src[0], src[1]);
- return;
-
- case SpvOpUMulExtended:
- assert(glsl_type_is_struct(val->ssa->type));
- val->ssa->elems[0]->def = nir_imul(&b->nb, src[0], src[1]);
- val->ssa->elems[1]->def = nir_umul_high(&b->nb, src[0], src[1]);
- return;
-
- case SpvOpSMulExtended:
- assert(glsl_type_is_struct(val->ssa->type));
- val->ssa->elems[0]->def = nir_imul(&b->nb, src[0], src[1]);
- val->ssa->elems[1]->def = nir_imul_high(&b->nb, src[0], src[1]);
- return;
-
- case SpvOpFwidth:
- val->ssa->def = nir_fadd(&b->nb,
- nir_fabs(&b->nb, nir_fddx(&b->nb, src[0])),
- nir_fabs(&b->nb, nir_fddx(&b->nb, src[1])));
- return;
- case SpvOpFwidthFine:
- val->ssa->def = nir_fadd(&b->nb,
- nir_fabs(&b->nb, nir_fddx_fine(&b->nb, src[0])),
- nir_fabs(&b->nb, nir_fddx_fine(&b->nb, src[1])));
- return;
- case SpvOpFwidthCoarse:
- val->ssa->def = nir_fadd(&b->nb,
- nir_fabs(&b->nb, nir_fddx_coarse(&b->nb, src[0])),
- nir_fabs(&b->nb, nir_fddx_coarse(&b->nb, src[1])));
- return;
-
- case SpvOpVectorTimesScalar:
- /* The builder will take care of splatting for us. */
- val->ssa->def = nir_fmul(&b->nb, src[0], src[1]);
- return;
-
- case SpvOpIsNan:
- val->ssa->def = nir_fne(&b->nb, src[0], src[0]);
- return;
-
- case SpvOpIsInf:
- val->ssa->def = nir_feq(&b->nb, nir_fabs(&b->nb, src[0]),
- nir_imm_float(&b->nb, INFINITY));
- return;
-
- default: {
- bool swap;
- nir_op op = vtn_nir_alu_op_for_spirv_opcode(opcode, &swap);
-
- if (swap) {
- nir_ssa_def *tmp = src[0];
- src[0] = src[1];
- src[1] = tmp;
- }
-
- val->ssa->def = nir_build_alu(&b->nb, op, src[0], src[1], src[2], src[3]);
- return;
- } /* default */
- }
-}
diff --git a/src/glsl/nir/spirv/vtn_cfg.c b/src/glsl/nir/spirv/vtn_cfg.c
deleted file mode 100644
index 041408b1cfb..00000000000
--- a/src/glsl/nir/spirv/vtn_cfg.c
+++ /dev/null
@@ -1,768 +0,0 @@
-/*
- * Copyright © 2015 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include "vtn_private.h"
-#include "nir/nir_vla.h"
-
-static bool
-vtn_cfg_handle_prepass_instruction(struct vtn_builder *b, SpvOp opcode,
- const uint32_t *w, unsigned count)
-{
- switch (opcode) {
- case SpvOpFunction: {
- assert(b->func == NULL);
- b->func = rzalloc(b, struct vtn_function);
-
- list_inithead(&b->func->body);
- b->func->control = w[3];
-
- const struct glsl_type *result_type =
- vtn_value(b, w[1], vtn_value_type_type)->type->type;
- struct vtn_value *val = vtn_push_value(b, w[2], vtn_value_type_function);
- val->func = b->func;
-
- const struct glsl_type *func_type =
- vtn_value(b, w[4], vtn_value_type_type)->type->type;
-
- assert(glsl_get_function_return_type(func_type) == result_type);
-
- nir_function *func =
- nir_function_create(b->shader, ralloc_strdup(b->shader, val->name));
-
- func->num_params = glsl_get_length(func_type);
- func->params = ralloc_array(b->shader, nir_parameter, func->num_params);
- for (unsigned i = 0; i < func->num_params; i++) {
- const struct glsl_function_param *param =
- glsl_get_function_param(func_type, i);
- func->params[i].type = param->type;
- if (param->in) {
- if (param->out) {
- func->params[i].param_type = nir_parameter_inout;
- } else {
- func->params[i].param_type = nir_parameter_in;
- }
- } else {
- if (param->out) {
- func->params[i].param_type = nir_parameter_out;
- } else {
- assert(!"Parameter is neither in nor out");
- }
- }
- }
-
- func->return_type = glsl_get_function_return_type(func_type);
-
- b->func->impl = nir_function_impl_create(func);
- if (!glsl_type_is_void(func->return_type)) {
- b->func->impl->return_var =
- nir_local_variable_create(b->func->impl, func->return_type, "ret");
- }
-
- b->func_param_idx = 0;
- break;
- }
-
- case SpvOpFunctionEnd:
- b->func->end = w;
- b->func = NULL;
- break;
-
- case SpvOpFunctionParameter: {
- struct vtn_value *val =
- vtn_push_value(b, w[2], vtn_value_type_access_chain);
-
- assert(b->func_param_idx < b->func->impl->num_params);
- unsigned idx = b->func_param_idx++;
-
- nir_variable *param =
- nir_local_variable_create(b->func->impl,
- b->func->impl->function->params[idx].type,
- val->name);
- b->func->impl->params[idx] = param;
-
- struct vtn_variable *vtn_var = rzalloc(b, struct vtn_variable);
- vtn_var->mode = vtn_variable_mode_param;
- vtn_var->type = vtn_value(b, w[1], vtn_value_type_type)->type;
- vtn_var->var = param;
- vtn_var->chain.var = vtn_var;
- vtn_var->chain.length = 0;
-
- val->access_chain = &vtn_var->chain;
- break;
- }
-
- case SpvOpLabel: {
- assert(b->block == NULL);
- b->block = rzalloc(b, struct vtn_block);
- b->block->node.type = vtn_cf_node_type_block;
- b->block->label = w;
- vtn_push_value(b, w[1], vtn_value_type_block)->block = b->block;
-
- if (b->func->start_block == NULL) {
- /* This is the first block encountered for this function. In this
- * case, we set the start block and add it to the list of
- * implemented functions that we'll walk later.
- */
- b->func->start_block = b->block;
- exec_list_push_tail(&b->functions, &b->func->node);
- }
- break;
- }
-
- case SpvOpSelectionMerge:
- case SpvOpLoopMerge:
- assert(b->block && b->block->merge == NULL);
- b->block->merge = w;
- break;
-
- case SpvOpBranch:
- case SpvOpBranchConditional:
- case SpvOpSwitch:
- case SpvOpKill:
- case SpvOpReturn:
- case SpvOpReturnValue:
- case SpvOpUnreachable:
- assert(b->block && b->block->branch == NULL);
- b->block->branch = w;
- b->block = NULL;
- break;
-
- default:
- /* Continue on as per normal */
- return true;
- }
-
- return true;
-}
-
-static void
-vtn_add_case(struct vtn_builder *b, struct vtn_switch *swtch,
- struct vtn_block *break_block,
- uint32_t block_id, uint32_t val, bool is_default)
-{
- struct vtn_block *case_block =
- vtn_value(b, block_id, vtn_value_type_block)->block;
-
- /* Don't create dummy cases that just break */
- if (case_block == break_block)
- return;
-
- if (case_block->switch_case == NULL) {
- struct vtn_case *c = ralloc(b, struct vtn_case);
-
- list_inithead(&c->body);
- c->start_block = case_block;
- c->fallthrough = NULL;
- nir_array_init(&c->values, b);
- c->is_default = false;
- c->visited = false;
-
- list_addtail(&c->link, &swtch->cases);
-
- case_block->switch_case = c;
- }
-
- if (is_default) {
- case_block->switch_case->is_default = true;
- } else {
- nir_array_add(&case_block->switch_case->values, uint32_t, val);
- }
-}
-
-/* This function performs a depth-first search of the cases and puts them
- * in fall-through order.
- */
-static void
-vtn_order_case(struct vtn_switch *swtch, struct vtn_case *cse)
-{
- if (cse->visited)
- return;
-
- cse->visited = true;
-
- list_del(&cse->link);
-
- if (cse->fallthrough) {
- vtn_order_case(swtch, cse->fallthrough);
-
- /* If we have a fall-through, place this case right before the case it
- * falls through to. This ensures that fallthroughs come one after
- * the other. These two can never get separated because that would
- * imply something else falling through to the same case. Also, this
- * can't break ordering because the DFS ensures that this case is
- * visited before anything that falls through to it.
- */
- list_addtail(&cse->link, &cse->fallthrough->link);
- } else {
- list_add(&cse->link, &swtch->cases);
- }
-}
-
-static enum vtn_branch_type
-vtn_get_branch_type(struct vtn_block *block,
- struct vtn_case *swcase, struct vtn_block *switch_break,
- struct vtn_block *loop_break, struct vtn_block *loop_cont)
-{
- if (block->switch_case) {
- /* This branch is actually a fallthrough */
- assert(swcase->fallthrough == NULL ||
- swcase->fallthrough == block->switch_case);
- swcase->fallthrough = block->switch_case;
- return vtn_branch_type_switch_fallthrough;
- } else if (block == switch_break) {
- return vtn_branch_type_switch_break;
- } else if (block == loop_break) {
- return vtn_branch_type_loop_break;
- } else if (block == loop_cont) {
- return vtn_branch_type_loop_continue;
- } else {
- return vtn_branch_type_none;
- }
-}
-
-static void
-vtn_cfg_walk_blocks(struct vtn_builder *b, struct list_head *cf_list,
- struct vtn_block *start, struct vtn_case *switch_case,
- struct vtn_block *switch_break,
- struct vtn_block *loop_break, struct vtn_block *loop_cont,
- struct vtn_block *end)
-{
- struct vtn_block *block = start;
- while (block != end) {
- if (block->merge && (*block->merge & SpvOpCodeMask) == SpvOpLoopMerge &&
- !block->loop) {
- struct vtn_loop *loop = ralloc(b, struct vtn_loop);
-
- loop->node.type = vtn_cf_node_type_loop;
- list_inithead(&loop->body);
- list_inithead(&loop->cont_body);
- loop->control = block->merge[3];
-
- list_addtail(&loop->node.link, cf_list);
- block->loop = loop;
-
- struct vtn_block *new_loop_break =
- vtn_value(b, block->merge[1], vtn_value_type_block)->block;
- struct vtn_block *new_loop_cont =
- vtn_value(b, block->merge[2], vtn_value_type_block)->block;
-
- /* Note: This recursive call will start with the current block as
- * its start block. If we weren't careful, we would get here
- * again and end up in infinite recursion. This is why we set
- * block->loop above and check for it before creating one. This
- * way, we only create the loop once and the second call that
- * tries to handle this loop goes to the cases below and gets
- * handled as a regular block.
- *
- * Note: When we make the recursive walk calls, we pass NULL for
- * the switch break since you have to break out of the loop first.
- * We do, however, still pass the current switch case because it's
- * possible that the merge block for the loop is the start of
- * another case.
- */
- vtn_cfg_walk_blocks(b, &loop->body, block, switch_case, NULL,
- new_loop_break, new_loop_cont, NULL );
- vtn_cfg_walk_blocks(b, &loop->cont_body, new_loop_cont, NULL, NULL,
- new_loop_break, NULL, block);
-
- block = new_loop_break;
- continue;
- }
-
- assert(block->node.link.next == NULL);
- list_addtail(&block->node.link, cf_list);
-
- switch (*block->branch & SpvOpCodeMask) {
- case SpvOpBranch: {
- struct vtn_block *branch_block =
- vtn_value(b, block->branch[1], vtn_value_type_block)->block;
-
- block->branch_type = vtn_get_branch_type(branch_block,
- switch_case, switch_break,
- loop_break, loop_cont);
-
- if (block->branch_type != vtn_branch_type_none)
- return;
-
- block = branch_block;
- continue;
- }
-
- case SpvOpReturn:
- case SpvOpReturnValue:
- block->branch_type = vtn_branch_type_return;
- return;
-
- case SpvOpKill:
- block->branch_type = vtn_branch_type_discard;
- return;
-
- case SpvOpBranchConditional: {
- struct vtn_block *then_block =
- vtn_value(b, block->branch[2], vtn_value_type_block)->block;
- struct vtn_block *else_block =
- vtn_value(b, block->branch[3], vtn_value_type_block)->block;
-
- struct vtn_if *if_stmt = ralloc(b, struct vtn_if);
-
- if_stmt->node.type = vtn_cf_node_type_if;
- if_stmt->condition = block->branch[1];
- list_inithead(&if_stmt->then_body);
- list_inithead(&if_stmt->else_body);
-
- list_addtail(&if_stmt->node.link, cf_list);
-
- if (block->merge &&
- (*block->merge & SpvOpCodeMask) == SpvOpSelectionMerge) {
- if_stmt->control = block->merge[2];
- }
-
- if_stmt->then_type = vtn_get_branch_type(then_block,
- switch_case, switch_break,
- loop_break, loop_cont);
- if_stmt->else_type = vtn_get_branch_type(else_block,
- switch_case, switch_break,
- loop_break, loop_cont);
-
- if (if_stmt->then_type == vtn_branch_type_none &&
- if_stmt->else_type == vtn_branch_type_none) {
- /* Neither side of the if is something we can short-circuit. */
- assert((*block->merge & SpvOpCodeMask) == SpvOpSelectionMerge);
- struct vtn_block *merge_block =
- vtn_value(b, block->merge[1], vtn_value_type_block)->block;
-
- vtn_cfg_walk_blocks(b, &if_stmt->then_body, then_block,
- switch_case, switch_break,
- loop_break, loop_cont, merge_block);
- vtn_cfg_walk_blocks(b, &if_stmt->else_body, else_block,
- switch_case, switch_break,
- loop_break, loop_cont, merge_block);
-
- enum vtn_branch_type merge_type =
- vtn_get_branch_type(merge_block, switch_case, switch_break,
- loop_break, loop_cont);
- if (merge_type == vtn_branch_type_none) {
- block = merge_block;
- continue;
- } else {
- return;
- }
- } else if (if_stmt->then_type != vtn_branch_type_none &&
- if_stmt->else_type != vtn_branch_type_none) {
- /* Both sides were short-circuited. We're done here. */
- return;
- } else {
- /* Exeactly one side of the branch could be short-circuited.
- * We set the branch up as a predicated break/continue and we
- * continue on with the other side as if it were what comes
- * after the if.
- */
- if (if_stmt->then_type == vtn_branch_type_none) {
- block = then_block;
- } else {
- block = else_block;
- }
- continue;
- }
- unreachable("Should have returned or continued");
- }
-
- case SpvOpSwitch: {
- assert((*block->merge & SpvOpCodeMask) == SpvOpSelectionMerge);
- struct vtn_block *break_block =
- vtn_value(b, block->merge[1], vtn_value_type_block)->block;
-
- struct vtn_switch *swtch = ralloc(b, struct vtn_switch);
-
- swtch->node.type = vtn_cf_node_type_switch;
- swtch->selector = block->branch[1];
- list_inithead(&swtch->cases);
-
- list_addtail(&swtch->node.link, cf_list);
-
- /* First, we go through and record all of the cases. */
- const uint32_t *branch_end =
- block->branch + (block->branch[0] >> SpvWordCountShift);
-
- vtn_add_case(b, swtch, break_block, block->branch[2], 0, true);
- for (const uint32_t *w = block->branch + 3; w < branch_end; w += 2)
- vtn_add_case(b, swtch, break_block, w[1], w[0], false);
-
- /* Now, we go through and walk the blocks. While we walk through
- * the blocks, we also gather the much-needed fall-through
- * information.
- */
- list_for_each_entry(struct vtn_case, cse, &swtch->cases, link) {
- assert(cse->start_block != break_block);
- vtn_cfg_walk_blocks(b, &cse->body, cse->start_block, cse,
- break_block, NULL, loop_cont, NULL);
- }
-
- /* Finally, we walk over all of the cases one more time and put
- * them in fall-through order.
- */
- for (const uint32_t *w = block->branch + 2; w < branch_end; w += 2) {
- struct vtn_block *case_block =
- vtn_value(b, *w, vtn_value_type_block)->block;
-
- if (case_block == break_block)
- continue;
-
- assert(case_block->switch_case);
-
- vtn_order_case(swtch, case_block->switch_case);
- }
-
- block = break_block;
- continue;
- }
-
- case SpvOpUnreachable:
- return;
-
- default:
- unreachable("Unhandled opcode");
- }
- }
-}
-
-void
-vtn_build_cfg(struct vtn_builder *b, const uint32_t *words, const uint32_t *end)
-{
- vtn_foreach_instruction(b, words, end,
- vtn_cfg_handle_prepass_instruction);
-
- foreach_list_typed(struct vtn_function, func, node, &b->functions) {
- vtn_cfg_walk_blocks(b, &func->body, func->start_block,
- NULL, NULL, NULL, NULL, NULL);
- }
-}
-
-static bool
-vtn_handle_phis_first_pass(struct vtn_builder *b, SpvOp opcode,
- const uint32_t *w, unsigned count)
-{
- if (opcode == SpvOpLabel)
- return true; /* Nothing to do */
-
- /* If this isn't a phi node, stop. */
- if (opcode != SpvOpPhi)
- return false;
-
- /* For handling phi nodes, we do a poor-man's out-of-ssa on the spot.
- * For each phi, we create a variable with the appropreate type and
- * do a load from that variable. Then, in a second pass, we add
- * stores to that variable to each of the predecessor blocks.
- *
- * We could do something more intelligent here. However, in order to
- * handle loops and things properly, we really need dominance
- * information. It would end up basically being the into-SSA
- * algorithm all over again. It's easier if we just let
- * lower_vars_to_ssa do that for us instead of repeating it here.
- */
- struct vtn_value *val = vtn_push_value(b, w[2], vtn_value_type_ssa);
-
- struct vtn_type *type = vtn_value(b, w[1], vtn_value_type_type)->type;
- nir_variable *phi_var =
- nir_local_variable_create(b->nb.impl, type->type, "phi");
- _mesa_hash_table_insert(b->phi_table, w, phi_var);
-
- val->ssa = vtn_local_load(b, nir_deref_var_create(b, phi_var));
-
- return true;
-}
-
-static bool
-vtn_handle_phi_second_pass(struct vtn_builder *b, SpvOp opcode,
- const uint32_t *w, unsigned count)
-{
- if (opcode != SpvOpPhi)
- return true;
-
- struct hash_entry *phi_entry = _mesa_hash_table_search(b->phi_table, w);
- assert(phi_entry);
- nir_variable *phi_var = phi_entry->data;
-
- for (unsigned i = 3; i < count; i += 2) {
- struct vtn_ssa_value *src = vtn_ssa_value(b, w[i]);
- struct vtn_block *pred =
- vtn_value(b, w[i + 1], vtn_value_type_block)->block;
-
- b->nb.cursor = nir_after_block_before_jump(pred->end_block);
-
- vtn_local_store(b, src, nir_deref_var_create(b, phi_var));
- }
-
- return true;
-}
-
-static void
-vtn_emit_branch(struct vtn_builder *b, enum vtn_branch_type branch_type,
- nir_variable *switch_fall_var, bool *has_switch_break)
-{
- switch (branch_type) {
- case vtn_branch_type_switch_break:
- nir_store_var(&b->nb, switch_fall_var, nir_imm_int(&b->nb, NIR_FALSE), 1);
- *has_switch_break = true;
- break;
- case vtn_branch_type_switch_fallthrough:
- break; /* Nothing to do */
- case vtn_branch_type_loop_break:
- nir_jump(&b->nb, nir_jump_break);
- break;
- case vtn_branch_type_loop_continue:
- nir_jump(&b->nb, nir_jump_continue);
- break;
- case vtn_branch_type_return:
- nir_jump(&b->nb, nir_jump_return);
- break;
- case vtn_branch_type_discard: {
- nir_intrinsic_instr *discard =
- nir_intrinsic_instr_create(b->nb.shader, nir_intrinsic_discard);
- nir_builder_instr_insert(&b->nb, &discard->instr);
- break;
- }
- default:
- unreachable("Invalid branch type");
- }
-}
-
-static void
-vtn_emit_cf_list(struct vtn_builder *b, struct list_head *cf_list,
- nir_variable *switch_fall_var, bool *has_switch_break,
- vtn_instruction_handler handler)
-{
- list_for_each_entry(struct vtn_cf_node, node, cf_list, link) {
- switch (node->type) {
- case vtn_cf_node_type_block: {
- struct vtn_block *block = (struct vtn_block *)node;
-
- const uint32_t *block_start = block->label;
- const uint32_t *block_end = block->merge ? block->merge :
- block->branch;
-
- block_start = vtn_foreach_instruction(b, block_start, block_end,
- vtn_handle_phis_first_pass);
-
- vtn_foreach_instruction(b, block_start, block_end, handler);
-
- block->end_block = nir_cursor_current_block(b->nb.cursor);
-
- if ((*block->branch & SpvOpCodeMask) == SpvOpReturnValue) {
- struct vtn_ssa_value *src = vtn_ssa_value(b, block->branch[1]);
- vtn_local_store(b, src,
- nir_deref_var_create(b, b->impl->return_var));
- }
-
- if (block->branch_type != vtn_branch_type_none) {
- vtn_emit_branch(b, block->branch_type,
- switch_fall_var, has_switch_break);
- }
-
- break;
- }
-
- case vtn_cf_node_type_if: {
- struct vtn_if *vtn_if = (struct vtn_if *)node;
-
- nir_if *if_stmt = nir_if_create(b->shader);
- if_stmt->condition =
- nir_src_for_ssa(vtn_ssa_value(b, vtn_if->condition)->def);
- nir_cf_node_insert(b->nb.cursor, &if_stmt->cf_node);
-
- bool sw_break = false;
-
- b->nb.cursor = nir_after_cf_list(&if_stmt->then_list);
- if (vtn_if->then_type == vtn_branch_type_none) {
- vtn_emit_cf_list(b, &vtn_if->then_body,
- switch_fall_var, &sw_break, handler);
- } else {
- vtn_emit_branch(b, vtn_if->then_type, switch_fall_var, &sw_break);
- }
-
- b->nb.cursor = nir_after_cf_list(&if_stmt->else_list);
- if (vtn_if->else_type == vtn_branch_type_none) {
- vtn_emit_cf_list(b, &vtn_if->else_body,
- switch_fall_var, &sw_break, handler);
- } else {
- vtn_emit_branch(b, vtn_if->else_type, switch_fall_var, &sw_break);
- }
-
- b->nb.cursor = nir_after_cf_node(&if_stmt->cf_node);
-
- /* If we encountered a switch break somewhere inside of the if,
- * then it would have been handled correctly by calling
- * emit_cf_list or emit_branch for the interrior. However, we
- * need to predicate everything following on wether or not we're
- * still going.
- */
- if (sw_break) {
- *has_switch_break = true;
-
- nir_if *switch_if = nir_if_create(b->shader);
- switch_if->condition =
- nir_src_for_ssa(nir_load_var(&b->nb, switch_fall_var));
- nir_cf_node_insert(b->nb.cursor, &switch_if->cf_node);
-
- b->nb.cursor = nir_after_cf_list(&if_stmt->then_list);
- }
- break;
- }
-
- case vtn_cf_node_type_loop: {
- struct vtn_loop *vtn_loop = (struct vtn_loop *)node;
-
- nir_loop *loop = nir_loop_create(b->shader);
- nir_cf_node_insert(b->nb.cursor, &loop->cf_node);
-
- b->nb.cursor = nir_after_cf_list(&loop->body);
- vtn_emit_cf_list(b, &vtn_loop->body, NULL, NULL, handler);
-
- if (!list_empty(&vtn_loop->cont_body)) {
- /* If we have a non-trivial continue body then we need to put
- * it at the beginning of the loop with a flag to ensure that
- * it doesn't get executed in the first iteration.
- */
- nir_variable *do_cont =
- nir_local_variable_create(b->nb.impl, glsl_bool_type(), "cont");
-
- b->nb.cursor = nir_before_cf_node(&loop->cf_node);
- nir_store_var(&b->nb, do_cont, nir_imm_int(&b->nb, NIR_FALSE), 1);
-
- b->nb.cursor = nir_before_cf_list(&loop->body);
- nir_if *cont_if = nir_if_create(b->shader);
- cont_if->condition = nir_src_for_ssa(nir_load_var(&b->nb, do_cont));
- nir_cf_node_insert(b->nb.cursor, &cont_if->cf_node);
-
- b->nb.cursor = nir_after_cf_list(&cont_if->then_list);
- vtn_emit_cf_list(b, &vtn_loop->cont_body, NULL, NULL, handler);
-
- b->nb.cursor = nir_after_cf_node(&cont_if->cf_node);
- nir_store_var(&b->nb, do_cont, nir_imm_int(&b->nb, NIR_TRUE), 1);
-
- b->has_loop_continue = true;
- }
-
- b->nb.cursor = nir_after_cf_node(&loop->cf_node);
- break;
- }
-
- case vtn_cf_node_type_switch: {
- struct vtn_switch *vtn_switch = (struct vtn_switch *)node;
-
- /* First, we create a variable to keep track of whether or not the
- * switch is still going at any given point. Any switch breaks
- * will set this variable to false.
- */
- nir_variable *fall_var =
- nir_local_variable_create(b->nb.impl, glsl_bool_type(), "fall");
- nir_store_var(&b->nb, fall_var, nir_imm_int(&b->nb, NIR_FALSE), 1);
-
- /* Next, we gather up all of the conditions. We have to do this
- * up-front because we also need to build an "any" condition so
- * that we can use !any for default.
- */
- const int num_cases = list_length(&vtn_switch->cases);
- NIR_VLA(nir_ssa_def *, conditions, num_cases);
-
- nir_ssa_def *sel = vtn_ssa_value(b, vtn_switch->selector)->def;
- /* An accumulation of all conditions. Used for the default */
- nir_ssa_def *any = NULL;
-
- int i = 0;
- list_for_each_entry(struct vtn_case, cse, &vtn_switch->cases, link) {
- if (cse->is_default) {
- conditions[i++] = NULL;
- continue;
- }
-
- nir_ssa_def *cond = NULL;
- nir_array_foreach(&cse->values, uint32_t, val) {
- nir_ssa_def *is_val =
- nir_ieq(&b->nb, sel, nir_imm_int(&b->nb, *val));
-
- cond = cond ? nir_ior(&b->nb, cond, is_val) : is_val;
- }
-
- any = any ? nir_ior(&b->nb, any, cond) : cond;
- conditions[i++] = cond;
- }
- assert(i == num_cases);
-
- /* Now we can walk the list of cases and actually emit code */
- i = 0;
- list_for_each_entry(struct vtn_case, cse, &vtn_switch->cases, link) {
- /* Figure out the condition */
- nir_ssa_def *cond = conditions[i++];
- if (cse->is_default) {
- assert(cond == NULL);
- cond = nir_inot(&b->nb, any);
- }
- /* Take fallthrough into account */
- cond = nir_ior(&b->nb, cond, nir_load_var(&b->nb, fall_var));
-
- nir_if *case_if = nir_if_create(b->nb.shader);
- case_if->condition = nir_src_for_ssa(cond);
- nir_cf_node_insert(b->nb.cursor, &case_if->cf_node);
-
- bool has_break = false;
- b->nb.cursor = nir_after_cf_list(&case_if->then_list);
- nir_store_var(&b->nb, fall_var, nir_imm_int(&b->nb, NIR_TRUE), 1);
- vtn_emit_cf_list(b, &cse->body, fall_var, &has_break, handler);
- (void)has_break; /* We don't care */
-
- b->nb.cursor = nir_after_cf_node(&case_if->cf_node);
- }
- assert(i == num_cases);
-
- break;
- }
-
- default:
- unreachable("Invalid CF node type");
- }
- }
-}
-
-void
-vtn_function_emit(struct vtn_builder *b, struct vtn_function *func,
- vtn_instruction_handler instruction_handler)
-{
- nir_builder_init(&b->nb, func->impl);
- b->nb.cursor = nir_after_cf_list(&func->impl->body);
- b->has_loop_continue = false;
- b->phi_table = _mesa_hash_table_create(b, _mesa_hash_pointer,
- _mesa_key_pointer_equal);
-
- vtn_emit_cf_list(b, &func->body, NULL, NULL, instruction_handler);
-
- vtn_foreach_instruction(b, func->start_block->label, func->end,
- vtn_handle_phi_second_pass);
-
- /* Continue blocks for loops get inserted before the body of the loop
- * but instructions in the continue may use SSA defs in the loop body.
- * Therefore, we need to repair SSA to insert the needed phi nodes.
- */
- if (b->has_loop_continue)
- nir_repair_ssa_impl(func->impl);
-}
diff --git a/src/glsl/nir/spirv/vtn_glsl450.c b/src/glsl/nir/spirv/vtn_glsl450.c
deleted file mode 100644
index bc38aa4b1be..00000000000
--- a/src/glsl/nir/spirv/vtn_glsl450.c
+++ /dev/null
@@ -1,684 +0,0 @@
-/*
- * Copyright © 2015 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- *
- * Authors:
- * Jason Ekstrand ([email protected])
- *
- */
-
-#include "vtn_private.h"
-#include "GLSL.std.450.h"
-
-#define M_PIf ((float) M_PI)
-#define M_PI_2f ((float) M_PI_2)
-#define M_PI_4f ((float) M_PI_4)
-
-static nir_ssa_def *
-build_mat2_det(nir_builder *b, nir_ssa_def *col[2])
-{
- unsigned swiz[4] = {1, 0, 0, 0};
- nir_ssa_def *p = nir_fmul(b, col[0], nir_swizzle(b, col[1], swiz, 2, true));
- return nir_fsub(b, nir_channel(b, p, 0), nir_channel(b, p, 1));
-}
-
-static nir_ssa_def *
-build_mat3_det(nir_builder *b, nir_ssa_def *col[3])
-{
- unsigned yzx[4] = {1, 2, 0, 0};
- unsigned zxy[4] = {2, 0, 1, 0};
-
- nir_ssa_def *prod0 =
- nir_fmul(b, col[0],
- nir_fmul(b, nir_swizzle(b, col[1], yzx, 3, true),
- nir_swizzle(b, col[2], zxy, 3, true)));
- nir_ssa_def *prod1 =
- nir_fmul(b, col[0],
- nir_fmul(b, nir_swizzle(b, col[1], zxy, 3, true),
- nir_swizzle(b, col[2], yzx, 3, true)));
-
- nir_ssa_def *diff = nir_fsub(b, prod0, prod1);
-
- return nir_fadd(b, nir_channel(b, diff, 0),
- nir_fadd(b, nir_channel(b, diff, 1),
- nir_channel(b, diff, 2)));
-}
-
-static nir_ssa_def *
-build_mat4_det(nir_builder *b, nir_ssa_def **col)
-{
- nir_ssa_def *subdet[4];
- for (unsigned i = 0; i < 4; i++) {
- unsigned swiz[3];
- for (unsigned j = 0, k = 0; j < 3; j++, k++) {
- if (k == i)
- k++; /* skip column */
- swiz[j] = k;
- }
-
- nir_ssa_def *subcol[3];
- subcol[0] = nir_swizzle(b, col[1], swiz, 3, true);
- subcol[1] = nir_swizzle(b, col[2], swiz, 3, true);
- subcol[2] = nir_swizzle(b, col[3], swiz, 3, true);
-
- subdet[i] = build_mat3_det(b, subcol);
- }
-
- nir_ssa_def *prod = nir_fmul(b, col[0], nir_vec(b, subdet, 4));
-
- return nir_fadd(b, nir_fsub(b, nir_channel(b, prod, 0),
- nir_channel(b, prod, 1)),
- nir_fsub(b, nir_channel(b, prod, 2),
- nir_channel(b, prod, 3)));
-}
-
-static nir_ssa_def *
-build_mat_det(struct vtn_builder *b, struct vtn_ssa_value *src)
-{
- unsigned size = glsl_get_vector_elements(src->type);
-
- nir_ssa_def *cols[4];
- for (unsigned i = 0; i < size; i++)
- cols[i] = src->elems[i]->def;
-
- switch(size) {
- case 2: return build_mat2_det(&b->nb, cols);
- case 3: return build_mat3_det(&b->nb, cols);
- case 4: return build_mat4_det(&b->nb, cols);
- default:
- unreachable("Invalid matrix size");
- }
-}
-
-/* Computes the determinate of the submatrix given by taking src and
- * removing the specified row and column.
- */
-static nir_ssa_def *
-build_mat_subdet(struct nir_builder *b, struct vtn_ssa_value *src,
- unsigned size, unsigned row, unsigned col)
-{
- assert(row < size && col < size);
- if (size == 2) {
- return nir_channel(b, src->elems[1 - col]->def, 1 - row);
- } else {
- /* Swizzle to get all but the specified row */
- unsigned swiz[3];
- for (unsigned j = 0; j < 4; j++)
- swiz[j - (j > row)] = j;
-
- /* Grab all but the specified column */
- nir_ssa_def *subcol[3];
- for (unsigned j = 0; j < size; j++) {
- if (j != col) {
- subcol[j - (j > col)] = nir_swizzle(b, src->elems[j]->def,
- swiz, size - 1, true);
- }
- }
-
- if (size == 3) {
- return build_mat2_det(b, subcol);
- } else {
- assert(size == 4);
- return build_mat3_det(b, subcol);
- }
- }
-}
-
-static struct vtn_ssa_value *
-matrix_inverse(struct vtn_builder *b, struct vtn_ssa_value *src)
-{
- nir_ssa_def *adj_col[4];
- unsigned size = glsl_get_vector_elements(src->type);
-
- /* Build up an adjugate matrix */
- for (unsigned c = 0; c < size; c++) {
- nir_ssa_def *elem[4];
- for (unsigned r = 0; r < size; r++) {
- elem[r] = build_mat_subdet(&b->nb, src, size, c, r);
-
- if ((r + c) % 2)
- elem[r] = nir_fneg(&b->nb, elem[r]);
- }
-
- adj_col[c] = nir_vec(&b->nb, elem, size);
- }
-
- nir_ssa_def *det_inv = nir_frcp(&b->nb, build_mat_det(b, src));
-
- struct vtn_ssa_value *val = vtn_create_ssa_value(b, src->type);
- for (unsigned i = 0; i < size; i++)
- val->elems[i]->def = nir_fmul(&b->nb, adj_col[i], det_inv);
-
- return val;
-}
-
-static nir_ssa_def*
-build_length(nir_builder *b, nir_ssa_def *vec)
-{
- switch (vec->num_components) {
- case 1: return nir_fsqrt(b, nir_fmul(b, vec, vec));
- case 2: return nir_fsqrt(b, nir_fdot2(b, vec, vec));
- case 3: return nir_fsqrt(b, nir_fdot3(b, vec, vec));
- case 4: return nir_fsqrt(b, nir_fdot4(b, vec, vec));
- default:
- unreachable("Invalid number of components");
- }
-}
-
-static inline nir_ssa_def *
-build_fclamp(nir_builder *b,
- nir_ssa_def *x, nir_ssa_def *min_val, nir_ssa_def *max_val)
-{
- return nir_fmin(b, nir_fmax(b, x, min_val), max_val);
-}
-
-/**
- * Return e^x.
- */
-static nir_ssa_def *
-build_exp(nir_builder *b, nir_ssa_def *x)
-{
- return nir_fexp2(b, nir_fmul(b, x, nir_imm_float(b, M_LOG2E)));
-}
-
-/**
- * Return ln(x) - the natural logarithm of x.
- */
-static nir_ssa_def *
-build_log(nir_builder *b, nir_ssa_def *x)
-{
- return nir_fmul(b, nir_flog2(b, x), nir_imm_float(b, 1.0 / M_LOG2E));
-}
-
-static nir_ssa_def *
-build_asin(nir_builder *b, nir_ssa_def *x)
-{
- /*
- * asin(x) = sign(x) * (pi/2 - sqrt(1 - |x|) * (pi / 4 - 1 + |x| * (0.086566724 + |x| * -0.03102955)))
- */
- nir_ssa_def *abs_x = nir_fabs(b, x);
- return nir_fmul(b, nir_fsign(b, x),
- nir_fsub(b, nir_imm_float(b, M_PI_2f),
- nir_fmul(b, nir_fsqrt(b, nir_fsub(b, nir_imm_float(b, 1.0f), abs_x)),
- nir_fadd(b, nir_imm_float(b, M_PI_2f),
- nir_fmul(b, abs_x,
- nir_fadd(b, nir_imm_float(b, M_PI_4f - 1.0f),
- nir_fmul(b, abs_x,
- nir_fadd(b, nir_imm_float(b, 0.086566724f),
- nir_fmul(b, abs_x,
- nir_imm_float(b, -0.03102955f))))))))));
-}
-
-static nir_ssa_def *
-build_acos(nir_builder *b, nir_ssa_def *x)
-{
- /*
- * poly(x) = sign(x) * sqrt(1 - |x|) * (pi / 2 + |x| * (pi / 4 - 1 + |x| * (0.08132463 + |x| * -0.02363318)))
- */
- nir_ssa_def *abs_x = nir_fabs(b, x);
- nir_ssa_def *poly = nir_fmul(b, nir_fsqrt(b, nir_fsub(b, nir_imm_float(b, 1.0f), abs_x)),
- nir_fadd(b, nir_imm_float(b, M_PI_2f),
- nir_fmul(b, abs_x,
- nir_fadd(b, nir_imm_float(b, M_PI_4f - 1.0f),
- nir_fmul(b, abs_x,
- nir_fadd(b, nir_imm_float(b, 0.08132463f),
- nir_fmul(b, abs_x,
- nir_imm_float(b, -0.02363318f))))))));
- return nir_bcsel(b, nir_flt(b, x, nir_imm_float(b, 0)),
- nir_fsub(b, nir_imm_float(b, M_PI), poly),
- poly);
-}
-
-/**
- * Compute xs[0] + xs[1] + xs[2] + ... using fadd.
- */
-static nir_ssa_def *
-build_fsum(nir_builder *b, nir_ssa_def **xs, int terms)
-{
- nir_ssa_def *accum = xs[0];
-
- for (int i = 1; i < terms; i++)
- accum = nir_fadd(b, accum, xs[i]);
-
- return accum;
-}
-
-static nir_ssa_def *
-build_atan(nir_builder *b, nir_ssa_def *y_over_x)
-{
- nir_ssa_def *abs_y_over_x = nir_fabs(b, y_over_x);
- nir_ssa_def *one = nir_imm_float(b, 1.0f);
-
- /*
- * range-reduction, first step:
- *
- * / y_over_x if |y_over_x| <= 1.0;
- * x = <
- * \ 1.0 / y_over_x otherwise
- */
- nir_ssa_def *x = nir_fdiv(b, nir_fmin(b, abs_y_over_x, one),
- nir_fmax(b, abs_y_over_x, one));
-
- /*
- * approximate atan by evaluating polynomial:
- *
- * x * 0.9999793128310355 - x^3 * 0.3326756418091246 +
- * x^5 * 0.1938924977115610 - x^7 * 0.1173503194786851 +
- * x^9 * 0.0536813784310406 - x^11 * 0.0121323213173444
- */
- nir_ssa_def *x_2 = nir_fmul(b, x, x);
- nir_ssa_def *x_3 = nir_fmul(b, x_2, x);
- nir_ssa_def *x_5 = nir_fmul(b, x_3, x_2);
- nir_ssa_def *x_7 = nir_fmul(b, x_5, x_2);
- nir_ssa_def *x_9 = nir_fmul(b, x_7, x_2);
- nir_ssa_def *x_11 = nir_fmul(b, x_9, x_2);
-
- nir_ssa_def *polynomial_terms[] = {
- nir_fmul(b, x, nir_imm_float(b, 0.9999793128310355f)),
- nir_fmul(b, x_3, nir_imm_float(b, -0.3326756418091246f)),
- nir_fmul(b, x_5, nir_imm_float(b, 0.1938924977115610f)),
- nir_fmul(b, x_7, nir_imm_float(b, -0.1173503194786851f)),
- nir_fmul(b, x_9, nir_imm_float(b, 0.0536813784310406f)),
- nir_fmul(b, x_11, nir_imm_float(b, -0.0121323213173444f)),
- };
-
- nir_ssa_def *tmp =
- build_fsum(b, polynomial_terms, ARRAY_SIZE(polynomial_terms));
-
- /* range-reduction fixup */
- tmp = nir_fadd(b, tmp,
- nir_fmul(b,
- nir_b2f(b, nir_flt(b, one, abs_y_over_x)),
- nir_fadd(b, nir_fmul(b, tmp,
- nir_imm_float(b, -2.0f)),
- nir_imm_float(b, M_PI_2f))));
-
- /* sign fixup */
- return nir_fmul(b, tmp, nir_fsign(b, y_over_x));
-}
-
-static nir_ssa_def *
-build_atan2(nir_builder *b, nir_ssa_def *y, nir_ssa_def *x)
-{
- nir_ssa_def *zero = nir_imm_float(b, 0.0f);
-
- /* If |x| >= 1.0e-8 * |y|: */
- nir_ssa_def *condition =
- nir_fge(b, nir_fabs(b, x),
- nir_fmul(b, nir_imm_float(b, 1.0e-8f), nir_fabs(b, y)));
-
- /* Then...call atan(y/x) and fix it up: */
- nir_ssa_def *atan1 = build_atan(b, nir_fdiv(b, y, x));
- nir_ssa_def *r_then =
- nir_bcsel(b, nir_flt(b, x, zero),
- nir_fadd(b, atan1,
- nir_bcsel(b, nir_fge(b, y, zero),
- nir_imm_float(b, M_PIf),
- nir_imm_float(b, -M_PIf))),
- atan1);
-
- /* Else... */
- nir_ssa_def *r_else =
- nir_fmul(b, nir_fsign(b, y), nir_imm_float(b, M_PI_2f));
-
- return nir_bcsel(b, condition, r_then, r_else);
-}
-
-static nir_ssa_def *
-build_frexp(nir_builder *b, nir_ssa_def *x, nir_ssa_def **exponent)
-{
- nir_ssa_def *abs_x = nir_fabs(b, x);
- nir_ssa_def *zero = nir_imm_float(b, 0.0f);
-
- /* Single-precision floating-point values are stored as
- * 1 sign bit;
- * 8 exponent bits;
- * 23 mantissa bits.
- *
- * An exponent shift of 23 will shift the mantissa out, leaving only the
- * exponent and sign bit (which itself may be zero, if the absolute value
- * was taken before the bitcast and shift.
- */
- nir_ssa_def *exponent_shift = nir_imm_int(b, 23);
- nir_ssa_def *exponent_bias = nir_imm_int(b, -126);
-
- nir_ssa_def *sign_mantissa_mask = nir_imm_int(b, 0x807fffffu);
-
- /* Exponent of floating-point values in the range [0.5, 1.0). */
- nir_ssa_def *exponent_value = nir_imm_int(b, 0x3f000000u);
-
- nir_ssa_def *is_not_zero = nir_fne(b, abs_x, zero);
-
- *exponent =
- nir_iadd(b, nir_ushr(b, abs_x, exponent_shift),
- nir_bcsel(b, is_not_zero, exponent_bias, zero));
-
- return nir_ior(b, nir_iand(b, x, sign_mantissa_mask),
- nir_bcsel(b, is_not_zero, exponent_value, zero));
-}
-
-static void
-handle_glsl450_alu(struct vtn_builder *b, enum GLSLstd450 entrypoint,
- const uint32_t *w, unsigned count)
-{
- struct nir_builder *nb = &b->nb;
- const struct glsl_type *dest_type =
- vtn_value(b, w[1], vtn_value_type_type)->type->type;
-
- struct vtn_value *val = vtn_push_value(b, w[2], vtn_value_type_ssa);
- val->ssa = vtn_create_ssa_value(b, dest_type);
-
- /* Collect the various SSA sources */
- unsigned num_inputs = count - 5;
- nir_ssa_def *src[3];
- for (unsigned i = 0; i < num_inputs; i++)
- src[i] = vtn_ssa_value(b, w[i + 5])->def;
-
- nir_op op;
- switch (entrypoint) {
- case GLSLstd450Round: op = nir_op_fround_even; break; /* TODO */
- case GLSLstd450RoundEven: op = nir_op_fround_even; break;
- case GLSLstd450Trunc: op = nir_op_ftrunc; break;
- case GLSLstd450FAbs: op = nir_op_fabs; break;
- case GLSLstd450SAbs: op = nir_op_iabs; break;
- case GLSLstd450FSign: op = nir_op_fsign; break;
- case GLSLstd450SSign: op = nir_op_isign; break;
- case GLSLstd450Floor: op = nir_op_ffloor; break;
- case GLSLstd450Ceil: op = nir_op_fceil; break;
- case GLSLstd450Fract: op = nir_op_ffract; break;
- case GLSLstd450Radians:
- val->ssa->def = nir_fmul(nb, src[0], nir_imm_float(nb, 0.01745329251));
- return;
- case GLSLstd450Degrees:
- val->ssa->def = nir_fmul(nb, src[0], nir_imm_float(nb, 57.2957795131));
- return;
- case GLSLstd450Sin: op = nir_op_fsin; break;
- case GLSLstd450Cos: op = nir_op_fcos; break;
- case GLSLstd450Tan:
- val->ssa->def = nir_fdiv(nb, nir_fsin(nb, src[0]),
- nir_fcos(nb, src[0]));
- return;
- case GLSLstd450Pow: op = nir_op_fpow; break;
- case GLSLstd450Exp2: op = nir_op_fexp2; break;
- case GLSLstd450Log2: op = nir_op_flog2; break;
- case GLSLstd450Sqrt: op = nir_op_fsqrt; break;
- case GLSLstd450InverseSqrt: op = nir_op_frsq; break;
-
- case GLSLstd450Modf: {
- nir_ssa_def *sign = nir_fsign(nb, src[0]);
- nir_ssa_def *abs = nir_fabs(nb, src[0]);
- val->ssa->def = nir_fmul(nb, sign, nir_ffract(nb, abs));
- nir_store_deref_var(nb, vtn_nir_deref(b, w[6]),
- nir_fmul(nb, sign, nir_ffloor(nb, abs)), 0xf);
- return;
- }
-
- case GLSLstd450ModfStruct: {
- nir_ssa_def *sign = nir_fsign(nb, src[0]);
- nir_ssa_def *abs = nir_fabs(nb, src[0]);
- assert(glsl_type_is_struct(val->ssa->type));
- val->ssa->elems[0]->def = nir_fmul(nb, sign, nir_ffract(nb, abs));
- val->ssa->elems[1]->def = nir_fmul(nb, sign, nir_ffloor(nb, abs));
- return;
- }
-
- case GLSLstd450FMin: op = nir_op_fmin; break;
- case GLSLstd450UMin: op = nir_op_umin; break;
- case GLSLstd450SMin: op = nir_op_imin; break;
- case GLSLstd450FMax: op = nir_op_fmax; break;
- case GLSLstd450UMax: op = nir_op_umax; break;
- case GLSLstd450SMax: op = nir_op_imax; break;
- case GLSLstd450FMix: op = nir_op_flrp; break;
- case GLSLstd450Step:
- val->ssa->def = nir_sge(nb, src[1], src[0]);
- return;
-
- case GLSLstd450Fma: op = nir_op_ffma; break;
- case GLSLstd450Ldexp: op = nir_op_ldexp; break;
-
- /* Packing/Unpacking functions */
- case GLSLstd450PackSnorm4x8: op = nir_op_pack_snorm_4x8; break;
- case GLSLstd450PackUnorm4x8: op = nir_op_pack_unorm_4x8; break;
- case GLSLstd450PackSnorm2x16: op = nir_op_pack_snorm_2x16; break;
- case GLSLstd450PackUnorm2x16: op = nir_op_pack_unorm_2x16; break;
- case GLSLstd450PackHalf2x16: op = nir_op_pack_half_2x16; break;
- case GLSLstd450UnpackSnorm4x8: op = nir_op_unpack_snorm_4x8; break;
- case GLSLstd450UnpackUnorm4x8: op = nir_op_unpack_unorm_4x8; break;
- case GLSLstd450UnpackSnorm2x16: op = nir_op_unpack_snorm_2x16; break;
- case GLSLstd450UnpackUnorm2x16: op = nir_op_unpack_unorm_2x16; break;
- case GLSLstd450UnpackHalf2x16: op = nir_op_unpack_half_2x16; break;
-
- case GLSLstd450Length:
- val->ssa->def = build_length(nb, src[0]);
- return;
- case GLSLstd450Distance:
- val->ssa->def = build_length(nb, nir_fsub(nb, src[0], src[1]));
- return;
- case GLSLstd450Normalize:
- val->ssa->def = nir_fdiv(nb, src[0], build_length(nb, src[0]));
- return;
-
- case GLSLstd450Exp:
- val->ssa->def = build_exp(nb, src[0]);
- return;
-
- case GLSLstd450Log:
- val->ssa->def = build_log(nb, src[0]);
- return;
-
- case GLSLstd450FClamp:
- val->ssa->def = build_fclamp(nb, src[0], src[1], src[2]);
- return;
- case GLSLstd450UClamp:
- val->ssa->def = nir_umin(nb, nir_umax(nb, src[0], src[1]), src[2]);
- return;
- case GLSLstd450SClamp:
- val->ssa->def = nir_imin(nb, nir_imax(nb, src[0], src[1]), src[2]);
- return;
-
- case GLSLstd450Cross: {
- unsigned yzx[4] = { 1, 2, 0, 0 };
- unsigned zxy[4] = { 2, 0, 1, 0 };
- val->ssa->def =
- nir_fsub(nb, nir_fmul(nb, nir_swizzle(nb, src[0], yzx, 3, true),
- nir_swizzle(nb, src[1], zxy, 3, true)),
- nir_fmul(nb, nir_swizzle(nb, src[0], zxy, 3, true),
- nir_swizzle(nb, src[1], yzx, 3, true)));
- return;
- }
-
- case GLSLstd450SmoothStep: {
- /* t = clamp((x - edge0) / (edge1 - edge0), 0, 1) */
- nir_ssa_def *t =
- build_fclamp(nb, nir_fdiv(nb, nir_fsub(nb, src[2], src[0]),
- nir_fsub(nb, src[1], src[0])),
- nir_imm_float(nb, 0.0), nir_imm_float(nb, 1.0));
- /* result = t * t * (3 - 2 * t) */
- val->ssa->def =
- nir_fmul(nb, t, nir_fmul(nb, t,
- nir_fsub(nb, nir_imm_float(nb, 3.0),
- nir_fmul(nb, nir_imm_float(nb, 2.0), t))));
- return;
- }
-
- case GLSLstd450FaceForward:
- val->ssa->def =
- nir_bcsel(nb, nir_flt(nb, nir_fdot(nb, src[2], src[1]),
- nir_imm_float(nb, 0.0)),
- src[0], nir_fneg(nb, src[0]));
- return;
-
- case GLSLstd450Reflect:
- /* I - 2 * dot(N, I) * N */
- val->ssa->def =
- nir_fsub(nb, src[0], nir_fmul(nb, nir_imm_float(nb, 2.0),
- nir_fmul(nb, nir_fdot(nb, src[0], src[1]),
- src[1])));
- return;
-
- case GLSLstd450Refract: {
- nir_ssa_def *I = src[0];
- nir_ssa_def *N = src[1];
- nir_ssa_def *eta = src[2];
- nir_ssa_def *n_dot_i = nir_fdot(nb, N, I);
- nir_ssa_def *one = nir_imm_float(nb, 1.0);
- nir_ssa_def *zero = nir_imm_float(nb, 0.0);
- /* k = 1.0 - eta * eta * (1.0 - dot(N, I) * dot(N, I)) */
- nir_ssa_def *k =
- nir_fsub(nb, one, nir_fmul(nb, eta, nir_fmul(nb, eta,
- nir_fsub(nb, one, nir_fmul(nb, n_dot_i, n_dot_i)))));
- nir_ssa_def *result =
- nir_fsub(nb, nir_fmul(nb, eta, I),
- nir_fmul(nb, nir_fadd(nb, nir_fmul(nb, eta, n_dot_i),
- nir_fsqrt(nb, k)), N));
- /* XXX: bcsel, or if statement? */
- val->ssa->def = nir_bcsel(nb, nir_flt(nb, k, zero), zero, result);
- return;
- }
-
- case GLSLstd450Sinh:
- /* 0.5 * (e^x - e^(-x)) */
- val->ssa->def =
- nir_fmul(nb, nir_imm_float(nb, 0.5f),
- nir_fsub(nb, build_exp(nb, src[0]),
- build_exp(nb, nir_fneg(nb, src[0]))));
- return;
-
- case GLSLstd450Cosh:
- /* 0.5 * (e^x + e^(-x)) */
- val->ssa->def =
- nir_fmul(nb, nir_imm_float(nb, 0.5f),
- nir_fadd(nb, build_exp(nb, src[0]),
- build_exp(nb, nir_fneg(nb, src[0]))));
- return;
-
- case GLSLstd450Tanh:
- /* (0.5 * (e^x - e^(-x))) / (0.5 * (e^x + e^(-x))) */
- val->ssa->def =
- nir_fdiv(nb, nir_fmul(nb, nir_imm_float(nb, 0.5f),
- nir_fsub(nb, build_exp(nb, src[0]),
- build_exp(nb, nir_fneg(nb, src[0])))),
- nir_fmul(nb, nir_imm_float(nb, 0.5f),
- nir_fadd(nb, build_exp(nb, src[0]),
- build_exp(nb, nir_fneg(nb, src[0])))));
- return;
-
- case GLSLstd450Asinh:
- val->ssa->def = nir_fmul(nb, nir_fsign(nb, src[0]),
- build_log(nb, nir_fadd(nb, nir_fabs(nb, src[0]),
- nir_fsqrt(nb, nir_fadd(nb, nir_fmul(nb, src[0], src[0]),
- nir_imm_float(nb, 1.0f))))));
- return;
- case GLSLstd450Acosh:
- val->ssa->def = build_log(nb, nir_fadd(nb, src[0],
- nir_fsqrt(nb, nir_fsub(nb, nir_fmul(nb, src[0], src[0]),
- nir_imm_float(nb, 1.0f)))));
- return;
- case GLSLstd450Atanh: {
- nir_ssa_def *one = nir_imm_float(nb, 1.0);
- val->ssa->def = nir_fmul(nb, nir_imm_float(nb, 0.5f),
- build_log(nb, nir_fdiv(nb, nir_fadd(nb, one, src[0]),
- nir_fsub(nb, one, src[0]))));
- return;
- }
-
- case GLSLstd450FindILsb: op = nir_op_find_lsb; break;
- case GLSLstd450FindSMsb: op = nir_op_ifind_msb; break;
- case GLSLstd450FindUMsb: op = nir_op_ufind_msb; break;
-
- case GLSLstd450Asin:
- val->ssa->def = build_asin(nb, src[0]);
- return;
-
- case GLSLstd450Acos:
- val->ssa->def = build_acos(nb, src[0]);
- return;
-
- case GLSLstd450Atan:
- val->ssa->def = build_atan(nb, src[0]);
- return;
-
- case GLSLstd450Atan2:
- val->ssa->def = build_atan2(nb, src[0], src[1]);
- return;
-
- case GLSLstd450Frexp: {
- nir_ssa_def *exponent;
- val->ssa->def = build_frexp(nb, src[0], &exponent);
- nir_store_deref_var(nb, vtn_nir_deref(b, w[6]), exponent, 0xf);
- return;
- }
-
- case GLSLstd450FrexpStruct: {
- assert(glsl_type_is_struct(val->ssa->type));
- val->ssa->elems[0]->def = build_frexp(nb, src[0],
- &val->ssa->elems[1]->def);
- return;
- }
-
- case GLSLstd450PackDouble2x32:
- case GLSLstd450UnpackDouble2x32:
- default:
- unreachable("Unhandled opcode");
- }
-
- nir_alu_instr *instr = nir_alu_instr_create(b->shader, op);
- nir_ssa_dest_init(&instr->instr, &instr->dest.dest,
- glsl_get_vector_elements(val->ssa->type), val->name);
- instr->dest.write_mask = (1 << instr->dest.dest.ssa.num_components) - 1;
- val->ssa->def = &instr->dest.dest.ssa;
-
- for (unsigned i = 0; i < nir_op_infos[op].num_inputs; i++)
- instr->src[i].src = nir_src_for_ssa(src[i]);
-
- nir_builder_instr_insert(nb, &instr->instr);
-}
-
-bool
-vtn_handle_glsl450_instruction(struct vtn_builder *b, uint32_t ext_opcode,
- const uint32_t *w, unsigned count)
-{
- switch ((enum GLSLstd450)ext_opcode) {
- case GLSLstd450Determinant: {
- struct vtn_value *val = vtn_push_value(b, w[2], vtn_value_type_ssa);
- val->ssa = rzalloc(b, struct vtn_ssa_value);
- val->ssa->type = vtn_value(b, w[1], vtn_value_type_type)->type->type;
- val->ssa->def = build_mat_det(b, vtn_ssa_value(b, w[5]));
- break;
- }
-
- case GLSLstd450MatrixInverse: {
- struct vtn_value *val = vtn_push_value(b, w[2], vtn_value_type_ssa);
- val->ssa = matrix_inverse(b, vtn_ssa_value(b, w[5]));
- break;
- }
-
- case GLSLstd450InterpolateAtCentroid:
- case GLSLstd450InterpolateAtSample:
- case GLSLstd450InterpolateAtOffset:
- unreachable("Unhandled opcode");
-
- default:
- handle_glsl450_alu(b, (enum GLSLstd450)ext_opcode, w, count);
- }
-
- return true;
-}
diff --git a/src/glsl/nir/spirv/vtn_private.h b/src/glsl/nir/spirv/vtn_private.h
deleted file mode 100644
index 3840d8c4b65..00000000000
--- a/src/glsl/nir/spirv/vtn_private.h
+++ /dev/null
@@ -1,484 +0,0 @@
-/*
- * Copyright © 2015 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- *
- * Authors:
- * Jason Ekstrand ([email protected])
- *
- */
-
-#include "nir/nir.h"
-#include "nir/nir_builder.h"
-#include "nir/nir_array.h"
-#include "nir_spirv.h"
-#include "spirv.h"
-
-struct vtn_builder;
-struct vtn_decoration;
-
-enum vtn_value_type {
- vtn_value_type_invalid = 0,
- vtn_value_type_undef,
- vtn_value_type_string,
- vtn_value_type_decoration_group,
- vtn_value_type_type,
- vtn_value_type_constant,
- vtn_value_type_access_chain,
- vtn_value_type_function,
- vtn_value_type_block,
- vtn_value_type_ssa,
- vtn_value_type_extension,
- vtn_value_type_image_pointer,
- vtn_value_type_sampled_image,
-};
-
-enum vtn_branch_type {
- vtn_branch_type_none,
- vtn_branch_type_switch_break,
- vtn_branch_type_switch_fallthrough,
- vtn_branch_type_loop_break,
- vtn_branch_type_loop_continue,
- vtn_branch_type_discard,
- vtn_branch_type_return,
-};
-
-enum vtn_cf_node_type {
- vtn_cf_node_type_block,
- vtn_cf_node_type_if,
- vtn_cf_node_type_loop,
- vtn_cf_node_type_switch,
-};
-
-struct vtn_cf_node {
- struct list_head link;
- enum vtn_cf_node_type type;
-};
-
-struct vtn_loop {
- struct vtn_cf_node node;
-
- /* The main body of the loop */
- struct list_head body;
-
- /* The "continue" part of the loop. This gets executed after the body
- * and is where you go when you hit a continue.
- */
- struct list_head cont_body;
-
- SpvLoopControlMask control;
-};
-
-struct vtn_if {
- struct vtn_cf_node node;
-
- uint32_t condition;
-
- enum vtn_branch_type then_type;
- struct list_head then_body;
-
- enum vtn_branch_type else_type;
- struct list_head else_body;
-
- SpvSelectionControlMask control;
-};
-
-struct vtn_case {
- struct list_head link;
-
- struct list_head body;
-
- /* The block that starts this case */
- struct vtn_block *start_block;
-
- /* The fallthrough case, if any */
- struct vtn_case *fallthrough;
-
- /* The uint32_t values that map to this case */
- nir_array values;
-
- /* True if this is the default case */
- bool is_default;
-
- /* Initialized to false; used when sorting the list of cases */
- bool visited;
-};
-
-struct vtn_switch {
- struct vtn_cf_node node;
-
- uint32_t selector;
-
- struct list_head cases;
-};
-
-struct vtn_block {
- struct vtn_cf_node node;
-
- /** A pointer to the label instruction */
- const uint32_t *label;
-
- /** A pointer to the merge instruction (or NULL if non exists) */
- const uint32_t *merge;
-
- /** A pointer to the branch instruction that ends this block */
- const uint32_t *branch;
-
- enum vtn_branch_type branch_type;
-
- /** Points to the loop that this block starts (if it starts a loop) */
- struct vtn_loop *loop;
-
- /** Points to the switch case started by this block (if any) */
- struct vtn_case *switch_case;
-
- /** The last block in this SPIR-V block. */
- nir_block *end_block;
-};
-
-struct vtn_function {
- struct exec_node node;
-
- nir_function_impl *impl;
- struct vtn_block *start_block;
-
- struct list_head body;
-
- const uint32_t *end;
-
- SpvFunctionControlMask control;
-};
-
-typedef bool (*vtn_instruction_handler)(struct vtn_builder *, uint32_t,
- const uint32_t *, unsigned);
-
-void vtn_build_cfg(struct vtn_builder *b, const uint32_t *words,
- const uint32_t *end);
-void vtn_function_emit(struct vtn_builder *b, struct vtn_function *func,
- vtn_instruction_handler instruction_handler);
-
-const uint32_t *
-vtn_foreach_instruction(struct vtn_builder *b, const uint32_t *start,
- const uint32_t *end, vtn_instruction_handler handler);
-
-struct vtn_ssa_value {
- union {
- nir_ssa_def *def;
- struct vtn_ssa_value **elems;
- };
-
- /* For matrices, if this is non-NULL, then this value is actually the
- * transpose of some other value. The value that `transposed` points to
- * always dominates this value.
- */
- struct vtn_ssa_value *transposed;
-
- const struct glsl_type *type;
-};
-
-struct vtn_type {
- const struct glsl_type *type;
-
- /* The value that declares this type. Used for finding decorations */
- struct vtn_value *val;
-
- /* for matrices, whether the matrix is stored row-major */
- bool row_major;
-
- /* for structs, the offset of each member */
- unsigned *offsets;
-
- /* for structs, whether it was decorated as a "non-SSBO-like" block */
- bool block;
-
- /* for structs, whether it was decorated as an "SSBO-like" block */
- bool buffer_block;
-
- /* for structs with block == true, whether this is a builtin block (i.e. a
- * block that contains only builtins).
- */
- bool builtin_block;
-
- /* Image format for image_load_store type images */
- unsigned image_format;
-
- /* Access qualifier for storage images */
- SpvAccessQualifier access_qualifier;
-
- /* for arrays and matrices, the array stride */
- unsigned stride;
-
- /* for arrays, the vtn_type for the elements of the array */
- struct vtn_type *array_element;
-
- /* for structures, the vtn_type for each member */
- struct vtn_type **members;
-
- /* Whether this type, or a parent type, has been decorated as a builtin */
- bool is_builtin;
-
- SpvBuiltIn builtin;
-};
-
-struct vtn_variable;
-
-enum vtn_access_mode {
- vtn_access_mode_id,
- vtn_access_mode_literal,
-};
-
-struct vtn_access_link {
- enum vtn_access_mode mode;
- uint32_t id;
-};
-
-struct vtn_access_chain {
- struct vtn_variable *var;
-
- uint32_t length;
-
- /* Struct elements and array offsets */
- struct vtn_access_link link[0];
-};
-
-enum vtn_variable_mode {
- vtn_variable_mode_local,
- vtn_variable_mode_global,
- vtn_variable_mode_param,
- vtn_variable_mode_ubo,
- vtn_variable_mode_ssbo,
- vtn_variable_mode_push_constant,
- vtn_variable_mode_image,
- vtn_variable_mode_sampler,
- vtn_variable_mode_workgroup,
- vtn_variable_mode_input,
- vtn_variable_mode_output,
-};
-
-struct vtn_variable {
- enum vtn_variable_mode mode;
-
- struct vtn_type *type;
-
- unsigned descriptor_set;
- unsigned binding;
-
- nir_variable *var;
- nir_variable **members;
-
- struct vtn_access_chain chain;
-};
-
-struct vtn_image_pointer {
- struct vtn_access_chain *image;
- nir_ssa_def *coord;
- nir_ssa_def *sample;
-};
-
-struct vtn_sampled_image {
- struct vtn_access_chain *image; /* Image or array of images */
- struct vtn_access_chain *sampler; /* Sampler */
-};
-
-struct vtn_value {
- enum vtn_value_type value_type;
- const char *name;
- struct vtn_decoration *decoration;
- union {
- void *ptr;
- char *str;
- struct vtn_type *type;
- struct {
- nir_constant *constant;
- const struct glsl_type *const_type;
- };
- struct vtn_access_chain *access_chain;
- struct vtn_image_pointer *image;
- struct vtn_sampled_image *sampled_image;
- struct vtn_function *func;
- struct vtn_block *block;
- struct vtn_ssa_value *ssa;
- vtn_instruction_handler ext_handler;
- };
-};
-
-#define VTN_DEC_DECORATION -1
-#define VTN_DEC_EXECUTION_MODE -2
-#define VTN_DEC_STRUCT_MEMBER0 0
-
-struct vtn_decoration {
- struct vtn_decoration *next;
-
- /* Specifies how to apply this decoration. Negative values represent a
- * decoration or execution mode. (See the VTN_DEC_ #defines above.)
- * Non-negative values specify that it applies to a structure member.
- */
- int scope;
-
- const uint32_t *literals;
- struct vtn_value *group;
-
- union {
- SpvDecoration decoration;
- SpvExecutionMode exec_mode;
- };
-};
-
-struct vtn_builder {
- nir_builder nb;
-
- nir_shader *shader;
- nir_function_impl *impl;
- struct vtn_block *block;
-
- /* Current file, line, and column. Useful for debugging. Set
- * automatically by vtn_foreach_instruction.
- */
- char *file;
- int line, col;
-
- /*
- * In SPIR-V, constants are global, whereas in NIR, the load_const
- * instruction we use is per-function. So while we parse each function, we
- * keep a hash table of constants we've resolved to nir_ssa_value's so
- * far, and we lazily resolve them when we see them used in a function.
- */
- struct hash_table *const_table;
-
- /*
- * Map from phi instructions (pointer to the start of the instruction)
- * to the variable corresponding to it.
- */
- struct hash_table *phi_table;
-
- unsigned num_specializations;
- struct nir_spirv_specialization *specializations;
-
- unsigned value_id_bound;
- struct vtn_value *values;
-
- gl_shader_stage entry_point_stage;
- const char *entry_point_name;
- struct vtn_value *entry_point;
- bool origin_upper_left;
-
- struct vtn_function *func;
- struct exec_list functions;
-
- /* Current function parameter index */
- unsigned func_param_idx;
-
- bool has_loop_continue;
-};
-
-static inline struct vtn_value *
-vtn_push_value(struct vtn_builder *b, uint32_t value_id,
- enum vtn_value_type value_type)
-{
- assert(value_id < b->value_id_bound);
- assert(b->values[value_id].value_type == vtn_value_type_invalid);
-
- b->values[value_id].value_type = value_type;
-
- return &b->values[value_id];
-}
-
-static inline struct vtn_value *
-vtn_untyped_value(struct vtn_builder *b, uint32_t value_id)
-{
- assert(value_id < b->value_id_bound);
- return &b->values[value_id];
-}
-
-static inline struct vtn_value *
-vtn_value(struct vtn_builder *b, uint32_t value_id,
- enum vtn_value_type value_type)
-{
- struct vtn_value *val = vtn_untyped_value(b, value_id);
- assert(val->value_type == value_type);
- return val;
-}
-
-struct vtn_ssa_value *vtn_ssa_value(struct vtn_builder *b, uint32_t value_id);
-
-struct vtn_ssa_value *vtn_create_ssa_value(struct vtn_builder *b,
- const struct glsl_type *type);
-
-struct vtn_ssa_value *vtn_ssa_transpose(struct vtn_builder *b,
- struct vtn_ssa_value *src);
-
-nir_ssa_def *vtn_vector_extract(struct vtn_builder *b, nir_ssa_def *src,
- unsigned index);
-nir_ssa_def *vtn_vector_extract_dynamic(struct vtn_builder *b, nir_ssa_def *src,
- nir_ssa_def *index);
-nir_ssa_def *vtn_vector_insert(struct vtn_builder *b, nir_ssa_def *src,
- nir_ssa_def *insert, unsigned index);
-nir_ssa_def *vtn_vector_insert_dynamic(struct vtn_builder *b, nir_ssa_def *src,
- nir_ssa_def *insert, nir_ssa_def *index);
-
-nir_deref_var *vtn_nir_deref(struct vtn_builder *b, uint32_t id);
-
-nir_deref_var *vtn_access_chain_to_deref(struct vtn_builder *b,
- struct vtn_access_chain *chain);
-nir_ssa_def *
-vtn_access_chain_to_offset(struct vtn_builder *b,
- struct vtn_access_chain *chain,
- nir_ssa_def **index_out, struct vtn_type **type_out,
- unsigned *end_idx_out, bool stop_at_matrix);
-
-struct vtn_ssa_value *vtn_local_load(struct vtn_builder *b, nir_deref_var *src);
-
-void vtn_local_store(struct vtn_builder *b, struct vtn_ssa_value *src,
- nir_deref_var *dest);
-
-struct vtn_ssa_value *
-vtn_variable_load(struct vtn_builder *b, struct vtn_access_chain *src);
-
-void vtn_variable_store(struct vtn_builder *b, struct vtn_ssa_value *src,
- struct vtn_access_chain *dest);
-
-void vtn_handle_variables(struct vtn_builder *b, SpvOp opcode,
- const uint32_t *w, unsigned count);
-
-
-typedef void (*vtn_decoration_foreach_cb)(struct vtn_builder *,
- struct vtn_value *,
- int member,
- const struct vtn_decoration *,
- void *);
-
-void vtn_foreach_decoration(struct vtn_builder *b, struct vtn_value *value,
- vtn_decoration_foreach_cb cb, void *data);
-
-typedef void (*vtn_execution_mode_foreach_cb)(struct vtn_builder *,
- struct vtn_value *,
- const struct vtn_decoration *,
- void *);
-
-void vtn_foreach_execution_mode(struct vtn_builder *b, struct vtn_value *value,
- vtn_execution_mode_foreach_cb cb, void *data);
-
-nir_op vtn_nir_alu_op_for_spirv_opcode(SpvOp opcode, bool *swap);
-
-void vtn_handle_alu(struct vtn_builder *b, SpvOp opcode,
- const uint32_t *w, unsigned count);
-
-bool vtn_handle_glsl450_instruction(struct vtn_builder *b, uint32_t ext_opcode,
- const uint32_t *words, unsigned count);
diff --git a/src/glsl/nir/spirv/vtn_variables.c b/src/glsl/nir/spirv/vtn_variables.c
deleted file mode 100644
index 3ad98aa5310..00000000000
--- a/src/glsl/nir/spirv/vtn_variables.c
+++ /dev/null
@@ -1,1412 +0,0 @@
-/*
- * Copyright © 2015 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- *
- * Authors:
- * Jason Ekstrand ([email protected])
- *
- */
-
-#include "vtn_private.h"
-
-static struct vtn_access_chain *
-vtn_access_chain_extend(struct vtn_builder *b, struct vtn_access_chain *old,
- unsigned new_ids)
-{
- struct vtn_access_chain *chain;
-
- unsigned new_len = old->length + new_ids;
- chain = ralloc_size(b, sizeof(*chain) + new_len * sizeof(chain->link[0]));
-
- chain->var = old->var;
- chain->length = new_len;
-
- for (unsigned i = 0; i < old->length; i++)
- chain->link[i] = old->link[i];
-
- return chain;
-}
-
-static nir_ssa_def *
-vtn_access_link_as_ssa(struct vtn_builder *b, struct vtn_access_link link,
- unsigned stride)
-{
- assert(stride > 0);
- if (link.mode == vtn_access_mode_literal) {
- return nir_imm_int(&b->nb, link.id * stride);
- } else if (stride == 1) {
- return vtn_ssa_value(b, link.id)->def;
- } else {
- return nir_imul(&b->nb, vtn_ssa_value(b, link.id)->def,
- nir_imm_int(&b->nb, stride));
- }
-}
-
-static struct vtn_type *
-vtn_access_chain_tail_type(struct vtn_builder *b,
- struct vtn_access_chain *chain)
-{
- struct vtn_type *type = chain->var->type;
- for (unsigned i = 0; i < chain->length; i++) {
- if (glsl_type_is_struct(type->type)) {
- assert(chain->link[i].mode == vtn_access_mode_literal);
- type = type->members[chain->link[i].id];
- } else {
- type = type->array_element;
- }
- }
- return type;
-}
-
-/* Crawls a chain of array derefs and rewrites the types so that the
- * lengths stay the same but the terminal type is the one given by
- * tail_type. This is useful for split structures.
- */
-static void
-rewrite_deref_types(nir_deref *deref, const struct glsl_type *type)
-{
- deref->type = type;
- if (deref->child) {
- assert(deref->child->deref_type == nir_deref_type_array);
- assert(glsl_type_is_array(deref->type));
- rewrite_deref_types(deref->child, glsl_get_array_element(type));
- }
-}
-
-nir_deref_var *
-vtn_access_chain_to_deref(struct vtn_builder *b, struct vtn_access_chain *chain)
-{
- nir_deref_var *deref_var;
- if (chain->var->var) {
- deref_var = nir_deref_var_create(b, chain->var->var);
- } else {
- assert(chain->var->members);
- /* Create the deref_var manually. It will get filled out later. */
- deref_var = rzalloc(b, nir_deref_var);
- deref_var->deref.deref_type = nir_deref_type_var;
- }
-
- struct vtn_type *deref_type = chain->var->type;
- nir_deref *tail = &deref_var->deref;
- nir_variable **members = chain->var->members;
-
- for (unsigned i = 0; i < chain->length; i++) {
- enum glsl_base_type base_type = glsl_get_base_type(deref_type->type);
- switch (base_type) {
- case GLSL_TYPE_UINT:
- case GLSL_TYPE_INT:
- case GLSL_TYPE_FLOAT:
- case GLSL_TYPE_DOUBLE:
- case GLSL_TYPE_BOOL:
- case GLSL_TYPE_ARRAY: {
- deref_type = deref_type->array_element;
-
- nir_deref_array *deref_arr = nir_deref_array_create(b);
- deref_arr->deref.type = deref_type->type;
-
- if (chain->link[i].mode == vtn_access_mode_literal) {
- deref_arr->deref_array_type = nir_deref_array_type_direct;
- deref_arr->base_offset = chain->link[i].id;
- } else {
- assert(chain->link[i].mode == vtn_access_mode_id);
- deref_arr->deref_array_type = nir_deref_array_type_indirect;
- deref_arr->base_offset = 0;
- deref_arr->indirect =
- nir_src_for_ssa(vtn_ssa_value(b, chain->link[i].id)->def);
- }
- tail->child = &deref_arr->deref;
- tail = tail->child;
- break;
- }
-
- case GLSL_TYPE_STRUCT: {
- assert(chain->link[i].mode == vtn_access_mode_literal);
- unsigned idx = chain->link[i].id;
- deref_type = deref_type->members[idx];
- if (members) {
- /* This is a pre-split structure. */
- deref_var->var = members[idx];
- rewrite_deref_types(&deref_var->deref, members[idx]->type);
- assert(tail->type == deref_type->type);
- members = NULL;
- } else {
- nir_deref_struct *deref_struct = nir_deref_struct_create(b, idx);
- deref_struct->deref.type = deref_type->type;
- tail->child = &deref_struct->deref;
- tail = tail->child;
- }
- break;
- }
- default:
- unreachable("Invalid type for deref");
- }
- }
-
- assert(members == NULL);
- return deref_var;
-}
-
-static void
-_vtn_local_load_store(struct vtn_builder *b, bool load, nir_deref_var *deref,
- nir_deref *tail, struct vtn_ssa_value *inout)
-{
- /* The deref tail may contain a deref to select a component of a vector (in
- * other words, it might not be an actual tail) so we have to save it away
- * here since we overwrite it later.
- */
- nir_deref *old_child = tail->child;
-
- if (glsl_type_is_vector_or_scalar(tail->type)) {
- /* Terminate the deref chain in case there is one more link to pick
- * off a component of the vector.
- */
- tail->child = NULL;
-
- nir_intrinsic_op op = load ? nir_intrinsic_load_var :
- nir_intrinsic_store_var;
-
- nir_intrinsic_instr *intrin = nir_intrinsic_instr_create(b->shader, op);
- intrin->variables[0] =
- nir_deref_as_var(nir_copy_deref(intrin, &deref->deref));
- intrin->num_components = glsl_get_vector_elements(tail->type);
-
- if (load) {
- nir_ssa_dest_init(&intrin->instr, &intrin->dest,
- intrin->num_components, NULL);
- inout->def = &intrin->dest.ssa;
- } else {
- intrin->const_index[0] = (1 << intrin->num_components) - 1;
- intrin->src[0] = nir_src_for_ssa(inout->def);
- }
-
- nir_builder_instr_insert(&b->nb, &intrin->instr);
- } else if (glsl_get_base_type(tail->type) == GLSL_TYPE_ARRAY ||
- glsl_type_is_matrix(tail->type)) {
- unsigned elems = glsl_get_length(tail->type);
- nir_deref_array *deref_arr = nir_deref_array_create(b);
- deref_arr->deref_array_type = nir_deref_array_type_direct;
- deref_arr->deref.type = glsl_get_array_element(tail->type);
- tail->child = &deref_arr->deref;
- for (unsigned i = 0; i < elems; i++) {
- deref_arr->base_offset = i;
- _vtn_local_load_store(b, load, deref, tail->child, inout->elems[i]);
- }
- } else {
- assert(glsl_get_base_type(tail->type) == GLSL_TYPE_STRUCT);
- unsigned elems = glsl_get_length(tail->type);
- nir_deref_struct *deref_struct = nir_deref_struct_create(b, 0);
- tail->child = &deref_struct->deref;
- for (unsigned i = 0; i < elems; i++) {
- deref_struct->index = i;
- deref_struct->deref.type = glsl_get_struct_field(tail->type, i);
- _vtn_local_load_store(b, load, deref, tail->child, inout->elems[i]);
- }
- }
-
- tail->child = old_child;
-}
-
-nir_deref_var *
-vtn_nir_deref(struct vtn_builder *b, uint32_t id)
-{
- struct vtn_access_chain *chain =
- vtn_value(b, id, vtn_value_type_access_chain)->access_chain;
-
- return vtn_access_chain_to_deref(b, chain);
-}
-
-/*
- * Gets the NIR-level deref tail, which may have as a child an array deref
- * selecting which component due to OpAccessChain supporting per-component
- * indexing in SPIR-V.
- */
-static nir_deref *
-get_deref_tail(nir_deref_var *deref)
-{
- nir_deref *cur = &deref->deref;
- while (!glsl_type_is_vector_or_scalar(cur->type) && cur->child)
- cur = cur->child;
-
- return cur;
-}
-
-struct vtn_ssa_value *
-vtn_local_load(struct vtn_builder *b, nir_deref_var *src)
-{
- nir_deref *src_tail = get_deref_tail(src);
- struct vtn_ssa_value *val = vtn_create_ssa_value(b, src_tail->type);
- _vtn_local_load_store(b, true, src, src_tail, val);
-
- if (src_tail->child) {
- nir_deref_array *vec_deref = nir_deref_as_array(src_tail->child);
- assert(vec_deref->deref.child == NULL);
- val->type = vec_deref->deref.type;
- if (vec_deref->deref_array_type == nir_deref_array_type_direct)
- val->def = vtn_vector_extract(b, val->def, vec_deref->base_offset);
- else
- val->def = vtn_vector_extract_dynamic(b, val->def,
- vec_deref->indirect.ssa);
- }
-
- return val;
-}
-
-void
-vtn_local_store(struct vtn_builder *b, struct vtn_ssa_value *src,
- nir_deref_var *dest)
-{
- nir_deref *dest_tail = get_deref_tail(dest);
-
- if (dest_tail->child) {
- struct vtn_ssa_value *val = vtn_create_ssa_value(b, dest_tail->type);
- _vtn_local_load_store(b, true, dest, dest_tail, val);
- nir_deref_array *deref = nir_deref_as_array(dest_tail->child);
- assert(deref->deref.child == NULL);
- if (deref->deref_array_type == nir_deref_array_type_direct)
- val->def = vtn_vector_insert(b, val->def, src->def,
- deref->base_offset);
- else
- val->def = vtn_vector_insert_dynamic(b, val->def, src->def,
- deref->indirect.ssa);
- _vtn_local_load_store(b, false, dest, dest_tail, val);
- } else {
- _vtn_local_load_store(b, false, dest, dest_tail, src);
- }
-}
-
-static nir_ssa_def *
-get_vulkan_resource_index(struct vtn_builder *b, struct vtn_access_chain *chain,
- struct vtn_type **type, unsigned *chain_idx)
-{
- /* Push constants have no explicit binding */
- if (chain->var->mode == vtn_variable_mode_push_constant) {
- *chain_idx = 0;
- *type = chain->var->type;
- return NULL;
- }
-
- nir_ssa_def *array_index;
- if (glsl_type_is_array(chain->var->type->type)) {
- assert(chain->length > 0);
- array_index = vtn_access_link_as_ssa(b, chain->link[0], 1);
- *chain_idx = 1;
- *type = chain->var->type->array_element;
- } else {
- array_index = nir_imm_int(&b->nb, 0);
- *chain_idx = 0;
- *type = chain->var->type;
- }
-
- nir_intrinsic_instr *instr =
- nir_intrinsic_instr_create(b->nb.shader,
- nir_intrinsic_vulkan_resource_index);
- instr->src[0] = nir_src_for_ssa(array_index);
- instr->const_index[0] = chain->var->descriptor_set;
- instr->const_index[1] = chain->var->binding;
-
- nir_ssa_dest_init(&instr->instr, &instr->dest, 1, NULL);
- nir_builder_instr_insert(&b->nb, &instr->instr);
-
- return &instr->dest.ssa;
-}
-
-nir_ssa_def *
-vtn_access_chain_to_offset(struct vtn_builder *b,
- struct vtn_access_chain *chain,
- nir_ssa_def **index_out, struct vtn_type **type_out,
- unsigned *end_idx_out, bool stop_at_matrix)
-{
- unsigned idx = 0;
- struct vtn_type *type;
- *index_out = get_vulkan_resource_index(b, chain, &type, &idx);
-
- nir_ssa_def *offset = nir_imm_int(&b->nb, 0);
- for (; idx < chain->length; idx++) {
- enum glsl_base_type base_type = glsl_get_base_type(type->type);
- switch (base_type) {
- case GLSL_TYPE_UINT:
- case GLSL_TYPE_INT:
- case GLSL_TYPE_FLOAT:
- case GLSL_TYPE_DOUBLE:
- case GLSL_TYPE_BOOL:
- /* Some users may not want matrix or vector derefs */
- if (stop_at_matrix)
- goto end;
- /* Fall through */
-
- case GLSL_TYPE_ARRAY:
- offset = nir_iadd(&b->nb, offset,
- vtn_access_link_as_ssa(b, chain->link[idx],
- type->stride));
-
- type = type->array_element;
- break;
-
- case GLSL_TYPE_STRUCT: {
- assert(chain->link[idx].mode == vtn_access_mode_literal);
- unsigned member = chain->link[idx].id;
- offset = nir_iadd(&b->nb, offset,
- nir_imm_int(&b->nb, type->offsets[member]));
- type = type->members[member];
- break;
- }
-
- default:
- unreachable("Invalid type for deref");
- }
- }
-
-end:
- *type_out = type;
- if (end_idx_out)
- *end_idx_out = idx;
-
- return offset;
-}
-
-static void
-_vtn_load_store_tail(struct vtn_builder *b, nir_intrinsic_op op, bool load,
- nir_ssa_def *index, nir_ssa_def *offset,
- struct vtn_ssa_value **inout, const struct glsl_type *type)
-{
- nir_intrinsic_instr *instr = nir_intrinsic_instr_create(b->nb.shader, op);
- instr->num_components = glsl_get_vector_elements(type);
-
- int src = 0;
- if (!load) {
- instr->const_index[0] = (1 << instr->num_components) - 1; /* write mask */
- instr->src[src++] = nir_src_for_ssa((*inout)->def);
- }
-
- /* We set the base and size for push constant load to the entire push
- * constant block for now.
- */
- if (op == nir_intrinsic_load_push_constant) {
- instr->const_index[0] = 0;
- instr->const_index[1] = 128;
- }
-
- if (index)
- instr->src[src++] = nir_src_for_ssa(index);
-
- instr->src[src++] = nir_src_for_ssa(offset);
-
- if (load) {
- nir_ssa_dest_init(&instr->instr, &instr->dest,
- instr->num_components, NULL);
- (*inout)->def = &instr->dest.ssa;
- }
-
- nir_builder_instr_insert(&b->nb, &instr->instr);
-
- if (load && glsl_get_base_type(type) == GLSL_TYPE_BOOL)
- (*inout)->def = nir_ine(&b->nb, (*inout)->def, nir_imm_int(&b->nb, 0));
-}
-
-static void
-_vtn_block_load_store(struct vtn_builder *b, nir_intrinsic_op op, bool load,
- nir_ssa_def *index, nir_ssa_def *offset,
- struct vtn_access_chain *chain, unsigned chain_idx,
- struct vtn_type *type, struct vtn_ssa_value **inout)
-{
- if (chain && chain_idx >= chain->length)
- chain = NULL;
-
- if (load && chain == NULL && *inout == NULL)
- *inout = vtn_create_ssa_value(b, type->type);
-
- enum glsl_base_type base_type = glsl_get_base_type(type->type);
- switch (base_type) {
- case GLSL_TYPE_UINT:
- case GLSL_TYPE_INT:
- case GLSL_TYPE_FLOAT:
- case GLSL_TYPE_BOOL:
- /* This is where things get interesting. At this point, we've hit
- * a vector, a scalar, or a matrix.
- */
- if (glsl_type_is_matrix(type->type)) {
- if (chain == NULL) {
- /* Loading the whole matrix */
- struct vtn_ssa_value *transpose;
- unsigned num_ops, vec_width;
- if (type->row_major) {
- num_ops = glsl_get_vector_elements(type->type);
- vec_width = glsl_get_matrix_columns(type->type);
- if (load) {
- const struct glsl_type *transpose_type =
- glsl_matrix_type(base_type, vec_width, num_ops);
- *inout = vtn_create_ssa_value(b, transpose_type);
- } else {
- transpose = vtn_ssa_transpose(b, *inout);
- inout = &transpose;
- }
- } else {
- num_ops = glsl_get_matrix_columns(type->type);
- vec_width = glsl_get_vector_elements(type->type);
- }
-
- for (unsigned i = 0; i < num_ops; i++) {
- nir_ssa_def *elem_offset =
- nir_iadd(&b->nb, offset,
- nir_imm_int(&b->nb, i * type->stride));
- _vtn_load_store_tail(b, op, load, index, elem_offset,
- &(*inout)->elems[i],
- glsl_vector_type(base_type, vec_width));
- }
-
- if (load && type->row_major)
- *inout = vtn_ssa_transpose(b, *inout);
- } else if (type->row_major) {
- /* Row-major but with an access chiain. */
- nir_ssa_def *col_offset =
- vtn_access_link_as_ssa(b, chain->link[chain_idx],
- type->array_element->stride);
- offset = nir_iadd(&b->nb, offset, col_offset);
-
- if (chain_idx + 1 < chain->length) {
- /* Picking off a single element */
- nir_ssa_def *row_offset =
- vtn_access_link_as_ssa(b, chain->link[chain_idx + 1],
- type->stride);
- offset = nir_iadd(&b->nb, offset, row_offset);
- if (load)
- *inout = vtn_create_ssa_value(b, glsl_scalar_type(base_type));
- _vtn_load_store_tail(b, op, load, index, offset, inout,
- glsl_scalar_type(base_type));
- } else {
- /* Grabbing a column; picking one element off each row */
- unsigned num_comps = glsl_get_vector_elements(type->type);
- const struct glsl_type *column_type =
- glsl_get_column_type(type->type);
-
- nir_ssa_def *comps[4];
- for (unsigned i = 0; i < num_comps; i++) {
- nir_ssa_def *elem_offset =
- nir_iadd(&b->nb, offset,
- nir_imm_int(&b->nb, i * type->stride));
-
- struct vtn_ssa_value *comp, temp_val;
- if (!load) {
- temp_val.def = nir_channel(&b->nb, (*inout)->def, i);
- temp_val.type = glsl_scalar_type(base_type);
- }
- comp = &temp_val;
- _vtn_load_store_tail(b, op, load, index, elem_offset,
- &comp, glsl_scalar_type(base_type));
- comps[i] = comp->def;
- }
-
- if (load) {
- if (*inout == NULL)
- *inout = vtn_create_ssa_value(b, column_type);
-
- (*inout)->def = nir_vec(&b->nb, comps, num_comps);
- }
- }
- } else {
- /* Column-major with a deref. Fall through to array case. */
- nir_ssa_def *col_offset =
- vtn_access_link_as_ssa(b, chain->link[chain_idx], type->stride);
- offset = nir_iadd(&b->nb, offset, col_offset);
-
- _vtn_block_load_store(b, op, load, index, offset,
- chain, chain_idx + 1,
- type->array_element, inout);
- }
- } else if (chain == NULL) {
- /* Single whole vector */
- assert(glsl_type_is_vector_or_scalar(type->type));
- _vtn_load_store_tail(b, op, load, index, offset, inout, type->type);
- } else {
- /* Single component of a vector. Fall through to array case. */
- nir_ssa_def *elem_offset =
- vtn_access_link_as_ssa(b, chain->link[chain_idx], type->stride);
- offset = nir_iadd(&b->nb, offset, elem_offset);
-
- _vtn_block_load_store(b, op, load, index, offset, NULL, 0,
- type->array_element, inout);
- }
- return;
-
- case GLSL_TYPE_ARRAY: {
- unsigned elems = glsl_get_length(type->type);
- for (unsigned i = 0; i < elems; i++) {
- nir_ssa_def *elem_off =
- nir_iadd(&b->nb, offset, nir_imm_int(&b->nb, i * type->stride));
- _vtn_block_load_store(b, op, load, index, elem_off, NULL, 0,
- type->array_element, &(*inout)->elems[i]);
- }
- return;
- }
-
- case GLSL_TYPE_STRUCT: {
- unsigned elems = glsl_get_length(type->type);
- for (unsigned i = 0; i < elems; i++) {
- nir_ssa_def *elem_off =
- nir_iadd(&b->nb, offset, nir_imm_int(&b->nb, type->offsets[i]));
- _vtn_block_load_store(b, op, load, index, elem_off, NULL, 0,
- type->members[i], &(*inout)->elems[i]);
- }
- return;
- }
-
- default:
- unreachable("Invalid block member type");
- }
-}
-
-static struct vtn_ssa_value *
-vtn_block_load(struct vtn_builder *b, struct vtn_access_chain *src)
-{
- nir_intrinsic_op op;
- switch (src->var->mode) {
- case vtn_variable_mode_ubo:
- op = nir_intrinsic_load_ubo;
- break;
- case vtn_variable_mode_ssbo:
- op = nir_intrinsic_load_ssbo;
- break;
- case vtn_variable_mode_push_constant:
- op = nir_intrinsic_load_push_constant;
- break;
- default:
- assert(!"Invalid block variable mode");
- }
-
- nir_ssa_def *offset, *index = NULL;
- struct vtn_type *type;
- unsigned chain_idx;
- offset = vtn_access_chain_to_offset(b, src, &index, &type, &chain_idx, true);
-
- struct vtn_ssa_value *value = NULL;
- _vtn_block_load_store(b, op, true, index, offset,
- src, chain_idx, type, &value);
- return value;
-}
-
-static void
-vtn_block_store(struct vtn_builder *b, struct vtn_ssa_value *src,
- struct vtn_access_chain *dst)
-{
- nir_ssa_def *offset, *index = NULL;
- struct vtn_type *type;
- unsigned chain_idx;
- offset = vtn_access_chain_to_offset(b, dst, &index, &type, &chain_idx, true);
-
- _vtn_block_load_store(b, nir_intrinsic_store_ssbo, false, index, offset,
- dst, chain_idx, type, &src);
-}
-
-static bool
-vtn_variable_is_external_block(struct vtn_variable *var)
-{
- return var->mode == vtn_variable_mode_ssbo ||
- var->mode == vtn_variable_mode_ubo ||
- var->mode == vtn_variable_mode_push_constant;
-}
-
-static void
-_vtn_variable_load_store(struct vtn_builder *b, bool load,
- struct vtn_access_chain *chain,
- struct vtn_type *tail_type,
- struct vtn_ssa_value **inout)
-{
- enum glsl_base_type base_type = glsl_get_base_type(tail_type->type);
- switch (base_type) {
- case GLSL_TYPE_UINT:
- case GLSL_TYPE_INT:
- case GLSL_TYPE_FLOAT:
- case GLSL_TYPE_BOOL:
- /* At this point, we have a scalar, vector, or matrix so we know that
- * there cannot be any structure splitting still in the way. By
- * stopping at the matrix level rather than the vector level, we
- * ensure that matrices get loaded in the optimal way even if they
- * are storred row-major in a UBO.
- */
- if (load) {
- *inout = vtn_local_load(b, vtn_access_chain_to_deref(b, chain));
- } else {
- vtn_local_store(b, *inout, vtn_access_chain_to_deref(b, chain));
- }
- return;
-
- case GLSL_TYPE_ARRAY:
- case GLSL_TYPE_STRUCT: {
- struct vtn_access_chain *new_chain =
- vtn_access_chain_extend(b, chain, 1);
- new_chain->link[chain->length].mode = vtn_access_mode_literal;
- unsigned elems = glsl_get_length(tail_type->type);
- if (load) {
- assert(*inout == NULL);
- *inout = rzalloc(b, struct vtn_ssa_value);
- (*inout)->type = tail_type->type;
- (*inout)->elems = rzalloc_array(b, struct vtn_ssa_value *, elems);
- }
- for (unsigned i = 0; i < elems; i++) {
- new_chain->link[chain->length].id = i;
- struct vtn_type *elem_type = base_type == GLSL_TYPE_ARRAY ?
- tail_type->array_element : tail_type->members[i];
- _vtn_variable_load_store(b, load, new_chain, elem_type,
- &(*inout)->elems[i]);
- }
- return;
- }
-
- default:
- unreachable("Invalid access chain type");
- }
-}
-
-struct vtn_ssa_value *
-vtn_variable_load(struct vtn_builder *b, struct vtn_access_chain *src)
-{
- if (vtn_variable_is_external_block(src->var)) {
- return vtn_block_load(b, src);
- } else {
- struct vtn_type *tail_type = vtn_access_chain_tail_type(b, src);
- struct vtn_ssa_value *val = NULL;
- _vtn_variable_load_store(b, true, src, tail_type, &val);
- return val;
- }
-}
-
-void
-vtn_variable_store(struct vtn_builder *b, struct vtn_ssa_value *src,
- struct vtn_access_chain *dest)
-{
- if (vtn_variable_is_external_block(dest->var)) {
- assert(dest->var->mode == vtn_variable_mode_ssbo);
- vtn_block_store(b, src, dest);
- } else {
- struct vtn_type *tail_type = vtn_access_chain_tail_type(b, dest);
- _vtn_variable_load_store(b, false, dest, tail_type, &src);
- }
-}
-
-static void
-_vtn_variable_copy(struct vtn_builder *b, struct vtn_access_chain *dest,
- struct vtn_access_chain *src, struct vtn_type *tail_type)
-{
- enum glsl_base_type base_type = glsl_get_base_type(tail_type->type);
- switch (base_type) {
- case GLSL_TYPE_UINT:
- case GLSL_TYPE_INT:
- case GLSL_TYPE_FLOAT:
- case GLSL_TYPE_BOOL:
- /* At this point, we have a scalar, vector, or matrix so we know that
- * there cannot be any structure splitting still in the way. By
- * stopping at the matrix level rather than the vector level, we
- * ensure that matrices get loaded in the optimal way even if they
- * are storred row-major in a UBO.
- */
- vtn_variable_store(b, vtn_variable_load(b, src), dest);
- return;
-
- case GLSL_TYPE_ARRAY:
- case GLSL_TYPE_STRUCT: {
- struct vtn_access_chain *new_src, *new_dest;
- new_src = vtn_access_chain_extend(b, src, 1);
- new_dest = vtn_access_chain_extend(b, dest, 1);
- new_src->link[src->length].mode = vtn_access_mode_literal;
- new_dest->link[dest->length].mode = vtn_access_mode_literal;
- unsigned elems = glsl_get_length(tail_type->type);
- for (unsigned i = 0; i < elems; i++) {
- new_src->link[src->length].id = i;
- new_dest->link[dest->length].id = i;
- struct vtn_type *elem_type = base_type == GLSL_TYPE_ARRAY ?
- tail_type->array_element : tail_type->members[i];
- _vtn_variable_copy(b, new_dest, new_src, elem_type);
- }
- return;
- }
-
- default:
- unreachable("Invalid access chain type");
- }
-}
-
-static void
-vtn_variable_copy(struct vtn_builder *b, struct vtn_access_chain *dest,
- struct vtn_access_chain *src)
-{
- struct vtn_type *tail_type = vtn_access_chain_tail_type(b, src);
- assert(vtn_access_chain_tail_type(b, dest)->type == tail_type->type);
-
- /* TODO: At some point, we should add a special-case for when we can
- * just emit a copy_var intrinsic.
- */
- _vtn_variable_copy(b, dest, src, tail_type);
-}
-
-static void
-set_mode_system_value(nir_variable_mode *mode)
-{
- assert(*mode == nir_var_system_value || *mode == nir_var_shader_in);
- *mode = nir_var_system_value;
-}
-
-static void
-vtn_get_builtin_location(struct vtn_builder *b,
- SpvBuiltIn builtin, int *location,
- nir_variable_mode *mode)
-{
- switch (builtin) {
- case SpvBuiltInPosition:
- *location = VARYING_SLOT_POS;
- break;
- case SpvBuiltInPointSize:
- *location = VARYING_SLOT_PSIZ;
- break;
- case SpvBuiltInClipDistance:
- *location = VARYING_SLOT_CLIP_DIST0; /* XXX CLIP_DIST1? */
- break;
- case SpvBuiltInCullDistance:
- /* XXX figure this out */
- break;
- case SpvBuiltInVertexIndex:
- *location = SYSTEM_VALUE_VERTEX_ID;
- set_mode_system_value(mode);
- break;
- case SpvBuiltInVertexId:
- /* Vulkan defines VertexID to be zero-based and reserves the new
- * builtin keyword VertexIndex to indicate the non-zero-based value.
- */
- *location = SYSTEM_VALUE_VERTEX_ID_ZERO_BASE;
- set_mode_system_value(mode);
- break;
- case SpvBuiltInInstanceIndex:
- *location = SYSTEM_VALUE_INSTANCE_INDEX;
- set_mode_system_value(mode);
- break;
- case SpvBuiltInInstanceId:
- *location = SYSTEM_VALUE_INSTANCE_ID;
- set_mode_system_value(mode);
- break;
- case SpvBuiltInPrimitiveId:
- *location = VARYING_SLOT_PRIMITIVE_ID;
- *mode = nir_var_shader_out;
- break;
- case SpvBuiltInInvocationId:
- *location = SYSTEM_VALUE_INVOCATION_ID;
- set_mode_system_value(mode);
- break;
- case SpvBuiltInLayer:
- *location = VARYING_SLOT_LAYER;
- *mode = nir_var_shader_out;
- break;
- case SpvBuiltInViewportIndex:
- *location = VARYING_SLOT_VIEWPORT;
- if (b->shader->stage == MESA_SHADER_GEOMETRY)
- *mode = nir_var_shader_out;
- else if (b->shader->stage == MESA_SHADER_FRAGMENT)
- *mode = nir_var_shader_in;
- else
- unreachable("invalid stage for SpvBuiltInViewportIndex");
- break;
- case SpvBuiltInTessLevelOuter:
- case SpvBuiltInTessLevelInner:
- case SpvBuiltInTessCoord:
- case SpvBuiltInPatchVertices:
- unreachable("no tessellation support");
- case SpvBuiltInFragCoord:
- *location = VARYING_SLOT_POS;
- assert(*mode == nir_var_shader_in);
- break;
- case SpvBuiltInPointCoord:
- *location = VARYING_SLOT_PNTC;
- assert(*mode == nir_var_shader_in);
- break;
- case SpvBuiltInFrontFacing:
- *location = VARYING_SLOT_FACE;
- assert(*mode == nir_var_shader_in);
- break;
- case SpvBuiltInSampleId:
- *location = SYSTEM_VALUE_SAMPLE_ID;
- set_mode_system_value(mode);
- break;
- case SpvBuiltInSamplePosition:
- *location = SYSTEM_VALUE_SAMPLE_POS;
- set_mode_system_value(mode);
- break;
- case SpvBuiltInSampleMask:
- *location = SYSTEM_VALUE_SAMPLE_MASK_IN; /* XXX out? */
- set_mode_system_value(mode);
- break;
- case SpvBuiltInFragDepth:
- *location = FRAG_RESULT_DEPTH;
- assert(*mode == nir_var_shader_out);
- break;
- case SpvBuiltInNumWorkgroups:
- *location = SYSTEM_VALUE_NUM_WORK_GROUPS;
- set_mode_system_value(mode);
- break;
- case SpvBuiltInWorkgroupSize:
- /* This should already be handled */
- unreachable("unsupported builtin");
- break;
- case SpvBuiltInWorkgroupId:
- *location = SYSTEM_VALUE_WORK_GROUP_ID;
- set_mode_system_value(mode);
- break;
- case SpvBuiltInLocalInvocationId:
- *location = SYSTEM_VALUE_LOCAL_INVOCATION_ID;
- set_mode_system_value(mode);
- break;
- case SpvBuiltInLocalInvocationIndex:
- *location = SYSTEM_VALUE_LOCAL_INVOCATION_INDEX;
- set_mode_system_value(mode);
- break;
- case SpvBuiltInGlobalInvocationId:
- *location = SYSTEM_VALUE_GLOBAL_INVOCATION_ID;
- set_mode_system_value(mode);
- break;
- case SpvBuiltInHelperInvocation:
- default:
- unreachable("unsupported builtin");
- }
-}
-
-static void
-var_decoration_cb(struct vtn_builder *b, struct vtn_value *val, int member,
- const struct vtn_decoration *dec, void *void_var)
-{
- struct vtn_variable *vtn_var = void_var;
-
- /* Handle decorations that apply to a vtn_variable as a whole */
- switch (dec->decoration) {
- case SpvDecorationBinding:
- vtn_var->binding = dec->literals[0];
- return;
- case SpvDecorationDescriptorSet:
- vtn_var->descriptor_set = dec->literals[0];
- return;
-
- case SpvDecorationLocation: {
- unsigned location = dec->literals[0];
- bool is_vertex_input;
- if (b->shader->stage == MESA_SHADER_FRAGMENT &&
- vtn_var->mode == vtn_variable_mode_output) {
- is_vertex_input = false;
- location += FRAG_RESULT_DATA0;
- } else if (b->shader->stage == MESA_SHADER_VERTEX &&
- vtn_var->mode == vtn_variable_mode_input) {
- is_vertex_input = true;
- location += VERT_ATTRIB_GENERIC0;
- } else if (vtn_var->mode == vtn_variable_mode_input ||
- vtn_var->mode == vtn_variable_mode_output) {
- is_vertex_input = false;
- location += VARYING_SLOT_VAR0;
- } else {
- assert(!"Location must be on input or output variable");
- }
-
- if (vtn_var->var) {
- vtn_var->var->data.location = location;
- vtn_var->var->data.explicit_location = true;
- } else {
- assert(vtn_var->members);
- unsigned length = glsl_get_length(vtn_var->type->type);
- for (unsigned i = 0; i < length; i++) {
- vtn_var->members[i]->data.location = location;
- vtn_var->members[i]->data.explicit_location = true;
- location +=
- glsl_count_attribute_slots(vtn_var->members[i]->interface_type,
- is_vertex_input);
- }
- }
- return;
- }
-
- default:
- break;
- }
-
- /* Now we handle decorations that apply to a particular nir_variable */
- nir_variable *nir_var = vtn_var->var;
- if (val->value_type == vtn_value_type_access_chain) {
- assert(val->access_chain->length == 0);
- assert(val->access_chain->var == void_var);
- assert(member == -1);
- } else {
- assert(val->value_type == vtn_value_type_type);
- if (member != -1)
- nir_var = vtn_var->members[member];
- }
-
- if (nir_var == NULL)
- return;
-
- switch (dec->decoration) {
- case SpvDecorationRelaxedPrecision:
- break; /* FIXME: Do nothing with this for now. */
- case SpvDecorationNoPerspective:
- nir_var->data.interpolation = INTERP_QUALIFIER_NOPERSPECTIVE;
- break;
- case SpvDecorationFlat:
- nir_var->data.interpolation = INTERP_QUALIFIER_FLAT;
- break;
- case SpvDecorationCentroid:
- nir_var->data.centroid = true;
- break;
- case SpvDecorationSample:
- nir_var->data.sample = true;
- break;
- case SpvDecorationInvariant:
- nir_var->data.invariant = true;
- break;
- case SpvDecorationConstant:
- assert(nir_var->constant_initializer != NULL);
- nir_var->data.read_only = true;
- break;
- case SpvDecorationNonWritable:
- nir_var->data.read_only = true;
- break;
- case SpvDecorationComponent:
- nir_var->data.location_frac = dec->literals[0];
- break;
- case SpvDecorationIndex:
- nir_var->data.explicit_index = true;
- nir_var->data.index = dec->literals[0];
- break;
- case SpvDecorationBuiltIn: {
- SpvBuiltIn builtin = dec->literals[0];
-
- if (builtin == SpvBuiltInWorkgroupSize) {
- /* This shouldn't be a builtin. It's actually a constant. */
- nir_var->data.mode = nir_var_global;
- nir_var->data.read_only = true;
-
- nir_constant *c = rzalloc(nir_var, nir_constant);
- c->value.u[0] = b->shader->info.cs.local_size[0];
- c->value.u[1] = b->shader->info.cs.local_size[1];
- c->value.u[2] = b->shader->info.cs.local_size[2];
- nir_var->constant_initializer = c;
- break;
- }
-
- nir_variable_mode mode = nir_var->data.mode;
- vtn_get_builtin_location(b, builtin, &nir_var->data.location, &mode);
- nir_var->data.explicit_location = true;
- nir_var->data.mode = mode;
-
- if (builtin == SpvBuiltInFragCoord || builtin == SpvBuiltInSamplePosition)
- nir_var->data.origin_upper_left = b->origin_upper_left;
- break;
- }
- case SpvDecorationRowMajor:
- case SpvDecorationColMajor:
- case SpvDecorationGLSLShared:
- case SpvDecorationPatch:
- case SpvDecorationRestrict:
- case SpvDecorationAliased:
- case SpvDecorationVolatile:
- case SpvDecorationCoherent:
- case SpvDecorationNonReadable:
- case SpvDecorationUniform:
- /* This is really nice but we have no use for it right now. */
- case SpvDecorationCPacked:
- case SpvDecorationSaturatedConversion:
- case SpvDecorationStream:
- case SpvDecorationOffset:
- case SpvDecorationXfbBuffer:
- case SpvDecorationFuncParamAttr:
- case SpvDecorationFPRoundingMode:
- case SpvDecorationFPFastMathMode:
- case SpvDecorationLinkageAttributes:
- case SpvDecorationSpecId:
- break;
- default:
- unreachable("Unhandled variable decoration");
- }
-}
-
-/* Tries to compute the size of an interface block based on the strides and
- * offsets that are provided to us in the SPIR-V source.
- */
-static unsigned
-vtn_type_block_size(struct vtn_type *type)
-{
- enum glsl_base_type base_type = glsl_get_base_type(type->type);
- switch (base_type) {
- case GLSL_TYPE_UINT:
- case GLSL_TYPE_INT:
- case GLSL_TYPE_FLOAT:
- case GLSL_TYPE_BOOL:
- case GLSL_TYPE_DOUBLE: {
- unsigned cols = type->row_major ? glsl_get_vector_elements(type->type) :
- glsl_get_matrix_columns(type->type);
- if (cols > 1) {
- assert(type->stride > 0);
- return type->stride * cols;
- } else if (base_type == GLSL_TYPE_DOUBLE) {
- return glsl_get_vector_elements(type->type) * 8;
- } else {
- return glsl_get_vector_elements(type->type) * 4;
- }
- }
-
- case GLSL_TYPE_STRUCT:
- case GLSL_TYPE_INTERFACE: {
- unsigned size = 0;
- unsigned num_fields = glsl_get_length(type->type);
- for (unsigned f = 0; f < num_fields; f++) {
- unsigned field_end = type->offsets[f] +
- vtn_type_block_size(type->members[f]);
- size = MAX2(size, field_end);
- }
- return size;
- }
-
- case GLSL_TYPE_ARRAY:
- assert(type->stride > 0);
- assert(glsl_get_length(type->type) > 0);
- return type->stride * glsl_get_length(type->type);
-
- default:
- assert(!"Invalid block type");
- return 0;
- }
-}
-
-void
-vtn_handle_variables(struct vtn_builder *b, SpvOp opcode,
- const uint32_t *w, unsigned count)
-{
- switch (opcode) {
- case SpvOpVariable: {
- struct vtn_variable *var = rzalloc(b, struct vtn_variable);
- var->type = vtn_value(b, w[1], vtn_value_type_type)->type;
-
- var->chain.var = var;
- var->chain.length = 0;
-
- struct vtn_value *val =
- vtn_push_value(b, w[2], vtn_value_type_access_chain);
- val->access_chain = &var->chain;
-
- struct vtn_type *without_array = var->type;
- while(glsl_type_is_array(without_array->type))
- without_array = without_array->array_element;
-
- nir_variable_mode nir_mode;
- switch ((SpvStorageClass)w[3]) {
- case SpvStorageClassUniform:
- case SpvStorageClassUniformConstant:
- if (without_array->block) {
- var->mode = vtn_variable_mode_ubo;
- b->shader->info.num_ubos++;
- } else if (without_array->buffer_block) {
- var->mode = vtn_variable_mode_ssbo;
- b->shader->info.num_ssbos++;
- } else if (glsl_type_is_image(without_array->type)) {
- var->mode = vtn_variable_mode_image;
- nir_mode = nir_var_uniform;
- b->shader->info.num_images++;
- } else if (glsl_type_is_sampler(without_array->type)) {
- var->mode = vtn_variable_mode_sampler;
- nir_mode = nir_var_uniform;
- b->shader->info.num_textures++;
- } else {
- assert(!"Invalid uniform variable type");
- }
- break;
- case SpvStorageClassPushConstant:
- var->mode = vtn_variable_mode_push_constant;
- assert(b->shader->num_uniforms == 0);
- b->shader->num_uniforms = vtn_type_block_size(var->type) * 4;
- break;
- case SpvStorageClassInput:
- var->mode = vtn_variable_mode_input;
- nir_mode = nir_var_shader_in;
- break;
- case SpvStorageClassOutput:
- var->mode = vtn_variable_mode_output;
- nir_mode = nir_var_shader_out;
- break;
- case SpvStorageClassPrivate:
- var->mode = vtn_variable_mode_global;
- nir_mode = nir_var_global;
- break;
- case SpvStorageClassFunction:
- var->mode = vtn_variable_mode_local;
- nir_mode = nir_var_local;
- break;
- case SpvStorageClassWorkgroup:
- var->mode = vtn_variable_mode_workgroup;
- nir_mode = nir_var_shared;
- break;
- case SpvStorageClassCrossWorkgroup:
- case SpvStorageClassGeneric:
- case SpvStorageClassAtomicCounter:
- default:
- unreachable("Unhandled variable storage class");
- }
-
- switch (var->mode) {
- case vtn_variable_mode_local:
- case vtn_variable_mode_global:
- case vtn_variable_mode_image:
- case vtn_variable_mode_sampler:
- case vtn_variable_mode_workgroup:
- /* For these, we create the variable normally */
- var->var = rzalloc(b->shader, nir_variable);
- var->var->name = ralloc_strdup(var->var, val->name);
- var->var->type = var->type->type;
- var->var->data.mode = nir_mode;
-
- switch (var->mode) {
- case vtn_variable_mode_image:
- case vtn_variable_mode_sampler:
- var->var->interface_type = without_array->type;
- break;
- default:
- var->var->interface_type = NULL;
- break;
- }
- break;
-
- case vtn_variable_mode_input:
- case vtn_variable_mode_output: {
- /* For inputs and outputs, we immediately split structures. This
- * is for a couple of reasons. For one, builtins may all come in
- * a struct and we really want those split out into separate
- * variables. For another, interpolation qualifiers can be
- * applied to members of the top-level struct ane we need to be
- * able to preserve that information.
- */
-
- int array_length = -1;
- struct vtn_type *interface_type = var->type;
- if (b->shader->stage == MESA_SHADER_GEOMETRY &&
- glsl_type_is_array(var->type->type)) {
- /* In Geometry shaders (and some tessellation), inputs come
- * in per-vertex arrays. However, some builtins come in
- * non-per-vertex, hence the need for the is_array check. In
- * any case, there are no non-builtin arrays allowed so this
- * check should be sufficient.
- */
- interface_type = var->type->array_element;
- array_length = glsl_get_length(var->type->type);
- }
-
- if (glsl_type_is_struct(interface_type->type)) {
- /* It's a struct. Split it. */
- unsigned num_members = glsl_get_length(interface_type->type);
- var->members = ralloc_array(b, nir_variable *, num_members);
-
- for (unsigned i = 0; i < num_members; i++) {
- const struct glsl_type *mtype = interface_type->members[i]->type;
- if (array_length >= 0)
- mtype = glsl_array_type(mtype, array_length);
-
- var->members[i] = rzalloc(b->shader, nir_variable);
- var->members[i]->name =
- ralloc_asprintf(var->members[i], "%s.%d", val->name, i);
- var->members[i]->type = mtype;
- var->members[i]->interface_type =
- interface_type->members[i]->type;
- var->members[i]->data.mode = nir_mode;
- }
- } else {
- var->var = rzalloc(b->shader, nir_variable);
- var->var->name = ralloc_strdup(var->var, val->name);
- var->var->type = var->type->type;
- var->var->interface_type = interface_type->type;
- var->var->data.mode = nir_mode;
- }
-
- /* For inputs and outputs, we need to grab locations and builtin
- * information from the interface type.
- */
- vtn_foreach_decoration(b, interface_type->val, var_decoration_cb, var);
- break;
-
- case vtn_variable_mode_param:
- unreachable("Not created through OpVariable");
- }
-
- case vtn_variable_mode_ubo:
- case vtn_variable_mode_ssbo:
- case vtn_variable_mode_push_constant:
- /* These don't need actual variables. */
- break;
- }
-
- if (count > 4) {
- assert(count == 5);
- nir_constant *constant =
- vtn_value(b, w[4], vtn_value_type_constant)->constant;
- var->var->constant_initializer =
- nir_constant_clone(constant, var->var);
- }
-
- vtn_foreach_decoration(b, val, var_decoration_cb, var);
-
- if (var->mode == vtn_variable_mode_image ||
- var->mode == vtn_variable_mode_sampler) {
- /* XXX: We still need the binding information in the nir_variable
- * for these. We should fix that.
- */
- var->var->data.binding = var->binding;
- var->var->data.descriptor_set = var->descriptor_set;
-
- if (var->mode == vtn_variable_mode_image)
- var->var->data.image.format = without_array->image_format;
- }
-
- if (var->mode == vtn_variable_mode_local) {
- assert(var->members == NULL && var->var != NULL);
- nir_function_impl_add_variable(b->impl, var->var);
- } else if (var->var) {
- nir_shader_add_variable(b->shader, var->var);
- } else if (var->members) {
- unsigned count = glsl_get_length(without_array->type);
- for (unsigned i = 0; i < count; i++) {
- assert(var->members[i]->data.mode != nir_var_local);
- nir_shader_add_variable(b->shader, var->members[i]);
- }
- } else {
- assert(var->mode == vtn_variable_mode_ubo ||
- var->mode == vtn_variable_mode_ssbo ||
- var->mode == vtn_variable_mode_push_constant);
- }
- break;
- }
-
- case SpvOpAccessChain:
- case SpvOpInBoundsAccessChain: {
- struct vtn_access_chain *base, *chain;
- struct vtn_value *base_val = vtn_untyped_value(b, w[3]);
- if (base_val->value_type == vtn_value_type_sampled_image) {
- /* This is rather insane. SPIR-V allows you to use OpSampledImage
- * to combine an array of images with a single sampler to get an
- * array of sampled images that all share the same sampler.
- * Fortunately, this means that we can more-or-less ignore the
- * sampler when crawling the access chain, but it does leave us
- * with this rather awkward little special-case.
- */
- base = base_val->sampled_image->image;
- } else {
- assert(base_val->value_type == vtn_value_type_access_chain);
- base = base_val->access_chain;
- }
-
- chain = vtn_access_chain_extend(b, base, count - 4);
-
- unsigned idx = base->length;
- for (int i = 4; i < count; i++) {
- struct vtn_value *link_val = vtn_untyped_value(b, w[i]);
- if (link_val->value_type == vtn_value_type_constant) {
- chain->link[idx].mode = vtn_access_mode_literal;
- chain->link[idx].id = link_val->constant->value.u[0];
- } else {
- chain->link[idx].mode = vtn_access_mode_id;
- chain->link[idx].id = w[i];
- }
- idx++;
- }
-
- if (base_val->value_type == vtn_value_type_sampled_image) {
- struct vtn_value *val =
- vtn_push_value(b, w[2], vtn_value_type_sampled_image);
- val->sampled_image = ralloc(b, struct vtn_sampled_image);
- val->sampled_image->image = chain;
- val->sampled_image->sampler = base_val->sampled_image->sampler;
- } else {
- struct vtn_value *val =
- vtn_push_value(b, w[2], vtn_value_type_access_chain);
- val->access_chain = chain;
- }
- break;
- }
-
- case SpvOpCopyMemory: {
- struct vtn_value *dest = vtn_value(b, w[1], vtn_value_type_access_chain);
- struct vtn_value *src = vtn_value(b, w[2], vtn_value_type_access_chain);
-
- vtn_variable_copy(b, dest->access_chain, src->access_chain);
- break;
- }
-
- case SpvOpLoad: {
- struct vtn_access_chain *src =
- vtn_value(b, w[3], vtn_value_type_access_chain)->access_chain;
-
- if (src->var->mode == vtn_variable_mode_image ||
- src->var->mode == vtn_variable_mode_sampler) {
- vtn_push_value(b, w[2], vtn_value_type_access_chain)->access_chain = src;
- return;
- }
-
- struct vtn_value *val = vtn_push_value(b, w[2], vtn_value_type_ssa);
- val->ssa = vtn_variable_load(b, src);
- break;
- }
-
- case SpvOpStore: {
- struct vtn_access_chain *dest =
- vtn_value(b, w[1], vtn_value_type_access_chain)->access_chain;
- struct vtn_ssa_value *src = vtn_ssa_value(b, w[2]);
- vtn_variable_store(b, src, dest);
- break;
- }
-
- case SpvOpArrayLength: {
- struct vtn_access_chain *chain =
- vtn_value(b, w[3], vtn_value_type_access_chain)->access_chain;
-
- const uint32_t offset = chain->var->type->offsets[w[4]];
- const uint32_t stride = chain->var->type->members[w[4]]->stride;
-
- unsigned chain_idx;
- struct vtn_type *type;
- nir_ssa_def *index =
- get_vulkan_resource_index(b, chain, &type, &chain_idx);
-
- nir_intrinsic_instr *instr =
- nir_intrinsic_instr_create(b->nb.shader,
- nir_intrinsic_get_buffer_size);
- instr->src[0] = nir_src_for_ssa(index);
- nir_ssa_dest_init(&instr->instr, &instr->dest, 1, NULL);
- nir_builder_instr_insert(&b->nb, &instr->instr);
- nir_ssa_def *buf_size = &instr->dest.ssa;
-
- /* array_length = max(buffer_size - offset, 0) / stride */
- nir_ssa_def *array_length =
- nir_idiv(&b->nb,
- nir_imax(&b->nb,
- nir_isub(&b->nb,
- buf_size,
- nir_imm_int(&b->nb, offset)),
- nir_imm_int(&b->nb, 0u)),
- nir_imm_int(&b->nb, stride));
-
- struct vtn_value *val = vtn_push_value(b, w[2], vtn_value_type_ssa);
- val->ssa = vtn_create_ssa_value(b, glsl_uint_type());
- val->ssa->def = array_length;
- break;
- }
-
- case SpvOpCopyMemorySized:
- default:
- unreachable("Unhandled opcode");
- }
-}
diff --git a/src/glsl/nir/spirv2nir.c b/src/glsl/nir/spirv2nir.c
deleted file mode 100644
index c837186bdfc..00000000000
--- a/src/glsl/nir/spirv2nir.c
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright © 2015 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- *
- * Authors:
- * Jason Ekstrand ([email protected])
- *
- */
-
-/*
- * A simple executable that opens a SPIR-V shader, converts it to NIR, and
- * dumps out the result. This should be useful for testing the
- * spirv_to_nir code.
- */
-
-#include "spirv/nir_spirv.h"
-
-#include <sys/mman.h>
-#include <sys/types.h>
-#include <fcntl.h>
-#include <unistd.h>
-
-int main(int argc, char **argv)
-{
- int fd = open(argv[1], O_RDONLY);
- off_t len = lseek(fd, 0, SEEK_END);
-
- assert(len % 4 == 0);
- size_t word_count = len / 4;
-
- const void *map = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0);
- assert(map != NULL);
-
- nir_function *func = spirv_to_nir(map, word_count, NULL, 0,
- MESA_SHADER_FRAGMENT, "main", NULL);
- nir_print_shader(func->shader, stderr);
-}
diff --git a/src/glsl/nir/tests/control_flow_tests.cpp b/src/glsl/nir/tests/control_flow_tests.cpp
deleted file mode 100644
index b9379ef3b06..00000000000
--- a/src/glsl/nir/tests/control_flow_tests.cpp
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * Copyright © 2015 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-#include <gtest/gtest.h>
-#include "nir.h"
-#include "nir_builder.h"
-
-class nir_cf_test : public ::testing::Test {
-protected:
- nir_cf_test();
- ~nir_cf_test();
-
- nir_builder b;
-};
-
-nir_cf_test::nir_cf_test()
-{
- static const nir_shader_compiler_options options = { };
- nir_builder_init_simple_shader(&b, NULL, MESA_SHADER_VERTEX, &options);
-}
-
-nir_cf_test::~nir_cf_test()
-{
- ralloc_free(b.shader);
-}
-
-TEST_F(nir_cf_test, delete_break_in_loop)
-{
- /* Create IR:
- *
- * while (...) { break; }
- */
- nir_loop *loop = nir_loop_create(b.shader);
- nir_cf_node_insert(nir_after_cf_list(&b.impl->body), &loop->cf_node);
-
- b.cursor = nir_after_cf_list(&loop->body);
-
- nir_jump_instr *jump = nir_jump_instr_create(b.shader, nir_jump_break);
- nir_builder_instr_insert(&b, &jump->instr);
-
- /* At this point, we should have:
- *
- * impl main {
- * block block_0:
- * // preds:
- * // succs: block_1
- * loop {
- * block block_1:
- * // preds: block_0
- * break
- * // succs: block_2
- * }
- * block block_2:
- * // preds: block_1
- * // succs: block_3
- * block block_3:
- * }
- */
- nir_block *block_0 = nir_start_block(b.impl);
- nir_block *block_1 = nir_cf_node_as_block(nir_loop_first_cf_node(loop));
- nir_block *block_2 = nir_cf_node_as_block(nir_cf_node_next(&loop->cf_node));
- nir_block *block_3 = b.impl->end_block;
- ASSERT_EQ(nir_cf_node_block, block_0->cf_node.type);
- ASSERT_EQ(nir_cf_node_block, block_1->cf_node.type);
- ASSERT_EQ(nir_cf_node_block, block_2->cf_node.type);
- ASSERT_EQ(nir_cf_node_block, block_3->cf_node.type);
-
- /* Verify the successors and predecessors. */
- EXPECT_EQ(block_1, block_0->successors[0]);
- EXPECT_EQ(NULL, block_0->successors[1]);
- EXPECT_EQ(block_2, block_1->successors[0]);
- EXPECT_EQ(NULL, block_1->successors[1]);
- EXPECT_EQ(block_3, block_2->successors[0]);
- EXPECT_EQ(NULL, block_2->successors[1]);
- EXPECT_EQ(NULL, block_3->successors[0]);
- EXPECT_EQ(NULL, block_3->successors[1]);
- EXPECT_EQ(0, block_0->predecessors->entries);
- EXPECT_EQ(1, block_1->predecessors->entries);
- EXPECT_EQ(1, block_2->predecessors->entries);
- EXPECT_EQ(1, block_3->predecessors->entries);
- EXPECT_TRUE(_mesa_set_search(block_1->predecessors, block_0));
- EXPECT_TRUE(_mesa_set_search(block_2->predecessors, block_1));
- EXPECT_TRUE(_mesa_set_search(block_3->predecessors, block_2));
-
- nir_print_shader(b.shader, stderr);
-
- /* Now remove the break. */
- nir_instr_remove(&jump->instr);
-
- nir_print_shader(b.shader, stderr);
-
- /* At this point, we should have:
- *
- * impl main {
- * block block_0:
- * // preds:
- * // succs: block_1
- * loop {
- * block block_1:
- * // preds: block_0 block_1
- * // succs: block_1
- * }
- * block block_2:
- * // preds: block_1
- * // succs: block_3
- * block block_3:
- * }
- *
- * Re-verify the predecessors and successors.
- */
- EXPECT_EQ(block_1, block_0->successors[0]);
- EXPECT_EQ(NULL, block_0->successors[1]);
- EXPECT_EQ(block_1, block_1->successors[0]); /* back to itself */
- EXPECT_EQ(block_2, block_1->successors[1]); /* fake successor */
- EXPECT_EQ(block_3, block_2->successors[0]);
- EXPECT_EQ(NULL, block_2->successors[1]);
- EXPECT_EQ(NULL, block_3->successors[0]);
- EXPECT_EQ(NULL, block_3->successors[1]);
- EXPECT_EQ(0, block_0->predecessors->entries);
- EXPECT_EQ(2, block_1->predecessors->entries);
- EXPECT_EQ(1, block_2->predecessors->entries);
- EXPECT_EQ(1, block_3->predecessors->entries);
- EXPECT_TRUE(_mesa_set_search(block_1->predecessors, block_0));
- EXPECT_TRUE(_mesa_set_search(block_1->predecessors, block_1));
- EXPECT_TRUE(_mesa_set_search(block_2->predecessors, block_1));
- EXPECT_TRUE(_mesa_set_search(block_3->predecessors, block_2));
-
- nir_metadata_require(b.impl, nir_metadata_dominance);
-}