diff --git a/src/nouveau/codegen/nv50_ir_ra.cpp b/src/nouveau/codegen/nv50_ir_ra.cpp index 92bd5a67372..ea45ff751a2 100644 --- a/src/nouveau/codegen/nv50_ir_ra.cpp +++ b/src/nouveau/codegen/nv50_ir_ra.cpp @@ -823,6 +823,7 @@ private: void simplifyEdge(RIG_Node *, RIG_Node *); void simplifyNode(RIG_Node *); + void copyCompound(Value *dst, Value *src); bool coalesceValues(Value *, Value *, bool force); void resolveSplitsAndMerges(); void makeCompound(Instruction *, bool isSplit); @@ -955,6 +956,34 @@ GCRA::RIG_Node::init(const RegisterSet& regs, LValue *lval) livei.insert(lval->livei); } +// Used when coalescing moves. The non-compound value will become one, e.g.: +// mov b32 $r0 $r2 / merge b64 $r0d { $r0 $r1 } +// split b64 { $r0 $r1 } $r0d / mov b64 $r0d f64 $r2d +void +GCRA::copyCompound(Value *dst, Value *src) +{ + LValue *ldst = dst->asLValue(); + LValue *lsrc = src->asLValue(); + + if (ldst->compound && !lsrc->compound) { + LValue *swap = lsrc; + lsrc = ldst; + ldst = swap; + } + + assert(!ldst->compound); + + if (lsrc->compound) { + for (ValueDef *d : mergedDefs(ldst->join)) { + LValue *ldst = d->get()->asLValue(); + if (!ldst->compound) + ldst->compMask = 0xff; + ldst->compound = 1; + ldst->compMask &= lsrc->compMask; + } + } +} + bool GCRA::coalesceValues(Value *dst, Value *src, bool force) { @@ -997,9 +1026,16 @@ GCRA::coalesceValues(Value *dst, Value *src, bool force) if (!force && nRep->livei.overlaps(nVal->livei)) return false; + // TODO: Handle this case properly. + if (!force && rep->compound && val->compound) + return false; + INFO_DBG(prog->dbgFlags, REG_ALLOC, "joining %%%i($%i) <- %%%i\n", rep->id, rep->reg.data.id, val->id); + if (!force) + copyCompound(dst, src); + // set join pointer of all values joined with val const std::list &defs = mergedDefs(val); for (ValueDef *def : defs) @@ -1067,24 +1103,6 @@ static inline uint8_t makeCompMask(int compSize, int base, int size) } } -// Used when coalescing moves. The non-compound value will become one, e.g.: -// mov b32 $r0 $r2 / merge b64 $r0d { $r0 $r1 } -// split b64 { $r0 $r1 } $r0d / mov b64 $r0d f64 $r2d -static inline void copyCompound(Value *dst, Value *src) -{ - LValue *ldst = dst->asLValue(); - LValue *lsrc = src->asLValue(); - - if (ldst->compound && !lsrc->compound) { - LValue *swap = lsrc; - lsrc = ldst; - ldst = swap; - } - - ldst->compound = lsrc->compound; - ldst->compMask = lsrc->compMask; -} - void GCRA::makeCompound(Instruction *insn, bool split) { @@ -1170,8 +1188,7 @@ GCRA::doCoalesce(ArrayList& insns, unsigned int mask) break; i = insn->getSrc(0)->getUniqueInsn(); if (i && !i->constrainedDefs()) { - if (coalesceValues(insn->getDef(0), insn->getSrc(0), false)) - copyCompound(insn->getSrc(0), insn->getDef(0)); + coalesceValues(insn->getDef(0), insn->getSrc(0), false); } break; case OP_TEX: @@ -2617,7 +2634,8 @@ RegAlloc::InsertConstraintsPass::insertConstraintMove(Instruction *cst, int s) defi->src(0).getFile() == FILE_MEMORY_CONST && !defi->src(0).isIndirect(0); // catch some cases where don't really need MOVs - if (cst->getSrc(s)->refCount() == 1 && !defi->constrainedDefs()) { + if (cst->getSrc(s)->refCount() == 1 && !defi->constrainedDefs() + && defi->op != OP_MERGE && defi->op != OP_SPLIT) { if (imm || load) { // Move the defi right before the cst. No point in expanding // the range.