[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