nv50/ir: Decouple object cloning logic from the sub-object recursion policy.
authorFrancisco Jerez <currojerez@riseup.net>
Sat, 14 Apr 2012 19:24:16 +0000 (21:24 +0200)
committerChristoph Bumiller <e0425955@student.tuwien.ac.at>
Sat, 14 Apr 2012 19:54:01 +0000 (21:54 +0200)
src/gallium/drivers/nv50/codegen/nv50_ir.cpp
src/gallium/drivers/nv50/codegen/nv50_ir.h
src/gallium/drivers/nv50/codegen/nv50_ir_from_tgsi.cpp
src/gallium/drivers/nv50/codegen/nv50_ir_inlines.h
src/gallium/drivers/nv50/codegen/nv50_ir_peephole.cpp
src/gallium/drivers/nv50/codegen/nv50_ir_util.h
src/gallium/drivers/nvc0/codegen/nv50_ir_lowering_nvc0.cpp

index a93dc73..86e3d1c 100644 (file)
@@ -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<Function>& pol) const
 {
-   LValue *that = new_LValue(func, reg.file);
+   LValue *that = new_LValue(pol.context(), reg.file);
+
+   pol.set<Value>(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<Function>& pol) const
 {
-   Program *prog = func->getProgram();
+   Program *prog = pol.context()->getProgram();
 
    Symbol *that = new_Symbol(prog, reg.file, reg.fileIndex);
 
+   pol.set<Value>(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<Function>& 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<Instruction>(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<Function>& pol, Instruction *i) const
 {
-   TexInstruction *tex = new_TexInstruction(bb->getFunction(), op);
-   cloneBase(tex, deep);
+   TexInstruction *tex = (i ? static_cast<TexInstruction *>(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<Function>& pol, Instruction *i) const
 {
-   CmpInstruction *cmp = new_CmpInstruction(bb->getFunction(), op);
-   cloneBase(cmp, deep);
-   cmp->setCond = setCond;
+   CmpInstruction *cmp = (i ? static_cast<CmpInstruction *>(i) :
+                          new_CmpInstruction(pol.context(), op));
    cmp->dType = dType;
+   Instruction::clone(pol, cmp);
+   cmp->setCond = setCond;
    return cmp;
 }
 
index 8d86a9c..b5cf4b8 100644 (file)
@@ -451,7 +451,7 @@ public:
    Value();
    virtual ~Value() { }
 
-   virtual Value *clone(Function *) const { return NULL; }
+   virtual Value *clone(ClonePolicy<Function>&) 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<Function>&) 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<Function>&) 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<Function>&,
+                              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<Function>&,
+                                 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<Function>&,
+                                 Instruction * = NULL) const;
 
    void setCondition(CondCode cond) { setCond = cond; }
    CondCode getCondition() const { return setCond; }
index 5b2ee69..bc602f4 100644 (file)
@@ -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);
index 7136531..4aec6ea 100644 (file)
@@ -274,6 +274,16 @@ const TexInstruction *Instruction::asTex() const
    return NULL;
 }
 
+static inline Instruction *cloneForward(Function *ctx, Instruction *obj)
+{
+   DeepClonePolicy<Function> 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()
 {
index 93ba4c5..8bb49c2 100644 (file)
@@ -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)
index 1a19bdd..23759d2 100644 (file)
 #include <new>
 #include <assert.h>
 #include <stdio.h>
+#include <map>
+
+#ifndef NDEBUG
+# include <typeinfo>
+#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<typename C>
+class ClonePolicy
+{
+protected:
+   C *c;
+
+public:
+   ClonePolicy(C *c) : c(c) {}
+
+   C *context() { return c; }
+
+   template<typename T> T *get(T *obj)
+   {
+      void *clone = lookup(obj);
+      if (!clone)
+         clone = obj->clone(*this);
+      return reinterpret_cast<T *>(clone);
+   }
+
+   template<typename T> 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<typename C>
+class ShallowClonePolicy : public ClonePolicy<C>
+{
+public:
+   ShallowClonePolicy(C *c) : ClonePolicy<C>(c) {}
+
+protected:
+   virtual void *lookup(void *obj)
+   {
+      return obj;
+   }
+
+   virtual void insert(const void *obj, void *clone)
+   {
+   }
+};
+
+template<typename C, typename T>
+inline T *cloneShallow(C *c, T *obj)
+{
+   ShallowClonePolicy<C> 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<typename C>
+class DeepClonePolicy : public ClonePolicy<C>
+{
+public:
+   DeepClonePolicy(C *c) : ClonePolicy<C>(c) {}
+
+private:
+   std::map<const void *, void *> 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__
index 6eb0bf4..bd33fbf 100644 (file)
@@ -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