[Mesa-dev] [PATCH 1/4] nir/instr_set: Add an allow_loads field
Iago Toral Quiroga
itoral at igalia.com
Tue Oct 27 02:28:58 PDT 2015
We need this so we can configure different behaviors for passes that
cannot deal with side-effectful instructions (CSE) and passes that can
(we will add a load-combine pass shortly).
For now, when allow_loads is true, we let the instruction set rewrite
SSBO loads.
---
src/glsl/nir/nir_instr_set.c | 51 ++++++++++++++++++++++++++++----------------
src/glsl/nir/nir_instr_set.h | 20 ++++++++++++-----
src/glsl/nir/nir_opt_cse.c | 4 ++--
3 files changed, 50 insertions(+), 25 deletions(-)
diff --git a/src/glsl/nir/nir_instr_set.c b/src/glsl/nir/nir_instr_set.c
index d3f939f..583618f 100644
--- a/src/glsl/nir/nir_instr_set.c
+++ b/src/glsl/nir/nir_instr_set.c
@@ -398,6 +398,13 @@ dest_is_ssa(nir_dest *dest, void *data)
return dest->is_ssa;
}
+static bool
+is_load(nir_intrinsic_instr *instr)
+{
+ return instr->intrinsic == nir_intrinsic_load_ssbo ||
+ instr->intrinsic == nir_intrinsic_load_ssbo_indirect;
+}
+
/* 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
@@ -406,7 +413,7 @@ dest_is_ssa(nir_dest *dest, void *data)
*/
static bool
-instr_can_rewrite(nir_instr *instr)
+instr_can_rewrite(nir_instr *instr, bool allow_loads)
{
/* We only handle SSA. */
if (!nir_foreach_dest(instr, dest_is_ssa, NULL) ||
@@ -428,11 +435,15 @@ instr_can_rewrite(nir_instr *instr)
return true;
}
case nir_instr_type_intrinsic: {
+ nir_intrinsic_instr *intrinsic = nir_instr_as_intrinsic(instr);
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 */
+ &nir_intrinsic_infos[intrinsic->intrinsic];
+ bool can_eliminate_and_reorder =
+ (info->flags & NIR_INTRINSIC_CAN_ELIMINATE) &&
+ (info->flags & NIR_INTRINSIC_CAN_REORDER) &&
+ info->num_variables == 0; /* not implemented yet */
+ return can_eliminate_and_reorder ?
+ true: allow_loads && is_load(intrinsic);
}
case nir_instr_type_call:
case nir_instr_type_jump:
@@ -475,25 +486,29 @@ cmp_func(const void *data1, const void *data2)
return nir_instrs_equal(data1, data2);
}
-struct set *
-nir_instr_set_create(void *mem_ctx)
+struct nir_instr_set *
+nir_instr_set_create(void *mem_ctx, bool allow_loads)
{
- return _mesa_set_create(mem_ctx, hash_instr, cmp_func);
+ struct nir_instr_set *instr_set = ralloc(mem_ctx, struct nir_instr_set);
+ instr_set->set = _mesa_set_create(mem_ctx, hash_instr, cmp_func);
+ instr_set->allow_loads = allow_loads;
+ return instr_set;
}
void
-nir_instr_set_destroy(struct set *instr_set)
+nir_instr_set_destroy(struct nir_instr_set *instr_set)
{
- _mesa_set_destroy(instr_set, NULL);
+ _mesa_set_destroy(instr_set->set, NULL);
+ ralloc_free(instr_set);
}
bool
-nir_instr_set_add_or_rewrite(struct set *instr_set, nir_instr *instr)
+nir_instr_set_add_or_rewrite(struct nir_instr_set *instr_set, nir_instr *instr)
{
- if (!instr_can_rewrite(instr))
+ if (!instr_can_rewrite(instr, instr_set->allow_loads))
return false;
- struct set_entry *entry = _mesa_set_search(instr_set, instr);
+ struct set_entry *entry = _mesa_set_search(instr_set->set, instr);
if (entry) {
nir_ssa_def *def = nir_instr_get_dest_ssa_def(instr);
nir_ssa_def *new_def =
@@ -502,18 +517,18 @@ nir_instr_set_add_or_rewrite(struct set *instr_set, nir_instr *instr)
return true;
}
- _mesa_set_add(instr_set, instr);
+ _mesa_set_add(instr_set->set, instr);
return false;
}
void
-nir_instr_set_remove(struct set *instr_set, nir_instr *instr)
+nir_instr_set_remove(struct nir_instr_set *instr_set, nir_instr *instr)
{
- if (!instr_can_rewrite(instr))
+ if (!instr_can_rewrite(instr, instr_set->allow_loads))
return;
- struct set_entry *entry = _mesa_set_search(instr_set, instr);
+ struct set_entry *entry = _mesa_set_search(instr_set->set, instr);
if (entry)
- _mesa_set_remove(instr_set, entry);
+ _mesa_set_remove(instr_set->set, entry);
}
diff --git a/src/glsl/nir/nir_instr_set.h b/src/glsl/nir/nir_instr_set.h
index 939e8dd..d00f9a8 100644
--- a/src/glsl/nir/nir_instr_set.h
+++ b/src/glsl/nir/nir_instr_set.h
@@ -38,11 +38,20 @@
/*@{*/
-/** Creates an instruction set, using a given ralloc mem_ctx */
-struct set *nir_instr_set_create(void *mem_ctx);
+struct nir_instr_set {
+ struct set *set;
+ bool allow_loads;
+};
+
+/**
+ * Creates an instruction set, using a given ralloc mem_ctx. If allow_loads
+ * is true, then side-effectful instructions like SSBO loads that can't be
+ * freely moved around can still be rewritten.
+ */
+struct nir_instr_set *nir_instr_set_create(void *mem_ctx, bool allow_loads);
/** Destroys an instruction set. */
-void nir_instr_set_destroy(struct set *instr_set);
+void nir_instr_set_destroy(struct nir_instr_set *instr_set);
/**
* Adds an instruction to an instruction set if it doesn't exist, or if it
@@ -50,13 +59,14 @@ void nir_instr_set_destroy(struct set *instr_set);
* 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);
+bool nir_instr_set_add_or_rewrite(struct nir_instr_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);
+void nir_instr_set_remove(struct nir_instr_set *instr_set, nir_instr *instr);
/*@}*/
diff --git a/src/glsl/nir/nir_opt_cse.c b/src/glsl/nir/nir_opt_cse.c
index 93a6635..eb7296a 100644
--- a/src/glsl/nir/nir_opt_cse.c
+++ b/src/glsl/nir/nir_opt_cse.c
@@ -39,7 +39,7 @@
*/
static bool
-cse_block(nir_block *block, struct set *instr_set)
+cse_block(nir_block *block, struct nir_instr_set *instr_set)
{
bool progress = false;
@@ -64,7 +64,7 @@ cse_block(nir_block *block, struct set *instr_set)
static bool
nir_opt_cse_impl(nir_function_impl *impl)
{
- struct set *instr_set = nir_instr_set_create(NULL);
+ struct nir_instr_set *instr_set = nir_instr_set_create(NULL, false);
nir_metadata_require(impl, nir_metadata_dominance);
--
1.9.1
More information about the mesa-dev
mailing list