<div dir="ltr">On 3 October 2013 11:00, Matt Turner <span dir="ltr"><<a href="mailto:mattst88@gmail.com" target="_blank">mattst88@gmail.com</a>></span> wrote:<br><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div class="im">v2: Check fixed_hw_reg.{file,nr} instead of dst.reg.<br>
</div>v3: Store the bool emitted_addc_or_subb in the class, not static.<br>
---<br>
 src/mesa/drivers/dri/i965/brw_vec4.h           |   3 +<br>
 src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp | 104 ++++++++++++++++++++++++-<br>
 2 files changed, 106 insertions(+), 1 deletion(-)<br></blockquote><div><br></div><div>My concerns about patch 9/10 apply to this patch as well.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">

<br>
diff --git a/src/mesa/drivers/dri/i965/brw_vec4.h b/src/mesa/drivers/dri/i965/brw_vec4.h<br>
index 25427d7..9e2204d 100644<br>
<div class="im">--- a/src/mesa/drivers/dri/i965/brw_vec4.h<br>
+++ b/src/mesa/drivers/dri/i965/brw_vec4.h<br>
@@ -507,6 +507,7 @@ public:<br>
<br>
    bool try_emit_sat(ir_expression *ir);<br>
    bool try_emit_mad(ir_expression *ir, int mul_arg);<br>
+   void try_combine_add_with_addc_subb();<br>
    void resolve_ud_negate(src_reg *reg);<br>
<br>
    src_reg get_timestamp();<br>
</div>@@ -530,6 +531,8 @@ protected:<br>
    virtual int compute_array_stride(ir_dereference_array *ir);<br>
<br>
    const bool debug_flag;<br>
+<br>
+   bool emitted_addc_or_subb;<br>
 };<br>
<br>
<br>
diff --git a/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp b/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp<br>
index ffb2cfc..74bdd4d 100644<br>
<div><div class="h5">--- a/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp<br>
+++ b/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp<br>
@@ -1122,6 +1122,102 @@ vec4_visitor::try_emit_mad(ir_expression *ir, int mul_arg)<br>
    return true;<br>
 }<br>
<br>
+/**<br>
+ * The addition and carry in the uaddCarry() built-in function are implemented<br>
+ * separately as ir_binop_add and ir_binop_carry respectively. i965 generates<br>
+ * ADDC and a MOV from the accumulator for the carry.<br>
+ *<br>
+ * The generated code for uaddCarry(uint x, uint y, out uint carry) would look<br>
+ * like this:<br>
+ *<br>
+ *    addc null, x, y<br>
+ *    mov  carry, acc0<br>
+ *    add  sum, x, y<br>
+ *<br>
+ * This peephole pass optimizes this into<br>
+ *<br>
+ *    addc sum, x, y<br>
+ *    mov carry, acc0<br>
+ *<br>
+ * usubBorrow() works in the same fashion.<br>
+ */<br>
+void<br>
+vec4_visitor::try_combine_add_with_addc_subb()<br>
+{<br>
+   /* ADDC/SUBB was introduced in gen7. */<br>
+   if (brw->gen < 7)<br>
+      return;<br>
+<br>
+   vec4_instruction *add_inst = (vec4_instruction *) instructions.get_tail();<br>
+   assert(add_inst->opcode == BRW_OPCODE_ADD);<br>
+<br>
+   /* ADDC/SUBB only operates on UD. */<br>
+   if (add_inst->dst.type != BRW_REGISTER_TYPE_UD ||<br>
+       add_inst->src[0].type != BRW_REGISTER_TYPE_UD ||<br>
+       add_inst->src[1].type != BRW_REGISTER_TYPE_UD)<br>
+      return;<br>
+<br>
+   bool found = false;<br>
+   vec4_instruction *match = (vec4_instruction *) add_inst->prev;<br>
+   /* The ADDC should appear within 2 instructions of ADD. SUBB should appear<br>
+    * farther away because of the extra MOV negate.<br>
+    */<br>
+   for (int i = 0; i < 4; i++, match = (vec4_instruction *) match->prev) {<br>
+      if (match->is_head_sentinel())<br>
+         return;<br>
+<br>
+      /* Look for an ADDC/SUBB instruction whose destination is the null<br>
+       * register (ir_binop_carry emits ADDC with null destination; same for<br>
+       * ir_binop_borrow with SUBB) and whose sources are identical to those<br>
+       * of the ADD.<br>
+       */<br>
+      if (match->opcode != BRW_OPCODE_ADDC && match->opcode != BRW_OPCODE_SUBB)<br>
+         continue;<br>
+<br>
+      /* Only look for newly emitted ADDC/SUBB with null destination. */<br>
+      if (match->dst.file != HW_REG ||<br>
+          match->dst.fixed_hw_reg.file != BRW_ARCHITECTURE_REGISTER_FILE ||<br>
+          match-><a href="http://dst.fixed_hw_reg.nr" target="_blank">dst.fixed_hw_reg.nr</a> != BRW_ARF_NULL)<br>
+         continue;<br>
+<br>
+      src_reg *src0 = &add_inst->src[0];<br>
+      src_reg *src1 = &add_inst->src[1];<br>
+<br>
+      /* For SUBB, the ADD's second source will contain a negate modifier<br>
+       * which at this point will be in the form of a<br>
+       *<br>
+       *    MOV dst, -src<br>
+       *<br>
+       * instruction, so src[1].file will be GRF, even if it's a uniform push<br>
+       * constant.<br>
+       */<br>
+      if (match->src[1].reg != add_inst->src[1].reg) {<br>
+         /* The negating MOV should be immediately before the ADD. */<br>
+         vec4_instruction *mov_inst = (vec4_instruction *) add_inst->prev;<br>
+         if (mov_inst->opcode != BRW_OPCODE_MOV)<br>
+            continue;<br>
+<br>
+         src1 = &mov_inst->src[0];<br>
+      }<br>
+<br>
+      /* If everything matches, we're done. */<br>
+      if (match->src[0].file == src0->file &&<br>
+          match->src[1].file == src1->file &&<br>
+          match->src[0].reg == src0->reg &&<br>
+          match->src[1].reg == src1->reg &&<br>
+          match->src[0].reg_offset == src0->reg_offset &&<br>
+          match->src[1].reg_offset == src1->reg_offset) {<br>
+         found = true;<br>
+         break;<br>
+      }<br>
+   }<br>
+<br>
+   if (found) {<br>
+      match->dst = add_inst->dst;<br>
+      add_inst->remove();<br>
+   }<br>
+}<br>
+<br>
 void<br>
 vec4_visitor::emit_bool_comparison(unsigned int op,<br>
                                 dst_reg dst, src_reg src0, src_reg src1)<br>
</div></div>@@ -1319,6 +1415,8 @@ vec4_visitor::visit(ir_expression *ir)<br>
<div class="im"><br>
    case ir_binop_add:<br>
       emit(ADD(result_dst, op[0], op[1]));<br>
+      if (emitted_addc_or_subb)<br>
+         try_combine_add_with_addc_subb();<br>
       break;<br>
    case ir_binop_sub:<br>
       assert(!"not reached: should be handled by ir_sub_to_add_neg");<br>
</div>@@ -1359,6 +1457,8 @@ vec4_visitor::visit(ir_expression *ir)<br>
<div class="im">       emit_math(SHADER_OPCODE_INT_QUOTIENT, result_dst, op[0], op[1]);<br>
       break;<br>
    case ir_binop_carry: {<br>
+      emitted_addc_or_subb = true;<br>
+<br>
       struct brw_reg acc = retype(brw_acc_reg(), BRW_REGISTER_TYPE_UD);<br>
<br>
       emit(ADDC(dst_null_ud(), op[0], op[1]));<br>
</div>@@ -1366,6 +1466,8 @@ vec4_visitor::visit(ir_expression *ir)<br>
<div class="im">       break;<br>
    }<br>
    case ir_binop_borrow: {<br>
+      emitted_addc_or_subb = true;<br>
+<br>
       struct brw_reg acc = retype(brw_acc_reg(), BRW_REGISTER_TYPE_UD);<br>
<br>
       emit(SUBB(dst_null_ud(), op[0], op[1]));<br>
</div>@@ -3058,7 +3160,7 @@ vec4_visitor::vec4_visitor(struct brw_context *brw,<br>
                           struct brw_shader *shader,<br>
                           void *mem_ctx,<br>
                            bool debug_flag)<br>
-   : debug_flag(debug_flag)<br>
+   : debug_flag(debug_flag), emitted_addc_or_subb(false)<br>
 {<br>
    this->brw = brw;<br>
    this->ctx = &brw->ctx;<br>
<div class="HOEnZb"><div class="h5">--<br>
1.8.3.2<br>
<br>
_______________________________________________<br>
mesa-dev mailing list<br>
<a href="mailto:mesa-dev@lists.freedesktop.org">mesa-dev@lists.freedesktop.org</a><br>
<a href="http://lists.freedesktop.org/mailman/listinfo/mesa-dev" target="_blank">http://lists.freedesktop.org/mailman/listinfo/mesa-dev</a><br>
</div></div></blockquote></div><br></div></div>