glsl: Add a pass to lower bitfield-insert into bfm+bfi.
authorMatt Turner <mattst88@gmail.com>
Wed, 10 Apr 2013 05:43:05 +0000 (22:43 -0700)
committerMatt Turner <mattst88@gmail.com>
Mon, 6 May 2013 17:17:13 +0000 (10:17 -0700)
i965/Gen7+ and Radeon/Evergreen+ have bfm/bfi instructions to implement
bitfieldInsert() from ARB_gpu_shader5.

v2: Add ir_binop_bfm and ir_triop_bfi to st_glsl_to_tgsi.cpp.
    Remove spurious temporary assignment and dereference.

Reviewed-by: Chris Forbes <chrisf@ijw.co.nz>
src/glsl/ir.cpp
src/glsl/ir.h
src/glsl/ir_optimization.h
src/glsl/ir_validate.cpp
src/glsl/lower_instructions.cpp
src/mesa/program/ir_to_mesa.cpp
src/mesa/state_tracker/st_glsl_to_tgsi.cpp

index 2c989c91678f62624ab3423bbf62de937e6fef69..2c54525938044b113c94040f858d9fe92a55aa57 100644 (file)
@@ -508,8 +508,10 @@ static const char *const operator_strs[] = {
    "max",
    "pow",
    "packHalf2x16_split",
+   "bfm",
    "ubo_load",
    "lrp",
+   "bfi",
    "bitfield_extract",
    "bitfield_insert",
    "vector",
index 470c08ca00dfb6183ca1308df7cc2828ee719397..6783ecaf2e911640e8e5ffe75e840fb06dcd566e 100644 (file)
@@ -1118,6 +1118,15 @@ enum ir_expression_operation {
    ir_binop_pack_half_2x16_split,
    /*@}*/
 
+   /**
+    * \name First half of a lowered bitfieldInsert() operation.
+    *
+    * \see lower_instructions::bitfield_insert_to_bfm_bfi
+    */
+   /*@{*/
+   ir_binop_bfm,
+   /*@}*/
+
    /**
     * Load a value the size of a given GLSL type from a uniform block.
     *
@@ -1133,6 +1142,15 @@ enum ir_expression_operation {
 
    ir_triop_lrp,
 
+   /**
+    * \name Second half of a lowered bitfieldInsert() operation.
+    *
+    * \see lower_instructions::bitfield_insert_to_bfm_bfi
+    */
+   /*@{*/
+   ir_triop_bfi,
+   /*@}*/
+
    ir_triop_bitfield_extract,
 
    /**
index a8885d7225b1727e675a2ba86128736fe0847ccf..49b1475b5424403eda6c97b9f0185ab7298b7904 100644 (file)
@@ -37,6 +37,7 @@
 #define MOD_TO_FRACT       0x20
 #define INT_DIV_TO_MUL_RCP 0x40
 #define LRP_TO_ARITH       0x80
+#define BITFIELD_INSERT_TO_BFM_BFI 0x100
 
 /**
  * \see class lower_packing_builtins_visitor
index 4a8df6953eeec2c159be9064a4477eeb5744c8e1..26f09c71f631eab223bfe0eccea0be9e600661fc 100644 (file)
@@ -474,6 +474,12 @@ ir_validate::visit_leave(ir_expression *ir)
       assert(ir->operands[1]->type == glsl_type::float_type);
       break;
 
+   case ir_binop_bfm:
+      assert(ir->type->is_integer());
+      assert(ir->operands[0]->type->is_integer());
+      assert(ir->operands[1]->type->is_integer());
+      break;
+
    case ir_binop_ubo_load:
       assert(ir->operands[0]->as_constant());
       assert(ir->operands[0]->type == glsl_type::uint_type);
@@ -487,6 +493,12 @@ ir_validate::visit_leave(ir_expression *ir)
       assert(ir->operands[2]->type == ir->operands[0]->type || ir->operands[2]->type == glsl_type::float_type);
       break;
 
+   case ir_triop_bfi:
+      assert(ir->operands[0]->type->is_integer());
+      assert(ir->operands[1]->type == ir->operands[2]->type);
+      assert(ir->operands[1]->type == ir->type);
+      break;
+
    case ir_triop_bitfield_extract:
       assert(ir->operands[0]->type == ir->type);
       assert(ir->operands[1]->type == glsl_type::int_type);
index 1ce7b7c9df4d01a650346fc6c4e113b649ceeb6f..d32ec80d6bba5db9d24f11cdab5773823543bfee 100644 (file)
@@ -38,6 +38,7 @@
  * - LOG_TO_LOG2
  * - MOD_TO_FRACT
  * - LRP_TO_ARITH
+ * - BITFIELD_INSERT_TO_BFM_BFI
  *
  * SUB_TO_ADD_NEG:
  * ---------------
  * LRP_TO_ARITH:
  * -------------
  * Converts ir_triop_lrp to (op0 * (1.0f - op2)) + (op1 * op2).
+ *
+ * BITFIELD_INSERT_TO_BFM_BFI:
+ * ---------------------------
+ * Breaks ir_quadop_bitfield_insert into ir_binop_bfm (bitfield mask) and
+ * ir_triop_bfi (bitfield insert).
+ *
+ * Many GPUs implement the bitfieldInsert() built-in from ARB_gpu_shader_5
+ * with a pair of instructions.
+ *
  */
 
 #include "main/core.h" /* for M_LOG2E */
@@ -114,6 +124,7 @@ private:
    void pow_to_exp2(ir_expression *);
    void log_to_log2(ir_expression *);
    void lrp_to_arith(ir_expression *);
+   void bitfield_insert_to_bfm_bfi(ir_expression *);
 };
 
 /**
@@ -298,6 +309,29 @@ lower_instructions_visitor::lrp_to_arith(ir_expression *ir)
    this->progress = true;
 }
 
+void
+lower_instructions_visitor::bitfield_insert_to_bfm_bfi(ir_expression *ir)
+{
+   /* Translates
+    *    ir_quadop_bitfield_insert base insert offset bits
+    * into
+    *    ir_triop_bfi (ir_binop_bfm bits offset) insert base
+    */
+
+   ir_rvalue *base_expr = ir->operands[0];
+
+   ir->operation = ir_triop_bfi;
+   ir->operands[0] = new(ir) ir_expression(ir_binop_bfm,
+                                           ir->type->get_base_type(),
+                                           ir->operands[3],
+                                           ir->operands[2]);
+   /* ir->operands[1] is still the value to insert. */
+   ir->operands[2] = base_expr;
+   ir->operands[3] = NULL;
+
+   this->progress = true;
+}
+
 ir_visitor_status
 lower_instructions_visitor::visit_leave(ir_expression *ir)
 {
@@ -339,6 +373,11 @@ lower_instructions_visitor::visit_leave(ir_expression *ir)
         lrp_to_arith(ir);
       break;
 
+   case ir_quadop_bitfield_insert:
+      if (lowering(BITFIELD_INSERT_TO_BFM_BFI))
+         bitfield_insert_to_bfm_bfi(ir);
+      break;
+
    default:
       return visit_continue;
    }
index c6f6bf42ea015eb46f7f53f6bf161f03e03b1abb..084846201c9878c1305ac24fba4559a9bc89e0f9 100644 (file)
@@ -1489,6 +1489,8 @@ ir_to_mesa_visitor::visit(ir_expression *ir)
       emit(ir, OPCODE_LRP, result_dst, op[2], op[1], op[0]);
       break;
 
+   case ir_binop_bfm:
+   case ir_triop_bfi:
    case ir_triop_bitfield_extract:
    case ir_quadop_bitfield_insert:
       assert(!"not supported");
index ad936bd20d0482d83e8d57756e850c75e38f5059..ed314a0497f4ea6c99a43645a913266ade86904b 100644 (file)
@@ -1973,6 +1973,8 @@ glsl_to_tgsi_visitor::visit(ir_expression *ir)
    case ir_unop_bit_count:
    case ir_unop_find_msb:
    case ir_unop_find_lsb:
+   case ir_binop_bfm:
+   case ir_triop_bfi:
    case ir_triop_bitfield_extract:
    case ir_quadop_bitfield_insert:
    case ir_quadop_vector: