nv50/ir: Check for valid insn instead of def size
[mesa.git] / src / gallium / drivers / nouveau / codegen / nv50_ir_ra.cpp
index f5143bf3137334fe490cb46c1bd23c9a274d52e8..500ab8915de7f3f222ace12c2fc4b096253fae50 100644 (file)
@@ -103,6 +103,8 @@ public:
 
    void print() const;
 
+   const bool restrictedGPR16Range;
+
 private:
    BitSet bits[LAST_REGISTER_FILE + 1];
 
@@ -110,8 +112,6 @@ private:
 
    int last[LAST_REGISTER_FILE + 1];
    int fill[LAST_REGISTER_FILE + 1];
-
-   const bool restrictedGPR16Range;
 };
 
 void
@@ -840,6 +840,32 @@ GCRA::printNodeInfo() const
    }
 }
 
+static bool
+isShortRegOp(Instruction *insn)
+{
+   // Immediates are always in src1. Every other situation can be resolved by
+   // using a long encoding.
+   return insn->srcExists(1) && insn->src(1).getFile() == FILE_IMMEDIATE;
+}
+
+// Check if this LValue is ever used in an instruction that can't be encoded
+// with long registers (i.e. > r63)
+static bool
+isShortRegVal(LValue *lval)
+{
+   if (lval->getInsn() == NULL)
+      return false;
+   for (Value::DefCIterator def = lval->defs.begin();
+        def != lval->defs.end(); ++def)
+      if (isShortRegOp((*def)->getInsn()))
+         return true;
+   for (Value::UseCIterator use = lval->uses.begin();
+        use != lval->uses.end(); ++use)
+      if (isShortRegOp((*use)->getInsn()))
+         return true;
+   return false;
+}
+
 void
 GCRA::RIG_Node::init(const RegisterSet& regs, LValue *lval)
 {
@@ -855,7 +881,12 @@ GCRA::RIG_Node::init(const RegisterSet& regs, LValue *lval)
 
    weight = std::numeric_limits<float>::infinity();
    degree = 0;
-   degreeLimit = regs.getFileSize(f, lval->reg.size);
+   int size = regs.getFileSize(f, lval->reg.size);
+   // On nv50, we lose a bit of gpr encoding when there's an embedded
+   // immediate.
+   if (regs.restrictedGPR16Range && f == FILE_GPR && isShortRegVal(lval))
+      size /= 2;
+   degreeLimit = size;
    degreeLimit -= relDegree[1][colors] - 1;
 
    livei.insert(lval->livei);
@@ -937,6 +968,7 @@ GCRA::coalesce(ArrayList& insns)
    case 0xf0:
    case 0x100:
    case 0x110:
+   case 0x120:
       ret = doCoalesce(insns, JOIN_MASK_UNION);
       break;
    default:
@@ -1434,6 +1466,19 @@ GCRA::allocateRegisters(ArrayList& insns)
       if (lval) {
          nodes[i].init(regs, lval);
          RIG.insert(&nodes[i]);
+
+         if (lval->inFile(FILE_GPR) && lval->getInsn() != NULL &&
+             prog->getTarget()->getChipset() < 0xc0) {
+            Instruction *insn = lval->getInsn();
+            if (insn->op == OP_MAD || insn->op == OP_SAD)
+               // Short encoding only possible if they're all GPRs, no need to
+               // affect them otherwise.
+               if (insn->flagsDef < 0 &&
+                   insn->src(0).getFile() == FILE_GPR &&
+                   insn->src(1).getFile() == FILE_GPR &&
+                   insn->src(2).getFile() == FILE_GPR)
+                  nodes[i].addRegPreference(getNode(insn->getSrc(2)->asLValue()));
+         }
       }
    }
 
@@ -1500,6 +1545,9 @@ GCRA::cleanup(const bool success)
 
    delete[] nodes;
    nodes = NULL;
+   hi.next = hi.prev = &hi;
+   lo[0].next = lo[0].prev = &lo[0];
+   lo[1].next = lo[1].prev = &lo[1];
 }
 
 Symbol *
@@ -2184,6 +2232,7 @@ RegAlloc::InsertConstraintsPass::visit(BasicBlock *bb)
             texConstraintNVE0(tex);
             break;
          case 0x110:
+         case 0x120:
             texConstraintGM107(tex);
             break;
          default: