nv50/ir: make OP_SELP a compare instruction
authorSamuel Pitoiset <samuel.pitoiset@gmail.com>
Fri, 5 Feb 2016 14:09:07 +0000 (15:09 +0100)
committerSamuel Pitoiset <samuel.pitoiset@gmail.com>
Sun, 21 Feb 2016 09:42:29 +0000 (10:42 +0100)
This OP_SELP insn will be used to handle compare and swap subops.

Changes from v2:
 - fix logic for GK110+

Signed-off-by: Samuel Pitoiset <samuel.pitoiset@gmail.com>
Reviewed-by: Ilia Mirkin <imirkin@alum.mit.edu>
src/gallium/drivers/nouveau/codegen/nv50_ir_emit_gk110.cpp
src/gallium/drivers/nouveau/codegen/nv50_ir_emit_nvc0.cpp
src/gallium/drivers/nouveau/codegen/nv50_ir_inlines.h

index 4bb4e5240e6cdbe1e281c184569a0fcb7803ed49..8268e08b11803bb2f14817eec088dae384c29572 100644 (file)
@@ -112,7 +112,7 @@ private:
 
    void emitSET(const CmpInstruction *);
    void emitSLCT(const CmpInstruction *);
-   void emitSELP(const Instruction *);
+   void emitSELP(const CmpInstruction *);
 
    void emitTEXBAR(const Instruction *);
    void emitTEX(const TexInstruction *);
@@ -433,6 +433,10 @@ CodeEmitterGK110::emitForm_21(const Instruction *i, uint32_t opc2,
          srcId(i->src(s), s ? ((s == 2) ? 42 : s1) : 10);
          break;
       default:
+         if (i->op == OP_SELP) {
+            assert(s == 2 && i->src(s).getFile() == FILE_PREDICATE);
+            srcId(i->src(s), 42);
+         }
          // ignore here, can be predicate or flags, but must not be address
          break;
       }
@@ -1041,11 +1045,11 @@ CodeEmitterGK110::emitSLCT(const CmpInstruction *i)
    }
 }
 
-void CodeEmitterGK110::emitSELP(const Instruction *i)
+void CodeEmitterGK110::emitSELP(const CmpInstruction *i)
 {
    emitForm_21(i, 0x250, 0x050);
 
-   if ((i->cc == CC_NOT_P) ^ (bool)(i->src(2).mod & Modifier(NV50_IR_MOD_NOT)))
+   if ((i->setCond == CC_NOT_P) ^ (bool)(i->src(2).mod & Modifier(NV50_IR_MOD_NOT)))
       code[1] |= 1 << 13;
 }
 
@@ -1933,7 +1937,7 @@ CodeEmitterGK110::emitInstruction(Instruction *insn)
       emitSET(insn->asCmp());
       break;
    case OP_SELP:
-      emitSELP(insn);
+      emitSELP(insn->asCmp());
       break;
    case OP_SLCT:
       emitSLCT(insn->asCmp());
index a7c49a24efb947f31ab080252580cfe8a78e5033..d588d7e8845572baf785ef03791fd6214a4f5bbb 100644 (file)
@@ -120,7 +120,7 @@ private:
 
    void emitSET(const CmpInstruction *);
    void emitSLCT(const CmpInstruction *);
-   void emitSELP(const Instruction *);
+   void emitSELP(const CmpInstruction *);
 
    void emitTEXBAR(const Instruction *);
    void emitTEX(const TexInstruction *);
@@ -398,6 +398,11 @@ CodeEmitterNVC0::emitForm_A(const Instruction *i, uint64_t opc)
          srcId(i->src(s), s ? ((s == 2) ? 49 : s1) : 20);
          break;
       default:
+         if (i->op == OP_SELP) {
+            // OP_SELP is used to implement shared+atomics on Fermi.
+            assert(s == 2 && i->src(s).getFile() == FILE_PREDICATE);
+            srcId(i->src(s), 49);
+         }
          // ignore here, can be predicate or flags, but must not be address
          break;
       }
@@ -1170,11 +1175,11 @@ CodeEmitterNVC0::emitSLCT(const CmpInstruction *i)
       code[0] |= 1 << 5;
 }
 
-void CodeEmitterNVC0::emitSELP(const Instruction *i)
+void CodeEmitterNVC0::emitSELP(const CmpInstruction *i)
 {
    emitForm_A(i, HEX64(20000000, 00000004));
 
-   if (i->cc == CC_NOT_P || i->src(2).mod & Modifier(NV50_IR_MOD_NOT))
+   if (i->setCond == CC_NOT_P || i->src(2).mod & Modifier(NV50_IR_MOD_NOT))
       code[1] |= 1 << 20;
 }
 
@@ -2433,7 +2438,7 @@ CodeEmitterNVC0::emitInstruction(Instruction *insn)
       emitSET(insn->asCmp());
       break;
    case OP_SELP:
-      emitSELP(insn);
+      emitSELP(insn->asCmp());
       break;
    case OP_SLCT:
       emitSLCT(insn->asCmp());
index e465f24845b10b94b1bbfbd759fdb7804d61edf9..02e6157e65b4004f8d8383b7ee31e114c1d6389f 100644 (file)
@@ -281,14 +281,14 @@ Value *TexInstruction::getIndirectS() const
 
 CmpInstruction *Instruction::asCmp()
 {
-   if (op >= OP_SET_AND && op <= OP_SLCT && op != OP_SELP)
+   if (op >= OP_SET_AND && op <= OP_SLCT)
       return static_cast<CmpInstruction *>(this);
    return NULL;
 }
 
 const CmpInstruction *Instruction::asCmp() const
 {
-   if (op >= OP_SET_AND && op <= OP_SLCT && op != OP_SELP)
+   if (op >= OP_SET_AND && op <= OP_SLCT)
       return static_cast<const CmpInstruction *>(this);
    return NULL;
 }