From: Francisco Jerez Date: Thu, 29 Mar 2012 21:23:53 +0000 (+0200) Subject: nv50/ir/ra: Use matching physical regs for function args in caller and callee. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=ed255dbae2ada50cbdb71f6b03f4e42d3ed7ebc6;p=mesa.git nv50/ir/ra: Use matching physical regs for function args in caller and callee. --- diff --git a/src/gallium/drivers/nv50/codegen/nv50_ir_ra.cpp b/src/gallium/drivers/nv50/codegen/nv50_ir_ra.cpp index a91a088353e..a08ca31ff84 100644 --- a/src/gallium/drivers/nv50/codegen/nv50_ir_ra.cpp +++ b/src/gallium/drivers/nv50/codegen/nv50_ir_ra.cpp @@ -43,7 +43,7 @@ public: bool assign(Value **, int nr); void release(const Value *); - void occupy(const Value *); + bool occupy(const Value *); int getMaxAssigned(DataFile f) const { return fill[f]; } @@ -148,22 +148,25 @@ RegisterSet::assign(Value **def, int nr) return true; } -void +bool RegisterSet::occupy(const Value *val) { int id = val->reg.data.id; - if (id < 0) - return; unsigned int f = val->reg.file; uint32_t m = (1 << (val->reg.size >> unit[f])) - 1; + if (id < 0 || bits[f][id / 32] & m << (id % 32)) + return false; + INFO_DBG(0, REG_ALLOC, "reg occupy: %u[%i] %x\n", f, id, m); bits[f][id / 32] |= m << (id % 32); if (fill[f] < id) fill[f] = id; + + return true; } void @@ -207,6 +210,11 @@ private: inline bool needNewElseBlock(BasicBlock *b, BasicBlock *p); }; + class ArgumentMovesPass : public Pass { + private: + virtual bool visit(BasicBlock *); + }; + class BuildIntervalsPass : public Pass { private: virtual bool visit(BasicBlock *); @@ -344,6 +352,70 @@ RegAlloc::PhiMovesPass::visit(BasicBlock *bb) return true; } +bool +RegAlloc::ArgumentMovesPass::visit(BasicBlock *bb) +{ + // Bind function call inputs/outputs to the same physical register + // the callee uses, inserting moves as appropriate for the case a + // conflict arises. + for (Instruction *i = bb->getEntry(); i; i = i->next) { + FlowInstruction *cal = i->asFlow(); + if (!cal || cal->op != OP_CALL || cal->builtin) + continue; + RegisterSet clobberSet(prog->getTarget()); + + // Bind input values. + for (int s = 0; cal->srcExists(s); ++s) { + LValue *tmp = new_LValue(func, cal->getSrc(s)->asLValue()); + tmp->reg.data.id = cal->target.fn->ins[s].rep()->reg.data.id; + + Instruction *mov = + new_Instruction(func, OP_MOV, typeOfSize(tmp->reg.size)); + mov->setDef(0, tmp); + mov->setSrc(0, cal->getSrc(s)); + cal->setSrc(s, tmp); + + bb->insertBefore(cal, mov); + } + + // Bind output values. + for (int d = 0; cal->defExists(d); ++d) { + LValue *tmp = new_LValue(func, cal->getDef(d)->asLValue()); + tmp->reg.data.id = cal->target.fn->outs[d].rep()->reg.data.id; + + Instruction *mov = + new_Instruction(func, OP_MOV, typeOfSize(tmp->reg.size)); + mov->setSrc(0, tmp); + mov->setDef(0, cal->getDef(d)); + cal->setDef(d, tmp); + + bb->insertAfter(cal, mov); + clobberSet.occupy(tmp); + } + + // Bind clobbered values. + for (std::deque::iterator it = cal->target.fn->clobbers.begin(); + it != cal->target.fn->clobbers.end(); + ++it) { + if (clobberSet.occupy(*it)) { + Value *tmp = new_LValue(func, (*it)->asLValue()); + tmp->reg.data.id = (*it)->reg.data.id; + cal->setDef(cal->defCount(), tmp); + } + } + } + + // Update the clobber set of the function. + if (BasicBlock::get(func->cfgExit) == bb) { + func->buildDefSets(); + for (unsigned int i = 0; i < bb->defSet.getSize(); ++i) + if (bb->defSet.test(i)) + func->clobbers.push_back(func->getLValue(i)); + } + + return true; +} + // Build the set of live-in variables of bb. bool RegAlloc::buildLiveSets(BasicBlock *bb) @@ -737,7 +809,8 @@ bool RegAlloc::execFunc() { InsertConstraintsPass insertConstr; - PhiMovesPass insertMoves; + PhiMovesPass insertPhiMoves; + ArgumentMovesPass insertArgMoves; BuildIntervalsPass buildIntervals; unsigned int i; @@ -747,7 +820,11 @@ RegAlloc::execFunc() if (!ret) goto out; - ret = insertMoves.run(func); + ret = insertPhiMoves.run(func); + if (!ret) + goto out; + + ret = insertArgMoves.run(func, true); if (!ret) goto out;