From 9236af8b6c395041b0cfd70fc6764e13d66cf854 Mon Sep 17 00:00:00 2001 From: Pierre Moreau Date: Thu, 28 Jul 2022 10:49:03 +0200 Subject: [PATCH] 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 Part-of: --- src/nouveau/codegen/nv50_ir_build_util.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/nouveau/codegen/nv50_ir_build_util.cpp b/src/nouveau/codegen/nv50_ir_build_util.cpp index 8d40f7e5c0e..3da4bd18e82 100644 --- a/src/nouveau/codegen/nv50_ir_build_util.cpp +++ b/src/nouveau/codegen/nv50_ir_build_util.cpp @@ -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);