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;
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;
}
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
}
}
-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;
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;
}
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;
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;
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;
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 *);
private:
void init();
-protected:
- void cloneBase(Instruction *clone, bool deep) const;
};
enum TexQuery
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)
{
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; }
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);
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);
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()
{
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);
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);
{
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;
}
}
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;
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)
#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"
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__
return;
i->dType = i->sType = TYPE_U32;
- i->bb->insertAfter(i, i->clone(true)); // deep cloning
+ i->bb->insertAfter(i, cloneForward(func, 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