nvc0/ir: be careful about propagating very large offsets into const load
authorIlia Mirkin <imirkin@alum.mit.edu>
Mon, 11 Jan 2016 21:41:18 +0000 (16:41 -0500)
committerIlia Mirkin <imirkin@alum.mit.edu>
Thu, 14 Jan 2016 23:20:27 +0000 (18:20 -0500)
Indirect constbuf indexing works by using very large offsets. However if
an indirect constbuf index load is const-propagated, it becomes a very
large const offset. Take that into account when legalizing the SSA by
moving the high parts of that offset into the file index. Also disallow
very large (or small) indices on most other instructions.

This fixes regressions in ubo_array_indexing/*-two-arrays piglit tests.

Fixes: abd326e81b (nv50/ir: propagate indirect loads into instructions)
Signed-off-by: Ilia Mirkin <imirkin@alum.mit.edu>
src/gallium/drivers/nouveau/codegen/nv50_ir_lowering_nvc0.cpp
src/gallium/drivers/nouveau/codegen/nv50_ir_target.h
src/gallium/drivers/nouveau/codegen/nv50_ir_target_nvc0.cpp
src/gallium/drivers/nouveau/codegen/nv50_ir_target_nvc0.h

index 6530078b938c4c8b8bd2ba05efb0f6542f2ded8c..dc1ab769b989f3aa80ab59897a194872ce358856 100644 (file)
@@ -540,6 +540,12 @@ NVC0LegalizePostRA::visit(BasicBlock *bb)
          // It seems like barriers are never required for tessellation since
          // the warp size is 32, and there are always at most 32 tcs threads.
          bb->remove(i);
+      } else
+      if (i->op == OP_LOAD && i->subOp == NV50_IR_SUBOP_LDC_IS) {
+         int offset = i->src(0).get()->reg.data.offset;
+         if (abs(offset) > 0x10000)
+            i->src(0).get()->reg.fileIndex += offset >> 16;
+         i->src(0).get()->reg.data.offset = (int)(short)offset;
       } else {
          // TODO: Move this to before register allocation for operations that
          // need the $c register !
index 673f8811ff3c19cfbb063b92f546a604874f9d1c..e6e1912adae023e3e74b8a49aae9d2d680c73170 100644 (file)
@@ -192,7 +192,7 @@ public:
    virtual bool insnCanLoad(const Instruction *insn, int s,
                             const Instruction *ld) const = 0;
    virtual bool insnCanLoadOffset(const Instruction *insn, int s,
-                                  int offset) const { return true; }
+                                  int offset) const = 0;
    virtual bool isOpSupported(operation, DataType) const = 0;
    virtual bool isAccessSupported(DataFile, DataType) const = 0;
    virtual bool isModSupported(const Instruction *,
index 014c652eeded0b9dd857886102bb620a1f30b4ff..a03afa8dc8dc4d4776452ad63ef71a404c84b75f 100644 (file)
@@ -383,6 +383,16 @@ TargetNVC0::insnCanLoad(const Instruction *i, int s,
    return true;
 }
 
+bool
+TargetNVC0::insnCanLoadOffset(const Instruction *insn, int s, int offset) const
+{
+   const ValueRef& ref = insn->src(s);
+   if (ref.getFile() == FILE_MEMORY_CONST &&
+       (insn->op != OP_LOAD || insn->subOp != NV50_IR_SUBOP_LDC_IS))
+      return offset >= -0x8000 && offset < 0x8000;
+   return true;
+}
+
 bool
 TargetNVC0::isAccessSupported(DataFile file, DataType ty) const
 {
index 3c5c7480405bd17ba1369571f94b6607be01587f..7d11cd963159942564418d5d82912c1de36b77cf 100644 (file)
@@ -48,6 +48,8 @@ public:
 
    virtual bool insnCanLoad(const Instruction *insn, int s,
                             const Instruction *ld) const;
+   virtual bool insnCanLoadOffset(const Instruction *insn, int s,
+                                  int offset) const;
    virtual bool isOpSupported(operation, DataType) const;
    virtual bool isAccessSupported(DataFile, DataType) const;
    virtual bool isModSupported(const Instruction *, int s, Modifier) const;