nv50/ir: avoid deleting pseudo instructions too early
authorIlia Mirkin <imirkin@alum.mit.edu>
Thu, 25 Sep 2014 01:45:07 +0000 (21:45 -0400)
committerIlia Mirkin <imirkin@alum.mit.edu>
Fri, 26 Sep 2014 02:15:49 +0000 (22:15 -0400)
What happens is that a SPLIT operation is part of the spill node, and as
a pseudo op, the instruction gets erased after processing its first def.
However the later defs still need to refer to it, so instead delay
deleting until after that whole RA node is done processing.

Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=79462
Signed-off-by: Ilia Mirkin <imirkin@alum.mit.edu>
Cc: "10.2 10.3" <mesa-stable@lists.freedesktop.org>
src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp

index 4b105b453c3fd99b1fb20c4945b33cb90be22778..d47fed26d8261c9e8aee83b481c9cdee47286d1e 100644 (file)
@@ -25,6 +25,7 @@
 
 #include <stack>
 #include <limits>
+#include <tr1/unordered_set>
 
 namespace nv50_ir {
 
@@ -1547,6 +1548,11 @@ SpillCodeInserter::run(const std::list<ValuePair>& lst)
       LValue *lval = it->first->asLValue();
       Symbol *mem = it->second ? it->second->asSym() : NULL;
 
+      // Keep track of which instructions to delete later. Deleting them
+      // inside the loop is unsafe since a single instruction may have
+      // multiple destinations that all need to be spilled (like OP_SPLIT).
+      std::tr1::unordered_set<Instruction *> to_del;
+
       for (Value::DefIterator d = lval->defs.begin(); d != lval->defs.end();
            ++d) {
          Value *slot = mem ?
@@ -1579,7 +1585,7 @@ SpillCodeInserter::run(const std::list<ValuePair>& lst)
             d = lval->defs.erase(d);
             --d;
             if (slot->reg.file == FILE_MEMORY_LOCAL)
-               delete_Instruction(func->getProgram(), defi);
+               to_del.insert(defi);
             else
                defi->setDef(0, slot);
          } else {
@@ -1587,6 +1593,9 @@ SpillCodeInserter::run(const std::list<ValuePair>& lst)
          }
       }
 
+      for (std::tr1::unordered_set<Instruction *>::const_iterator it = to_del.begin();
+           it != to_del.end(); ++it)
+         delete_Instruction(func->getProgram(), *it);
    }
 
    // TODO: We're not trying to reuse old slots in a potential next iteration.