util/hash_set: Rework the API to know about hashing
[mesa.git] / src / glsl / lower_instructions.cpp
index d01879cbd4fbba80354ee953918d5ad7e24d9199..684285350d05a685270b3da79eb9a2d836c76602 100644 (file)
  * - LOG_TO_LOG2
  * - MOD_TO_FRACT
  * - LDEXP_TO_ARITH
- * - LRP_TO_ARITH
  * - BITFIELD_INSERT_TO_BFM_BFI
+ * - CARRY_TO_ARITH
+ * - BORROW_TO_ARITH
+ * - SAT_TO_CLAMP
  *
  * SUB_TO_ADD_NEG:
  * ---------------
  * -------------
  * Converts ir_binop_ldexp to arithmetic and bit operations.
  *
- * 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
  * Many GPUs implement the bitfieldInsert() built-in from ARB_gpu_shader_5
  * with a pair of instructions.
  *
+ * CARRY_TO_ARITH:
+ * ---------------
+ * Converts ir_carry into (x + y) < x.
+ *
+ * BORROW_TO_ARITH:
+ * ----------------
+ * Converts ir_borrow into (x < y).
+ *
+ * SAT_TO_CLAMP:
+ * -------------
+ * Converts ir_unop_saturate into min(max(x, 0.0), 1.0)
+ *
  */
 
 #include "main/core.h" /* for M_LOG2E */
@@ -130,9 +140,11 @@ private:
    void exp_to_exp2(ir_expression *);
    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 *);
    void ldexp_to_arith(ir_expression *);
+   void carry_to_arith(ir_expression *);
+   void borrow_to_arith(ir_expression *);
+   void sat_to_clamp(ir_expression *);
 };
 
 } /* anonymous namespace */
@@ -298,27 +310,6 @@ lower_instructions_visitor::mod_to_fract(ir_expression *ir)
    this->progress = true;
 }
 
-void
-lower_instructions_visitor::lrp_to_arith(ir_expression *ir)
-{
-   /* (lrp x y a) -> x*(1-a) + y*a */
-
-   /* Save op2 */
-   ir_variable *temp = new(ir) ir_variable(ir->operands[2]->type, "lrp_factor",
-                                          ir_var_temporary);
-   this->base_ir->insert_before(temp);
-   this->base_ir->insert_before(assign(temp, ir->operands[2]));
-
-   ir_constant *one = new(ir) ir_constant(1.0f);
-
-   ir->operation = ir_binop_add;
-   ir->operands[0] = mul(ir->operands[0], sub(one, temp));
-   ir->operands[1] = mul(ir->operands[1], temp);
-   ir->operands[2] = NULL;
-
-   this->progress = true;
-}
-
 void
 lower_instructions_visitor::bitfield_insert_to_bfm_bfi(ir_expression *ir)
 {
@@ -383,12 +374,11 @@ lower_instructions_visitor::ldexp_to_arith(ir_expression *ir)
 
    /* Constants */
    ir_constant *zeroi = ir_constant::zero(ir, ivec);
-   ir_constant *zerof = ir_constant::zero(ir, ir->type);
 
-   ir_constant *sign_mantissa_mask = new(ir) ir_constant(0x807fffffu, vec_elem);
    ir_constant *sign_mask = new(ir) ir_constant(0x80000000u, vec_elem);
 
-   ir_constant *exp_shift = new(ir) ir_constant(23u, vec_elem);
+   ir_constant *exp_shift = new(ir) ir_constant(23);
+   ir_constant *exp_width = new(ir) ir_constant(8);
 
    /* Temporary variables */
    ir_variable *x = new(ir) ir_variable(ir->type, "x", ir_var_temporary);
@@ -429,8 +419,7 @@ lower_instructions_visitor::ldexp_to_arith(ir_expression *ir)
     */
    i.insert_before(zero_sign_x);
    i.insert_before(assign(zero_sign_x,
-                          bitcast_u2f(bit_or(bit_and(bitcast_f2u(x), sign_mask),
-                                             bitcast_f2u(zerof)))));
+                          bitcast_u2f(bit_and(bitcast_f2u(x), sign_mask))));
 
    i.insert_before(is_not_zero_or_underflow);
    i.insert_before(assign(is_not_zero_or_underflow,
@@ -451,11 +440,71 @@ lower_instructions_visitor::ldexp_to_arith(ir_expression *ir)
     */
 
    ir_constant *exp_shift_clone = exp_shift->clone(ir, NULL);
-   ir->operation = ir_unop_bitcast_u2f;
-   ir->operands[0] = bit_or(bit_and(bitcast_f2u(x), sign_mantissa_mask),
-                            lshift(i2u(resulting_biased_exp), exp_shift_clone));
+   ir->operation = ir_unop_bitcast_i2f;
+   ir->operands[0] = bitfield_insert(bitcast_f2i(x), resulting_biased_exp,
+                                     exp_shift_clone, exp_width);
    ir->operands[1] = NULL;
 
+   /* Don't generate new IR that would need to be lowered in an additional
+    * pass.
+    */
+   if (lowering(BITFIELD_INSERT_TO_BFM_BFI))
+      bitfield_insert_to_bfm_bfi(ir->operands[0]->as_expression());
+
+   this->progress = true;
+}
+
+void
+lower_instructions_visitor::carry_to_arith(ir_expression *ir)
+{
+   /* Translates
+    *   ir_binop_carry x y
+    * into
+    *   sum = ir_binop_add x y
+    *   bcarry = ir_binop_less sum x
+    *   carry = ir_unop_b2i bcarry
+    */
+
+   ir_rvalue *x_clone = ir->operands[0]->clone(ir, NULL);
+   ir->operation = ir_unop_i2u;
+   ir->operands[0] = b2i(less(add(ir->operands[0], ir->operands[1]), x_clone));
+   ir->operands[1] = NULL;
+
+   this->progress = true;
+}
+
+void
+lower_instructions_visitor::borrow_to_arith(ir_expression *ir)
+{
+   /* Translates
+    *   ir_binop_borrow x y
+    * into
+    *   bcarry = ir_binop_less x y
+    *   carry = ir_unop_b2i bcarry
+    */
+
+   ir->operation = ir_unop_i2u;
+   ir->operands[0] = b2i(less(ir->operands[0], ir->operands[1]));
+   ir->operands[1] = NULL;
+
+   this->progress = true;
+}
+
+void
+lower_instructions_visitor::sat_to_clamp(ir_expression *ir)
+{
+   /* Translates
+    *   ir_unop_saturate x
+    * into
+    *   ir_binop_min (ir_binop_max(x, 0.0), 1.0)
+    */
+
+   ir->operation = ir_binop_min;
+   ir->operands[0] = new(ir) ir_expression(ir_binop_max, ir->operands[0]->type,
+                                           ir->operands[0],
+                                           new(ir) ir_constant(0.0f));
+   ir->operands[1] = new(ir) ir_constant(1.0f);
+
    this->progress = true;
 }
 
@@ -495,11 +544,6 @@ lower_instructions_visitor::visit_leave(ir_expression *ir)
         pow_to_exp2(ir);
       break;
 
-   case ir_triop_lrp:
-      if (lowering(LRP_TO_ARITH))
-        lrp_to_arith(ir);
-      break;
-
    case ir_quadop_bitfield_insert:
       if (lowering(BITFIELD_INSERT_TO_BFM_BFI))
          bitfield_insert_to_bfm_bfi(ir);
@@ -510,6 +554,21 @@ lower_instructions_visitor::visit_leave(ir_expression *ir)
          ldexp_to_arith(ir);
       break;
 
+   case ir_binop_carry:
+      if (lowering(CARRY_TO_ARITH))
+         carry_to_arith(ir);
+      break;
+
+   case ir_binop_borrow:
+      if (lowering(BORROW_TO_ARITH))
+         borrow_to_arith(ir);
+      break;
+
+   case ir_unop_saturate:
+      if (lowering(SAT_TO_CLAMP))
+         sat_to_clamp(ir);
+      break;
+
    default:
       return visit_continue;
    }