nv50/ir: Decouple object cloning logic from the sub-object recursion policy.

This commit is contained in:
Francisco Jerez 2012-04-14 21:24:16 +02:00 committed by Christoph Bumiller
parent da28ba00d8
commit a05e6a3fa2
7 changed files with 181 additions and 68 deletions

View 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;
}

View 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; }

View 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);

View 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()
{

View 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)

View File

@ -26,6 +26,11 @@
#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__

View 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