[Nouveau] [PATCH 09/11] nvc0/ir: add support for new TGSI double opcodes (v2)

Ilia Mirkin imirkin at alum.mit.edu
Thu Feb 19 17:02:38 PST 2015


v2: drop DDIV

Signed-off-by: Ilia Mirkin <imirkin at alum.mit.edu>
---
 .../drivers/nouveau/codegen/nv50_ir_from_tgsi.cpp  | 196 +++++++++++++++++++++
 1 file changed, 196 insertions(+)

diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir_from_tgsi.cpp b/src/gallium/drivers/nouveau/codegen/nv50_ir_from_tgsi.cpp
index 9ee927f..028a17e 100644
--- a/src/gallium/drivers/nouveau/codegen/nv50_ir_from_tgsi.cpp
+++ b/src/gallium/drivers/nouveau/codegen/nv50_ir_from_tgsi.cpp
@@ -441,6 +441,27 @@ nv50_ir::DataType Instruction::inferSrcType() const
    case TGSI_OPCODE_IBFE:
    case TGSI_OPCODE_IMSB:
       return nv50_ir::TYPE_S32;
+   case TGSI_OPCODE_D2F:
+   case TGSI_OPCODE_DABS:
+   case TGSI_OPCODE_DNEG:
+   case TGSI_OPCODE_DADD:
+   case TGSI_OPCODE_DMUL:
+   case TGSI_OPCODE_DMAX:
+   case TGSI_OPCODE_DMIN:
+   case TGSI_OPCODE_DSLT:
+   case TGSI_OPCODE_DSGE:
+   case TGSI_OPCODE_DSEQ:
+   case TGSI_OPCODE_DSNE:
+   case TGSI_OPCODE_DRCP:
+   case TGSI_OPCODE_DSQRT:
+   case TGSI_OPCODE_DMAD:
+   case TGSI_OPCODE_DFRAC:
+   case TGSI_OPCODE_DRSQ:
+   case TGSI_OPCODE_DTRUNC:
+   case TGSI_OPCODE_DCEIL:
+   case TGSI_OPCODE_DFLR:
+   case TGSI_OPCODE_DROUND:
+      return nv50_ir::TYPE_F64;
    default:
       return nv50_ir::TYPE_F32;
    }
@@ -455,10 +476,17 @@ nv50_ir::DataType Instruction::inferDstType() const
    case TGSI_OPCODE_FSGE:
    case TGSI_OPCODE_FSLT:
    case TGSI_OPCODE_FSNE:
+   case TGSI_OPCODE_DSEQ:
+   case TGSI_OPCODE_DSGE:
+   case TGSI_OPCODE_DSLT:
+   case TGSI_OPCODE_DSNE:
       return nv50_ir::TYPE_U32;
    case TGSI_OPCODE_I2F:
    case TGSI_OPCODE_U2F:
+   case TGSI_OPCODE_D2F:
       return nv50_ir::TYPE_F32;
+   case TGSI_OPCODE_F2D:
+      return nv50_ir::TYPE_F64;
    default:
       return inferSrcType();
    }
@@ -473,6 +501,7 @@ nv50_ir::CondCode Instruction::getSetCond() const
    case TGSI_OPCODE_ISLT:
    case TGSI_OPCODE_USLT:
    case TGSI_OPCODE_FSLT:
+   case TGSI_OPCODE_DSLT:
       return CC_LT;
    case TGSI_OPCODE_SLE:
       return CC_LE;
@@ -480,15 +509,18 @@ nv50_ir::CondCode Instruction::getSetCond() const
    case TGSI_OPCODE_ISGE:
    case TGSI_OPCODE_USGE:
    case TGSI_OPCODE_FSGE:
+   case TGSI_OPCODE_DSGE:
       return CC_GE;
    case TGSI_OPCODE_SGT:
       return CC_GT;
    case TGSI_OPCODE_SEQ:
    case TGSI_OPCODE_USEQ:
    case TGSI_OPCODE_FSEQ:
+   case TGSI_OPCODE_DSEQ:
       return CC_EQ;
    case TGSI_OPCODE_SNE:
    case TGSI_OPCODE_FSNE:
+   case TGSI_OPCODE_DSNE:
       return CC_NEU;
    case TGSI_OPCODE_USNE:
       return CC_NE;
@@ -601,6 +633,25 @@ static nv50_ir::operation translateOpcode(uint opcode)
    NV50_IR_OPCODE_CASE(USLT, SET);
    NV50_IR_OPCODE_CASE(USNE, SET);
 
+   NV50_IR_OPCODE_CASE(DABS, ABS);
+   NV50_IR_OPCODE_CASE(DNEG, NEG);
+   NV50_IR_OPCODE_CASE(DADD, ADD);
+   NV50_IR_OPCODE_CASE(DMUL, MUL);
+   NV50_IR_OPCODE_CASE(DMAX, MAX);
+   NV50_IR_OPCODE_CASE(DMIN, MIN);
+   NV50_IR_OPCODE_CASE(DSLT, SET);
+   NV50_IR_OPCODE_CASE(DSGE, SET);
+   NV50_IR_OPCODE_CASE(DSEQ, SET);
+   NV50_IR_OPCODE_CASE(DSNE, SET);
+   NV50_IR_OPCODE_CASE(DRCP, RCP);
+   NV50_IR_OPCODE_CASE(DSQRT, SQRT);
+   NV50_IR_OPCODE_CASE(DMAD, MAD);
+   NV50_IR_OPCODE_CASE(DRSQ, RSQ);
+   NV50_IR_OPCODE_CASE(DTRUNC, TRUNC);
+   NV50_IR_OPCODE_CASE(DCEIL, CEIL);
+   NV50_IR_OPCODE_CASE(DFLR, FLOOR);
+   NV50_IR_OPCODE_CASE(DROUND, CVT);
+
    NV50_IR_OPCODE_CASE(IMUL_HI, MUL);
    NV50_IR_OPCODE_CASE(UMUL_HI, MUL);
 
@@ -2880,6 +2931,151 @@ Converter::handleInstruction(const struct tgsi_full_instruction *insn)
    case TGSI_OPCODE_INTERP_OFFSET:
       handleINTERP(dst0);
       break;
+   case TGSI_OPCODE_D2F: {
+      int pos = 0;
+      FOR_EACH_DST_ENABLED_CHANNEL(0, c, tgsi) {
+         Value *dreg = getSSA(8);
+         src0 = fetchSrc(0, pos);
+         src1 = fetchSrc(0, pos + 1);
+         mkOp2(OP_MERGE, TYPE_U64, dreg, src0, src1);
+         mkCvt(OP_CVT, dstTy, dst0[c], srcTy, dreg);
+         pos += 2;
+      }
+      break;
+   }
+   case TGSI_OPCODE_F2D:
+      FOR_EACH_DST_ENABLED_CHANNEL(0, c, tgsi) {
+         Value *dreg = getSSA(8);
+         mkCvt(OP_CVT, dstTy, dreg, srcTy, fetchSrc(0, c / 2));
+         mkSplit(&dst0[c], 4, dreg);
+         c++;
+      }
+      break;
+   case TGSI_OPCODE_DABS:
+   case TGSI_OPCODE_DNEG:
+   case TGSI_OPCODE_DRCP:
+   case TGSI_OPCODE_DSQRT:
+   case TGSI_OPCODE_DRSQ:
+   case TGSI_OPCODE_DTRUNC:
+   case TGSI_OPCODE_DCEIL:
+   case TGSI_OPCODE_DFLR:
+      FOR_EACH_DST_ENABLED_CHANNEL(0, c, tgsi) {
+         src0 = getSSA(8);
+         Value *dst = getSSA(8), *tmp[2];
+         tmp[0] = fetchSrc(0, c);
+         tmp[1] = fetchSrc(0, c + 1);
+         mkOp2(OP_MERGE, TYPE_U64, src0, tmp[0], tmp[1]);
+         mkOp1(op, dstTy, dst, src0);
+         mkSplit(&dst0[c], 4, dst);
+         c++;
+      }
+      break;
+   case TGSI_OPCODE_DFRAC:
+      FOR_EACH_DST_ENABLED_CHANNEL(0, c, tgsi) {
+         src0 = getSSA(8);
+         Value *dst = getSSA(8), *tmp[2];
+         tmp[0] = fetchSrc(0, c);
+         tmp[1] = fetchSrc(0, c + 1);
+         mkOp2(OP_MERGE, TYPE_U64, src0, tmp[0], tmp[1]);
+         mkOp1(OP_FLOOR, TYPE_F64, dst, src0);
+         mkOp2(OP_SUB, TYPE_F64, dst, src0, dst);
+         mkSplit(&dst0[c], 4, dst);
+         c++;
+      }
+      break;
+   case TGSI_OPCODE_DSLT:
+   case TGSI_OPCODE_DSGE:
+   case TGSI_OPCODE_DSEQ:
+   case TGSI_OPCODE_DSNE: {
+      int pos = 0;
+      FOR_EACH_DST_ENABLED_CHANNEL(0, c, tgsi) {
+         Value *tmp[2];
+
+         src0 = getSSA(8);
+         src1 = getSSA(8);
+         tmp[0] = fetchSrc(0, pos);
+         tmp[1] = fetchSrc(0, pos + 1);
+         mkOp2(OP_MERGE, TYPE_U64, src0, tmp[0], tmp[1]);
+         tmp[0] = fetchSrc(1, pos);
+         tmp[1] = fetchSrc(1, pos + 1);
+         mkOp2(OP_MERGE, TYPE_U64, src1, tmp[0], tmp[1]);
+         mkCmp(op, tgsi.getSetCond(), dstTy, dst0[c], srcTy, src0, src1);
+         pos += 2;
+      }
+      break;
+   }
+   case TGSI_OPCODE_DADD:
+   case TGSI_OPCODE_DMUL:
+   case TGSI_OPCODE_DMAX:
+   case TGSI_OPCODE_DMIN:
+      FOR_EACH_DST_ENABLED_CHANNEL(0, c, tgsi) {
+         src0 = getSSA(8);
+         src1 = getSSA(8);
+         Value *dst = getSSA(8), *tmp[2];
+         tmp[0] = fetchSrc(0, c);
+         tmp[1] = fetchSrc(0, c + 1);
+         mkOp2(OP_MERGE, TYPE_U64, src0, tmp[0], tmp[1]);
+         tmp[0] = fetchSrc(1, c);
+         tmp[1] = fetchSrc(1, c + 1);
+         mkOp2(OP_MERGE, TYPE_U64, src1, tmp[0], tmp[1]);
+         mkOp2(op, dstTy, dst, src0, src1);
+         mkSplit(&dst0[c], 4, dst);
+         c++;
+      }
+      break;
+   case TGSI_OPCODE_DMAD:
+      FOR_EACH_DST_ENABLED_CHANNEL(0, c, tgsi) {
+         src0 = getSSA(8);
+         src1 = getSSA(8);
+         src2 = getSSA(8);
+         Value *dst = getSSA(8), *tmp[2];
+         tmp[0] = fetchSrc(0, c);
+         tmp[1] = fetchSrc(0, c + 1);
+         mkOp2(OP_MERGE, TYPE_U64, src0, tmp[0], tmp[1]);
+         tmp[0] = fetchSrc(1, c);
+         tmp[1] = fetchSrc(1, c + 1);
+         mkOp2(OP_MERGE, TYPE_U64, src1, tmp[0], tmp[1]);
+         tmp[0] = fetchSrc(2, c);
+         tmp[1] = fetchSrc(2, c + 1);
+         mkOp2(OP_MERGE, TYPE_U64, src2, tmp[0], tmp[1]);
+         mkOp3(op, dstTy, dst, src0, src1, src2);
+         mkSplit(&dst0[c], 4, dst);
+         c++;
+      }
+      break;
+   case TGSI_OPCODE_DROUND:
+      FOR_EACH_DST_ENABLED_CHANNEL(0, c, tgsi) {
+         src0 = getSSA(8);
+         Value *dst = getSSA(8), *tmp[2];
+         tmp[0] = fetchSrc(0, c);
+         tmp[1] = fetchSrc(0, c + 1);
+         mkOp2(OP_MERGE, TYPE_U64, src0, tmp[0], tmp[1]);
+         mkCvt(OP_CVT, TYPE_F64, dst, TYPE_F64, src0)
+         ->rnd = ROUND_NI;
+         mkSplit(&dst0[c], 4, dst);
+         c++;
+      }
+      break;
+   case TGSI_OPCODE_DSSG:
+      FOR_EACH_DST_ENABLED_CHANNEL(0, c, tgsi) {
+         src0 = getSSA(8);
+         Value *dst = getSSA(8), *dstF32 = getSSA(), *tmp[2];
+         tmp[0] = fetchSrc(0, c);
+         tmp[1] = fetchSrc(0, c + 1);
+         mkOp2(OP_MERGE, TYPE_U64, src0, tmp[0], tmp[1]);
+
+         val0 = getScratch();
+         val1 = getScratch();
+         // The zero is wrong here since it's only 32-bit, but it works out in
+         // the end since it gets replaced with $r63.
+         mkCmp(OP_SET, CC_GT, TYPE_F32, val0, TYPE_F64, src0, zero);
+         mkCmp(OP_SET, CC_LT, TYPE_F32, val1, TYPE_F64, src0, zero);
+         mkOp2(OP_SUB, TYPE_F32, dstF32, val0, val1);
+         mkCvt(OP_CVT, TYPE_F64, dst, TYPE_F32, dstF32);
+         mkSplit(&dst0[c], 4, dst);
+         c++;
+      }
+      break;
    default:
       ERROR("unhandled TGSI opcode: %u\n", tgsi.getOpcode());
       assert(0);
-- 
2.0.5



More information about the Nouveau mailing list