gallivm: add InstSimplify pass
[mesa.git] / src / compiler / glsl / ir.cpp
index 4df511fbf8d31d76e060a2a49adc1fb0665b77ed..71be1e1c7c133e14769b6e482cb0d6c2d0187a41 100644 (file)
@@ -293,11 +293,44 @@ ir_expression::ir_expression(int op, ir_rvalue *op0)
       break;
 
    case ir_unop_f2f16:
+   case ir_unop_f2fmp:
    case ir_unop_b2f16:
       this->type = glsl_type::get_instance(GLSL_TYPE_FLOAT16,
                                           op0->type->vector_elements, 1);
       break;
 
+   case ir_unop_i2imp:
+      this->type = glsl_type::get_instance(GLSL_TYPE_INT16,
+                                          op0->type->vector_elements, 1);
+      break;
+
+   case ir_unop_i2i:
+      if (op0->type->base_type == GLSL_TYPE_INT) {
+         this->type = glsl_type::get_instance(GLSL_TYPE_INT16,
+                                              op0->type->vector_elements, 1);
+      } else {
+         assert(op0->type->base_type == GLSL_TYPE_INT16);
+         this->type = glsl_type::get_instance(GLSL_TYPE_INT,
+                                              op0->type->vector_elements, 1);
+      }
+      break;
+
+   case ir_unop_u2u:
+      if (op0->type->base_type == GLSL_TYPE_UINT) {
+         this->type = glsl_type::get_instance(GLSL_TYPE_UINT16,
+                                              op0->type->vector_elements, 1);
+      } else {
+         assert(op0->type->base_type == GLSL_TYPE_UINT16);
+         this->type = glsl_type::get_instance(GLSL_TYPE_UINT,
+                                              op0->type->vector_elements, 1);
+      }
+      break;
+
+   case ir_unop_u2ump:
+      this->type = glsl_type::get_instance(GLSL_TYPE_UINT16,
+                                          op0->type->vector_elements, 1);
+      break;
+
    case ir_unop_f2b:
    case ir_unop_i2b:
    case ir_unop_d2b:
@@ -344,9 +377,6 @@ ir_expression::ir_expression(int op, ir_rvalue *op0)
       this->type = glsl_type::get_instance(GLSL_TYPE_UINT64,
                                           op0->type->vector_elements, 1);
       break;
-   case ir_unop_noise:
-      this->type = glsl_type::float_type;
-      break;
 
    case ir_unop_unpack_double_2x32:
    case ir_unop_unpack_uint_2x32:
@@ -730,6 +760,32 @@ ir_constant::ir_constant(double d, unsigned vector_elements)
    }
 }
 
+ir_constant::ir_constant(int16_t i16, unsigned vector_elements)
+   : ir_rvalue(ir_type_constant)
+{
+   assert(vector_elements <= 4);
+   this->type = glsl_type::get_instance(GLSL_TYPE_INT16, vector_elements, 1);
+   for (unsigned i = 0; i < vector_elements; i++) {
+      this->value.i16[i] = i16;
+   }
+   for (unsigned i = vector_elements; i < 16; i++) {
+      this->value.i16[i] = 0;
+   }
+}
+
+ir_constant::ir_constant(uint16_t u16, unsigned vector_elements)
+   : ir_rvalue(ir_type_constant)
+{
+   assert(vector_elements <= 4);
+   this->type = glsl_type::get_instance(GLSL_TYPE_UINT16, vector_elements, 1);
+   for (unsigned i = 0; i < vector_elements; i++) {
+      this->value.u16[i] = u16;
+   }
+   for (unsigned i = vector_elements; i < 16; i++) {
+      this->value.u16[i] = 0;
+   }
+}
+
 ir_constant::ir_constant(unsigned int u, unsigned vector_elements)
    : ir_rvalue(ir_type_constant)
 {
@@ -801,7 +857,23 @@ ir_constant::ir_constant(const ir_constant *c, unsigned i)
    this->const_elements = NULL;
    this->type = c->type->get_base_type();
 
+   /* Section 5.11 (Out-of-Bounds Accesses) of the GLSL 4.60 spec says:
+    *
+    *    In the subsections described above for array, vector, matrix and
+    *    structure accesses, any out-of-bounds access produced undefined
+    *    behavior....Out-of-bounds reads return undefined values, which
+    *    include values from other variables of the active program or zero.
+    *
+    * GL_KHR_robustness and GL_ARB_robustness encourage us to return zero.
+    */
+   if (i >= c->type->vector_elements) {
+      this->value = { { 0 } };
+      return;
+   }
+
    switch (this->type->base_type) {
+   case GLSL_TYPE_UINT16:  this->value.u16[0] = c->value.u16[i]; break;
+   case GLSL_TYPE_INT16:  this->value.i16[0] = c->value.i16[i]; break;
    case GLSL_TYPE_UINT:  this->value.u[0] = c->value.u[i]; break;
    case GLSL_TYPE_INT:   this->value.i[0] = c->value.i[i]; break;
    case GLSL_TYPE_FLOAT: this->value.f[0] = c->value.f[i]; break;
@@ -872,6 +944,11 @@ ir_constant::ir_constant(const struct glsl_type *type, exec_list *value_list)
       } else {
         /* Vector or scalar - fill all components */
         switch (type->base_type) {
+         case GLSL_TYPE_UINT16:
+        case GLSL_TYPE_INT16:
+           for (unsigned i = 0; i < type->components(); i++)
+              this->value.u16[i] = value->value.u16[0];
+           break;
         case GLSL_TYPE_UINT:
         case GLSL_TYPE_INT:
            for (unsigned i = 0; i < type->components(); i++)
@@ -945,6 +1022,12 @@ ir_constant::ir_constant(const struct glsl_type *type, exec_list *value_list)
 
       for (unsigned j = 0; j < value->type->components(); j++) {
         switch (type->base_type) {
+         case GLSL_TYPE_UINT16:
+           this->value.u16[i] = value->get_uint16_component(j);
+           break;
+        case GLSL_TYPE_INT16:
+           this->value.i16[i] = value->get_int16_component(j);
+           break;
         case GLSL_TYPE_UINT:
            this->value.u[i] = value->get_uint_component(j);
            break;
@@ -1019,6 +1102,8 @@ bool
 ir_constant::get_bool_component(unsigned i) const
 {
    switch (this->type->base_type) {
+   case GLSL_TYPE_UINT16:return this->value.u16[i] != 0;
+   case GLSL_TYPE_INT16: return this->value.i16[i] != 0;
    case GLSL_TYPE_UINT:  return this->value.u[i] != 0;
    case GLSL_TYPE_INT:   return this->value.i[i] != 0;
    case GLSL_TYPE_FLOAT: return ((int)this->value.f[i]) != 0;
@@ -1042,6 +1127,8 @@ float
 ir_constant::get_float_component(unsigned i) const
 {
    switch (this->type->base_type) {
+   case GLSL_TYPE_UINT16:return (float) this->value.u16[i];
+   case GLSL_TYPE_INT16: return (float) this->value.i16[i];
    case GLSL_TYPE_UINT:  return (float) this->value.u[i];
    case GLSL_TYPE_INT:   return (float) this->value.i[i];
    case GLSL_TYPE_FLOAT: return this->value.f[i];
@@ -1074,6 +1161,8 @@ double
 ir_constant::get_double_component(unsigned i) const
 {
    switch (this->type->base_type) {
+   case GLSL_TYPE_UINT16:return (double) this->value.u16[i];
+   case GLSL_TYPE_INT16: return (double) this->value.i16[i];
    case GLSL_TYPE_UINT:  return (double) this->value.u[i];
    case GLSL_TYPE_INT:   return (double) this->value.i[i];
    case GLSL_TYPE_FLOAT: return (double) this->value.f[i];
@@ -1093,10 +1182,62 @@ ir_constant::get_double_component(unsigned i) const
    return 0.0;
 }
 
+int16_t
+ir_constant::get_int16_component(unsigned i) const
+{
+   switch (this->type->base_type) {
+   case GLSL_TYPE_UINT16:return this->value.u16[i];
+   case GLSL_TYPE_INT16: return this->value.i16[i];
+   case GLSL_TYPE_UINT:  return this->value.u[i];
+   case GLSL_TYPE_INT:   return this->value.i[i];
+   case GLSL_TYPE_FLOAT: return (int16_t) this->value.f[i];
+   case GLSL_TYPE_FLOAT16: return (int16_t) _mesa_half_to_float(this->value.f16[i]);
+   case GLSL_TYPE_BOOL:  return this->value.b[i] ? 1 : 0;
+   case GLSL_TYPE_DOUBLE: return (int16_t) this->value.d[i];
+   case GLSL_TYPE_SAMPLER:
+   case GLSL_TYPE_IMAGE:
+   case GLSL_TYPE_UINT64: return (int16_t) this->value.u64[i];
+   case GLSL_TYPE_INT64:  return (int16_t) this->value.i64[i];
+   default:              assert(!"Should not get here."); break;
+   }
+
+   /* Must return something to make the compiler happy.  This is clearly an
+    * error case.
+    */
+   return 0;
+}
+
+uint16_t
+ir_constant::get_uint16_component(unsigned i) const
+{
+   switch (this->type->base_type) {
+   case GLSL_TYPE_UINT16:return this->value.u16[i];
+   case GLSL_TYPE_INT16: return this->value.i16[i];
+   case GLSL_TYPE_UINT:  return this->value.u[i];
+   case GLSL_TYPE_INT:   return this->value.i[i];
+   case GLSL_TYPE_FLOAT: return (uint16_t) this->value.f[i];
+   case GLSL_TYPE_FLOAT16: return (uint16_t) _mesa_half_to_float(this->value.f16[i]);
+   case GLSL_TYPE_BOOL:  return this->value.b[i] ? 1 : 0;
+   case GLSL_TYPE_DOUBLE: return (uint16_t) this->value.d[i];
+   case GLSL_TYPE_SAMPLER:
+   case GLSL_TYPE_IMAGE:
+   case GLSL_TYPE_UINT64: return (uint16_t) this->value.u64[i];
+   case GLSL_TYPE_INT64:  return (uint16_t) this->value.i64[i];
+   default:              assert(!"Should not get here."); break;
+   }
+
+   /* Must return something to make the compiler happy.  This is clearly an
+    * error case.
+    */
+   return 0;
+}
+
 int
 ir_constant::get_int_component(unsigned i) const
 {
    switch (this->type->base_type) {
+   case GLSL_TYPE_UINT16:return this->value.u16[i];
+   case GLSL_TYPE_INT16: return this->value.i16[i];
    case GLSL_TYPE_UINT:  return this->value.u[i];
    case GLSL_TYPE_INT:   return this->value.i[i];
    case GLSL_TYPE_FLOAT: return (int) this->value.f[i];
@@ -1120,6 +1261,8 @@ unsigned
 ir_constant::get_uint_component(unsigned i) const
 {
    switch (this->type->base_type) {
+   case GLSL_TYPE_UINT16:return this->value.u16[i];
+   case GLSL_TYPE_INT16: return this->value.i16[i];
    case GLSL_TYPE_UINT:  return this->value.u[i];
    case GLSL_TYPE_INT:   return this->value.i[i];
    case GLSL_TYPE_FLOAT: return (unsigned) this->value.f[i];
@@ -1143,6 +1286,8 @@ int64_t
 ir_constant::get_int64_component(unsigned i) const
 {
    switch (this->type->base_type) {
+   case GLSL_TYPE_UINT16:return this->value.u16[i];
+   case GLSL_TYPE_INT16: return this->value.i16[i];
    case GLSL_TYPE_UINT:  return this->value.u[i];
    case GLSL_TYPE_INT:   return this->value.i[i];
    case GLSL_TYPE_FLOAT: return (int64_t) this->value.f[i];
@@ -1166,6 +1311,8 @@ uint64_t
 ir_constant::get_uint64_component(unsigned i) const
 {
    switch (this->type->base_type) {
+   case GLSL_TYPE_UINT16:return this->value.u16[i];
+   case GLSL_TYPE_INT16: return this->value.i16[i];
    case GLSL_TYPE_UINT:  return this->value.u[i];
    case GLSL_TYPE_INT:   return this->value.i[i];
    case GLSL_TYPE_FLOAT: return (uint64_t) this->value.f[i];
@@ -1221,6 +1368,8 @@ void
 ir_constant::copy_offset(ir_constant *src, int offset)
 {
    switch (this->type->base_type) {
+   case GLSL_TYPE_UINT16:
+   case GLSL_TYPE_INT16:
    case GLSL_TYPE_UINT:
    case GLSL_TYPE_INT:
    case GLSL_TYPE_FLOAT:
@@ -1235,6 +1384,12 @@ ir_constant::copy_offset(ir_constant *src, int offset)
       assert (size <= this->type->components() - offset);
       for (unsigned int i=0; i<size; i++) {
         switch (this->type->base_type) {
+         case GLSL_TYPE_UINT16:
+           value.u16[i+offset] = src->get_uint16_component(i);
+           break;
+        case GLSL_TYPE_INT16:
+           value.i16[i+offset] = src->get_int16_component(i);
+           break;
         case GLSL_TYPE_UINT:
            value.u[i+offset] = src->get_uint_component(i);
            break;
@@ -1297,6 +1452,12 @@ ir_constant::copy_masked_offset(ir_constant *src, int offset, unsigned int mask)
    for (int i=0; i<4; i++) {
       if (mask & (1 << i)) {
         switch (this->type->base_type) {
+         case GLSL_TYPE_UINT16:
+           value.u16[i+offset] = src->get_uint16_component(id++);
+           break;
+        case GLSL_TYPE_INT16:
+           value.i16[i+offset] = src->get_int16_component(id++);
+           break;
         case GLSL_TYPE_UINT:
            value.u[i+offset] = src->get_uint_component(id++);
            break;
@@ -1347,6 +1508,14 @@ ir_constant::has_value(const ir_constant *c) const
 
    for (unsigned i = 0; i < this->type->components(); i++) {
       switch (this->type->base_type) {
+      case GLSL_TYPE_UINT16:
+        if (this->value.u16[i] != c->value.u16[i])
+           return false;
+        break;
+      case GLSL_TYPE_INT16:
+        if (this->value.i16[i] != c->value.i16[i])
+           return false;
+        break;
       case GLSL_TYPE_UINT:
         if (this->value.u[i] != c->value.u[i])
            return false;
@@ -1412,6 +1581,14 @@ ir_constant::is_value(float f, int i) const
          if (_mesa_half_to_float(this->value.f16[c]) != f)
             return false;
          break;
+      case GLSL_TYPE_INT16:
+        if (this->value.i16[c] != int16_t(i))
+           return false;
+        break;
+      case GLSL_TYPE_UINT16:
+        if (this->value.u16[c] != uint16_t(i))
+           return false;
+        break;
       case GLSL_TYPE_INT:
         if (this->value.i[c] != i)
            return false;
@@ -1836,6 +2013,7 @@ ir_variable::ir_variable(const struct glsl_type *type, const char *name,
    this->data.explicit_binding = false;
    this->data.explicit_component = false;
    this->data.has_initializer = false;
+   this->data.is_implicit_initializer = false;
    this->data.is_unmatched_generic_inout = false;
    this->data.is_xfb_only = false;
    this->data.explicit_xfb_buffer = false;