nv50/ir/opt: try to make use of SUCLAMP addend
authorChristoph Bumiller <e0425955@student.tuwien.ac.at>
Mon, 25 Feb 2013 14:52:10 +0000 (15:52 +0100)
committerChristoph Bumiller <e0425955@student.tuwien.ac.at>
Tue, 12 Mar 2013 11:55:36 +0000 (12:55 +0100)
src/gallium/drivers/nv50/codegen/nv50_ir_peephole.cpp

index 997d21aaf27b836968296101938cfd37f963f082..0af44baa8fcb911bf4a24011c62d93fb616c5524 100644 (file)
@@ -933,6 +933,7 @@ private:
    void handleSLCT(Instruction *);
    void handleLOGOP(Instruction *);
    void handleCVT(Instruction *);
+   void handleSUCLAMP(Instruction *);
 
    BuildUtil bld;
 };
@@ -1217,6 +1218,47 @@ AlgebraicOpt::handleCVT(Instruction *cvt)
    delete_Instruction(prog, cvt);
 }
 
+// SUCLAMP dst, (ADD b imm), k, 0 -> SUCLAMP dst, b, k, imm (if imm fits s6)
+void
+AlgebraicOpt::handleSUCLAMP(Instruction *insn)
+{
+   ImmediateValue imm;
+   int32_t val = insn->getSrc(2)->asImm()->reg.data.s32;
+   int s;
+   Instruction *add;
+
+   assert(insn->srcExists(0) && insn->src(0).getFile() == FILE_GPR);
+
+   // look for ADD (TODO: only count references by non-SUCLAMP)
+   if (insn->getSrc(0)->refCount() > 1)
+      return;
+   add = insn->getSrc(0)->getInsn();
+   if (!add || add->op != OP_ADD ||
+       (add->dType != TYPE_U32 &&
+        add->dType != TYPE_S32))
+      return;
+
+   // look for immediate
+   for (s = 0; s < 2; ++s)
+      if (add->src(s).getImmediate(imm))
+         break;
+   if (s >= 2)
+      return;
+   s = s ? 0 : 1;
+   // determine if immediate fits
+   val += imm.reg.data.s32;
+   if (val > 31 || val < -32)
+      return;
+   // determine if other addend fits
+   if (add->src(s).getFile() != FILE_GPR || add->src(s).mod != Modifier(0))
+      return;
+
+   bld.setPosition(insn, false); // make sure bld is init'ed
+   // replace sources
+   insn->setSrc(2, bld.mkImm(val));
+   insn->setSrc(0, add->getSrc(s));
+}
+
 bool
 AlgebraicOpt::visit(BasicBlock *bb)
 {
@@ -1248,6 +1290,9 @@ AlgebraicOpt::visit(BasicBlock *bb)
       case OP_CVT:
          handleCVT(i);
          break;
+      case OP_SUCLAMP:
+         handleSUCLAMP(i);
+         break;
       default:
          break;
       }