summaryrefslogtreecommitdiffstats
path: root/src/gallium
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium')
-rw-r--r--src/gallium/drivers/nv50/codegen/nv50_ir_build_util.cpp142
-rw-r--r--src/gallium/drivers/nv50/codegen/nv50_ir_build_util.h79
-rw-r--r--src/gallium/drivers/nv50/codegen/nv50_ir_from_tgsi.cpp213
-rw-r--r--src/gallium/drivers/nv50/codegen/nv50_ir_util.h25
4 files changed, 236 insertions, 223 deletions
diff --git a/src/gallium/drivers/nv50/codegen/nv50_ir_build_util.cpp b/src/gallium/drivers/nv50/codegen/nv50_ir_build_util.cpp
index bdde9eaa904..cb63854b043 100644
--- a/src/gallium/drivers/nv50/codegen/nv50_ir_build_util.cpp
+++ b/src/gallium/drivers/nv50/codegen/nv50_ir_build_util.cpp
@@ -27,7 +27,19 @@ namespace nv50_ir {
BuildUtil::BuildUtil()
{
- prog = NULL;
+ init(NULL);
+}
+
+BuildUtil::BuildUtil(Program *prog)
+{
+ init(prog);
+}
+
+void
+BuildUtil::init(Program *prog)
+{
+ this->prog = prog;
+
func = NULL;
bb = NULL;
pos = NULL;
@@ -417,127 +429,91 @@ BuildUtil::mkSysVal(SVSemantic svName, uint32_t svIndex)
}
void
-BuildUtil::DataArray::init()
-{
- values = NULL;
- baseAddr = 0;
- arrayLen = 0;
-
- vecDim = 4;
- eltSize = 2;
-
- file = FILE_GPR;
- regOnly = true;
-}
-
-BuildUtil::DataArray::DataArray()
-{
- init();
-}
-
-BuildUtil::DataArray::DataArray(BuildUtil *bld) : up(bld)
-{
- init();
-}
-
-BuildUtil::DataArray::~DataArray()
-{
- if (values)
- delete[] values;
-}
-
-void
-BuildUtil::DataArray::setup(uint32_t base, int len, int v, int size,
- DataFile f, int8_t fileIndex)
-{
- baseAddr = base;
- arrayLen = len;
-
- vecDim = v;
- eltSize = size;
-
- file = f;
- regOnly = !isMemoryFile(f);
-
- values = new Value * [arrayLen * vecDim];
- if (values)
- memset(values, 0, arrayLen * vecDim * sizeof(Value *));
+BuildUtil::DataArray::setup(unsigned array, unsigned arrayIdx,
+ uint32_t base, int len, int vecDim, int eltSize,
+ DataFile file, int8_t fileIdx)
+{
+ this->array = array;
+ this->arrayIdx = arrayIdx;
+ this->baseAddr = base;
+ this->arrayLen = len;
+ this->vecDim = vecDim;
+ this->eltSize = eltSize;
+ this->file = file;
+ this->regOnly = !isMemoryFile(file);
if (!regOnly) {
- baseSym = new_Symbol(up->getProgram(), file, fileIndex);
+ baseSym = new_Symbol(up->getProgram(), file, fileIdx);
baseSym->setOffset(baseAddr);
- baseSym->reg.size = size;
+ baseSym->reg.size = eltSize;
+ } else {
+ baseSym = NULL;
}
}
Value *
-BuildUtil::DataArray::acquire(int i, int c)
+BuildUtil::DataArray::acquire(ValueMap &m, int i, int c)
{
- const unsigned int idx = i * vecDim + c;
-
- assert(idx < arrayLen * vecDim);
-
if (regOnly) {
- const unsigned int idx = i * 4 + c; // vecDim always 4 if regOnly
- if (!values[idx])
- values[idx] = new_LValue(up->getFunction(), file);
- return values[idx];
+ Value *v = lookup(m, i, c);
+ if (!v)
+ v = insert(m, i, c, new_LValue(up->getFunction(), file));
+
+ return v;
} else {
return up->getScratch();
}
}
Value *
-BuildUtil::DataArray::load(int i, int c, Value *ptr)
+BuildUtil::DataArray::load(ValueMap &m, int i, int c, Value *ptr)
{
- const unsigned int idx = i * vecDim + c;
-
- assert(idx < arrayLen * vecDim);
-
if (regOnly) {
- if (!values[idx])
- values[idx] = new_LValue(up->getFunction(), file);
- return values[idx];
+ Value *v = lookup(m, i, c);
+ if (!v)
+ v = insert(m, i, c, new_LValue(up->getFunction(), file));
+
+ return v;
} else {
- Symbol *sym = reinterpret_cast<Symbol *>(values[idx]);
+ Value *sym = lookup(m, i, c);
if (!sym)
- values[idx] = sym = this->mkSymbol(i, c, baseSym);
- return up->mkLoad(typeOfSize(eltSize), sym, ptr);
+ sym = insert(m, i, c, mkSymbol(i, c));
+
+ return up->mkLoad(typeOfSize(eltSize), static_cast<Symbol *>(sym), ptr);
}
}
void
-BuildUtil::DataArray::store(int i, int c, Value *ptr, Value *value)
+BuildUtil::DataArray::store(ValueMap &m, int i, int c, Value *ptr, Value *value)
{
- const unsigned int idx = i * vecDim + c;
-
- assert(idx < arrayLen * vecDim);
-
if (regOnly) {
assert(!ptr);
- assert(!values[idx] || values[idx] == value);
- values[idx] = value;
+ if (!lookup(m, i, c))
+ insert(m, i, c, value);
+
+ assert(lookup(m, i, c) == value);
} else {
- Symbol *sym = reinterpret_cast<Symbol *>(values[idx]);
+ Value *sym = lookup(m, i, c);
if (!sym)
- values[idx] = sym = this->mkSymbol(i, c, baseSym);
- up->mkStore(OP_STORE, typeOfSize(value->reg.size), sym, ptr, value);
+ sym = insert(m, i, c, mkSymbol(i, c));
+
+ const DataType stTy = typeOfSize(value->reg.size);
+
+ up->mkStore(OP_STORE, stTy, static_cast<Symbol *>(sym), ptr, value);
}
}
Symbol *
-BuildUtil::DataArray::mkSymbol(int i, int c, Symbol *base)
+BuildUtil::DataArray::mkSymbol(int i, int c)
{
const unsigned int idx = i * vecDim + c;
-
Symbol *sym = new_Symbol(up->getProgram(), file, 0);
- assert(base || (idx < arrayLen && c < vecDim));
+ assert(baseSym || (idx < arrayLen && c < vecDim));
sym->reg.size = eltSize;
sym->reg.type = typeOfSize(eltSize);
-
- sym->setAddress(base, baseAddr + idx * eltSize);
+ sym->setAddress(baseSym, baseAddr + idx * eltSize);
return sym;
}
diff --git a/src/gallium/drivers/nv50/codegen/nv50_ir_build_util.h b/src/gallium/drivers/nv50/codegen/nv50_ir_build_util.h
index f815cf06759..69158861533 100644
--- a/src/gallium/drivers/nv50/codegen/nv50_ir_build_util.h
+++ b/src/gallium/drivers/nv50/codegen/nv50_ir_build_util.h
@@ -29,6 +29,7 @@ class BuildUtil
{
public:
BuildUtil();
+ BuildUtil(Program *);
inline void setProgram(Program *);
inline Program *getProgram() const { return prog; }
@@ -94,29 +95,58 @@ public:
Value *loadImm(Value *dst, int i) { return loadImm(dst, (uint32_t)i); }
+ struct Location
+ {
+ Location(unsigned array, unsigned arrayIdx, unsigned i, unsigned c)
+ : array(array), arrayIdx(arrayIdx), i(i), c(c) { }
+ Location(const Location &l)
+ : array(l.array), arrayIdx(l.arrayIdx), i(l.i), c(l.c) { }
+
+ bool operator==(const Location &l) const
+ {
+ return
+ array == l.array && arrayIdx == l.arrayIdx && i == l.i && c == l.c;
+ }
+
+ bool operator<(const Location &l) const
+ {
+ return array != l.array ? array < l.array :
+ arrayIdx != l.arrayIdx ? arrayIdx < l.arrayIdx :
+ i != l.i ? i < l.i :
+ c != l.c ? c < l.c :
+ false;
+ }
+
+ unsigned array, arrayIdx, i, c;
+ };
+
+ typedef bimap<Location, Value *> ValueMap;
+
class DataArray
{
public:
- DataArray();
- DataArray(BuildUtil *);
- ~DataArray();
-
- inline void setParent(BuildUtil *bld) { assert(!up); up = bld; }
+ DataArray(BuildUtil *bld) : up(bld) { }
- void setup(uint32_t base, int len, int vecDim, int size,
- DataFile, int8_t fileIndex = 0);
+ void setup(unsigned array, unsigned arrayIdx,
+ uint32_t base, int len, int vecDim, int eltSize,
+ DataFile file, int8_t fileIdx);
- inline bool exists(unsigned int i, unsigned int c);
+ inline bool exists(ValueMap&, unsigned int i, unsigned int c);
- Value *load(int i, int c, Value *ptr);
- void store(int i, int c, Value *ptr, Value *value);
- Value *acquire(int i, int c);
+ Value *load(ValueMap&, int i, int c, Value *ptr);
+ void store(ValueMap&, int i, int c, Value *ptr, Value *value);
+ Value *acquire(ValueMap&, int i, int c);
private:
- Symbol *mkSymbol(int i, int c, Symbol *base);
+ inline Value *lookup(ValueMap&, unsigned i, unsigned c);
+ inline Value *insert(ValueMap&, unsigned i, unsigned c, Value *v);
+
+ Symbol *mkSymbol(int i, int c);
private:
- Value **values;
+ BuildUtil *up;
+ unsigned array, arrayIdx;
+
uint32_t baseAddr;
uint32_t arrayLen;
Symbol *baseSym;
@@ -126,10 +156,6 @@ public:
DataFile file;
bool regOnly;
-
- BuildUtil *up;
-
- void init();
};
Symbol *mkSymbol(DataFile file, int8_t fileIndex,
@@ -138,6 +164,7 @@ public:
Symbol *mkSysVal(SVSemantic svName, uint32_t svIndex);
private:
+ void init(Program *);
void addImmediate(ImmediateValue *);
inline unsigned int u32Hash(uint32_t);
@@ -256,10 +283,24 @@ BuildUtil::mkOp3v(operation op, DataType ty, Value *dst,
}
bool
-BuildUtil::DataArray::exists(unsigned int i, unsigned int c)
+BuildUtil::DataArray::exists(ValueMap &m, unsigned int i, unsigned int c)
{
assert(i < arrayLen && c < vecDim);
- return !regOnly || values[i * vecDim + c];
+ return !regOnly || m.r.count(Location(array, arrayIdx, i, c));
+}
+
+Value *
+BuildUtil::DataArray::lookup(ValueMap &m, unsigned i, unsigned c)
+{
+ ValueMap::r_iterator it = m.r.find(Location(array, arrayIdx, i, c));
+ return it != m.r.end() ? it->second : NULL;
+}
+
+Value *
+BuildUtil::DataArray::insert(ValueMap &m, unsigned i, unsigned c, Value *v)
+{
+ m.insert(Location(array, arrayIdx, i, c), v);
+ return v;
}
} // namespace nv50_ir
diff --git a/src/gallium/drivers/nv50/codegen/nv50_ir_from_tgsi.cpp b/src/gallium/drivers/nv50/codegen/nv50_ir_from_tgsi.cpp
index bc602f4ee9f..9f735bfb2e2 100644
--- a/src/gallium/drivers/nv50/codegen/nv50_ir_from_tgsi.cpp
+++ b/src/gallium/drivers/nv50/codegen/nv50_ir_from_tgsi.cpp
@@ -1029,6 +1029,7 @@ public:
private:
Value *getVertexBase(int s);
+ DataArray *getArrayForFile(unsigned file, int idx);
Value *fetchSrc(int s, int c);
Value *acquireDst(int d, int c);
void storeDst(int d, int c, Value *);
@@ -1078,8 +1079,10 @@ private:
DataArray aData; // TGSI_FILE_ADDRESS
DataArray pData; // TGSI_FILE_PREDICATE
DataArray oData; // TGSI_FILE_OUTPUT (if outputs in registers)
- DataArray *lData; // TGSI_FILE_TEMPORARY_ARRAY
- DataArray *iData; // TGSI_FILE_IMMEDIATE_ARRAY
+ std::vector<DataArray> lData; // TGSI_FILE_TEMPORARY_ARRAY
+ std::vector<DataArray> iData; // TGSI_FILE_IMMEDIATE_ARRAY
+
+ ValueMap values;
Value *zero;
Value *fragCoord[4];
@@ -1252,34 +1255,44 @@ Converter::fetchSrc(int s, int c)
return applySrcMod(res, s, c);
}
-Value *
-Converter::fetchSrc(tgsi::Instruction::SrcRegister src, int c, Value *ptr)
+Converter::DataArray *
+Converter::getArrayForFile(unsigned file, int idx)
{
- const int idx = src.getIndex(0);
- const int swz = src.getSwizzle(c);
-
- switch (src.getFile()) {
+ switch (file) {
case TGSI_FILE_TEMPORARY:
- return tData.load(idx, swz, ptr);
+ return &tData;
case TGSI_FILE_PREDICATE:
- return pData.load(idx, swz, ptr);
+ return &pData;
case TGSI_FILE_ADDRESS:
- return aData.load(idx, swz, ptr);
-
+ return &aData;
case TGSI_FILE_TEMPORARY_ARRAY:
- assert(src.is2D() && src.getIndex(1) < code->tempArrayCount);
- return lData[src.getIndex(1)].load(idx, swz, ptr);
+ assert(idx < code->tempArrayCount);
+ return &lData[idx];
case TGSI_FILE_IMMEDIATE_ARRAY:
- assert(src.is2D() && src.getIndex(1) < code->immdArrayCount);
- return iData[src.getIndex(1)].load(idx, swz, ptr);
+ assert(idx < code->immdArrayCount);
+ return &iData[idx];
+ case TGSI_FILE_OUTPUT:
+ assert(prog->getType() == Program::TYPE_FRAGMENT);
+ return &oData;
+ default:
+ assert(!"invalid/unhandled TGSI source file");
+ return NULL;
+ }
+}
+Value *
+Converter::fetchSrc(tgsi::Instruction::SrcRegister src, int c, Value *ptr)
+{
+ const int idx2d = src.is2D() ? src.getIndex(1) : 0;
+ const int idx = src.getIndex(0);
+ const int swz = src.getSwizzle(c);
+
+ switch (src.getFile()) {
case TGSI_FILE_IMMEDIATE:
assert(!ptr);
return loadImm(NULL, info->immd.data[idx * 4 + swz]);
-
case TGSI_FILE_CONSTANT:
return mkLoad(TYPE_U32, srcToSym(src, c), ptr);
-
case TGSI_FILE_INPUT:
if (prog->getType() == Program::TYPE_FRAGMENT) {
// don't load masked inputs, won't be assigned a slot
@@ -1290,18 +1303,14 @@ Converter::fetchSrc(tgsi::Instruction::SrcRegister src, int c, Value *ptr)
return interpolate(src, c, ptr);
}
return mkLoad(TYPE_U32, srcToSym(src, c), ptr);
-
+ case TGSI_FILE_OUTPUT:
+ assert(!"load from output file");
+ return NULL;
case TGSI_FILE_SYSTEM_VALUE:
assert(!ptr);
return mkOp1v(OP_RDSV, TYPE_U32, getSSA(), srcToSym(src, c));
-
- case TGSI_FILE_OUTPUT:
- case TGSI_FILE_RESOURCE:
- case TGSI_FILE_SAMPLER:
- case TGSI_FILE_NULL:
default:
- assert(!"invalid/unhandled TGSI source file");
- return NULL;
+ return getArrayForFile(src.getFile(), idx2d)->load(values, idx, swz, ptr);
}
}
@@ -1309,35 +1318,20 @@ Value *
Converter::acquireDst(int d, int c)
{
const tgsi::Instruction::DstRegister dst = tgsi.getDst(d);
-
- if (dst.isMasked(c))
- return NULL;
- if (dst.isIndirect(0))
- return getScratch();
-
+ const unsigned f = dst.getFile();
const int idx = dst.getIndex(0);
+ const int idx2d = dst.is2D() ? dst.getIndex(1) : 0;
- switch (dst.getFile()) {
- case TGSI_FILE_TEMPORARY:
- return tData.acquire(idx, c);
- case TGSI_FILE_TEMPORARY_ARRAY:
- return getScratch();
- case TGSI_FILE_PREDICATE:
- return pData.acquire(idx, c);
- case TGSI_FILE_ADDRESS:
- return aData.acquire(idx, c);
+ if (dst.isMasked(c) || f == TGSI_FILE_RESOURCE)
+ return NULL;
- case TGSI_FILE_OUTPUT:
- if (prog->getType() == Program::TYPE_FRAGMENT)
- return oData.acquire(idx, c);
- // fall through
- case TGSI_FILE_SYSTEM_VALUE:
+ if (dst.isIndirect(0) ||
+ f == TGSI_FILE_TEMPORARY_ARRAY ||
+ f == TGSI_FILE_SYSTEM_VALUE ||
+ (f == TGSI_FILE_OUTPUT && prog->getType() != Program::TYPE_FRAGMENT))
return getScratch();
- default:
- assert(!"invalid dst file");
- return NULL;
- }
+ return getArrayForFile(f, idx2d)-> acquire(values, idx, c);
}
void
@@ -1377,38 +1371,25 @@ void
Converter::storeDst(const tgsi::Instruction::DstRegister dst, int c,
Value *val, Value *ptr)
{
+ const unsigned f = dst.getFile();
const int idx = dst.getIndex(0);
+ const int idx2d = dst.is2D() ? dst.getIndex(1) : 0;
- switch (dst.getFile()) {
- case TGSI_FILE_TEMPORARY:
- tData.store(idx, c, ptr, val);
- break;
- case TGSI_FILE_TEMPORARY_ARRAY:
- assert(dst.is2D() && dst.getIndex(1) < code->tempArrayCount);
- lData[dst.getIndex(1)].store(idx, c, ptr, val);
- break;
- case TGSI_FILE_PREDICATE:
- pData.store(idx, c, ptr, val);
- break;
- case TGSI_FILE_ADDRESS:
- aData.store(idx, c, ptr, val);
- break;
-
- case TGSI_FILE_OUTPUT:
- if (prog->getType() == Program::TYPE_FRAGMENT)
- oData.store(idx, c, ptr, val);
- else
- mkStore(OP_EXPORT, TYPE_U32, dstToSym(dst, c), ptr, val);
- break;
-
- case TGSI_FILE_SYSTEM_VALUE:
+ if (f == TGSI_FILE_SYSTEM_VALUE) {
assert(!ptr);
mkOp2(OP_WRSV, TYPE_U32, NULL, dstToSym(dst, c), val);
- break;
-
- default:
+ } else
+ if (f == TGSI_FILE_OUTPUT && prog->getType() != Program::TYPE_FRAGMENT) {
+ mkStore(OP_EXPORT, TYPE_U32, dstToSym(dst, c), ptr, val);
+ } else
+ if (f == TGSI_FILE_TEMPORARY ||
+ f == TGSI_FILE_TEMPORARY_ARRAY ||
+ f == TGSI_FILE_PREDICATE ||
+ f == TGSI_FILE_ADDRESS ||
+ f == TGSI_FILE_OUTPUT) {
+ getArrayForFile(f, idx2d)->store(values, idx, c, ptr, val);
+ } else {
assert(!"invalid dst file");
- break;
}
}
@@ -2237,34 +2218,57 @@ Converter::exportOutputs()
{
for (unsigned int i = 0; i < info->numOutputs; ++i) {
for (unsigned int c = 0; c < 4; ++c) {
- if (!oData.exists(i, c))
+ if (!oData.exists(values, i, c))
continue;
Symbol *sym = mkSymbol(FILE_SHADER_OUTPUT, 0, TYPE_F32,
info->out[i].slot[c] * 4);
- Value *val = oData.load(i, c, NULL);
+ Value *val = oData.load(values, i, c, NULL);
if (val)
mkStore(OP_EXPORT, TYPE_F32, sym, NULL, val);
}
}
}
-Converter::Converter(Program *ir, const tgsi::Source *src)
- : code(src),
+Converter::Converter(Program *ir, const tgsi::Source *code) : BuildUtil(ir),
+ code(code),
tgsi(NULL),
tData(this), aData(this), pData(this), oData(this)
{
- prog = ir;
info = code->info;
- DataFile tFile = code->mainTempsInLMem ? FILE_MEMORY_LOCAL : FILE_GPR;
+ const DataFile tFile = code->mainTempsInLMem ? FILE_MEMORY_LOCAL : FILE_GPR;
+
+ const unsigned tSize = code->fileSize(TGSI_FILE_TEMPORARY);
+ const unsigned pSize = code->fileSize(TGSI_FILE_PREDICATE);
+ const unsigned aSize = code->fileSize(TGSI_FILE_ADDRESS);
+ const unsigned oSize = code->fileSize(TGSI_FILE_OUTPUT);
+
+ tData.setup(TGSI_FILE_TEMPORARY, 0, 0, tSize, 4, 4, tFile, 0);
+ pData.setup(TGSI_FILE_PREDICATE, 0, 0, pSize, 4, 4, FILE_PREDICATE, 0);
+ aData.setup(TGSI_FILE_ADDRESS, 0, 0, aSize, 4, 4, FILE_ADDRESS, 0);
+ oData.setup(TGSI_FILE_OUTPUT, 0, 0, oSize, 4, 4, FILE_GPR, 0);
+
+ for (int vol = 0, i = 0; i < code->tempArrayCount; ++i) {
+ int len = code->tempArrays[i].u32 >> 2;
+ int dim = code->tempArrays[i].u32 & 3;
+
+ lData.push_back(DataArray(this));
+ lData.back().setup(TGSI_FILE_TEMPORARY_ARRAY, i, vol, len, dim, 4,
+ FILE_MEMORY_LOCAL, 0);
- tData.setup(0, code->fileSize(TGSI_FILE_TEMPORARY), 4, 4, tFile);
- pData.setup(0, code->fileSize(TGSI_FILE_PREDICATE), 4, 4, FILE_PREDICATE);
- aData.setup(0, code->fileSize(TGSI_FILE_ADDRESS), 4, 4, FILE_ADDRESS);
- oData.setup(0, code->fileSize(TGSI_FILE_OUTPUT), 4, 4, FILE_GPR);
+ vol += (len * dim * 4 + 0xf) & ~0xf;
+ }
+
+ for (int vol = 0, i = 0; i < code->immdArrayCount; ++i) {
+ int len = code->immdArrays[i].u32 >> 2;
+ int dim = code->immdArrays[i].u32 & 3;
+
+ lData.push_back(DataArray(this));
+ lData.back().setup(TGSI_FILE_IMMEDIATE_ARRAY, i, vol, len, dim, 4,
+ FILE_MEMORY_CONST, 14);
- lData = NULL;
- iData = NULL;
+ vol += (len * dim * 4 + 0xf) & ~0xf;
+ }
zero = mkImm((uint32_t)0);
@@ -2273,10 +2277,6 @@ Converter::Converter(Program *ir, const tgsi::Source *src)
Converter::~Converter()
{
- if (lData)
- delete[] lData;
- if (iData)
- delete[] iData;
}
bool
@@ -2285,33 +2285,6 @@ Converter::run()
BasicBlock *entry = new BasicBlock(prog->main);
BasicBlock *leave = new BasicBlock(prog->main);
- if (code->tempArrayCount && !lData) {
- uint32_t volume = 0;
- lData = new DataArray[code->tempArrayCount];
- if (!lData)
- return false;
- for (int i = 0; i < code->tempArrayCount; ++i) {
- int len = code->tempArrays[i].u32 >> 2;
- int dim = code->tempArrays[i].u32 & 3;
- lData[i].setParent(this);
- lData[i].setup(volume, len, dim, 4, FILE_MEMORY_LOCAL);
- volume += (len * dim * 4 + 0xf) & ~0xf;
- }
- }
- if (code->immdArrayCount && !iData) {
- uint32_t volume = 0;
- iData = new DataArray[code->immdArrayCount];
- if (!iData)
- return false;
- for (int i = 0; i < code->immdArrayCount; ++i) {
- int len = code->immdArrays[i].u32 >> 2;
- int dim = code->immdArrays[i].u32 & 3;
- iData[i].setParent(this);
- iData[i].setup(volume, len, dim, 4, FILE_MEMORY_CONST, 14);
- volume += (len * dim * 4 + 0xf) & ~0xf;
- }
- }
-
prog->main->setEntry(entry);
prog->main->setExit(leave);
diff --git a/src/gallium/drivers/nv50/codegen/nv50_ir_util.h b/src/gallium/drivers/nv50/codegen/nv50_ir_util.h
index dc6be9f3af8..262cf9cd496 100644
--- a/src/gallium/drivers/nv50/codegen/nv50_ir_util.h
+++ b/src/gallium/drivers/nv50/codegen/nv50_ir_util.h
@@ -26,8 +26,8 @@
#include <new>
#include <assert.h>
#include <stdio.h>
-#include <map>
#include <memory>
+#include <map>
#ifndef NDEBUG
# include <typeinfo>
@@ -704,6 +704,29 @@ protected:
}
};
+template<typename S, typename T>
+struct bimap
+{
+ std::map<S, T> forth;
+ std::map<T, S> back;
+
+public:
+ bimap() : l(back), r(forth) { }
+ bimap(const bimap<S, T> &m)
+ : forth(m.forth), back(m.back), l(back), r(forth) { }
+
+ void insert(const S &s, const T &t)
+ {
+ forth.insert(std::make_pair(s, t));
+ back.insert(std::make_pair(t, s));
+ }
+
+ typedef typename std::map<T, S>::const_iterator l_iterator;
+ const std::map<T, S> &l;
+ typedef typename std::map<S, T>::const_iterator r_iterator;
+ const std::map<S, T> &r;
+};
+
} // namespace nv50_ir
#endif // __NV50_IR_UTIL_H__