Mesa (master): glsl: Lower ir_binop_pow to a sequence of EXP2 and LOG2

Ian Romanick idr at kemper.freedesktop.org
Wed Dec 1 20:04:34 UTC 2010


Module: Mesa
Branch: master
Commit: c4285be9a5bd1adaa89050989374b95a9a601cdc
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=c4285be9a5bd1adaa89050989374b95a9a601cdc

Author: Ian Romanick <ian.d.romanick at intel.com>
Date:   Wed Nov 24 22:21:10 2010 -0800

glsl: Lower ir_binop_pow to a sequence of EXP2 and LOG2

---

 src/glsl/ir_optimization.h      |    5 +++--
 src/glsl/lower_instructions.cpp |   26 ++++++++++++++++++++++++++
 src/mesa/main/mtypes.h          |    1 +
 src/mesa/program/ir_to_mesa.cpp |    5 +++--
 4 files changed, 33 insertions(+), 4 deletions(-)

diff --git a/src/glsl/ir_optimization.h b/src/glsl/ir_optimization.h
index 1048ff9..f264265 100644
--- a/src/glsl/ir_optimization.h
+++ b/src/glsl/ir_optimization.h
@@ -32,8 +32,9 @@
 #define SUB_TO_ADD_NEG 0x01
 #define DIV_TO_MUL_RCP 0x02
 #define EXP_TO_EXP2    0x04
-#define LOG_TO_LOG2    0x08
-#define MOD_TO_FRACT   0x10
+#define POW_TO_EXP2    0x08
+#define LOG_TO_LOG2    0x10
+#define MOD_TO_FRACT   0x20
 
 bool do_common_optimization(exec_list *ir, bool linked, unsigned max_unroll_iterations);
 
diff --git a/src/glsl/lower_instructions.cpp b/src/glsl/lower_instructions.cpp
index 0d9374d..a5f61f2 100644
--- a/src/glsl/lower_instructions.cpp
+++ b/src/glsl/lower_instructions.cpp
@@ -33,6 +33,7 @@
  * - SUB_TO_ADD_NEG
  * - DIV_TO_MUL_RCP
  * - EXP_TO_EXP2
+ * - POW_TO_EXP2
  * - LOG_TO_LOG2
  * - MOD_TO_FRACT
  *
@@ -61,6 +62,11 @@
  * do have base 2 versions, so this pass converts exp and log to exp2
  * and log2 operations.
  *
+ * POW_TO_EXP2:
+ * -----------
+ * Many older GPUs don't have an x**y instruction.  For these GPUs, convert
+ * x**y to 2**(y * log2(x)).
+ *
  * MOD_TO_FRACT:
  * -------------
  * Breaks an ir_unop_mod expression down to (op1 * fract(op0 / op1))
@@ -91,6 +97,7 @@ private:
    void div_to_mul_rcp(ir_expression *);
    void mod_to_fract(ir_expression *);
    void exp_to_exp2(ir_expression *);
+   void pow_to_exp2(ir_expression *);
    void log_to_log2(ir_expression *);
 };
 
@@ -181,6 +188,20 @@ lower_instructions_visitor::exp_to_exp2(ir_expression *ir)
 }
 
 void
+lower_instructions_visitor::pow_to_exp2(ir_expression *ir)
+{
+   ir_expression *const log2_x =
+      new(ir) ir_expression(ir_unop_log2, ir->operands[0]->type,
+			    ir->operands[0]);
+
+   ir->operation = ir_unop_exp2;
+   ir->operands[0] = new(ir) ir_expression(ir_binop_mul, ir->operands[1]->type,
+					   ir->operands[1], log2_x);
+   ir->operands[1] = NULL;
+   this->progress = true;
+}
+
+void
 lower_instructions_visitor::log_to_log2(ir_expression *ir)
 {
    ir->operation = ir_binop_mul;
@@ -254,6 +275,11 @@ lower_instructions_visitor::visit_leave(ir_expression *ir)
 	 mod_to_fract(ir);
       break;
 
+   case ir_binop_pow:
+      if (lowering(POW_TO_EXP2))
+	 pow_to_exp2(ir);
+      break;
+
    default:
       return visit_continue;
    }
diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
index 80c20e0..8249571 100644
--- a/src/mesa/main/mtypes.h
+++ b/src/mesa/main/mtypes.h
@@ -2197,6 +2197,7 @@ struct gl_shader_compiler_options
    GLboolean EmitNoCont;                  /**< Emit CONT opcode? */
    GLboolean EmitNoMainReturn;            /**< Emit CONT/RET opcodes? */
    GLboolean EmitNoNoise;                 /**< Emit NOISE opcodes? */
+   GLboolean EmitNoPow;                   /**< Emit POW opcodes? */
 
    /**
     * \name Forms of indirect addressing the driver cannot do.
diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp
index d9d86b6..b274a96 100644
--- a/src/mesa/program/ir_to_mesa.cpp
+++ b/src/mesa/program/ir_to_mesa.cpp
@@ -2849,8 +2849,9 @@ _mesa_ir_link_shader(struct gl_context *ctx, struct gl_shader_program *prog)
 
 	 /* Lowering */
 	 do_mat_op_to_vec(ir);
-	 lower_instructions(ir, MOD_TO_FRACT | DIV_TO_MUL_RCP | EXP_TO_EXP2
-			      | LOG_TO_LOG2);
+	 lower_instructions(ir, (MOD_TO_FRACT | DIV_TO_MUL_RCP | EXP_TO_EXP2
+				 | LOG_TO_LOG2
+				 | ((options->EmitNoPow) ? POW_TO_EXP2 : 0)));
 
 	 progress = do_lower_jumps(ir, true, true, options->EmitNoMainReturn, options->EmitNoCont, options->EmitNoLoops) || progress;
 




More information about the mesa-commit mailing list