summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKarol Herbst <kherbst@redhat.com>2017-12-12 21:01:28 +0100
committerKarol Herbst <kherbst@redhat.com>2019-03-17 10:33:28 +0100
commit7481abcd0ca41e0d801f2efd4b088a23e6a56892 (patch)
tree4d844813e0f1847409d2afaecca5ef0fcfbaccab
parent9298664a5f8e81af6f7cd8bc1493c6d5a6b4ddb4 (diff)
nv50/ir/nir: track defs and provide easy access functions
v2: add helper function for indirects v4: add new getIndirect overload for easier use v5: use getSSA for ssa values we can just create the values for unassigned registers in getSrc v6: always create at least 32 bit values v8: don't require C++11 features v9: include unordered_map on supported stdlibs replace '(*it).' with 'it->' Signed-off-by: Karol Herbst <kherbst@redhat.com>
-rw-r--r--src/gallium/drivers/nouveau/codegen/nv50_ir_from_nir.cpp150
1 files changed, 150 insertions, 0 deletions
diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir_from_nir.cpp b/src/gallium/drivers/nouveau/codegen/nv50_ir_from_nir.cpp
index 9d2d16b97f5..f7908876e96 100644
--- a/src/gallium/drivers/nouveau/codegen/nv50_ir_from_nir.cpp
+++ b/src/gallium/drivers/nouveau/codegen/nv50_ir_from_nir.cpp
@@ -31,8 +31,23 @@
#include "codegen/nv50_ir_lowering_helper.h"
#include "codegen/nv50_ir_util.h"
+#if __cplusplus >= 201103L
+#include <unordered_map>
+#else
+#include <tr1/unordered_map>
+#endif
+#include <vector>
+
namespace {
+#if __cplusplus >= 201103L
+using std::hash;
+using std::unordered_map;
+#else
+using std::tr1::hash;
+using std::tr1::unordered_map;
+#endif
+
using namespace nv50_ir;
int
@@ -48,13 +63,148 @@ public:
bool run();
private:
+ typedef std::vector<LValue *> LValues;
+ typedef unordered_map<unsigned, LValues> NirDefMap;
+
+ LValues& convert(nir_alu_dest *);
+ LValues& convert(nir_dest *);
+ LValues& convert(nir_register *);
+ LValues& convert(nir_ssa_def *);
+
+ Value* getSrc(nir_alu_src *, uint8_t component = 0);
+ Value* getSrc(nir_register *, uint8_t);
+ Value* getSrc(nir_src *, uint8_t, bool indirect = false);
+ Value* getSrc(nir_ssa_def *, uint8_t);
+
+ // returned value is the constant part of the given source (either the
+ // nir_src or the selected source component of an intrinsic). Even though
+ // this is mostly an optimization to be able to skip indirects in a few
+ // cases, sometimes we require immediate values or set some fileds on
+ // instructions (e.g. tex) in order for codegen to consume those.
+ // If the found value has not a constant part, the Value gets returned
+ // through the Value parameter.
+ uint32_t getIndirect(nir_src *, uint8_t, Value *&);
+ uint32_t getIndirect(nir_intrinsic_instr *, uint8_t s, uint8_t c, Value *&);
+
nir_shader *nir;
+
+ NirDefMap ssaDefs;
+ NirDefMap regDefs;
};
Converter::Converter(Program *prog, nir_shader *nir, nv50_ir_prog_info *info)
: ConverterCommon(prog, info),
nir(nir) {}
+Converter::LValues&
+Converter::convert(nir_dest *dest)
+{
+ if (dest->is_ssa)
+ return convert(&dest->ssa);
+ if (dest->reg.indirect) {
+ ERROR("no support for indirects.");
+ assert(false);
+ }
+ return convert(dest->reg.reg);
+}
+
+Converter::LValues&
+Converter::convert(nir_register *reg)
+{
+ NirDefMap::iterator it = regDefs.find(reg->index);
+ if (it != regDefs.end())
+ return it->second;
+
+ LValues newDef(reg->num_components);
+ for (uint8_t i = 0; i < reg->num_components; i++)
+ newDef[i] = getScratch(std::max(4, reg->bit_size / 8));
+ return regDefs[reg->index] = newDef;
+}
+
+Converter::LValues&
+Converter::convert(nir_ssa_def *def)
+{
+ NirDefMap::iterator it = ssaDefs.find(def->index);
+ if (it != ssaDefs.end())
+ return it->second;
+
+ LValues newDef(def->num_components);
+ for (uint8_t i = 0; i < def->num_components; i++)
+ newDef[i] = getSSA(std::max(4, def->bit_size / 8));
+ return ssaDefs[def->index] = newDef;
+}
+
+Value*
+Converter::getSrc(nir_alu_src *src, uint8_t component)
+{
+ if (src->abs || src->negate) {
+ ERROR("modifiers currently not supported on nir_alu_src\n");
+ assert(false);
+ }
+ return getSrc(&src->src, src->swizzle[component]);
+}
+
+Value*
+Converter::getSrc(nir_register *reg, uint8_t idx)
+{
+ NirDefMap::iterator it = regDefs.find(reg->index);
+ if (it == regDefs.end())
+ return convert(reg)[idx];
+ return it->second[idx];
+}
+
+Value*
+Converter::getSrc(nir_src *src, uint8_t idx, bool indirect)
+{
+ if (src->is_ssa)
+ return getSrc(src->ssa, idx);
+
+ if (src->reg.indirect) {
+ if (indirect)
+ return getSrc(src->reg.indirect, idx);
+ ERROR("no support for indirects.");
+ assert(false);
+ return NULL;
+ }
+
+ return getSrc(src->reg.reg, idx);
+}
+
+Value*
+Converter::getSrc(nir_ssa_def *src, uint8_t idx)
+{
+ NirDefMap::iterator it = ssaDefs.find(src->index);
+ if (it == ssaDefs.end()) {
+ ERROR("SSA value %u not found\n", src->index);
+ assert(false);
+ return NULL;
+ }
+ return it->second[idx];
+}
+
+uint32_t
+Converter::getIndirect(nir_src *src, uint8_t idx, Value *&indirect)
+{
+ nir_const_value *offset = nir_src_as_const_value(*src);
+
+ if (offset) {
+ indirect = NULL;
+ return offset->u32[0];
+ }
+
+ indirect = getSrc(src, idx, true);
+ return 0;
+}
+
+uint32_t
+Converter::getIndirect(nir_intrinsic_instr *insn, uint8_t s, uint8_t c, Value *&indirect)
+{
+ int32_t idx = nir_intrinsic_base(insn) + getIndirect(&insn->src[s], c, indirect);
+ if (indirect)
+ indirect = mkOp2v(OP_SHL, TYPE_U32, getSSA(4, FILE_ADDRESS), indirect, loadImm(NULL, 4));
+ return idx;
+}
+
bool
Converter::run()
{