[Mesa-dev] [PATCH 07/16] glsl: Add bitfieldInsert-to-bfm/bitops lowering pass.

Matt Turner mattst88 at gmail.com
Mon Apr 22 17:08:23 PDT 2013


---
 src/glsl/ir_optimization.h      |    1 +
 src/glsl/lower_instructions.cpp |   61 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 62 insertions(+), 0 deletions(-)

diff --git a/src/glsl/ir_optimization.h b/src/glsl/ir_optimization.h
index 49b1475..445dc49 100644
--- a/src/glsl/ir_optimization.h
+++ b/src/glsl/ir_optimization.h
@@ -38,6 +38,7 @@
 #define INT_DIV_TO_MUL_RCP 0x40
 #define LRP_TO_ARITH       0x80
 #define BITFIELD_INSERT_TO_BFM_BFI 0x100
+#define BITFIELD_INSERT_TO_BFM_BITOPS 0x200
 
 /**
  * \see class lower_packing_builtins_visitor
diff --git a/src/glsl/lower_instructions.cpp b/src/glsl/lower_instructions.cpp
index ff9715d..1c1cad8 100644
--- a/src/glsl/lower_instructions.cpp
+++ b/src/glsl/lower_instructions.cpp
@@ -39,6 +39,7 @@
  * - MOD_TO_FRACT
  * - LRP_TO_ARITH
  * - BITFIELD_INSERT_TO_BFM_BFI
+ * - BITFIELD_INSERT_TO_BFM_BITOPS
  *
  * SUB_TO_ADD_NEG:
  * ---------------
@@ -91,9 +92,20 @@
  * Breaks ir_quadop_bitfield_insert into ir_binop_bfm (bitfield mask) and
  * ir_triop_bfi (bitfield insert).
  *
+ * Mutually exclusive with BITFIELD_INSERT_TO_BFM_BITOPS.
+ *
  * Many GPUs implement the bitfieldInsert() built-in from ARB_gpu_shader_5
  * with a pair of instructions.
  *
+ * BITFIELD_INSERT_TO_BFM_BITOPS:
+ * ------------------------------
+ * Breaks ir_quadop_bitfield_insert into ir_binop_bfm (bitfield mask) and
+ * bit operations simulating ir_triop_bfi (bitfield insert).
+ *
+ * Mutually exclusive with BITFIELD_INSERT_TO_BFM_BITOPS.
+ *
+ * It's difficult to use vector three-source instructions in i965's vertex
+ * shader, so don't emit ir_triop_bfi, but rather bit operations.
  */
 
 #include "main/core.h" /* for M_LOG2E */
@@ -125,6 +137,7 @@ private:
    void log_to_log2(ir_expression *);
    void lrp_to_arith(ir_expression *);
    void bitfield_insert_to_bfm_bfi(ir_expression *);
+   void bitfield_insert_to_bfm_bitops(ir_expression *ir);
 };
 
 /**
@@ -335,6 +348,52 @@ lower_instructions_visitor::bitfield_insert_to_bfm_bfi(ir_expression *ir)
    this->progress = true;
 }
 
+void lower_instructions_visitor::bitfield_insert_to_bfm_bitops(ir_expression *ir)
+{
+   /* Translates
+    *    ir_quadop_bitfield_insert base insert offset bits
+    * into
+    *    (or (and base (not insert_mask))
+    *        (and (<< insert offset) insert_mask))
+    * where insert_mask is
+    *    (bfm bits offset)
+    */
+   ir_variable *base = new(ir) ir_variable(ir->operands[0]->type, "bfi_base",
+                                           ir_var_temporary);
+   this->base_ir->insert_before(base);
+   this->base_ir->insert_before(assign(base, ir->operands[0]));
+
+   ir_variable *insert = new(ir) ir_variable(ir->operands[1]->type, "bfi_insert",
+                                           ir_var_temporary);
+   this->base_ir->insert_before(insert);
+   this->base_ir->insert_before(assign(insert, ir->operands[1]));
+
+   ir_variable *offset = new(ir) ir_variable(ir->operands[2]->type, "bfi_offset",
+                                           ir_var_temporary);
+   this->base_ir->insert_before(offset);
+   this->base_ir->insert_before(assign(offset, ir->operands[2]));
+
+   ir_variable *bits = new(ir) ir_variable(ir->operands[3]->type, "bfi_bits",
+                                           ir_var_temporary);
+   this->base_ir->insert_before(bits);
+   this->base_ir->insert_before(assign(bits, ir->operands[3]));
+
+   ir_variable *insert_mask = new(ir) ir_variable(glsl_type::int_type,
+                                                  "insert_mask",
+                                                  ir_var_temporary);
+   this->base_ir->insert_before(insert_mask);
+   this->base_ir->insert_before(assign(insert_mask,
+                                       new(ir) ir_expression(ir_binop_bfm, ir->type,
+                                                             swizzle_xxxx(bits),
+                                                             swizzle_xxxx(offset))));
+
+   ir->operation = ir_binop_bit_or;
+   ir->operands[0] = bit_and(base, bit_not(insert_mask));
+   ir->operands[1] = bit_and(lshift(insert, offset), insert_mask);
+   ir->operands[2] = NULL;
+   ir->operands[3] = NULL;
+}
+
 ir_visitor_status
 lower_instructions_visitor::visit_leave(ir_expression *ir)
 {
@@ -379,6 +438,8 @@ lower_instructions_visitor::visit_leave(ir_expression *ir)
    case ir_quadop_bitfield_insert:
       if (lowering(BITFIELD_INSERT_TO_BFM_BFI))
          bitfield_insert_to_bfm_bfi(ir);
+      else if (lowering(BITFIELD_INSERT_TO_BFM_BITOPS))
+         bitfield_insert_to_bfm_bitops(ir);
       break;
 
    default:
-- 
1.7.8.6



More information about the mesa-dev mailing list