nv50/ir/opt: Improve modifier handling.

This commit is contained in:
Francisco Jerez 2012-03-21 00:39:00 +01:00 committed by Christoph Bumiller
parent 784848a94d
commit 14d5f975a6
3 changed files with 67 additions and 25 deletions

View File

@ -58,11 +58,12 @@ Modifier Modifier::operator*(const Modifier m) const
return Modifier(a | c);
}
ValueRef::ValueRef() : value(NULL), insn(NULL)
ValueRef::ValueRef(Value *v) : value(NULL), insn(NULL)
{
indirect[0] = -1;
indirect[1] = -1;
usedAsPtr = false;
set(v);
}
ValueRef::ValueRef(const ValueRef& ref) : value(NULL), insn(ref.insn)
@ -91,9 +92,9 @@ ImmediateValue *ValueRef::getImmediate() const
return NULL;
}
ValueDef::ValueDef() : value(NULL), insn(NULL)
ValueDef::ValueDef(Value *v) : value(NULL), insn(NULL)
{
// nothing to do
set(v);
}
ValueDef::ValueDef(const ValueDef& def) : value(NULL), insn(NULL)
@ -141,17 +142,58 @@ ValueDef::set(Value *defVal)
value = defVal;
}
void
ValueDef::replace(Value *repVal, bool doSet)
// Check if we can replace this definition's value by the value in @rep,
// including the source modifiers, i.e. make sure that all uses support
// @rep.mod.
bool
ValueDef::mayReplace(const ValueRef &rep)
{
if (value == repVal)
if (!rep.mod)
return true;
if (!insn || !insn->bb) // Unbound instruction ?
return false;
const Target *target = insn->bb->getProgram()->getTarget();
for (Value::UseIterator it = value->uses.begin(); it != value->uses.end();
++it) {
Instruction *insn = (*it)->getInsn();
int s = -1;
for (int i = 0; insn->srcExists(i); ++i) {
if (insn->src(i).get() == value) {
// If there are multiple references to us we'd have to check if the
// combination of mods is still supported, but just bail for now.
if (&insn->src(i) != (*it))
return false;
s = i;
}
}
assert(s >= 0); // integrity of uses list
if (!target->isModSupported(insn, s, rep.mod))
return false;
}
return true;
}
void
ValueDef::replace(const ValueRef &repVal, bool doSet)
{
assert(mayReplace(repVal));
if (value == repVal.get())
return;
while (value->refCount())
value->uses.front()->set(repVal);
while (!value->uses.empty()) {
ValueRef *ref = value->uses.front();
ref->set(repVal.get());
ref->mod *= repVal.mod;
}
if (doSet)
set(repVal);
set(repVal.get());
}
Value::Value()

View File

@ -356,6 +356,7 @@ public:
// @return new Modifier applying a after b (asserts if unrepresentable)
Modifier operator*(const Modifier) const;
Modifier operator*=(const Modifier m) { *this = *this * m; return *this; }
Modifier operator==(const Modifier m) const { return m.bits == bits; }
Modifier operator!=(const Modifier m) const { return m.bits != bits; }
@ -368,7 +369,7 @@ public:
inline int neg() const { return (bits & NV50_IR_MOD_NEG) ? 1 : 0; }
inline int abs() const { return (bits & NV50_IR_MOD_ABS) ? 1 : 0; }
inline operator bool() { return bits ? true : false; }
inline operator bool() const { return bits ? true : false; }
void applyTo(ImmediateValue &imm) const;
@ -381,7 +382,7 @@ private:
class ValueRef
{
public:
ValueRef();
ValueRef(Value * = NULL);
ValueRef(const ValueRef&);
~ValueRef();
@ -419,7 +420,7 @@ private:
class ValueDef
{
public:
ValueDef();
ValueDef(Value * = NULL);
ValueDef(const ValueDef&);
~ValueDef();
@ -428,7 +429,8 @@ public:
inline Value *get() const { return value; }
inline Value *rep() const;
void set(Value *);
void replace(Value *, bool doSet); // replace all uses of the old value
bool mayReplace(const ValueRef &);
void replace(const ValueRef &, bool doSet); // replace all uses of the old value
inline Instruction *getInsn() const { return insn; }
inline void setInsn(Instruction *inst) { insn = inst; }

View File

@ -853,7 +853,7 @@ ModifierFolding::visit(BasicBlock *bb)
}
if ((mod = Modifier(mi->op)) == Modifier(0))
continue;
mod = mod * mi->src(0).mod;
mod *= mi->src(0).mod;
if ((i->op == OP_ABS) || i->src(s).mod.abs()) {
// abs neg [abs] = abs
@ -872,7 +872,7 @@ ModifierFolding::visit(BasicBlock *bb)
if (target->isModSupported(i, s, mod)) {
i->setSrc(s, mi->getSrc(0));
i->src(s).mod = i->src(s).mod * mod;
i->src(s).mod *= mod;
}
}
@ -972,12 +972,12 @@ AlgebraicOpt::handleMINMAX(Instruction *minmax)
if (src0 != src1 || src0->reg.file != FILE_GPR)
return;
if (minmax->src(0).mod == minmax->src(1).mod) {
if (minmax->src(0).mod) {
if (minmax->def(0).mayReplace(minmax->src(0))) {
minmax->def(0).replace(minmax->src(0), false);
minmax->bb->remove(minmax);
} else {
minmax->op = OP_CVT;
minmax->setSrc(1, NULL);
} else {
minmax->def(0).replace(minmax->getSrc(0), false);
minmax->bb->remove(minmax);
}
} else {
// TODO:
@ -1027,11 +1027,9 @@ AlgebraicOpt::handleLOGOP(Instruction *logop)
return;
if (src0 == src1) {
if (logop->src(0).mod != Modifier(0) ||
logop->src(1).mod != Modifier(0))
return;
if (logop->op == OP_AND || logop->op == OP_OR) {
logop->def(0).replace(logop->getSrc(0), false);
if ((logop->op == OP_AND || logop->op == OP_OR) &&
logop->def(0).mayReplace(logop->src(0))) {
logop->def(0).replace(logop->src(0), false);
delete_Instruction(prog, logop);
}
} else {
@ -1457,7 +1455,7 @@ MemoryOpt::replaceLdFromSt(Instruction *ld, Record *rec)
return false;
if (st->getSrc(s)->reg.file != FILE_GPR)
return false;
ld->def(d).replace(st->getSrc(s), false);
ld->def(d).replace(st->src(s), false);
}
ld->bb->remove(ld);
return true;