nir: Use a single list for all shader variables
[mesa.git] / src / compiler / glsl / opt_algebraic.cpp
index f5858c838654c508ec3335b24ecf0636d0ac5f9a..7cef4fc6ef934f12b306a64d129ddc97f48ae386 100644 (file)
@@ -34,6 +34,7 @@
 #include "ir_optimization.h"
 #include "ir_builder.h"
 #include "compiler/glsl_types.h"
+#include "main/mtypes.h"
 
 using namespace ir_builder;
 
@@ -144,7 +145,7 @@ is_valid_vec_const(ir_constant *ir)
 static inline bool
 is_less_than_one(ir_constant *ir)
 {
-   assert(ir->type->base_type == GLSL_TYPE_FLOAT);
+   assert(ir->type->is_float());
 
    if (!is_valid_vec_const(ir))
       return false;
@@ -161,7 +162,7 @@ is_less_than_one(ir_constant *ir)
 static inline bool
 is_greater_than_zero(ir_constant *ir)
 {
-   assert(ir->type->base_type == GLSL_TYPE_FLOAT);
+   assert(ir->type->is_float());
 
    if (!is_valid_vec_const(ir))
       return false;
@@ -246,7 +247,7 @@ ir_algebraic_visitor::reassociate_operands(ir_expression *ir1,
 /**
  * Reassociates a constant down a tree of adds or multiplies.
  *
- * Consider (2 * (a * (b * 0.5))).  We want to send up with a * b.
+ * Consider (2 * (a * (b * 0.5))).  We want to end up with a * b.
  */
 bool
 ir_algebraic_visitor::reassociate_constant(ir_expression *ir1, int const_index,
@@ -263,9 +264,11 @@ ir_algebraic_visitor::reassociate_constant(ir_expression *ir1, int const_index,
        ir2->operands[1]->type->is_matrix())
       return false;
 
+   void *mem_ctx = ralloc_parent(ir2);
+
    ir_constant *ir2_const[2];
-   ir2_const[0] = ir2->operands[0]->constant_expression_value();
-   ir2_const[1] = ir2->operands[1]->constant_expression_value();
+   ir2_const[0] = ir2->operands[0]->constant_expression_value(mem_ctx);
+   ir2_const[1] = ir2->operands[1]->constant_expression_value(mem_ctx);
 
    if (ir2_const[0] && ir2_const[1])
       return false;
@@ -313,7 +316,6 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir)
 {
    ir_constant *op_const[4] = {NULL, NULL, NULL, NULL};
    ir_expression *op_expr[4] = {NULL, NULL, NULL, NULL};
-   unsigned int i;
 
    if (ir->operation == ir_binop_mul &&
        ir->operands[0]->type->is_matrix() &&
@@ -329,12 +331,13 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir)
       }
    }
 
-   assert(ir->get_num_operands() <= 4);
-   for (i = 0; i < ir->get_num_operands(); i++) {
+   assert(ir->num_operands <= 4);
+   for (unsigned i = 0; i < ir->num_operands; i++) {
       if (ir->operands[i]->type->is_matrix())
         return ir;
 
-      op_const[i] = ir->operands[i]->constant_expression_value();
+      op_const[i] =
+         ir->operands[i]->constant_expression_value(ralloc_parent(ir));
       op_expr[i] = ir->operands[i]->as_expression();
    }
 
@@ -436,8 +439,6 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir)
 
       switch (op_expr[0]->operation) {
       case ir_binop_less:    new_op = ir_binop_gequal;  break;
-      case ir_binop_greater: new_op = ir_binop_lequal;  break;
-      case ir_binop_lequal:  new_op = ir_binop_greater; break;
       case ir_binop_gequal:  new_op = ir_binop_less;    break;
       case ir_binop_equal:   new_op = ir_binop_nequal;  break;
       case ir_binop_nequal:  new_op = ir_binop_equal;   break;
@@ -472,12 +473,52 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir)
       }
       break;
 
+      /* This macro CANNOT use the do { } while(true) mechanism because
+       * then the breaks apply to the loop instead of the switch!
+       */
+#define HANDLE_PACK_UNPACK_INVERSE(inverse_operation)                   \
+      {                                                                 \
+         ir_expression *const op = ir->operands[0]->as_expression();    \
+         if (op == NULL)                                                \
+            break;                                                      \
+         if (op->operation == (inverse_operation))                      \
+            return op->operands[0];                                     \
+         break;                                                         \
+      }
+
+   case ir_unop_unpack_uint_2x32:
+      HANDLE_PACK_UNPACK_INVERSE(ir_unop_pack_uint_2x32);
+   case ir_unop_pack_uint_2x32:
+      HANDLE_PACK_UNPACK_INVERSE(ir_unop_unpack_uint_2x32);
+   case ir_unop_unpack_int_2x32:
+      HANDLE_PACK_UNPACK_INVERSE(ir_unop_pack_int_2x32);
+   case ir_unop_pack_int_2x32:
+      HANDLE_PACK_UNPACK_INVERSE(ir_unop_unpack_int_2x32);
+   case ir_unop_unpack_double_2x32:
+      HANDLE_PACK_UNPACK_INVERSE(ir_unop_pack_double_2x32);
+   case ir_unop_pack_double_2x32:
+      HANDLE_PACK_UNPACK_INVERSE(ir_unop_unpack_double_2x32);
+
+#undef HANDLE_PACK_UNPACK_INVERSE
+
    case ir_binop_add:
       if (is_vec_zero(op_const[0]))
         return ir->operands[1];
       if (is_vec_zero(op_const[1]))
         return ir->operands[0];
 
+      /* Replace (x + (-x)) with constant 0 */
+      for (int i = 0; i < 2; i++) {
+         if (op_expr[i]) {
+            if (op_expr[i]->operation == ir_unop_neg) {
+               ir_rvalue *other = ir->operands[(i + 1) % 2];
+               if (other && op_expr[i]->operands[0]->equals(other)) {
+                  return ir_constant::zero(ir, ir->type);
+               }
+            }
+         }
+      }
+
       /* Reassociate addition of constants so that we can do constant
        * folding.
        */
@@ -537,7 +578,8 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir)
                ir_rvalue *y_operand = inner_add->operands[1 - neg_pos];
                ir_rvalue *a_operand = mul->operands[1 - inner_add_pos];
 
-               if (x_operand->type != y_operand->type ||
+               if (!x_operand->type->is_float_16_32_64() ||
+                   x_operand->type != y_operand->type ||
                    x_operand->type != a_operand->type)
                   continue;
 
@@ -621,8 +663,7 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir)
 
    case ir_binop_div:
       if (is_vec_one(op_const[0]) && (
-                ir->type->base_type == GLSL_TYPE_FLOAT ||
-                ir->type->base_type == GLSL_TYPE_DOUBLE)) {
+                ir->type->is_float() || ir->type->is_double())) {
         return new(mem_ctx) ir_expression(ir_unop_rcp,
                                           ir->operands[1]->type,
                                           ir->operands[1],
@@ -668,8 +709,6 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir)
       break;
 
    case ir_binop_less:
-   case ir_binop_lequal:
-   case ir_binop_greater:
    case ir_binop_gequal:
    case ir_binop_equal:
    case ir_binop_nequal:
@@ -683,6 +722,12 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir)
          if (!is_vec_zero(zero))
             continue;
 
+         /* We are allowed to add scalars with a vector or matrix. In that
+          * case lets just exit early.
+          */
+         if (add->operands[0]->type != add->operands[1]->type)
+            continue;
+
          /* Depending of the zero position we want to optimize
           * (0 cmp x+y) into (-x cmp y) or (x+y cmp 0) into (x cmp -y)
           */
@@ -817,7 +862,7 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir)
 
    case ir_binop_min:
    case ir_binop_max:
-      if (ir->type->base_type != GLSL_TYPE_FLOAT || options->EmitNoSat)
+      if (!ir->type->is_float() || options->EmitNoSat)
          break;
 
       /* Replace min(max) operations and its commutative combinations with
@@ -939,6 +984,9 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir)
          ir_constant *one;
 
          switch (ir->type->base_type) {
+         case GLSL_TYPE_FLOAT16:
+            one = new(mem_ctx) ir_constant(float16_t::one(), op2_components);
+            break;
          case GLSL_TYPE_FLOAT:
             one = new(mem_ctx) ir_constant(1.0f, op2_components);
             break;
@@ -961,6 +1009,16 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir)
         return ir->operands[2];
       break;
 
+   /* Remove interpolateAt* instructions for demoted inputs. They are
+    * assigned a constant expression to facilitate this.
+    */
+   case ir_unop_interpolate_at_centroid:
+   case ir_binop_interpolate_at_offset:
+   case ir_binop_interpolate_at_sample:
+      if (op_const[0])
+         return ir->operands[0];
+      break;
+
    default:
       break;
    }