summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/nv50/codegen/nv50_ir.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/drivers/nv50/codegen/nv50_ir.cpp')
-rw-r--r--src/gallium/drivers/nv50/codegen/nv50_ir.cpp58
1 files changed, 50 insertions, 8 deletions
diff --git a/src/gallium/drivers/nv50/codegen/nv50_ir.cpp b/src/gallium/drivers/nv50/codegen/nv50_ir.cpp
index 8e7fc31eced..862293e39b2 100644
--- a/src/gallium/drivers/nv50/codegen/nv50_ir.cpp
+++ b/src/gallium/drivers/nv50/codegen/nv50_ir.cpp
@@ -58,11 +58,12 @@ Modifier Modifier::operator*(const Modifier m) const
return Modifier(a | c);
}
-ValueRef::ValueRef() : value(NULL), insn(NULL)
+ValueRef::ValueRef(Value *v) : value(NULL), insn(NULL)
{
indirect[0] = -1;
indirect[1] = -1;
usedAsPtr = false;
+ set(v);
}
ValueRef::ValueRef(const ValueRef& ref) : value(NULL), insn(ref.insn)
@@ -91,9 +92,9 @@ ImmediateValue *ValueRef::getImmediate() const
return NULL;
}
-ValueDef::ValueDef() : value(NULL), insn(NULL)
+ValueDef::ValueDef(Value *v) : value(NULL), insn(NULL)
{
- // nothing to do
+ set(v);
}
ValueDef::ValueDef(const ValueDef& def) : value(NULL), insn(NULL)
@@ -141,17 +142,58 @@ ValueDef::set(Value *defVal)
value = defVal;
}
+// Check if we can replace this definition's value by the value in @rep,
+// including the source modifiers, i.e. make sure that all uses support
+// @rep.mod.
+bool
+ValueDef::mayReplace(const ValueRef &rep)
+{
+ if (!rep.mod)
+ return true;
+
+ if (!insn || !insn->bb) // Unbound instruction ?
+ return false;
+
+ const Target *target = insn->bb->getProgram()->getTarget();
+
+ for (Value::UseIterator it = value->uses.begin(); it != value->uses.end();
+ ++it) {
+ Instruction *insn = (*it)->getInsn();
+ int s = -1;
+
+ for (int i = 0; insn->srcExists(i); ++i) {
+ if (insn->src(i).get() == value) {
+ // If there are multiple references to us we'd have to check if the
+ // combination of mods is still supported, but just bail for now.
+ if (&insn->src(i) != (*it))
+ return false;
+ s = i;
+ }
+ }
+ assert(s >= 0); // integrity of uses list
+
+ if (!target->isModSupported(insn, s, rep.mod))
+ return false;
+ }
+ return true;
+}
+
void
-ValueDef::replace(Value *repVal, bool doSet)
+ValueDef::replace(const ValueRef &repVal, bool doSet)
{
- if (value == repVal)
+ assert(mayReplace(repVal));
+
+ if (value == repVal.get())
return;
- while (value->refCount())
- value->uses.front()->set(repVal);
+ while (!value->uses.empty()) {
+ ValueRef *ref = value->uses.front();
+ ref->set(repVal.get());
+ ref->mod *= repVal.mod;
+ }
if (doSet)
- set(repVal);
+ set(repVal.get());
}
Value::Value()