nv50/ir: optimize signed integer modulo by pow-of-2
[mesa.git] / src / gallium / drivers / nouveau / codegen / nv50_ir.cpp
index 90fb51c26df5a18d5817c790e51cf8130acbb49b..6f12df70a117c799df0fba6a53a2c6309f0968c3 100644 (file)
@@ -25,8 +25,8 @@
 #include "codegen/nv50_ir_driver.h"
 
 extern "C" {
+#include "nouveau_debug.h"
 #include "nv50/nv50_program.h"
-#include "nv50/nv50_debug.h"
 }
 
 namespace nv50_ir {
@@ -141,9 +141,9 @@ ValueRef::set(Value *refVal)
    if (value == refVal)
       return;
    if (value)
-      value->uses.remove(this);
+      value->uses.erase(this);
    if (refVal)
-      refVal->uses.push_back(this);
+      refVal->uses.insert(this);
 
    value = refVal;
 }
@@ -206,7 +206,7 @@ ValueDef::replace(const ValueRef &repVal, bool doSet)
       return;
 
    while (!value->uses.empty()) {
-      ValueRef *ref = value->uses.front();
+      ValueRef *ref = *value->uses.begin();
       ref->set(repVal.get());
       ref->mod *= repVal.mod;
    }
@@ -393,6 +393,9 @@ ImmediateValue::isInteger(const int i) const
    case TYPE_S32:
    case TYPE_U32:
       return reg.data.s32 == i; // as if ...
+   case TYPE_S64:
+   case TYPE_U64:
+      return reg.data.s64 == i; // as if ...
    case TYPE_F32:
       return reg.data.f32 == static_cast<float>(i);
    case TYPE_F64:
@@ -420,13 +423,7 @@ ImmediateValue::isNegative() const
 bool
 ImmediateValue::isPow2() const
 {
-   switch (reg.type) {
-   case TYPE_U8:
-   case TYPE_U16:
-   case TYPE_U32: return util_is_power_of_two(reg.data.u32);
-   default:
-      return false;
-   }
+   return util_is_power_of_two(reg.data.u32);
 }
 
 void
@@ -572,6 +569,7 @@ void Instruction::init()
    encSize = 0;
    ipa = 0;
    mask = 0;
+   precise = 0;
 
    lanes = 0xf;
 
@@ -867,22 +865,22 @@ Instruction::writesPredicate() const
    return false;
 }
 
-static bool
-insnCheckCommutationDefSrc(const Instruction *a, const Instruction *b)
+bool
+Instruction::canCommuteDefSrc(const Instruction *i) const
 {
-   for (int d = 0; a->defExists(d); ++d)
-      for (int s = 0; b->srcExists(s); ++s)
-         if (a->getDef(d)->interfers(b->getSrc(s)))
+   for (int d = 0; defExists(d); ++d)
+      for (int s = 0; i->srcExists(s); ++s)
+         if (getDef(d)->interfers(i->getSrc(s)))
             return false;
    return true;
 }
 
-static bool
-insnCheckCommutationDefDef(const Instruction *a, const Instruction *b)
+bool
+Instruction::canCommuteDefDef(const Instruction *i) const
 {
-   for (int d = 0; a->defExists(d); ++d)
-      for (int c = 0; b->defExists(c); ++c)
-         if (a->getDef(d)->interfers(b->getDef(c)))
+   for (int d = 0; defExists(d); ++d)
+      for (int c = 0; i->defExists(c); ++c)
+         if (getDef(d)->interfers(i->getDef(c)))
             return false;
    return true;
 }
@@ -890,10 +888,9 @@ insnCheckCommutationDefDef(const Instruction *a, const Instruction *b)
 bool
 Instruction::isCommutationLegal(const Instruction *i) const
 {
-   bool ret = insnCheckCommutationDefDef(this, i);
-   ret = ret && insnCheckCommutationDefSrc(this, i);
-   ret = ret && insnCheckCommutationDefSrc(i, this);
-   return ret;
+   return canCommuteDefDef(i) &&
+      canCommuteDefSrc(i) &&
+      i->canCommuteDefSrc(this);
 }
 
 TexInstruction::TexInstruction(Function *fn, operation op)
@@ -903,6 +900,9 @@ TexInstruction::TexInstruction(Function *fn, operation op)
 
    tex.rIndirectSrc = -1;
    tex.sIndirectSrc = -1;
+
+   if (op == OP_TXF)
+      sType = TYPE_U32;
 }
 
 TexInstruction::~TexInstruction()
@@ -911,6 +911,9 @@ TexInstruction::~TexInstruction()
       dPdx[c].set(NULL);
       dPdy[c].set(NULL);
    }
+   for (int n = 0; n < 4; ++n)
+      for (int c = 0; c < 3; ++c)
+         offset[n][c].set(NULL);
 }
 
 TexInstruction *
@@ -930,6 +933,10 @@ TexInstruction::clone(ClonePolicy<Function>& pol, Instruction *i) const
       }
    }
 
+   for (int n = 0; n < tex->tex.useOffsets; ++n)
+      for (int c = 0; c < 3; ++c)
+         tex->offset[n][c].set(offset[n][c]);
+
    return tex;
 }
 
@@ -955,6 +962,57 @@ const struct TexInstruction::Target::Desc TexInstruction::Target::descTable[] =
    { "BUFFER",            1, 1, false, false, false },
 };
 
+const struct TexInstruction::ImgFormatDesc TexInstruction::formatTable[] =
+{
+   { "NONE",         0, {  0,  0,  0,  0 },  UINT },
+
+   { "RGBA32F",      4, { 32, 32, 32, 32 }, FLOAT },
+   { "RGBA16F",      4, { 16, 16, 16, 16 }, FLOAT },
+   { "RG32F",        2, { 32, 32,  0,  0 }, FLOAT },
+   { "RG16F",        2, { 16, 16,  0,  0 }, FLOAT },
+   { "R11G11B10F",   3, { 11, 11, 10,  0 }, FLOAT },
+   { "R32F",         1, { 32,  0,  0,  0 }, FLOAT },
+   { "R16F",         1, { 16,  0,  0,  0 }, FLOAT },
+
+   { "RGBA32UI",     4, { 32, 32, 32, 32 },  UINT },
+   { "RGBA16UI",     4, { 16, 16, 16, 16 },  UINT },
+   { "RGB10A2UI",    4, { 10, 10, 10,  2 },  UINT },
+   { "RGBA8UI",      4, {  8,  8,  8,  8 },  UINT },
+   { "RG32UI",       2, { 32, 32,  0,  0 },  UINT },
+   { "RG16UI",       2, { 16, 16,  0,  0 },  UINT },
+   { "RG8UI",        2, {  8,  8,  0,  0 },  UINT },
+   { "R32UI",        1, { 32,  0,  0,  0 },  UINT },
+   { "R16UI",        1, { 16,  0,  0,  0 },  UINT },
+   { "R8UI",         1, {  8,  0,  0,  0 },  UINT },
+
+   { "RGBA32I",      4, { 32, 32, 32, 32 },  SINT },
+   { "RGBA16I",      4, { 16, 16, 16, 16 },  SINT },
+   { "RGBA8I",       4, {  8,  8,  8,  8 },  SINT },
+   { "RG32I",        2, { 32, 32,  0,  0 },  SINT },
+   { "RG16I",        2, { 16, 16,  0,  0 },  SINT },
+   { "RG8I",         2, {  8,  8,  0,  0 },  SINT },
+   { "R32I",         1, { 32,  0,  0,  0 },  SINT },
+   { "R16I",         1, { 16,  0,  0,  0 },  SINT },
+   { "R8I",          1, {  8,  0,  0,  0 },  SINT },
+
+   { "RGBA16",       4, { 16, 16, 16, 16 }, UNORM },
+   { "RGB10A2",      4, { 10, 10, 10,  2 }, UNORM },
+   { "RGBA8",        4, {  8,  8,  8,  8 }, UNORM },
+   { "RG16",         2, { 16, 16,  0,  0 }, UNORM },
+   { "RG8",          2, {  8,  8,  0,  0 }, UNORM },
+   { "R16",          1, { 16,  0,  0,  0 }, UNORM },
+   { "R8",           1, {  8,  0,  0,  0 }, UNORM },
+
+   { "RGBA16_SNORM", 4, { 16, 16, 16, 16 }, SNORM },
+   { "RGBA8_SNORM",  4, {  8,  8,  8,  8 }, SNORM },
+   { "RG16_SNORM",   2, { 16, 16,  0,  0 }, SNORM },
+   { "RG8_SNORM",    2, {  8,  8,  0,  0 }, SNORM },
+   { "R16_SNORM",    1, { 16,  0,  0,  0 }, SNORM },
+   { "R8_SNORM",     1, {  8,  0,  0,  0 }, SNORM },
+
+   { "BGRA8",        4, {  8,  8,  8,  8 }, UNORM, true },
+};
+
 void
 TexInstruction::setIndirectR(Value *v)
 {
@@ -1111,17 +1169,19 @@ extern "C" {
 static void
 nv50_ir_init_prog_info(struct nv50_ir_prog_info *info)
 {
-#if defined(PIPE_SHADER_HULL) && defined(PIPE_SHADER_DOMAIN)
-   if (info->type == PIPE_SHADER_HULL || info->type == PIPE_SHADER_DOMAIN) {
+   if (info->type == PIPE_SHADER_TESS_CTRL || info->type == PIPE_SHADER_TESS_EVAL) {
       info->prop.tp.domain = PIPE_PRIM_MAX;
       info->prop.tp.outputPrim = PIPE_PRIM_MAX;
    }
-#endif
    if (info->type == PIPE_SHADER_GEOMETRY) {
       info->prop.gp.instanceCount = 1;
       info->prop.gp.maxVertices = 1;
    }
-   info->io.clipDistance = 0xff;
+   if (info->type == PIPE_SHADER_COMPUTE) {
+      info->prop.cp.numThreads[0] =
+      info->prop.cp.numThreads[1] =
+      info->prop.cp.numThreads[2] = 1;
+   }
    info->io.pointSize = 0xff;
    info->io.instanceId = 0xff;
    info->io.vertexId = 0xff;
@@ -1146,14 +1206,14 @@ nv50_ir_generate_code(struct nv50_ir_prog_info *info)
 
    switch (info->type) {
    PROG_TYPE_CASE(VERTEX, VERTEX);
-// PROG_TYPE_CASE(HULL, TESSELLATION_CONTROL);
-// PROG_TYPE_CASE(DOMAIN, TESSELLATION_EVAL);
+   PROG_TYPE_CASE(TESS_CTRL, TESSELLATION_CONTROL);
+   PROG_TYPE_CASE(TESS_EVAL, TESSELLATION_EVAL);
    PROG_TYPE_CASE(GEOMETRY, GEOMETRY);
    PROG_TYPE_CASE(FRAGMENT, FRAGMENT);
    PROG_TYPE_CASE(COMPUTE, COMPUTE);
    default:
-      type = nv50_ir::Program::TYPE_COMPUTE;
-      break;
+      INFO_DBG(info->dbgFlags, VERBOSE, "unsupported program type %u\n", info->type);
+      return -1;
    }
    INFO_DBG(info->dbgFlags, VERBOSE, "translating program of type %u\n", type);
 
@@ -1162,24 +1222,20 @@ nv50_ir_generate_code(struct nv50_ir_prog_info *info)
       return -1;
 
    nv50_ir::Program *prog = new nv50_ir::Program(type, targ);
-   if (!prog)
+   if (!prog) {
+      nv50_ir::Target::destroy(targ);
       return -1;
+   }
    prog->driver = info;
    prog->dbgFlags = info->dbgFlags;
    prog->optLevel = info->optLevel;
 
    switch (info->bin.sourceRep) {
-#if 0
-   case PIPE_IR_LLVM:
-   case PIPE_IR_GLSL:
-      return -1;
-   case PIPE_IR_SM4:
-      ret = prog->makeFromSM4(info) ? 0 : -2;
+   case PIPE_SHADER_IR_TGSI:
+      ret = prog->makeFromTGSI(info) ? 0 : -2;
       break;
-   case PIPE_IR_TGSI:
-#endif
    default:
-      ret = prog->makeFromTGSI(info) ? 0 : -2;
+      ret = -1;
       break;
    }
    if (ret < 0)