Page MenuHomePhabricator

Split 64-bit MAD/MUL
ActivePublic

Authored by pmoreau on May 28 2016, 8:34 PM.
Instruction *
BuildUtil::split64Mul(Function *fn, Instruction *i, Value *zero,
Value *carry)
{
DataType hTy;
switch (i->dType) {
case TYPE_U64: hTy = TYPE_U32; break;
case TYPE_S64: hTy = TYPE_S32; break;
default:
return NULL;
}
assert(i->op == OP_MAD || i->op == OP_MUL);
if (!carry || isFloatType(i->dType) || isFloatType(i->sType))
return NULL;
int srcNr = (i->op == OP_MAD) ? 3 : 2;
i->setType(hTy);
i->setDef(0, cloneShallow(fn, i->getDef(0)));
i->getDef(0)->reg.size = 4;
// d = a * b (+ c)?
Instruction *lo = i; // d.low = a.low * b.low (+ c.low)?
Instruction *tmp1 = cloneForward(fn, i); // d.high = a.low * b.high
tmp1->getDef(0)->reg.data.id++;
Instruction *tmp2 = cloneForward(fn, tmp1); // d.high = a.high * b.low + d.high
Instruction *hi = (i->op == OP_MAD) ? cloneForward(fn, tmp1) : NULL; // d.high = d.high + c.high
lo->bb->insertAfter(lo, tmp1);
lo->bb->insertAfter(tmp1, tmp2);
if (hi != NULL)
lo->bb->insertAfter(tmp2, hi);
auto lower = [fn, lo](Instruction *insn, int pos, int s){
insn->setSrc(pos, cloneShallow(fn, lo->getSrc(s)));
switch (lo->src(s).getFile()) {
case FILE_IMMEDIATE:
insn->getSrc(s)->reg.data.u64 >>= 32;
break;
case FILE_MEMORY_CONST:
case FILE_MEMORY_SHARED:
case FILE_SHADER_INPUT:
case FILE_SHADER_OUTPUT:
insn->getSrc(pos)->reg.data.offset += 4;
break;
default:
assert(insn->src(pos).getFile() == FILE_GPR);
insn->getSrc(pos)->reg.data.id++;
break;
}
};
for (int s = 0; s < srcNr; ++s) {
if (lo->getSrc(s)->reg.size < 8) {
if (s == 0)
tmp2->setSrc(s, zero);
else if (s == 1)
tmp1->setSrc(s, zero);
else if (s == 2)
hi->setSrc(1, zero);
} else {
if (lo->getSrc(s)->refCount() > 1)
lo->setSrc(s, cloneShallow(fn, lo->getSrc(s)));
lo->getSrc(s)->reg.size /= 2;
if (s == 0) {
tmp1->getSrc(s)->reg.size /= 2;
lower(tmp2, s, s);
} else if (s == 1) {
lower(tmp1, s ,s);
tmp2->getSrc(s)->reg.size /= 2;
} else if (s == 2)
lower(hi, 1, s);
}
}
tmp_high->reg.type = tmp1->getDef(0)->reg.type;
tmp1->op = OP_MUL;
tmp1->setDef(0, tmp_high);
tmp1->setSrc(2, NULL);
tmp2->op = OP_MAD;
tmp2->setSrc(2, tmp_high);
if (hi != nullptr) {
hi->op = OP_ADD;
hi->setSrc(0, hi->getDef(0));
hi->setSrc(2, NULL);
}
lo->setFlagsDef(1, carry);
if (hi != NULL)
hi->setFlagsSrc(hi->srcCount(), carry);
else
tmp2->setFlagsSrc(tmp2->srcCount(), carry);
return (hi != NULL) ? hi : tmp2;
}

Event Timeline

pmoreau created this paste.May 28 2016, 8:34 PM
pmoreau created this object with visibility "Public (No Login Required)".
pmoreau created this object with edit policy "Nouveau (Project)".
pmoreau updated the paste's language from diff to cpp.
pmoreau edited the content of this paste. (Show Details)
pmoreau edited the content of this paste. (Show Details)May 28 2016, 8:37 PM
pmoreau edited the content of this paste. (Show Details)