From: Ilia Mirkin Date: Fri, 29 Aug 2014 03:05:49 +0000 (-0400) Subject: nvc0/ir: avoid infinite recursion when finding first uses of tex X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=c4bb436f7660c951cd27e52660cf825da68793e5;p=mesa.git nvc0/ir: avoid infinite recursion when finding first uses of tex In certain circumstances, findFirstUses could end up doubling back on instructions it had already processed, resulting in an infinite recursion. Avoid this by keeping track of already-visited instructions. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=83079 Tested-by: Tobias Klausmann Signed-off-by: Ilia Mirkin Cc: "10.2 10.3" --- diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir_lowering_nvc0.cpp b/src/gallium/drivers/nouveau/codegen/nv50_ir_lowering_nvc0.cpp index 7da9b0be7e8..92f9a156f7c 100644 --- a/src/gallium/drivers/nouveau/codegen/nv50_ir_lowering_nvc0.cpp +++ b/src/gallium/drivers/nouveau/codegen/nv50_ir_lowering_nvc0.cpp @@ -174,15 +174,31 @@ NVC0LegalizePostRA::findOverwritingDefs(const Instruction *texi, } void -NVC0LegalizePostRA::findFirstUses(const Instruction *texi, - const Instruction *insn, - std::list &uses) +NVC0LegalizePostRA::findFirstUses( + const Instruction *texi, + const Instruction *insn, + std::list &uses, + std::tr1::unordered_set& visited) { for (int d = 0; insn->defExists(d); ++d) { Value *v = insn->getDef(d); for (Value::UseIterator u = v->uses.begin(); u != v->uses.end(); ++u) { Instruction *usei = (*u)->getInsn(); + /* XXX HACK ALERT XXX + * + * This shouldn't have to be here, we should always be making forward + * progress by looking at the uses. However this somehow does not + * appear to be the case. Probably because this is being done right + * after RA, when the defs/uses lists have been messed with by node + * merging. This should probably be moved to being done right before + * RA. But this will do for now. + */ + if (visited.find(usei) != visited.end()) + continue; + + visited.insert(usei); + if (usei->op == OP_PHI || usei->op == OP_UNION) { // need a barrier before WAW cases for (int s = 0; usei->srcExists(s); ++s) { @@ -197,11 +213,11 @@ NVC0LegalizePostRA::findFirstUses(const Instruction *texi, usei->op == OP_PHI || usei->op == OP_UNION) { // these uses don't manifest in the machine code - findFirstUses(texi, usei, uses); + findFirstUses(texi, usei, uses, visited); } else if (usei->op == OP_MOV && usei->getDef(0)->equals(usei->getSrc(0)) && usei->subOp != NV50_IR_SUBOP_MOV_FINAL) { - findFirstUses(texi, usei, uses); + findFirstUses(texi, usei, uses, visited); } else { addTexUse(uses, usei, insn); } @@ -257,8 +273,10 @@ NVC0LegalizePostRA::insertTextureBarriers(Function *fn) uses = new std::list[texes.size()]; if (!uses) return false; - for (size_t i = 0; i < texes.size(); ++i) - findFirstUses(texes[i], texes[i], uses[i]); + for (size_t i = 0; i < texes.size(); ++i) { + std::tr1::unordered_set visited; + findFirstUses(texes[i], texes[i], uses[i], visited); + } // determine the barrier level at each use for (size_t i = 0; i < texes.size(); ++i) { diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir_lowering_nvc0.h b/src/gallium/drivers/nouveau/codegen/nv50_ir_lowering_nvc0.h index 7f39c289554..d8ff5cd3d96 100644 --- a/src/gallium/drivers/nouveau/codegen/nv50_ir_lowering_nvc0.h +++ b/src/gallium/drivers/nouveau/codegen/nv50_ir_lowering_nvc0.h @@ -20,6 +20,8 @@ * OTHER DEALINGS IN THE SOFTWARE. */ +#include + #include "codegen/nv50_ir.h" #include "codegen/nv50_ir_build_util.h" @@ -69,7 +71,8 @@ private: bool insertTextureBarriers(Function *); inline bool insnDominatedBy(const Instruction *, const Instruction *) const; void findFirstUses(const Instruction *tex, const Instruction *def, - std::list&); + std::list&, + std::tr1::unordered_set&); void findOverwritingDefs(const Instruction *tex, Instruction *insn, const BasicBlock *term, std::list&);