nv50/ir: Avoid generating splits of splits

Among others, it would result in the spill offsets being wrong due to
being relative to the parent split and not absolute.

For example when computing a 64-bit multiply on Tesla (which only
supports 16-bit mul in hardware), the sources will first be split into
32-bit values and then a second time down to 16-bit ones. Looking at the
first source, the spill offsets ended being computed as follows:

    { .hihi = +2, .hilo = +0, .lohi = +2, .lolo = +0 }

instead of the expected

    { .hihi = +6, .hilo = +4, .lohi = +2, .lolo = +0 }

This is resolved with this patch.

Signed-off-by: Pierre Moreau <dev@pmoreau.org>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/10711>
This commit is contained in:
Pierre Moreau 2022-07-28 10:49:03 +02:00 committed by Marge Bot
parent b327f46e45
commit 9236af8b6c

View file

@ -300,6 +300,14 @@ BuildUtil::mkSplit(Value *h[2], uint8_t halfSize, Value *val)
h[1]->reg.size = halfSize;
h[1]->reg.data.offset += halfSize;
} else {
// The value might already be the result of a split, and further
// splitting it can lead to issues regarding spill-offsets computations
// among others. By forcing a move between the two splits, this can be
// avoided.
Instruction* valInsn = val->getInsn();
if (valInsn && valInsn->op == OP_SPLIT)
val = mkMov(getSSA(halfSize * 2), val, fTy)->getDef(0);
h[0] = getSSA(halfSize, val->reg.file);
h[1] = getSSA(halfSize, val->reg.file);
insn = mkOp1(OP_SPLIT, fTy, h[0], val);