summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/nvc0
diff options
context:
space:
mode:
authorChristoph Bumiller <[email protected]>2013-03-11 17:34:43 +0100
committerChristoph Bumiller <[email protected]>2013-03-12 12:55:37 +0100
commit75f1f852b00ad0d766684d01695322b93a2acd55 (patch)
treed443f317191289eea846b493952f63d2321609b9 /src/gallium/drivers/nvc0
parent18fdfbdc32f204d6728c1ad57a693b1a6ad0aec9 (diff)
nvc0/ir: try to fix CAS (CompareAndSwap)
Diffstat (limited to 'src/gallium/drivers/nvc0')
-rw-r--r--src/gallium/drivers/nvc0/codegen/nv50_ir_lowering_nvc0.cpp39
-rw-r--r--src/gallium/drivers/nvc0/codegen/nv50_ir_target_nvc0.cpp4
2 files changed, 42 insertions, 1 deletions
diff --git a/src/gallium/drivers/nvc0/codegen/nv50_ir_lowering_nvc0.cpp b/src/gallium/drivers/nvc0/codegen/nv50_ir_lowering_nvc0.cpp
index cd30f63037c..a82465af17f 100644
--- a/src/gallium/drivers/nvc0/codegen/nv50_ir_lowering_nvc0.cpp
+++ b/src/gallium/drivers/nvc0/codegen/nv50_ir_lowering_nvc0.cpp
@@ -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:
diff --git a/src/gallium/drivers/nvc0/codegen/nv50_ir_target_nvc0.cpp b/src/gallium/drivers/nvc0/codegen/nv50_ir_target_nvc0.cpp
index 04633228c8a..3aa29e222a1 100644
--- a/src/gallium/drivers/nvc0/codegen/nv50_ir_target_nvc0.cpp
+++ b/src/gallium/drivers/nvc0/codegen/nv50_ir_target_nvc0.cpp
@@ -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;