nv50/ir: check if the target supports the new offset before inlining
authorIlia Mirkin <imirkin@alum.mit.edu>
Tue, 8 Dec 2015 21:48:06 +0000 (16:48 -0500)
committerIlia Mirkin <imirkin@alum.mit.edu>
Wed, 9 Dec 2015 04:15:29 +0000 (23:15 -0500)
Fixes: abd326e81b (nv50/ir: propagate indirect loads into instructions)
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=93300
Signed-off-by: Ilia Mirkin <imirkin@alum.mit.edu>
src/gallium/drivers/nouveau/codegen/nv50_ir_peephole.cpp
src/gallium/drivers/nouveau/codegen/nv50_ir_target.h
src/gallium/drivers/nouveau/codegen/nv50_ir_target_nv50.cpp
src/gallium/drivers/nouveau/codegen/nv50_ir_target_nv50.h

index 2f21257d88a0faa380e3e05689973f833a406349..805be5fcb40f105836723d26618f6ebaeb404718 100644 (file)
@@ -290,20 +290,23 @@ IndirectPropagation::visit(BasicBlock *bb)
             continue;
          if (insn->op == OP_ADD && !isFloatType(insn->dType)) {
             if (insn->src(0).getFile() != targ->nativeFile(FILE_ADDRESS) ||
-                !insn->src(1).getImmediate(imm))
+                !insn->src(1).getImmediate(imm) ||
+                !targ->insnCanLoadOffset(i, s, imm.reg.data.s32))
                continue;
             i->setIndirect(s, 0, insn->getSrc(0));
             i->setSrc(s, cloneShallow(func, i->getSrc(s)));
             i->src(s).get()->reg.data.offset += imm.reg.data.u32;
          } else if (insn->op == OP_SUB && !isFloatType(insn->dType)) {
             if (insn->src(0).getFile() != targ->nativeFile(FILE_ADDRESS) ||
-                !insn->src(1).getImmediate(imm))
+                !insn->src(1).getImmediate(imm) ||
+                !targ->insnCanLoadOffset(i, s, -imm.reg.data.s32))
                continue;
             i->setIndirect(s, 0, insn->getSrc(0));
             i->setSrc(s, cloneShallow(func, i->getSrc(s)));
             i->src(s).get()->reg.data.offset -= imm.reg.data.u32;
          } else if (insn->op == OP_MOV) {
-            if (!insn->src(0).getImmediate(imm))
+            if (!insn->src(0).getImmediate(imm) ||
+                !targ->insnCanLoadOffset(i, s, imm.reg.data.s32))
                continue;
             i->setIndirect(s, 0, NULL);
             i->setSrc(s, cloneShallow(func, i->getSrc(s)));
index 4e33997e1c1984cc5dc60e95f185d2d370f20d7a..673f8811ff3c19cfbb063b92f546a604874f9d1c 100644 (file)
@@ -191,6 +191,8 @@ 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; }
    virtual bool isOpSupported(operation, DataType) const = 0;
    virtual bool isAccessSupported(DataFile, DataType) const = 0;
    virtual bool isModSupported(const Instruction *,
index 2d5baede2e0444c36dae34bf2ca27a045a80062a..101082e749185dd4879147c0fd3b5d5908c66591 100644 (file)
@@ -384,6 +384,21 @@ TargetNV50::insnCanLoad(const Instruction *i, int s,
    return true;
 }
 
+bool
+TargetNV50::insnCanLoadOffset(const Instruction *i, int s, int offset) const
+{
+   if (!i->src(s).isIndirect(0))
+      return true;
+   offset += i->src(s).get()->reg.data.offset;
+   if (i->op == OP_LOAD || i->op == OP_STORE) {
+      // There are some restrictions in theory, but in practice they're never
+      // going to be hit. When we enable shared/global memory, this will
+      // become more important.
+      return true;
+   }
+   return offset >= 0 && offset <= (int32_t)(127 * i->src(s).get()->reg.size);
+}
+
 bool
 TargetNV50::isAccessSupported(DataFile file, DataType ty) const
 {
index 0cbf180d048dd82933a5a58aef306c0b5f0da6d3..00243d7958ed7ad76121c37efa48edb165462d43 100644 (file)
@@ -46,6 +46,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;