nv50/ir/opt: Don't lose modifiers during constant folding.

This commit is contained in:
Francisco Jerez 2012-04-09 20:43:28 +02:00 committed by Christoph Bumiller
parent 14d5f975a6
commit d6d1f0e4a2
3 changed files with 92 additions and 72 deletions

View File

@ -77,19 +77,38 @@ ValueRef::~ValueRef()
this->set(NULL);
}
ImmediateValue *ValueRef::getImmediate() const
bool ValueRef::getImmediate(ImmediateValue &imm) const
{
Value *src = value;
const ValueRef *src = this;
Modifier m;
DataType type = src->insn->sType;
while (src) {
if (src->reg.file == FILE_IMMEDIATE)
return src->asImm();
if (src->mod) {
if (src->insn->sType != type)
break;
m *= src->mod;
}
if (src->getFile() == FILE_IMMEDIATE) {
imm = *(src->value->asImm());
// The immediate's type isn't required to match its use, it's
// more of a hint; applying a modifier makes use of that hint.
imm.reg.type = type;
m.applyTo(imm);
return true;
}
Instruction *insn = src->getUniqueInsn();
Instruction *insn = src->value->getUniqueInsn();
src = (insn && insn->op == OP_MOV) ? insn->getSrc(0) : NULL;
if (insn && insn->op == OP_MOV) {
src = &insn->src(0);
if (src->mod)
WARN("OP_MOV with modifier encountered !\n");
} else {
src = NULL;
}
}
return NULL;
return false;
}
ValueDef::ValueDef(Value *v) : value(NULL), insn(NULL)
@ -483,6 +502,13 @@ ImmediateValue::compare(CondCode cc, float fval) const
}
}
ImmediateValue&
ImmediateValue::operator=(const ImmediateValue &that)
{
this->reg = that.reg;
return (*this);
}
bool
Value::interfers(const Value *that) const
{

View File

@ -45,7 +45,7 @@ enum operation
OP_SPLIT, // $r0d -> { $r0, $r1 } ($r0d and $r0/$r1 will be coalesced)
OP_MERGE, // opposite of split, e.g. combine 2 32 bit into a 64 bit value
OP_CONSTRAINT, // copy values into consecutive registers
OP_MOV,
OP_MOV, // simple copy, no modifiers allowed
OP_LOAD,
OP_STORE,
OP_ADD,
@ -403,7 +403,7 @@ public:
inline unsigned getSize() const;
// SSA: return eventual (traverse MOVs) literal value, if it exists
ImmediateValue *getImmediate() const;
bool getImmediate(ImmediateValue&) const;
public:
Modifier mod;
@ -545,6 +545,7 @@ private:
class ImmediateValue : public Value
{
public:
ImmediateValue() { }
ImmediateValue(Program *, uint32_t);
ImmediateValue(Program *, float);
ImmediateValue(Program *, double);
@ -569,6 +570,8 @@ public:
ImmediateValue operator*(const ImmediateValue&) const;
ImmediateValue operator/(const ImmediateValue&) const;
ImmediateValue& operator=(const ImmediateValue&); // only sets value !
bool compare(CondCode cc, float fval) const;
virtual int print(char *, size_t, DataType ty = TYPE_NONE) const;

View File

@ -211,8 +211,8 @@ public:
private:
virtual bool visit(BasicBlock *);
void expr(Instruction *, ImmediateValue *, ImmediateValue *);
void opnd(Instruction *, ImmediateValue *, int s);
void expr(Instruction *, ImmediateValue&, ImmediateValue&);
void opnd(Instruction *, ImmediateValue&, int s);
void unary(Instruction *, const ImmediateValue&);
@ -249,16 +249,16 @@ ConstantFolding::visit(BasicBlock *bb)
if (i->op == OP_MOV) // continue early, MOV appears frequently
continue;
ImmediateValue *src0 = i->srcExists(0) ? i->src(0).getImmediate() : NULL;
ImmediateValue *src1 = i->srcExists(1) ? i->src(1).getImmediate() : NULL;
ImmediateValue src0, src1;
if (src0 && src1)
if (i->srcExists(1) &&
i->src(0).getImmediate(src0) && i->src(1).getImmediate(src1))
expr(i, src0, src1);
else
if (src0)
if (i->srcExists(0) && i->src(0).getImmediate(src0))
opnd(i, src0, 0);
else
if (src1)
if (i->srcExists(1) && i->src(1).getImmediate(src1))
opnd(i, src1, 1);
}
return true;
@ -365,15 +365,12 @@ Modifier::getOp() const
void
ConstantFolding::expr(Instruction *i,
ImmediateValue *src0, ImmediateValue *src1)
ImmediateValue &imm0, ImmediateValue &imm1)
{
ImmediateValue imm0(src0, i->sType);
ImmediateValue imm1(src1, i->sType);
struct Storage res;
struct Storage *const a = &imm0.reg, *const b = &imm1.reg;
struct Storage res;
i->src(0).mod.applyTo(imm0);
i->src(1).mod.applyTo(imm1);
memset(&res.data, 0, sizeof(res.data));
switch (i->op) {
case OP_MAD:
@ -490,9 +487,9 @@ ConstantFolding::expr(Instruction *i,
i->setSrc(0, i->getSrc(2));
i->setSrc(2, NULL);
src0 = i->src(0).getImmediate();
if (src0)
expr(i, src0, i->getSrc(1)->asImm());
ImmediateValue src0;
if (i->src(0).getImmediate(src0))
expr(i, src0, *i->getSrc(1)->asImm());
} else {
i->op = OP_MOV;
}
@ -537,28 +534,24 @@ ConstantFolding::tryCollapseChainedMULs(Instruction *mul2,
Instruction *mul1 = NULL; // mul1 before mul2
int e = 0;
float f = imm2.reg.data.f32;
ImmediateValue imm1;
assert(mul2->op == OP_MUL && mul2->dType == TYPE_F32);
if (mul2->getSrc(t)->refCount() == 1) {
insn = mul2->getSrc(t)->getInsn();
if (insn->op == OP_MUL && insn->dType == TYPE_F32)
if (!mul2->src(t).mod && insn->op == OP_MUL && insn->dType == TYPE_F32)
mul1 = insn;
if (mul1) {
int s1 = 0;
ImmediateValue *imm = mul1->src(s1).getImmediate();
if (!imm) {
s1 = 1;
imm = mul1->src(s1).getImmediate();
}
if (imm) {
int s1;
if (mul1->src(s1 = 0).getImmediate(imm1) ||
mul1->src(s1 = 1).getImmediate(imm1)) {
bld.setPosition(mul1, false);
// a = mul r, imm1
// d = mul a, imm2 -> d = mul r, (imm1 * imm2)
ImmediateValue imm1(mul1->src(s1).getImmediate(), TYPE_F32);
mul1->src(s1).mod.applyTo(imm1);
mul1->src(s1).mod = Modifier(0);
mul1->setSrc(s1, bld.loadImm(NULL, f * imm1.reg.data.f32));
mul1->src(s1).mod = Modifier(0);
mul2->def(0).replace(mul1->getDef(0), false);
} else
if (prog->getTarget()->isPostMultiplySupported(OP_MUL, f, e)) {
@ -567,7 +560,7 @@ ConstantFolding::tryCollapseChainedMULs(Instruction *mul2,
mul1->postFactor = e;
mul2->def(0).replace(mul1->getDef(0), false);
if (f < 0)
mul1->src(0).mod = mul1->src(0).mod ^ Modifier(NV50_IR_MOD_NEG);
mul1->src(0).mod *= Modifier(NV50_IR_MOD_NEG);
}
return;
}
@ -584,39 +577,36 @@ ConstantFolding::tryCollapseChainedMULs(Instruction *mul2,
s2 = insn->getSrc(0) == mul1->getDef(0) ? 0 : 1;
t2 = s2 ? 0 : 1;
if (insn->op == OP_MUL && insn->dType == TYPE_F32)
if (!insn->src(t2).getImmediate())
if (!insn->src(s2).mod && !insn->src(t2).getImmediate(imm1))
mul2 = insn;
if (mul2 && prog->getTarget()->isPostMultiplySupported(OP_MUL, f, e)) {
mul2->postFactor = e;
mul2->setSrc(s2, mul1->src(t));
if (f < 0)
mul2->src(s2).mod = mul2->src(s2).mod ^ Modifier(NV50_IR_MOD_NEG);
mul2->src(s2).mod *= Modifier(NV50_IR_MOD_NEG);
}
}
}
void
ConstantFolding::opnd(Instruction *i, ImmediateValue *src, int s)
ConstantFolding::opnd(Instruction *i, ImmediateValue &imm0, int s)
{
const int t = !s;
const operation op = i->op;
ImmediateValue imm(src, i->sType);
i->src(s).mod.applyTo(imm);
switch (i->op) {
case OP_MUL:
if (i->dType == TYPE_F32)
tryCollapseChainedMULs(i, s, imm);
tryCollapseChainedMULs(i, s, imm0);
if (imm.isInteger(0)) {
if (imm0.isInteger(0)) {
i->op = OP_MOV;
i->setSrc(0, i->getSrc(s));
i->setSrc(0, new_ImmediateValue(prog, 0u));
i->src(0).mod = Modifier(0);
i->setSrc(1, NULL);
} else
if (imm.isInteger(1) || imm.isInteger(-1)) {
if (imm.isNegative())
if (imm0.isInteger(1) || imm0.isInteger(-1)) {
if (imm0.isNegative())
i->src(t).mod = i->src(t).mod ^ Modifier(NV50_IR_MOD_NEG);
i->op = i->src(t).mod.getOp();
if (s == 0) {
@ -628,21 +618,24 @@ ConstantFolding::opnd(Instruction *i, ImmediateValue *src, int s)
i->src(0).mod = 0;
i->setSrc(1, NULL);
} else
if (imm.isInteger(2) || imm.isInteger(-2)) {
if (imm.isNegative())
if (imm0.isInteger(2) || imm0.isInteger(-2)) {
if (imm0.isNegative())
i->src(t).mod = i->src(t).mod ^ Modifier(NV50_IR_MOD_NEG);
i->op = OP_ADD;
i->setSrc(s, i->getSrc(t));
i->src(s).mod = i->src(t).mod;
} else
if (!isFloatType(i->sType) && !imm.isNegative() && imm.isPow2()) {
if (!isFloatType(i->sType) && !imm0.isNegative() && imm0.isPow2()) {
i->op = OP_SHL;
imm.applyLog2();
i->setSrc(1, new_ImmediateValue(prog, imm.reg.data.u32));
imm0.applyLog2();
i->setSrc(0, i->getSrc(t));
i->src(0).mod = i->src(t).mod;
i->setSrc(1, new_ImmediateValue(prog, imm0.reg.data.u32));
i->src(1).mod = 0;
}
break;
case OP_ADD:
if (imm.isInteger(0)) {
if (imm0.isInteger(0)) {
if (s == 0) {
i->setSrc(0, i->getSrc(1));
i->src(0).mod = i->src(1).mod;
@ -658,21 +651,21 @@ ConstantFolding::opnd(Instruction *i, ImmediateValue *src, int s)
if (s != 1 || (i->dType != TYPE_S32 && i->dType != TYPE_U32))
break;
bld.setPosition(i, false);
if (imm.reg.data.u32 == 0) {
if (imm0.reg.data.u32 == 0) {
break;
} else
if (imm.reg.data.u32 == 1) {
if (imm0.reg.data.u32 == 1) {
i->op = OP_MOV;
i->setSrc(1, NULL);
} else
if (i->dType == TYPE_U32 && imm.isPow2()) {
if (i->dType == TYPE_U32 && imm0.isPow2()) {
i->op = OP_SHR;
i->setSrc(1, bld.mkImm(util_logbase2(imm.reg.data.u32)));
i->setSrc(1, bld.mkImm(util_logbase2(imm0.reg.data.u32)));
} else
if (i->dType == TYPE_U32) {
Instruction *mul;
Value *tA, *tB;
const uint32_t d = imm.reg.data.u32;
const uint32_t d = imm0.reg.data.u32;
uint32_t m;
int r, s;
uint32_t l = util_logbase2(d);
@ -700,13 +693,13 @@ ConstantFolding::opnd(Instruction *i, ImmediateValue *src, int s)
delete_Instruction(prog, i);
} else
if (imm.reg.data.s32 == -1) {
if (imm0.reg.data.s32 == -1) {
i->op = OP_NEG;
i->setSrc(1, NULL);
} else {
LValue *tA, *tB;
LValue *tD;
const int32_t d = imm.reg.data.s32;
const int32_t d = imm0.reg.data.s32;
int32_t m;
int32_t l = util_logbase2(static_cast<unsigned>(abs(d)));
if ((1 << l) < abs(d))
@ -735,10 +728,10 @@ ConstantFolding::opnd(Instruction *i, ImmediateValue *src, int s)
break;
case OP_MOD:
if (i->sType == TYPE_U32 && imm.isPow2()) {
if (i->sType == TYPE_U32 && imm0.isPow2()) {
bld.setPosition(i, false);
i->op = OP_AND;
i->setSrc(1, bld.loadImm(NULL, imm.reg.data.u32 - 1));
i->setSrc(1, bld.loadImm(NULL, imm0.reg.data.u32 - 1));
}
break;
@ -748,7 +741,7 @@ ConstantFolding::opnd(Instruction *i, ImmediateValue *src, int s)
CondCode cc, ccZ;
if (i->src(t).mod != Modifier(0))
return;
if (imm.reg.data.u32 != 0 || !si || si->op != OP_SET)
if (imm0.reg.data.u32 != 0 || !si || si->op != OP_SET)
return;
cc = si->setCond;
ccZ = (CondCode)((unsigned int)i->asCmp()->setCond & ~CC_U);
@ -777,15 +770,13 @@ ConstantFolding::opnd(Instruction *i, ImmediateValue *src, int s)
break;
// try to concatenate shifts
Instruction *si = i->getSrc(0)->getInsn();
if (!si ||
si->op != OP_SHL || si->src(1).mod != Modifier(0))
if (!si || si->op != OP_SHL)
break;
ImmediateValue *siImm = si->src(1).getImmediate();
if (siImm) {
ImmediateValue imm1;
if (si->src(1).getImmediate(imm1)) {
bld.setPosition(i, false);
i->setSrc(0, si->getSrc(0));
i->setSrc(1, bld.loadImm(NULL,
imm.reg.data.u32 + siImm->reg.data.u32));
i->setSrc(1, bld.loadImm(NULL, imm0.reg.data.u32 + imm1.reg.data.u32));
}
}
break;
@ -801,7 +792,7 @@ ConstantFolding::opnd(Instruction *i, ImmediateValue *src, int s)
case OP_COS:
case OP_PREEX2:
case OP_EX2:
unary(i, imm);
unary(i, imm0);
break;
default:
return;