nv50/ir/opt: Improve modifier handling.
This commit is contained in:
parent
784848a94d
commit
14d5f975a6
|
@ -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()
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue