aboutsummaryrefslogtreecommitdiff
path: root/mesalib/src/glsl
diff options
context:
space:
mode:
Diffstat (limited to 'mesalib/src/glsl')
-rw-r--r--mesalib/src/glsl/Makefile.sources1
-rw-r--r--mesalib/src/glsl/ast_array_index.cpp10
-rw-r--r--mesalib/src/glsl/ast_function.cpp11
-rw-r--r--mesalib/src/glsl/ast_to_hir.cpp4
-rw-r--r--mesalib/src/glsl/builtin_functions.cpp6
-rw-r--r--mesalib/src/glsl/builtin_variables.cpp9
-rw-r--r--mesalib/src/glsl/glsl_lexer.ll9
-rw-r--r--mesalib/src/glsl/glsl_parser_extras.cpp31
-rw-r--r--mesalib/src/glsl/glsl_symbol_table.cpp2
-rw-r--r--mesalib/src/glsl/glsl_types.cpp34
-rw-r--r--mesalib/src/glsl/glsl_types.h11
-rw-r--r--mesalib/src/glsl/ir.cpp58
-rw-r--r--mesalib/src/glsl/ir.h207
-rw-r--r--mesalib/src/glsl/ir_clone.cpp19
-rw-r--r--mesalib/src/glsl/ir_function.cpp11
-rw-r--r--mesalib/src/glsl/ir_optimization.h2
-rw-r--r--mesalib/src/glsl/ir_validate.cpp19
-rw-r--r--mesalib/src/glsl/link_functions.cpp14
-rw-r--r--mesalib/src/glsl/link_uniforms.cpp36
-rw-r--r--mesalib/src/glsl/link_varyings.cpp5
-rw-r--r--mesalib/src/glsl/linker.cpp31
-rw-r--r--mesalib/src/glsl/linker.h3
-rw-r--r--mesalib/src/glsl/lower_offset_array.cpp3
-rw-r--r--mesalib/src/glsl/lower_packed_varyings.cpp1
-rw-r--r--mesalib/src/glsl/lower_texture_projection.cpp2
-rw-r--r--mesalib/src/glsl/lower_ubo_reference.cpp33
-rw-r--r--mesalib/src/glsl/main.cpp1
-rw-r--r--mesalib/src/glsl/opt_algebraic.cpp14
-rw-r--r--mesalib/src/glsl/opt_cse.cpp2
-rw-r--r--mesalib/src/glsl/opt_dead_builtin_variables.cpp81
-rw-r--r--mesalib/src/glsl/test_optpass.cpp1
31 files changed, 511 insertions, 160 deletions
diff --git a/mesalib/src/glsl/Makefile.sources b/mesalib/src/glsl/Makefile.sources
index cb8d5a6f7..bfb699353 100644
--- a/mesalib/src/glsl/Makefile.sources
+++ b/mesalib/src/glsl/Makefile.sources
@@ -87,6 +87,7 @@ LIBGLSL_FILES = \
$(GLSL_SRCDIR)/opt_copy_propagation.cpp \
$(GLSL_SRCDIR)/opt_copy_propagation_elements.cpp \
$(GLSL_SRCDIR)/opt_cse.cpp \
+ $(GLSL_SRCDIR)/opt_dead_builtin_variables.cpp \
$(GLSL_SRCDIR)/opt_dead_builtin_varyings.cpp \
$(GLSL_SRCDIR)/opt_dead_code.cpp \
$(GLSL_SRCDIR)/opt_dead_code_local.cpp \
diff --git a/mesalib/src/glsl/ast_array_index.cpp b/mesalib/src/glsl/ast_array_index.cpp
index 5ca85f6ab..49a8574f2 100644
--- a/mesalib/src/glsl/ast_array_index.cpp
+++ b/mesalib/src/glsl/ast_array_index.cpp
@@ -88,8 +88,14 @@ update_max_array_access(ir_rvalue *ir, unsigned idx, YYLTYPE *loc,
unsigned field_index =
deref_record->record->type->field_index(deref_record->field);
assert(field_index < interface_type->length);
- if (idx > deref_var->var->max_ifc_array_access[field_index]) {
- deref_var->var->max_ifc_array_access[field_index] = idx;
+
+ unsigned *const max_ifc_array_access =
+ deref_var->var->get_max_ifc_array_access();
+
+ assert(max_ifc_array_access != NULL);
+
+ if (idx > max_ifc_array_access[field_index]) {
+ max_ifc_array_access[field_index] = idx;
/* Check whether this access will, as a side effect, implicitly
* cause the size of a built-in array to be too large.
diff --git a/mesalib/src/glsl/ast_function.cpp b/mesalib/src/glsl/ast_function.cpp
index 7130d6162..cbff9d8b4 100644
--- a/mesalib/src/glsl/ast_function.cpp
+++ b/mesalib/src/glsl/ast_function.cpp
@@ -408,14 +408,17 @@ generate_call(exec_list *instructions, ir_function_signature *sig,
ir_dereference_variable *deref = NULL;
if (!sig->return_type->is_void()) {
/* Create a new temporary to hold the return value. */
+ char *const name = ir_variable::temporaries_allocate_names
+ ? ralloc_asprintf(ctx, "%s_retval", sig->function_name())
+ : NULL;
+
ir_variable *var;
- var = new(ctx) ir_variable(sig->return_type,
- ralloc_asprintf(ctx, "%s_retval",
- sig->function_name()),
- ir_var_temporary);
+ var = new(ctx) ir_variable(sig->return_type, name, ir_var_temporary);
instructions->push_tail(var);
+ ralloc_free(name);
+
deref = new(ctx) ir_dereference_variable(var);
}
ir_call *call = new(ctx) ir_call(sig, deref, actual_parameters);
diff --git a/mesalib/src/glsl/ast_to_hir.cpp b/mesalib/src/glsl/ast_to_hir.cpp
index 5ec1614be..068af295a 100644
--- a/mesalib/src/glsl/ast_to_hir.cpp
+++ b/mesalib/src/glsl/ast_to_hir.cpp
@@ -912,7 +912,6 @@ get_lvalue_copy(exec_list *instructions, ir_rvalue *lvalue)
var = new(ctx) ir_variable(lvalue->type, "_post_incdec_tmp",
ir_var_temporary);
instructions->push_tail(var);
- var->data.mode = ir_var_auto;
instructions->push_tail(new(ctx) ir_assignment(new(ctx) ir_dereference_variable(var),
lvalue));
@@ -2499,6 +2498,7 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
/* If there is no qualifier that changes the mode of the variable, leave
* the setting alone.
*/
+ assert(var->data.mode != ir_var_temporary);
if (qual->flags.q.in && qual->flags.q.out)
var->data.mode = ir_var_function_inout;
else if (qual->flags.q.in)
@@ -5031,7 +5031,7 @@ ast_type_specifier::hir(exec_list *instructions,
*/
ir_variable *const junk =
new(state) ir_variable(type, "#default precision",
- ir_var_temporary);
+ ir_var_auto);
state->symbols->add_variable(junk);
}
diff --git a/mesalib/src/glsl/builtin_functions.cpp b/mesalib/src/glsl/builtin_functions.cpp
index 9be7f6d1a..5a024cb43 100644
--- a/mesalib/src/glsl/builtin_functions.cpp
+++ b/mesalib/src/glsl/builtin_functions.cpp
@@ -1882,8 +1882,8 @@ builtin_builder::create_builtins()
NULL);
add_function("texture2DProjLod",
- _texture(ir_txl, v110_lod, glsl_type::vec4_type, glsl_type::sampler2D_type, glsl_type::vec3_type, TEX_PROJECT),
- _texture(ir_txl, v110_lod, glsl_type::vec4_type, glsl_type::sampler2D_type, glsl_type::vec4_type, TEX_PROJECT),
+ _texture(ir_txl, lod_exists_in_stage, glsl_type::vec4_type, glsl_type::sampler2D_type, glsl_type::vec3_type, TEX_PROJECT),
+ _texture(ir_txl, lod_exists_in_stage, glsl_type::vec4_type, glsl_type::sampler2D_type, glsl_type::vec4_type, TEX_PROJECT),
NULL);
add_function("texture3D",
@@ -1910,7 +1910,7 @@ builtin_builder::create_builtins()
NULL);
add_function("textureCubeLod",
- _texture(ir_txl, v110_lod, glsl_type::vec4_type, glsl_type::samplerCube_type, glsl_type::vec3_type),
+ _texture(ir_txl, lod_exists_in_stage, glsl_type::vec4_type, glsl_type::samplerCube_type, glsl_type::vec3_type),
NULL);
add_function("texture2DRect",
diff --git a/mesalib/src/glsl/builtin_variables.cpp b/mesalib/src/glsl/builtin_variables.cpp
index 5b6f4ae62..c36d19831 100644
--- a/mesalib/src/glsl/builtin_variables.cpp
+++ b/mesalib/src/glsl/builtin_variables.cpp
@@ -478,12 +478,9 @@ builtin_variable_generator::add_uniform(const glsl_type *type,
&_mesa_builtin_uniform_desc[i];
const unsigned array_count = type->is_array() ? type->length : 1;
- uni->num_state_slots = array_count * statevar->num_elements;
ir_state_slot *slots =
- ralloc_array(uni, ir_state_slot, uni->num_state_slots);
-
- uni->state_slots = slots;
+ uni->allocate_state_slots(array_count * statevar->num_elements);
for (unsigned a = 0; a < array_count; a++) {
for (unsigned j = 0; j < statevar->num_elements; j++) {
@@ -908,14 +905,14 @@ builtin_variable_generator::generate_fs_special_vars()
ir_variable *const var =
add_output(FRAG_RESULT_STENCIL, int_t, "gl_FragStencilRefARB");
if (state->ARB_shader_stencil_export_warn)
- var->warn_extension = "GL_ARB_shader_stencil_export";
+ var->enable_extension_warning("GL_ARB_shader_stencil_export");
}
if (state->AMD_shader_stencil_export_enable) {
ir_variable *const var =
add_output(FRAG_RESULT_STENCIL, int_t, "gl_FragStencilRefAMD");
if (state->AMD_shader_stencil_export_warn)
- var->warn_extension = "GL_AMD_shader_stencil_export";
+ var->enable_extension_warning("GL_AMD_shader_stencil_export");
}
if (state->ARB_sample_shading_enable) {
diff --git a/mesalib/src/glsl/glsl_lexer.ll b/mesalib/src/glsl/glsl_lexer.ll
index b7c4aad3a..e66a93591 100644
--- a/mesalib/src/glsl/glsl_lexer.ll
+++ b/mesalib/src/glsl/glsl_lexer.ll
@@ -81,7 +81,8 @@ static int classify_identifier(struct _mesa_glsl_parse_state *, const char *);
"illegal use of reserved word `%s'", yytext); \
return ERROR_TOK; \
} else { \
- yylval->identifier = strdup(yytext); \
+ void *mem_ctx = yyextra; \
+ yylval->identifier = ralloc_strdup(mem_ctx, yytext); \
return classify_identifier(yyextra, yytext); \
} \
} while (0)
@@ -232,7 +233,8 @@ HASH ^{SPC}#{SPC}
<PP>[ \t\r]* { }
<PP>: return COLON;
<PP>[_a-zA-Z][_a-zA-Z0-9]* {
- yylval->identifier = strdup(yytext);
+ void *mem_ctx = yyextra;
+ yylval->identifier = ralloc_strdup(mem_ctx, yytext);
return IDENTIFIER;
}
<PP>[1-9][0-9]* {
@@ -409,7 +411,8 @@ layout {
|| yyextra->ARB_compute_shader_enable) {
return LAYOUT_TOK;
} else {
- yylval->identifier = strdup(yytext);
+ void *mem_ctx = yyextra;
+ yylval->identifier = ralloc_strdup(mem_ctx, yytext);
return classify_identifier(yyextra, yytext);
}
}
diff --git a/mesalib/src/glsl/glsl_parser_extras.cpp b/mesalib/src/glsl/glsl_parser_extras.cpp
index 490c3c8ee..cc7d2d746 100644
--- a/mesalib/src/glsl/glsl_parser_extras.cpp
+++ b/mesalib/src/glsl/glsl_parser_extras.cpp
@@ -1440,6 +1440,9 @@ _mesa_glsl_compile_shader(struct gl_context *ctx, struct gl_shader *shader,
new(shader) _mesa_glsl_parse_state(ctx, shader->Stage, shader);
const char *source = shader->Source;
+ if (ctx->Const.GenerateTemporaryNames)
+ ir_variable::temporaries_allocate_names = true;
+
state->error = glcpp_preprocess(state, &source, &state->info_log,
&ctx->Extensions, ctx);
@@ -1483,6 +1486,26 @@ _mesa_glsl_compile_shader(struct gl_context *ctx, struct gl_shader *shader,
;
validate_ir_tree(shader->ir);
+
+ enum ir_variable_mode other;
+ switch (shader->Stage) {
+ case MESA_SHADER_VERTEX:
+ other = ir_var_shader_in;
+ break;
+ case MESA_SHADER_FRAGMENT:
+ other = ir_var_shader_out;
+ break;
+ default:
+ /* Something invalid to ensure optimize_dead_builtin_uniforms
+ * doesn't remove anything other than uniforms or constants.
+ */
+ other = ir_var_mode_count;
+ break;
+ }
+
+ optimize_dead_builtin_variables(shader->ir, other);
+
+ validate_ir_tree(shader->ir);
}
if (shader->InfoLog)
@@ -1516,9 +1539,13 @@ _mesa_glsl_compile_shader(struct gl_context *ctx, struct gl_shader *shader,
case ir_type_function:
shader->symbols->add_function((ir_function *) ir);
break;
- case ir_type_variable:
- shader->symbols->add_variable((ir_variable *) ir);
+ case ir_type_variable: {
+ ir_variable *const var = (ir_variable *) ir;
+
+ if (var->data.mode != ir_var_temporary)
+ shader->symbols->add_variable(var);
break;
+ }
default:
break;
}
diff --git a/mesalib/src/glsl/glsl_symbol_table.cpp b/mesalib/src/glsl/glsl_symbol_table.cpp
index a05236203..2294dda42 100644
--- a/mesalib/src/glsl/glsl_symbol_table.cpp
+++ b/mesalib/src/glsl/glsl_symbol_table.cpp
@@ -124,6 +124,8 @@ bool glsl_symbol_table::name_declared_this_scope(const char *name)
bool glsl_symbol_table::add_variable(ir_variable *v)
{
+ assert(v->data.mode != ir_var_temporary);
+
if (this->separate_function_namespace) {
/* In 1.10, functions and variables have separate namespaces. */
symbol_table_entry *existing = get_entry(v->name);
diff --git a/mesalib/src/glsl/glsl_types.cpp b/mesalib/src/glsl/glsl_types.cpp
index 66e9b1330..c11d86482 100644
--- a/mesalib/src/glsl/glsl_types.cpp
+++ b/mesalib/src/glsl/glsl_types.cpp
@@ -490,6 +490,20 @@ glsl_type::record_compare(const glsl_type *b) const
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;
@@ -678,12 +692,17 @@ glsl_type::component_slots() const
unsigned
glsl_type::uniform_locations() const
{
- if (this->is_matrix())
- return 1;
-
unsigned size = 0;
switch (this->base_type) {
+ case GLSL_TYPE_UINT:
+ case GLSL_TYPE_INT:
+ case GLSL_TYPE_FLOAT:
+ case GLSL_TYPE_BOOL:
+ case GLSL_TYPE_SAMPLER:
+ case GLSL_TYPE_IMAGE:
+ return 1;
+
case GLSL_TYPE_STRUCT:
case GLSL_TYPE_INTERFACE:
for (unsigned i = 0; i < this->length; i++)
@@ -692,13 +711,8 @@ glsl_type::uniform_locations() const
case GLSL_TYPE_ARRAY:
return this->length * this->fields.array->uniform_locations();
default:
- break;
+ return 0;
}
-
- /* The location count for many types match with component_slots() result,
- * all expections should be handled above.
- */
- return component_slots();
}
bool
@@ -965,7 +979,7 @@ glsl_type::std140_size(bool row_major) const
if (field_type->is_record() && (i + 1 < this->length))
size = glsl_align(size, 16);
}
- size = glsl_align(size, max_align);
+ size = glsl_align(size, MAX2(max_align, 16));
return size;
}
diff --git a/mesalib/src/glsl/glsl_types.h b/mesalib/src/glsl/glsl_types.h
index d545533dc..eeb14c274 100644
--- a/mesalib/src/glsl/glsl_types.h
+++ b/mesalib/src/glsl/glsl_types.h
@@ -279,6 +279,9 @@ struct glsl_type {
/**
* 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;
@@ -486,6 +489,14 @@ struct glsl_type {
}
/**
+ * Query if a type is unnamed/anonymous (named by the parser)
+ */
+ bool is_anonymous() const
+ {
+ return !strncmp(name, "#anon", 5);
+ }
+
+ /**
* Get the type stripped of any arrays
*
* \return
diff --git a/mesalib/src/glsl/ir.cpp b/mesalib/src/glsl/ir.cpp
index 739a9f412..c712c6a7b 100644
--- a/mesalib/src/glsl/ir.cpp
+++ b/mesalib/src/glsl/ir.cpp
@@ -1543,18 +1543,44 @@ ir_swizzle::variable_referenced() const
}
+bool ir_variable::temporaries_allocate_names = false;
+
+const char ir_variable::tmp_name[] = "compiler_temp";
+
ir_variable::ir_variable(const struct glsl_type *type, const char *name,
ir_variable_mode mode)
- : ir_instruction(ir_type_variable), max_ifc_array_access(NULL)
+ : ir_instruction(ir_type_variable)
{
this->type = type;
- this->name = ralloc_strdup(this, name);
+
+ if (mode == ir_var_temporary && !ir_variable::temporaries_allocate_names)
+ name = NULL;
+
+ /* The ir_variable clone method may call this constructor with name set to
+ * tmp_name.
+ */
+ assert(name != NULL
+ || mode == ir_var_temporary
+ || mode == ir_var_function_in
+ || mode == ir_var_function_out
+ || mode == ir_var_function_inout);
+ assert(name != ir_variable::tmp_name
+ || mode == ir_var_temporary);
+ if (mode == ir_var_temporary
+ && (name == NULL || name == ir_variable::tmp_name)) {
+ this->name = ir_variable::tmp_name;
+ } else {
+ this->name = ralloc_strdup(this, name);
+ }
+
+ this->u.max_ifc_array_access = NULL;
+
this->data.explicit_location = false;
this->data.has_initializer = false;
this->data.location = -1;
this->data.location_frac = 0;
this->data.binding = 0;
- this->warn_extension = NULL;
+ this->data.warn_extension_index = 0;
this->constant_value = NULL;
this->constant_initializer = NULL;
this->data.origin_upper_left = false;
@@ -1617,6 +1643,32 @@ ir_variable::determine_interpolation_mode(bool flat_shade)
return INTERP_QUALIFIER_SMOOTH;
}
+const char *const ir_variable::warn_extension_table[] = {
+ "",
+ "GL_ARB_shader_stencil_export",
+ "GL_AMD_shader_stencil_export",
+};
+
+void
+ir_variable::enable_extension_warning(const char *extension)
+{
+ for (unsigned i = 0; i < Elements(warn_extension_table); i++) {
+ if (strcmp(warn_extension_table[i], extension) == 0) {
+ this->data.warn_extension_index = i;
+ return;
+ }
+ }
+
+ assert(!"Should not get here.");
+ this->data.warn_extension_index = 0;
+}
+
+const char *
+ir_variable::get_extension_warning() const
+{
+ return this->data.warn_extension_index == 0
+ ? NULL : warn_extension_table[this->data.warn_extension_index];
+}
ir_function_signature::ir_function_signature(const glsl_type *return_type,
builtin_available_predicate b)
diff --git a/mesalib/src/glsl/ir.h b/mesalib/src/glsl/ir.h
index 8003f88ce..90c443c3d 100644
--- a/mesalib/src/glsl/ir.h
+++ b/mesalib/src/glsl/ir.h
@@ -475,7 +475,7 @@ public:
assert(this->interface_type == NULL);
this->interface_type = type;
if (this->is_interface_instance()) {
- this->max_ifc_array_access =
+ this->u.max_ifc_array_access =
rzalloc_array(this, unsigned, type->length);
}
}
@@ -487,7 +487,7 @@ public:
*/
void change_interface_type(const struct glsl_type *type)
{
- if (this->max_ifc_array_access != NULL) {
+ if (this->u.max_ifc_array_access != NULL) {
/* max_ifc_array_access has already been allocated, so make sure the
* new interface has the same number of fields as the old one.
*/
@@ -504,7 +504,7 @@ public:
*/
void reinit_interface_type(const struct glsl_type *type)
{
- if (this->max_ifc_array_access != NULL) {
+ if (this->u.max_ifc_array_access != NULL) {
#ifndef NDEBUG
/* Redeclaring gl_PerVertex is only allowed if none of the built-ins
* it defines have been accessed yet; so it's safe to throw away the
@@ -512,10 +512,10 @@ public:
* zero.
*/
for (unsigned i = 0; i < this->interface_type->length; i++)
- assert(this->max_ifc_array_access[i] == 0);
+ assert(this->u.max_ifc_array_access[i] == 0);
#endif
- ralloc_free(this->max_ifc_array_access);
- this->max_ifc_array_access = NULL;
+ ralloc_free(this->u.max_ifc_array_access);
+ this->u.max_ifc_array_access = NULL;
}
this->interface_type = NULL;
init_interface_type(type);
@@ -527,27 +527,80 @@ public:
}
/**
- * Declared type of the variable
+ * Get the max_ifc_array_access pointer
+ *
+ * A "set" function is not needed because the array is dynmically allocated
+ * as necessary.
*/
- const struct glsl_type *type;
+ inline unsigned *get_max_ifc_array_access()
+ {
+ assert(this->data._num_state_slots == 0);
+ return this->u.max_ifc_array_access;
+ }
+
+ inline unsigned get_num_state_slots() const
+ {
+ assert(!this->is_interface_instance()
+ || this->data._num_state_slots == 0);
+ return this->data._num_state_slots;
+ }
+
+ inline void set_num_state_slots(unsigned n)
+ {
+ assert(!this->is_interface_instance()
+ || n == 0);
+ this->data._num_state_slots = n;
+ }
+
+ inline ir_state_slot *get_state_slots()
+ {
+ return this->is_interface_instance() ? NULL : this->u.state_slots;
+ }
+
+ inline const ir_state_slot *get_state_slots() const
+ {
+ return this->is_interface_instance() ? NULL : this->u.state_slots;
+ }
+
+ inline ir_state_slot *allocate_state_slots(unsigned n)
+ {
+ assert(!this->is_interface_instance());
+
+ this->u.state_slots = ralloc_array(this, ir_state_slot, n);
+ this->data._num_state_slots = 0;
+
+ if (this->u.state_slots != NULL)
+ this->data._num_state_slots = n;
+
+ return this->u.state_slots;
+ }
+
+ inline bool is_name_ralloced() const
+ {
+ return this->name != ir_variable::tmp_name;
+ }
/**
- * Declared name of the variable
+ * Enable emitting extension warnings for this variable
*/
- const char *name;
+ void enable_extension_warning(const char *extension);
/**
- * For variables which satisfy the is_interface_instance() predicate, this
- * points to an array of integers such that if the ith member of the
- * interface block is an array, max_ifc_array_access[i] is the maximum
- * array element of that member that has been accessed. If the ith member
- * of the interface block is not an array, max_ifc_array_access[i] is
- * unused.
+ * Get the extension warning string for this variable
*
- * For variables whose type is not an interface block, this pointer is
- * NULL.
+ * If warnings are not enabled, \c NULL is returned.
+ */
+ const char *get_extension_warning() const;
+
+ /**
+ * Declared type of the variable
+ */
+ const struct glsl_type *type;
+
+ /**
+ * Declared name of the variable
*/
- unsigned *max_ifc_array_access;
+ const char *name;
struct ir_variable_data {
@@ -697,6 +750,13 @@ public:
*/
unsigned index: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.
+ */
+ ir_depth_layout depth_layout:3;
/**
* ARB_shader_image_load_store qualifiers.
@@ -707,16 +767,34 @@ public:
unsigned image_volatile:1;
unsigned image_restrict:1;
+ /**
+ * Emit a warning if this variable is accessed.
+ */
+ private:
+ uint8_t warn_extension_index;
+
+ public:
/** Image internal format if specified explicitly, otherwise GL_NONE. */
uint16_t image_format;
+ private:
/**
- * \brief Layout qualifier for gl_FragDepth.
+ * Number of state slots used
*
- * 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.
+ * \note
+ * This could be stored in as few as 7-bits, if necessary. If it is made
+ * smaller, add an assertion to \c ir_variable::allocate_state_slots to
+ * be safe.
*/
- ir_depth_layout depth_layout;
+ uint16_t _num_state_slots;
+
+ public:
+ /**
+ * Initial binding point for a sampler, atomic, or UBO.
+ *
+ * For array types, this represents the binding point for the first element.
+ */
+ int16_t binding;
/**
* Storage location of the base of this variable
@@ -744,13 +822,6 @@ public:
unsigned stream;
/**
- * Initial binding point for a sampler, atomic, or UBO.
- *
- * For array types, this represents the binding point for the first element.
- */
- int binding;
-
- /**
* Location an atomic counter is stored at.
*/
struct {
@@ -764,30 +835,13 @@ public:
*/
unsigned max_array_access;
+ /**
+ * Allow (only) ir_variable direct access private members.
+ */
+ friend class ir_variable;
} 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 */
- ir_state_slot *state_slots; /**< State descriptors. */
- /*@}*/
-
- /**
- * Emit a warning if this variable is accessed.
- */
- const char *warn_extension;
-
- /**
* Value assigned in the initializer of a variable declared "const"
*/
ir_constant *constant_value;
@@ -803,6 +857,33 @@ public:
ir_constant *constant_initializer;
private:
+ static const char *const warn_extension_table[];
+
+ union {
+ /**
+ * For variables which satisfy the is_interface_instance() predicate,
+ * this points to an array of integers such that if the ith member of
+ * the interface block is an array, max_ifc_array_access[i] is the
+ * maximum array element of that member that has been accessed. If the
+ * ith member of the interface block is not an array,
+ * max_ifc_array_access[i] is unused.
+ *
+ * For variables whose type is not an interface block, this pointer is
+ * NULL.
+ */
+ unsigned *max_ifc_array_access;
+
+ /**
+ * Built-in state that backs this uniform
+ *
+ * Once set at variable creation, \c state_slots must remain invariant.
+ *
+ * If the variable is not a uniform, \c _num_state_slots will be zero
+ * and \c state_slots will be \c NULL.
+ */
+ ir_state_slot *state_slots;
+ } u;
+
/**
* 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.
@@ -810,6 +891,30 @@ private:
* \sa ir_variable::location
*/
const glsl_type *interface_type;
+
+ /**
+ * Name used for anonymous compiler temporaries
+ */
+ static const char tmp_name[];
+
+public:
+ /**
+ * Should the construct keep names for ir_var_temporary variables?
+ *
+ * When this global is false, names passed to the constructor for
+ * \c ir_var_temporary variables will be dropped. Instead, the variable will
+ * be named "compiler_temp". This name will be in static storage.
+ *
+ * \warning
+ * \b NEVER change the mode of an \c ir_var_temporary.
+ *
+ * \warning
+ * This variable is \b not thread-safe. It is global, \b not
+ * per-context. It begins life false. A context can, at some point, make
+ * it true. From that point on, it will be true forever. This should be
+ * okay since it will only be set true while debugging.
+ */
+ static bool temporaries_allocate_names;
};
/**
diff --git a/mesalib/src/glsl/ir_clone.cpp b/mesalib/src/glsl/ir_clone.cpp
index 4b444d468..dffa57844 100644
--- a/mesalib/src/glsl/ir_clone.cpp
+++ b/mesalib/src/glsl/ir_clone.cpp
@@ -45,25 +45,18 @@ ir_variable::clone(void *mem_ctx, struct hash_table *ht) const
var->data.max_array_access = this->data.max_array_access;
if (this->is_interface_instance()) {
- var->max_ifc_array_access =
+ var->u.max_ifc_array_access =
rzalloc_array(var, unsigned, this->interface_type->length);
- memcpy(var->max_ifc_array_access, this->max_ifc_array_access,
+ memcpy(var->u.max_ifc_array_access, this->u.max_ifc_array_access,
this->interface_type->length * sizeof(unsigned));
}
memcpy(&var->data, &this->data, sizeof(var->data));
- var->warn_extension = this->warn_extension;
-
- var->num_state_slots = this->num_state_slots;
- if (this->state_slots) {
- /* FINISHME: This really wants to use something like talloc_reference, but
- * FINISHME: ralloc doesn't have any similar function.
- */
- var->state_slots = ralloc_array(var, ir_state_slot,
- this->num_state_slots);
- memcpy(var->state_slots, this->state_slots,
- sizeof(this->state_slots[0]) * var->num_state_slots);
+ if (this->get_state_slots()) {
+ ir_state_slot *s = var->allocate_state_slots(this->get_num_state_slots());
+ memcpy(s, this->get_state_slots(),
+ sizeof(s[0]) * var->get_num_state_slots());
}
if (this->constant_value)
diff --git a/mesalib/src/glsl/ir_function.cpp b/mesalib/src/glsl/ir_function.cpp
index 98bec45ce..2b2643c64 100644
--- a/mesalib/src/glsl/ir_function.cpp
+++ b/mesalib/src/glsl/ir_function.cpp
@@ -24,6 +24,7 @@
#include "glsl_types.h"
#include "ir.h"
#include "glsl_parser_extras.h"
+#include "main/errors.h"
typedef enum {
PARAMETER_LIST_NO_MATCH,
@@ -296,6 +297,7 @@ ir_function::matching_signature(_mesa_glsl_parse_state *state,
bool *is_exact)
{
ir_function_signature **inexact_matches = NULL;
+ ir_function_signature **inexact_matches_temp;
ir_function_signature *match = NULL;
int num_inexact_matches = 0;
@@ -321,11 +323,16 @@ ir_function::matching_signature(_mesa_glsl_parse_state *state,
free(inexact_matches);
return sig;
case PARAMETER_LIST_INEXACT_MATCH:
- inexact_matches = (ir_function_signature **)
+ inexact_matches_temp = (ir_function_signature **)
realloc(inexact_matches,
sizeof(*inexact_matches) *
(num_inexact_matches + 1));
- assert(inexact_matches);
+ if (inexact_matches_temp == NULL) {
+ _mesa_error_no_memory(__func__);
+ free(inexact_matches);
+ return NULL;
+ }
+ inexact_matches = inexact_matches_temp;
inexact_matches[num_inexact_matches++] = sig;
continue;
case PARAMETER_LIST_NO_MATCH:
diff --git a/mesalib/src/glsl/ir_optimization.h b/mesalib/src/glsl/ir_optimization.h
index 369dcd15b..0c3a63831 100644
--- a/mesalib/src/glsl/ir_optimization.h
+++ b/mesalib/src/glsl/ir_optimization.h
@@ -125,6 +125,8 @@ void lower_named_interface_blocks(void *mem_ctx, gl_shader *shader);
bool optimize_redundant_jumps(exec_list *instructions);
bool optimize_split_arrays(exec_list *instructions, bool linked);
bool lower_offset_arrays(exec_list *instructions);
+void optimize_dead_builtin_variables(exec_list *instructions,
+ enum ir_variable_mode other);
bool lower_vertex_id(gl_shader *shader);
diff --git a/mesalib/src/glsl/ir_validate.cpp b/mesalib/src/glsl/ir_validate.cpp
index 97a581dc2..5a6f8bbf5 100644
--- a/mesalib/src/glsl/ir_validate.cpp
+++ b/mesalib/src/glsl/ir_validate.cpp
@@ -654,7 +654,7 @@ ir_validate::visit(ir_variable *ir)
* in the ir_dereference_variable handler to ensure that a variable is
* declared before it is dereferenced.
*/
- if (ir->name)
+ if (ir->name && ir->is_name_ralloced())
assert(ralloc_parent(ir->name) == ir);
hash_table_insert(ht, ir, ir);
@@ -682,10 +682,15 @@ ir_validate::visit(ir_variable *ir)
ir->get_interface_type()->fields.structure;
for (unsigned i = 0; i < ir->get_interface_type()->length; i++) {
if (fields[i].type->array_size() > 0) {
- if (ir->max_ifc_array_access[i] >= fields[i].type->length) {
+ const unsigned *const max_ifc_array_access =
+ ir->get_max_ifc_array_access();
+
+ assert(max_ifc_array_access != NULL);
+
+ if (max_ifc_array_access[i] >= fields[i].type->length) {
printf("ir_variable has maximum access out of bounds for "
"field %s (%d vs %d)\n", fields[i].name,
- ir->max_ifc_array_access[i], fields[i].type->length);
+ max_ifc_array_access[i], fields[i].type->length);
ir->print();
abort();
}
@@ -700,6 +705,14 @@ ir_validate::visit(ir_variable *ir)
abort();
}
+ if (ir->data.mode == ir_var_uniform
+ && strncmp(ir->name, "gl_", 3) == 0
+ && ir->get_state_slots() == NULL) {
+ printf("built-in uniform has no state\n");
+ ir->print();
+ abort();
+ }
+
return visit_continue;
}
diff --git a/mesalib/src/glsl/link_functions.cpp b/mesalib/src/glsl/link_functions.cpp
index d62c16853..537f4dc77 100644
--- a/mesalib/src/glsl/link_functions.cpp
+++ b/mesalib/src/glsl/link_functions.cpp
@@ -245,11 +245,19 @@ public:
/* Similarly, we need implicit sizes of arrays within interface
* blocks to be sized by the maximal access in *any* shader.
*/
+ unsigned *const linked_max_ifc_array_access =
+ var->get_max_ifc_array_access();
+ unsigned *const ir_max_ifc_array_access =
+ ir->var->get_max_ifc_array_access();
+
+ assert(linked_max_ifc_array_access != NULL);
+ assert(ir_max_ifc_array_access != NULL);
+
for (unsigned i = 0; i < var->get_interface_type()->length;
i++) {
- var->max_ifc_array_access[i] =
- MAX2(var->max_ifc_array_access[i],
- ir->var->max_ifc_array_access[i]);
+ linked_max_ifc_array_access[i] =
+ MAX2(linked_max_ifc_array_access[i],
+ ir_max_ifc_array_access[i]);
}
}
}
diff --git a/mesalib/src/glsl/link_uniforms.cpp b/mesalib/src/glsl/link_uniforms.cpp
index 258d279ea..400e13479 100644
--- a/mesalib/src/glsl/link_uniforms.cpp
+++ b/mesalib/src/glsl/link_uniforms.cpp
@@ -749,7 +749,7 @@ link_update_uniform_buffer_variables(struct gl_shader *shader)
if (end == NULL)
continue;
- if (l != (end - begin))
+ if ((ptrdiff_t) l != (end - begin))
continue;
if (strncmp(var->name, begin, l) == 0) {
@@ -771,40 +771,6 @@ link_update_uniform_buffer_variables(struct gl_shader *shader)
}
}
-void
-link_assign_uniform_block_offsets(struct gl_shader *shader)
-{
- for (unsigned b = 0; b < shader->NumUniformBlocks; b++) {
- struct gl_uniform_block *block = &shader->UniformBlocks[b];
-
- unsigned offset = 0;
- for (unsigned int i = 0; i < block->NumUniforms; i++) {
- struct gl_uniform_buffer_variable *ubo_var = &block->Uniforms[i];
- const struct glsl_type *type = ubo_var->Type;
-
- unsigned alignment = type->std140_base_alignment(ubo_var->RowMajor);
- unsigned size = type->std140_size(ubo_var->RowMajor);
-
- offset = glsl_align(offset, alignment);
- ubo_var->Offset = offset;
- offset += size;
- }
-
- /* From the GL_ARB_uniform_buffer_object spec:
- *
- * "For uniform blocks laid out according to [std140] rules,
- * the minimum buffer object size returned by the
- * UNIFORM_BLOCK_DATA_SIZE query is derived by taking the
- * offset of the last basic machine unit consumed by the
- * last uniform of the uniform block (including any
- * end-of-array or end-of-structure padding), adding one,
- * and rounding up to the next multiple of the base
- * alignment required for a vec4."
- */
- block->UniformBufferSize = glsl_align(offset, 16);
- }
-}
-
/**
* Scan the program for image uniforms and store image unit access
* information into the gl_shader data structure.
diff --git a/mesalib/src/glsl/link_varyings.cpp b/mesalib/src/glsl/link_varyings.cpp
index 54ceae1b9..a738e2f38 100644
--- a/mesalib/src/glsl/link_varyings.cpp
+++ b/mesalib/src/glsl/link_varyings.cpp
@@ -318,6 +318,11 @@ tfeedback_decl::init(struct gl_context *ctx, const void *mem_ctx,
const char *base_name_end;
long subscript = parse_program_resource_name(input, &base_name_end);
this->var_name = ralloc_strndup(mem_ctx, input, base_name_end - input);
+ if (this->var_name == NULL) {
+ _mesa_error_no_memory(__func__);
+ return;
+ }
+
if (subscript >= 0) {
this->array_subscript = subscript;
this->is_subscripted = true;
diff --git a/mesalib/src/glsl/linker.cpp b/mesalib/src/glsl/linker.cpp
index 7689198b0..47a722d9d 100644
--- a/mesalib/src/glsl/linker.cpp
+++ b/mesalib/src/glsl/linker.cpp
@@ -976,7 +976,8 @@ populate_symbol_table(gl_shader *sh)
if ((func = inst->as_function()) != NULL) {
sh->symbols->add_function(func);
} else if ((var = inst->as_variable()) != NULL) {
- sh->symbols->add_variable(var);
+ if (var->data.mode != ir_var_temporary)
+ sh->symbols->add_variable(var);
}
}
}
@@ -1173,7 +1174,8 @@ public:
if (var->type->is_interface()) {
if (interface_contains_unsized_arrays(var->type)) {
const glsl_type *new_type =
- resize_interface_members(var->type, var->max_ifc_array_access);
+ resize_interface_members(var->type,
+ var->get_max_ifc_array_access());
var->type = new_type;
var->change_interface_type(new_type);
}
@@ -1182,7 +1184,7 @@ public:
if (interface_contains_unsized_arrays(var->type->fields.array)) {
const glsl_type *new_type =
resize_interface_members(var->type->fields.array,
- var->max_ifc_array_access);
+ var->get_max_ifc_array_access());
var->change_interface_type(new_type);
var->type =
glsl_type::get_array_instance(new_type, var->type->length);
@@ -1714,12 +1716,19 @@ link_intrastage_shaders(void *mem_ctx,
*/
gl_shader **linking_shaders = (gl_shader **)
calloc(num_shaders + 1, sizeof(gl_shader *));
- memcpy(linking_shaders, shader_list, num_shaders * sizeof(gl_shader *));
- linking_shaders[num_shaders] = _mesa_glsl_get_builtin_function_shader();
- ok = link_function_calls(prog, linked, linking_shaders, num_shaders + 1);
+ ok = linking_shaders != NULL;
- free(linking_shaders);
+ if (ok) {
+ memcpy(linking_shaders, shader_list, num_shaders * sizeof(gl_shader *));
+ linking_shaders[num_shaders] = _mesa_glsl_get_builtin_function_shader();
+
+ ok = link_function_calls(prog, linked, linking_shaders, num_shaders + 1);
+
+ free(linking_shaders);
+ } else {
+ _mesa_error_no_memory(__func__);
+ }
} else {
ok = link_function_calls(prog, linked, shader_list, num_shaders);
}
@@ -1824,9 +1833,10 @@ update_array_sizes(struct gl_shader_program *prog)
* Determine the number of slots per array element by dividing by
* the old (total) size.
*/
- if (var->num_state_slots > 0) {
- var->num_state_slots = (size + 1)
- * (var->num_state_slots / var->type->length);
+ const unsigned num_slots = var->get_num_state_slots();
+ if (num_slots > 0) {
+ var->set_num_state_slots((size + 1)
+ * (num_slots / var->type->length));
}
var->type = glsl_type::get_array_instance(var->type->fields.array,
@@ -2176,6 +2186,7 @@ demote_shader_inputs_and_outputs(gl_shader *sh, enum ir_variable_mode mode)
* to have a location assigned.
*/
if (var->data.is_unmatched_generic_inout) {
+ assert(var->data.mode != ir_var_temporary);
var->data.mode = ir_var_auto;
}
}
diff --git a/mesalib/src/glsl/linker.h b/mesalib/src/glsl/linker.h
index 9440794e2..6ee585898 100644
--- a/mesalib/src/glsl/linker.h
+++ b/mesalib/src/glsl/linker.h
@@ -50,9 +50,6 @@ link_cross_validate_uniform_block(void *mem_ctx,
unsigned int *num_linked_blocks,
struct gl_uniform_block *new_block);
-void
-link_assign_uniform_block_offsets(struct gl_shader *shader);
-
extern bool
link_uniform_blocks_are_compatible(const gl_uniform_block *a,
const gl_uniform_block *b);
diff --git a/mesalib/src/glsl/lower_offset_array.cpp b/mesalib/src/glsl/lower_offset_array.cpp
index 0c235eda3..5b48526db 100644
--- a/mesalib/src/glsl/lower_offset_array.cpp
+++ b/mesalib/src/glsl/lower_offset_array.cpp
@@ -63,7 +63,8 @@ brw_lower_offset_array_visitor::handle_rvalue(ir_rvalue **rv)
void *mem_ctx = ralloc_parent(ir);
- ir_variable *var = new (mem_ctx) ir_variable(ir->type, "result", ir_var_auto);
+ ir_variable *var =
+ new (mem_ctx) ir_variable(ir->type, "result", ir_var_temporary);
base_ir->insert_before(var);
for (int i = 0; i < 4; i++) {
diff --git a/mesalib/src/glsl/lower_packed_varyings.cpp b/mesalib/src/glsl/lower_packed_varyings.cpp
index 780148315..5e844c792 100644
--- a/mesalib/src/glsl/lower_packed_varyings.cpp
+++ b/mesalib/src/glsl/lower_packed_varyings.cpp
@@ -261,6 +261,7 @@ lower_packed_varyings_visitor::run(exec_list *instructions)
!var->type->contains_integer());
/* Change the old varying into an ordinary global. */
+ assert(var->data.mode != ir_var_temporary);
var->data.mode = ir_var_auto;
/* Create a reference to the old varying. */
diff --git a/mesalib/src/glsl/lower_texture_projection.cpp b/mesalib/src/glsl/lower_texture_projection.cpp
index 16d637680..95df106d9 100644
--- a/mesalib/src/glsl/lower_texture_projection.cpp
+++ b/mesalib/src/glsl/lower_texture_projection.cpp
@@ -62,7 +62,7 @@ lower_texture_projection_visitor::visit_leave(ir_texture *ir)
void *mem_ctx = ralloc_parent(ir);
ir_variable *var = new(mem_ctx) ir_variable(ir->projector->type,
- "projector", ir_var_auto);
+ "projector", ir_var_temporary);
base_ir->insert_before(var);
ir_dereference *deref = new(mem_ctx) ir_dereference_variable(var);
ir_expression *expr = new(mem_ctx) ir_expression(ir_unop_rcp,
diff --git a/mesalib/src/glsl/lower_ubo_reference.cpp b/mesalib/src/glsl/lower_ubo_reference.cpp
index 3cdfc04ac..43dd067fa 100644
--- a/mesalib/src/glsl/lower_ubo_reference.cpp
+++ b/mesalib/src/glsl/lower_ubo_reference.cpp
@@ -111,7 +111,7 @@ is_dereferenced_thing_row_major(const ir_dereference *deref)
case GLSL_MATRIX_LAYOUT_COLUMN_MAJOR:
return false;
case GLSL_MATRIX_LAYOUT_ROW_MAJOR:
- return matrix || deref->type->is_record();
+ return matrix || deref->type->without_array()->is_record();
}
unreachable("invalid matrix layout");
@@ -301,7 +301,14 @@ lower_ubo_reference_visitor::handle_rvalue(ir_rvalue **rvalue)
deref = deref_array->array->as_dereference();
break;
} else {
- array_stride = deref_array->type->std140_size(row_major);
+ /* Whether or not the field is row-major (because it might be a
+ * bvec2 or something) does not affect the array itself. We need
+ * to know whether an array element in its entirety is row-major.
+ */
+ const bool array_row_major =
+ is_dereferenced_thing_row_major(deref_array);
+
+ array_stride = deref_array->type->std140_size(array_row_major);
array_stride = glsl_align(array_stride, 16);
}
@@ -327,6 +334,15 @@ lower_ubo_reference_visitor::handle_rvalue(ir_rvalue **rvalue)
const glsl_type *struct_type = deref_record->record->type;
unsigned intra_struct_offset = 0;
+ /* glsl_type::std140_base_alignment doesn't grok interfaces. Use
+ * 16-bytes for the alignment because that is the general minimum of
+ * std140.
+ */
+ const unsigned struct_alignment = struct_type->is_interface()
+ ? 16
+ : struct_type->std140_base_alignment(row_major);
+
+
for (unsigned int i = 0; i < struct_type->length; i++) {
const glsl_type *type = struct_type->fields.structure[i].type;
@@ -346,6 +362,19 @@ lower_ubo_reference_visitor::handle_rvalue(ir_rvalue **rvalue)
deref_record->field) == 0)
break;
intra_struct_offset += type->std140_size(field_row_major);
+
+ /* If the field just examined was itself a structure, apply rule
+ * #9:
+ *
+ * "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 (type->without_array()->is_record()) {
+ intra_struct_offset = glsl_align(intra_struct_offset,
+ struct_alignment);
+
+ }
}
const_offset += intra_struct_offset;
diff --git a/mesalib/src/glsl/main.cpp b/mesalib/src/glsl/main.cpp
index a4452e023..feed10082 100644
--- a/mesalib/src/glsl/main.cpp
+++ b/mesalib/src/glsl/main.cpp
@@ -210,6 +210,7 @@ initialize_context(struct gl_context *ctx, gl_api api)
break;
}
+ ctx->Const.GenerateTemporaryNames = true;
ctx->Driver.NewShader = _mesa_new_shader;
}
diff --git a/mesalib/src/glsl/opt_algebraic.cpp b/mesalib/src/glsl/opt_algebraic.cpp
index 447618f9e..0cdb8ecfc 100644
--- a/mesalib/src/glsl/opt_algebraic.cpp
+++ b/mesalib/src/glsl/opt_algebraic.cpp
@@ -357,6 +357,20 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir)
if (op_expr[0]->operation == ir_unop_log2) {
return op_expr[0]->operands[0];
}
+
+ if (!options->EmitNoPow && op_expr[0]->operation == ir_binop_mul) {
+ for (int log2_pos = 0; log2_pos < 2; log2_pos++) {
+ ir_expression *log2_expr =
+ op_expr[0]->operands[log2_pos]->as_expression();
+
+ if (log2_expr && log2_expr->operation == ir_unop_log2) {
+ return new(mem_ctx) ir_expression(ir_binop_pow,
+ ir->type,
+ log2_expr->operands[0],
+ op_expr[0]->operands[1 - log2_pos]);
+ }
+ }
+ }
break;
case ir_unop_log2:
diff --git a/mesalib/src/glsl/opt_cse.cpp b/mesalib/src/glsl/opt_cse.cpp
index 0e720cc26..9c96835dd 100644
--- a/mesalib/src/glsl/opt_cse.cpp
+++ b/mesalib/src/glsl/opt_cse.cpp
@@ -276,7 +276,7 @@ cse_visitor::try_cse(ir_rvalue *rvalue)
ir_variable *var = new(rvalue) ir_variable(rvalue->type,
"cse",
- ir_var_auto);
+ ir_var_temporary);
/* Write the previous expression result into a new variable. */
base_ir->insert_before(var);
diff --git a/mesalib/src/glsl/opt_dead_builtin_variables.cpp b/mesalib/src/glsl/opt_dead_builtin_variables.cpp
new file mode 100644
index 000000000..85c75d6f2
--- /dev/null
+++ b/mesalib/src/glsl/opt_dead_builtin_variables.cpp
@@ -0,0 +1,81 @@
+/*
+ * 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 "ir.h"
+#include "ir_visitor.h"
+#include "ir_optimization.h"
+
+/**
+ * Pre-linking, optimize unused built-in variables
+ *
+ * Uniforms, constants, system values, inputs (vertex shader only), and
+ * outputs (fragment shader only) that are not used can be removed.
+ */
+void
+optimize_dead_builtin_variables(exec_list *instructions,
+ enum ir_variable_mode other)
+{
+ foreach_in_list_safe(ir_variable, var, instructions) {
+ if (var->ir_type != ir_type_variable || var->data.used)
+ continue;
+
+ if (var->data.mode != ir_var_uniform
+ && var->data.mode != ir_var_auto
+ && var->data.mode != ir_var_system_value
+ && var->data.mode != other)
+ continue;
+
+ /* So that linker rules can later be enforced, we cannot elimate
+ * variables that were redeclared in the shader code.
+ */
+ if ((var->data.mode == other || var->data.mode == ir_var_system_value)
+ && var->data.how_declared != ir_var_declared_implicitly)
+ continue;
+
+ if (strncmp(var->name, "gl_", 3) != 0)
+ continue;
+
+ /* gl_ModelViewProjectionMatrix and gl_Vertex are special because they
+ * are used by ftransform. No other built-in variable is used by a
+ * built-in function. The forward declarations of these variables in
+ * the built-in function shader does not have the "state slot"
+ * information, so removing these variables from the user shader will
+ * cause problems later.
+ *
+ * Matrix uniforms with "Transpose" are not eliminated because there's
+ * an optimization pass that can turn references to the regular matrix
+ * into references to the transpose matrix. Eliminating the transpose
+ * matrix would cause that pass to generate references to undeclareds
+ * variables (thank you, ir_validate).
+ *
+ * It doesn't seem worth the effort to track when the transpose could be
+ * eliminated (i.e., when the non-transpose was eliminated).
+ */
+ if (strcmp(var->name, "gl_ModelViewProjectionMatrix") == 0
+ || strcmp(var->name, "gl_Vertex") == 0
+ || strstr(var->name, "Transpose") != NULL)
+ continue;
+
+ var->remove();
+ }
+}
diff --git a/mesalib/src/glsl/test_optpass.cpp b/mesalib/src/glsl/test_optpass.cpp
index 24c06f11b..ac3e3f48c 100644
--- a/mesalib/src/glsl/test_optpass.cpp
+++ b/mesalib/src/glsl/test_optpass.cpp
@@ -200,6 +200,7 @@ int test_optpass(int argc, char **argv)
initialize_context_to_defaults(ctx, API_OPENGL_COMPAT);
ctx->Driver.NewShader = _mesa_new_shader;
+ ir_variable::temporaries_allocate_names = true;
struct gl_shader *shader = rzalloc(NULL, struct gl_shader);
shader->Type = shader_type;