Browse Source

nvc0/ir: try to fix CAS (CompareAndSwap)

tags/mesa-9.2-rc1
Christoph Bumiller 12 years ago
parent
commit
75f1f852b0

+ 39
- 0
src/gallium/drivers/nvc0/codegen/nv50_ir_lowering_nvc0.cpp View File

@@ -596,6 +596,7 @@ private:
bool handleTXQ(TexInstruction *);
bool handleManualTXD(TexInstruction *);
bool handleATOM(Instruction *);
bool handleCasExch(Instruction *, bool needCctl);
void handleSurfaceOpNVE4(TexInstruction *);

void checkPredicate(Instruction *);
@@ -857,6 +858,38 @@ NVC0LoweringPass::handleATOM(Instruction *atom)
return true;
}

bool
NVC0LoweringPass::handleCasExch(Instruction *cas, bool needCctl)
{
if (cas->subOp != NV50_IR_SUBOP_ATOM_CAS &&
cas->subOp != NV50_IR_SUBOP_ATOM_EXCH)
return false;
bld.setPosition(cas, true);

if (needCctl) {
Instruction *cctl = bld.mkOp1(OP_CCTL, TYPE_NONE, NULL, cas->getSrc(0));
cctl->setIndirect(0, 0, cas->getIndirect(0, 0));
cctl->fixed = 1;
cctl->subOp = NV50_IR_SUBOP_CCTL_IV;
if (cas->isPredicated())
cctl->setPredicate(cas->cc, cas->getPredicate());
}

if (cas->defExists(0) && cas->subOp == NV50_IR_SUBOP_ATOM_CAS) {
// CAS is crazy. It's 2nd source is a double reg, and the 3rd source
// should be set to the high part of the double reg or bad things will
// happen elsewhere in the universe.
// Also, it sometimes returns the new value instead of the old one
// under mysterious circumstances.
Value *dreg = bld.getSSA(8);
bld.setPosition(cas, false);
bld.mkOp2(OP_MERGE, TYPE_U64, dreg, cas->getSrc(1), cas->getSrc(2));
cas->setSrc(1, dreg);
}

return true;
}

inline Value *
NVC0LoweringPass::loadResInfo32(Value *ptr, uint32_t off)
{
@@ -1185,6 +1218,7 @@ NVC0LoweringPass::handleSurfaceOpNVE4(TexInstruction *su)
}

if (su->op == OP_SUREDB || su->op == OP_SUREDP) {
// FIXME: for out of bounds access, destination value will be undefined !
Value *pred = su->getSrc(2);
CondCode cc = CC_NOT_P;
if (su->getPredicate()) {
@@ -1208,6 +1242,7 @@ NVC0LoweringPass::handleSurfaceOpNVE4(TexInstruction *su)
red->setIndirect(0, 0, su->getSrc(0));
red->setPredicate(cc, pred);
delete_Instruction(bld.getProgram(), su);
handleCasExch(red, true);
} else {
su->sType = (su->tex.target == TEX_TARGET_BUFFER) ? TYPE_U32 : TYPE_U8;
}
@@ -1477,7 +1512,11 @@ NVC0LoweringPass::visit(Instruction *i)
}
break;
case OP_ATOM:
{
const bool cctl = i->src(0).getFile() == FILE_MEMORY_GLOBAL;
handleATOM(i);
handleCasExch(i, cctl);
}
break;
case OP_SULDB:
case OP_SULDP:

+ 3
- 1
src/gallium/drivers/nvc0/codegen/nv50_ir_target_nvc0.cpp View File

@@ -287,7 +287,9 @@ TargetNVC0::insnCanLoad(const Instruction *i, int s,

// immediate 0 can be represented by GPR $r63/$r255
if (sf == FILE_IMMEDIATE && ld->getSrc(0)->reg.data.u64 == 0)
return (!i->asTex() && i->op != OP_EXPORT && i->op != OP_STORE);
return (!i->isPseudo() &&
!i->asTex() &&
i->op != OP_EXPORT && i->op != OP_STORE);

if (s >= opInfo[i->op].srcNr)
return false;

Loading…
Cancel
Save