nv50/ir/ra: Use matching physical regs for function args in caller and callee.

This commit is contained in:
Francisco Jerez 2012-03-29 23:23:53 +02:00 committed by Christoph Bumiller
parent a3dd45e1c2
commit ed255dbae2

View file

@ -43,7 +43,7 @@ public:
bool assign(Value **, int nr); bool assign(Value **, int nr);
void release(const Value *); void release(const Value *);
void occupy(const Value *); bool occupy(const Value *);
int getMaxAssigned(DataFile f) const { return fill[f]; } int getMaxAssigned(DataFile f) const { return fill[f]; }
@ -148,22 +148,25 @@ RegisterSet::assign(Value **def, int nr)
return true; return true;
} }
void bool
RegisterSet::occupy(const Value *val) RegisterSet::occupy(const Value *val)
{ {
int id = val->reg.data.id; int id = val->reg.data.id;
if (id < 0)
return;
unsigned int f = val->reg.file; unsigned int f = val->reg.file;
uint32_t m = (1 << (val->reg.size >> unit[f])) - 1; 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); INFO_DBG(0, REG_ALLOC, "reg occupy: %u[%i] %x\n", f, id, m);
bits[f][id / 32] |= m << (id % 32); bits[f][id / 32] |= m << (id % 32);
if (fill[f] < id) if (fill[f] < id)
fill[f] = id; fill[f] = id;
return true;
} }
void void
@ -207,6 +210,11 @@ private:
inline bool needNewElseBlock(BasicBlock *b, BasicBlock *p); inline bool needNewElseBlock(BasicBlock *b, BasicBlock *p);
}; };
class ArgumentMovesPass : public Pass {
private:
virtual bool visit(BasicBlock *);
};
class BuildIntervalsPass : public Pass { class BuildIntervalsPass : public Pass {
private: private:
virtual bool visit(BasicBlock *); virtual bool visit(BasicBlock *);
@ -344,6 +352,70 @@ RegAlloc::PhiMovesPass::visit(BasicBlock *bb)
return true; 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. // Build the set of live-in variables of bb.
bool bool
RegAlloc::buildLiveSets(BasicBlock *bb) RegAlloc::buildLiveSets(BasicBlock *bb)
@ -737,7 +809,8 @@ bool
RegAlloc::execFunc() RegAlloc::execFunc()
{ {
InsertConstraintsPass insertConstr; InsertConstraintsPass insertConstr;
PhiMovesPass insertMoves; PhiMovesPass insertPhiMoves;
ArgumentMovesPass insertArgMoves;
BuildIntervalsPass buildIntervals; BuildIntervalsPass buildIntervals;
unsigned int i; unsigned int i;
@ -747,7 +820,11 @@ RegAlloc::execFunc()
if (!ret) if (!ret)
goto out; goto out;
ret = insertMoves.run(func); ret = insertPhiMoves.run(func);
if (!ret)
goto out;
ret = insertArgMoves.run(func, true);
if (!ret) if (!ret)
goto out; goto out;