[Mesa-dev] [PATCH 05/21] i965/fs: Implement SIMD16 integer multiplies on Gen 7.

Ben Widawsky benjamin.widawsky at intel.com
Mon Dec 22 19:29:15 PST 2014


From: Matt Turner <mattst88 at gmail.com>

In order to do a full 32x32 integer multiply using the MUL/MACH macro, the
operation must be split into 2 SIMD8 operations. This is required even if you
don't care about the high bits. My interpretation of the requirement is that the
accumulator simply doesn't have enough bits to perform the 32x32 multiply.

v2 by Ben:
Added real commit message
Squashed in some changes from Matt's simd16 branch
Change the way sechalf if used.
   According to my reading of the docs, the sechalf operation should only be
   used for the mov instruction to obtain low bits. Any other usage is for the
   high results from the MUL/MACH macro

Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=86822
Signed-off-by: Ben Widawsky <ben at bwidawsk.net>
---
 src/mesa/drivers/dri/i965/brw_fs_visitor.cpp | 28 +++++++++++++++++++---------
 1 file changed, 19 insertions(+), 9 deletions(-)

diff --git a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp
index 5b83c40..0d8cacb 100644
--- a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp
@@ -774,15 +774,25 @@ fs_visitor::visit(ir_expression *ir)
             else
                emit(MUL(this->result, op[0], op[1]));
          } else {
-            if (brw->gen >= 7)
-               no16("SIMD16 explicit accumulator operands unsupported\n");
-
-            struct brw_reg acc = retype(brw_acc_reg(dispatch_width),
-                                        this->result.type);
-
-            emit(MUL(acc, op[0], op[1]));
-            emit(MACH(reg_null_d, op[0], op[1]));
-            emit(MOV(this->result, fs_reg(acc)));
+            unsigned width = brw->gen == 7 ? 8 : dispatch_width;
+            fs_reg acc = fs_reg(retype(brw_acc_reg(width), this->result.type));
+            fs_reg null = fs_reg(retype(brw_null_vec(width), this->result.type));
+
+            if (brw->gen == 7 && dispatch_width == 16) {
+               emit(MUL(acc, half(op[0], 0), half(op[1], 0)));
+               emit(MACH(null, half(op[0], 0), half(op[1], 0)));
+               fs_inst *mov = emit(MOV(half(this->result, 0), acc));
+               mov->force_sechalf = true;
+
+               emit(MUL(acc, half(op[0], 1), half(op[1], 1)));
+               emit(MACH(null, half(op[0], 1), half(op[1], 1)));
+               mov = emit(MOV(half(this->result, 1), acc));
+               mov->force_sechalf = true;
+            } else {
+               emit(MUL(acc, op[0], op[1]));
+               emit(MACH(null, op[0], op[1]));
+               emit(MOV(this->result, acc));
+            }
          }
       } else {
 	 emit(MUL(this->result, op[0], op[1]));
-- 
2.2.1



More information about the mesa-dev mailing list