mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-07 11:28:05 +02:00
nv50/ir/ra: Use matching physical regs for function args in caller and callee.
This commit is contained in:
parent
a3dd45e1c2
commit
ed255dbae2
1 changed files with 83 additions and 6 deletions
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue