From a05e6a3fa28168d58a13cfb07f7a664e84b925ae Mon Sep 17 00:00:00 2001 From: Francisco Jerez Date: Sat, 14 Apr 2012 21:24:16 +0200 Subject: [PATCH] nv50/ir: Decouple object cloning logic from the sub-object recursion policy. --- src/gallium/drivers/nv50/codegen/nv50_ir.cpp | 103 +++++++++--------- src/gallium/drivers/nv50/codegen/nv50_ir.h | 17 +-- .../nv50/codegen/nv50_ir_from_tgsi.cpp | 4 +- .../drivers/nv50/codegen/nv50_ir_inlines.h | 10 ++ .../drivers/nv50/codegen/nv50_ir_peephole.cpp | 12 +- .../drivers/nv50/codegen/nv50_ir_util.h | 99 +++++++++++++++++ .../nvc0/codegen/nv50_ir_lowering_nvc0.cpp | 4 +- 7 files changed, 181 insertions(+), 68 deletions(-) diff --git a/src/gallium/drivers/nv50/codegen/nv50_ir.cpp b/src/gallium/drivers/nv50/codegen/nv50_ir.cpp index a93dc730e42..86e3d1c95af 100644 --- a/src/gallium/drivers/nv50/codegen/nv50_ir.cpp +++ b/src/gallium/drivers/nv50/codegen/nv50_ir.cpp @@ -238,9 +238,12 @@ LValue::LValue(Function *fn, LValue *lval) fn->add(this, this->id); } -Value *LValue::clone(Function *func) const +LValue * +LValue::clone(ClonePolicy& pol) const { - LValue *that = new_LValue(func, reg.file); + LValue *that = new_LValue(pol.context(), reg.file); + + pol.set(this, that); that->reg.size = this->reg.size; that->reg.type = this->reg.type; @@ -260,13 +263,15 @@ Symbol::Symbol(Program *prog, DataFile f, ubyte fidx) prog->add(this, this->id); } -Value * -Symbol::clone(Function *func) const +Symbol * +Symbol::clone(ClonePolicy& pol) const { - Program *prog = func->getProgram(); + Program *prog = pol.context()->getProgram(); Symbol *that = new_Symbol(prog, reg.file, reg.fileIndex); + pol.set(this, that); + that->reg.size = this->reg.size; that->reg.type = this->reg.type; that->reg.data = this->reg.data; @@ -623,51 +628,46 @@ Instruction::putExtraSources(int s, Value *values[3]) } Instruction * -Instruction::clone(bool deep) const +Instruction::clone(ClonePolicy& pol, Instruction *i) const { - Instruction *insn = new_Instruction(bb->getFunction(), op, dType); - assert(!asCmp() && !asFlow()); - cloneBase(insn, deep); - return insn; -} + if (!i) + i = new_Instruction(pol.context(), op, dType); + assert(typeid(*i) == typeid(*this)); -void -Instruction::cloneBase(Instruction *insn, bool deep) const -{ - insn->sType = this->sType; + pol.set(this, i); - insn->cc = this->cc; - insn->rnd = this->rnd; - insn->cache = this->cache; - insn->subOp = this->subOp; + i->sType = sType; - insn->saturate = this->saturate; - insn->atomic = this->atomic; - insn->ftz = this->ftz; - insn->dnz = this->dnz; - insn->ipa = this->ipa; - insn->lanes = this->lanes; - insn->perPatch = this->perPatch; + i->rnd = rnd; + i->cache = cache; + i->subOp = subOp; - insn->postFactor = this->postFactor; + i->saturate = saturate; + i->join = join; + i->exit = exit; + i->atomic = atomic; + i->ftz = ftz; + i->dnz = dnz; + i->ipa = ipa; + i->lanes = lanes; + i->perPatch = perPatch; - if (deep) { - if (!bb) - return; - Function *fn = bb->getFunction(); - for (int d = 0; this->defExists(d); ++d) - insn->setDef(d, this->getDef(d)->clone(fn)); - } else { - for (int d = 0; this->defExists(d); ++d) - insn->setDef(d, this->getDef(d)); + i->postFactor = postFactor; + + for (int d = 0; defExists(d); ++d) + i->setDef(d, pol.get(getDef(d))); + + for (int s = 0; srcExists(s); ++s) { + i->setSrc(s, pol.get(getSrc(s))); + i->src(s).mod = src(s).mod; } - for (int s = 0; this->srcExists(s); ++s) - insn->setSrc(s, this->srcs[s]); + i->cc = cc; + i->predSrc = predSrc; + i->flagsDef = flagsDef; + i->flagsSrc = flagsSrc; - insn->predSrc = this->predSrc; - insn->flagsDef = this->flagsDef; - insn->flagsSrc = this->flagsSrc; + return i; } unsigned int @@ -777,11 +777,13 @@ TexInstruction::~TexInstruction() } } -Instruction * -TexInstruction::clone(bool deep) const +TexInstruction * +TexInstruction::clone(ClonePolicy& pol, Instruction *i) const { - TexInstruction *tex = new_TexInstruction(bb->getFunction(), op); - cloneBase(tex, deep); + TexInstruction *tex = (i ? static_cast(i) : + new_TexInstruction(pol.context(), op)); + + Instruction::clone(pol, tex); tex->tex = this->tex; @@ -823,13 +825,14 @@ CmpInstruction::CmpInstruction(Function *fn, operation op) setCond = CC_ALWAYS; } -Instruction * -CmpInstruction::clone(bool deep) const +CmpInstruction * +CmpInstruction::clone(ClonePolicy& pol, Instruction *i) const { - CmpInstruction *cmp = new_CmpInstruction(bb->getFunction(), op); - cloneBase(cmp, deep); - cmp->setCond = setCond; + CmpInstruction *cmp = (i ? static_cast(i) : + new_CmpInstruction(pol.context(), op)); cmp->dType = dType; + Instruction::clone(pol, cmp); + cmp->setCond = setCond; return cmp; } diff --git a/src/gallium/drivers/nv50/codegen/nv50_ir.h b/src/gallium/drivers/nv50/codegen/nv50_ir.h index 8d86a9ce282..b5cf4b89a93 100644 --- a/src/gallium/drivers/nv50/codegen/nv50_ir.h +++ b/src/gallium/drivers/nv50/codegen/nv50_ir.h @@ -451,7 +451,7 @@ public: Value(); virtual ~Value() { } - virtual Value *clone(Function *) const { return NULL; } + virtual Value *clone(ClonePolicy&) const = 0; virtual int print(char *, size_t, DataType ty = TYPE_NONE) const = 0; @@ -499,7 +499,7 @@ public: LValue(Function *, LValue *); ~LValue() { } - virtual Value *clone(Function *) const; + virtual LValue *clone(ClonePolicy&) const; virtual int print(char *, size_t, DataType ty = TYPE_NONE) const; @@ -515,7 +515,7 @@ public: Symbol(Program *, DataFile file = FILE_MEMORY_CONST, ubyte fileIdx = 0); ~Symbol() { } - virtual Value *clone(Function *) const; + virtual Symbol *clone(ClonePolicy&) const; virtual bool equals(const Value *that, bool strict) const; @@ -577,7 +577,8 @@ public: Instruction(Function *, operation, DataType); virtual ~Instruction(); - virtual Instruction *clone(bool deep) const; + virtual Instruction *clone(ClonePolicy&, + Instruction * = NULL) const; void setDef(int i, Value *); void setSrc(int s, Value *); @@ -695,8 +696,6 @@ public: private: void init(); -protected: - void cloneBase(Instruction *clone, bool deep) const; }; enum TexQuery @@ -754,7 +753,8 @@ public: TexInstruction(Function *, operation); virtual ~TexInstruction(); - virtual Instruction *clone(bool deep) const; + virtual TexInstruction *clone(ClonePolicy&, + Instruction * = NULL) const; inline void setTexture(Target targ, uint8_t r, uint8_t s) { @@ -797,7 +797,8 @@ class CmpInstruction : public Instruction public: CmpInstruction(Function *, operation); - virtual Instruction *clone(bool deep) const; + virtual CmpInstruction *clone(ClonePolicy&, + Instruction * = NULL) const; void setCondition(CondCode cond) { setCond = cond; } CondCode getCondition() const { return setCond; } 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 5b2ee690454..bc602f4ee9f 100644 --- a/src/gallium/drivers/nv50/codegen/nv50_ir_from_tgsi.cpp +++ b/src/gallium/drivers/nv50/codegen/nv50_ir_from_tgsi.cpp @@ -1495,7 +1495,7 @@ Converter::loadProjTexCoords(Value *dst[4], Value *src[4], unsigned int mask) int c; if (insn->op == OP_PINTERP) { - bb->insertTail(insn = insn->clone(true)); + bb->insertTail(insn = cloneForward(func, insn)); insn->op = OP_LINTERP; insn->setInterpolate(NV50_IR_INTERP_LINEAR | insn->getSampleMode()); insn->setSrc(1, NULL); @@ -1510,7 +1510,7 @@ Converter::loadProjTexCoords(Value *dst[4], Value *src[4], unsigned int mask) continue; mask &= ~(1 << c); - bb->insertTail(insn = insn->clone(true)); + bb->insertTail(insn = cloneForward(func, insn)); insn->setInterpolate(NV50_IR_INTERP_PERSPECTIVE | insn->getSampleMode()); insn->setSrc(1, proj); dst[c] = insn->getDef(0); diff --git a/src/gallium/drivers/nv50/codegen/nv50_ir_inlines.h b/src/gallium/drivers/nv50/codegen/nv50_ir_inlines.h index 713653175fd..4aec6ea6723 100644 --- a/src/gallium/drivers/nv50/codegen/nv50_ir_inlines.h +++ b/src/gallium/drivers/nv50/codegen/nv50_ir_inlines.h @@ -274,6 +274,16 @@ const TexInstruction *Instruction::asTex() const return NULL; } +static inline Instruction *cloneForward(Function *ctx, Instruction *obj) +{ + DeepClonePolicy pol(ctx); + + for (int i = 0; obj->srcExists(i); ++i) + pol.set(obj->getSrc(i), obj->getSrc(i)); + + return obj->clone(pol); +} + // XXX: use a virtual function so we're really really safe ? LValue *Value::asLValue() { diff --git a/src/gallium/drivers/nv50/codegen/nv50_ir_peephole.cpp b/src/gallium/drivers/nv50/codegen/nv50_ir_peephole.cpp index 93ba4c5b6ae..8bb49c28a4e 100644 --- a/src/gallium/drivers/nv50/codegen/nv50_ir_peephole.cpp +++ b/src/gallium/drivers/nv50/codegen/nv50_ir_peephole.cpp @@ -1064,8 +1064,8 @@ AlgebraicOpt::handleLOGOP(Instruction *logop) set1->getSrc(s) == set0->getDef(0)) return; - set0 = set0->clone(true); - set1 = set1->clone(false); + set0 = cloneForward(func, set0); + set1 = cloneShallow(func, set1); logop->bb->insertAfter(logop, set1); logop->bb->insertAfter(logop, set0); @@ -1102,7 +1102,7 @@ AlgebraicOpt::handleCVT(Instruction *cvt) if (!insn || insn->op != OP_SET || insn->dType != TYPE_F32) return; - Instruction *bset = insn->clone(false); + Instruction *bset = cloneShallow(func, insn); bset->dType = TYPE_U32; bset->setDef(0, cvt->getDef(0)); cvt->bb->insertAfter(cvt, bset); @@ -1152,7 +1152,7 @@ updateLdStOffset(Instruction *ldst, int32_t offset, Function *fn) { if (offset != ldst->getSrc(0)->reg.data.offset) { if (ldst->getSrc(0)->refCount() > 1) - ldst->setSrc(0, ldst->getSrc(0)->clone(fn)); + ldst->setSrc(0, cloneShallow(fn, ldst->getSrc(0))); ldst->getSrc(0)->reg.data.offset = offset; } } @@ -1272,7 +1272,7 @@ MemoryOpt::combineLd(Record *rec, Instruction *ld) rec->insn->setDef(d, rec->insn->getDef(j - 1)); if (rec->insn->getSrc(0)->refCount() > 1) - rec->insn->setSrc(0, rec->insn->getSrc(0)->clone(func)); + rec->insn->setSrc(0, cloneShallow(func, rec->insn->getSrc(0))); rec->offset = rec->insn->getSrc(0)->reg.data.offset = offLd; d = 0; @@ -2215,7 +2215,7 @@ DeadCodeElim::checkSplitLoad(Instruction *ld1) if (!n2) return; - ld2 = ld1->clone(false); + ld2 = cloneShallow(func, ld1); updateLdStOffset(ld2, addr2, func); ld2->setType(typeOfSize(size2)); for (d = 0; d < 4; ++d) diff --git a/src/gallium/drivers/nv50/codegen/nv50_ir_util.h b/src/gallium/drivers/nv50/codegen/nv50_ir_util.h index 1a19bddb3b4..23759d2ded2 100644 --- a/src/gallium/drivers/nv50/codegen/nv50_ir_util.h +++ b/src/gallium/drivers/nv50/codegen/nv50_ir_util.h @@ -26,6 +26,11 @@ #include #include #include +#include + +#ifndef NDEBUG +# include +#endif #include "util/u_inlines.h" #include "util/u_memory.h" @@ -601,6 +606,100 @@ private: const unsigned int objStepLog2; }; +/** + * Composite object cloning policy. + * + * Encapsulates how sub-objects are to be handled (if at all) when a + * composite object is being cloned. + */ +template +class ClonePolicy +{ +protected: + C *c; + +public: + ClonePolicy(C *c) : c(c) {} + + C *context() { return c; } + + template T *get(T *obj) + { + void *clone = lookup(obj); + if (!clone) + clone = obj->clone(*this); + return reinterpret_cast(clone); + } + + template void set(const T *obj, T *clone) + { + insert(obj, clone); + } + +protected: + virtual void *lookup(void *obj) = 0; + virtual void insert(const void *obj, void *clone) = 0; +}; + +/** + * Shallow non-recursive cloning policy. + * + * Objects cloned with the "shallow" policy don't clone their + * children recursively, instead, the new copy shares its children + * with the original object. + */ +template +class ShallowClonePolicy : public ClonePolicy +{ +public: + ShallowClonePolicy(C *c) : ClonePolicy(c) {} + +protected: + virtual void *lookup(void *obj) + { + return obj; + } + + virtual void insert(const void *obj, void *clone) + { + } +}; + +template +inline T *cloneShallow(C *c, T *obj) +{ + ShallowClonePolicy pol(c); + return obj->clone(pol); +} + +/** + * Recursive cloning policy. + * + * Objects cloned with the "deep" policy clone their children + * recursively, keeping track of what has already been cloned to + * avoid making several new copies of the same object. + */ +template +class DeepClonePolicy : public ClonePolicy +{ +public: + DeepClonePolicy(C *c) : ClonePolicy(c) {} + +private: + std::map map; + +protected: + virtual void *lookup(void *obj) + { + return map[obj]; + } + + virtual void insert(const void *obj, void *clone) + { + map[obj] = clone; + } +}; + } // namespace nv50_ir #endif // __NV50_IR_UTIL_H__ diff --git a/src/gallium/drivers/nvc0/codegen/nv50_ir_lowering_nvc0.cpp b/src/gallium/drivers/nvc0/codegen/nv50_ir_lowering_nvc0.cpp index 6eb0bf48928..bd33fbfac5c 100644 --- a/src/gallium/drivers/nvc0/codegen/nv50_ir_lowering_nvc0.cpp +++ b/src/gallium/drivers/nvc0/codegen/nv50_ir_lowering_nvc0.cpp @@ -159,7 +159,7 @@ NVC0LegalizePostRA::split64BitOp(Instruction *i) return; i->dType = i->sType = TYPE_U32; - i->bb->insertAfter(i, i->clone(true)); // deep cloning + i->bb->insertAfter(i, cloneForward(func, i)); } } @@ -390,7 +390,7 @@ NVC0LoweringPass::handleManualTXD(TexInstruction *i) for (c = 0; c < dim; ++c) bld.mkQuadop(qOps[l][1], crd[c], l, i->dPdy[c].get(), crd[c]); // texture - bld.insert(tex = i->clone(true)); + bld.insert(tex = cloneForward(func, i)); for (c = 0; c < dim; ++c) tex->setSrc(c, crd[c]); // save results -- 2.30.2