summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFrancisco Jerez <[email protected]>2012-03-29 23:23:53 +0200
committerChristoph Bumiller <[email protected]>2012-04-14 21:54:02 +0200
commited255dbae2ada50cbdb71f6b03f4e42d3ed7ebc6 (patch)
tree7c221afd8b8a3a12824282e895fd048a9fc824bc
parenta3dd45e1c27e4e55dadb9467c2ea428f58083ac1 (diff)
nv50/ir/ra: Use matching physical regs for function args in caller and callee.
-rw-r--r--src/gallium/drivers/nv50/codegen/nv50_ir_ra.cpp89
1 files changed, 83 insertions, 6 deletions
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<Value *>::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;