glsl: Add 64-bit integer support for constant expressions
authorDave Airlie <airlied@redhat.com>
Wed, 8 Jun 2016 23:58:40 +0000 (09:58 +1000)
committerIan Romanick <ian.d.romanick@intel.com>
Fri, 20 Jan 2017 23:41:23 +0000 (15:41 -0800)
This just adds the new operations and add 64-bit integer support to all
the existing cases where it is needed.

v2: fix some issues found in testing.
v2.1: add unreachable (Ian), add missing int/uint pack/unpack (Dave).

v3 (idr): Rebase on top of idr's series to generate
ir_expression_operation_constant.h. In addition, this version:

    Adds missing support for ir_unop_bit_not, ir_binop_all_equal,
    ir_binop_any_nequal, ir_binop_vector_extract,
    ir_triop_vector_insert, and ir_quadop_vector.

    Removes support for uint64_t from ir_unop_abs and ir_unop_sign.

v4 (idr): "cut them down later" => Remove ir_unop_b2u64 and
ir_unop_u642b.  Handle these with extra i2u or u2i casts just like
uint(bool) and bool(uint) conversion is done.

Signed-off-by: Dave Airlie <airlied@redhat.com>
Signed-off-by: Ian Romanick <ian.d.romanick@intel.com>
Reviewed-by: Ian Romanick <ian.d.romanick@intel.com> [v2]
Reviewed-by: Matt Turner <mattst88@gmail.com> [v3]
Reviewed-by: Nicolai Hähnle <nicolai.haehnle@amd.com>
src/compiler/glsl/ir_constant_expression.cpp
src/compiler/glsl/ir_expression_operation.py

index 54b203aeec88d7bc053f69e86099c6d73d97fd59..cd3cd1bb5923462f8d54c62b9cd0c06453972e1b 100644 (file)
@@ -88,6 +88,42 @@ bitcast_f2u(float f)
    return u;
 }
 
+static double
+bitcast_u642d(uint64_t u)
+{
+   assert(sizeof(double) == sizeof(uint64_t));
+   double d;
+   memcpy(&d, &u, sizeof(d));
+   return d;
+}
+
+static double
+bitcast_i642d(int64_t i)
+{
+   assert(sizeof(double) == sizeof(int64_t));
+   double d;
+   memcpy(&d, &i, sizeof(d));
+   return d;
+}
+
+static double
+bitcast_d2u64(double d)
+{
+   assert(sizeof(double) == sizeof(uint64_t));
+   uint64_t u;
+   memcpy(&u, &d, sizeof(d));
+   return u;
+}
+
+static double
+bitcast_d2i64(double d)
+{
+   assert(sizeof(double) == sizeof(int64_t));
+   int64_t i;
+   memcpy(&i, &d, sizeof(d));
+   return i;
+}
+
 /**
  * Evaluate one component of a floating-point 4x8 unpacking function.
  */
index fbd8de8edaa62adb412da3eaf1db349e7426c516..f91ac9b822670dafeb702f6451b8886851cbddfb 100644 (file)
@@ -86,10 +86,10 @@ float_type = type("float", "f", "GLSL_TYPE_FLOAT")
 double_type = type("double", "d", "GLSL_TYPE_DOUBLE")
 bool_type = type("bool", "b", "GLSL_TYPE_BOOL")
 
-all_types = (uint_type, int_type, float_type, double_type, bool_type)
-numeric_types = (uint_type, int_type, float_type, double_type)
-signed_numeric_types = (int_type, float_type, double_type)
-integer_types = (uint_type, int_type)
+all_types = (uint_type, int_type, float_type, double_type, uint64_type, int64_type, bool_type)
+numeric_types = (uint_type, int_type, float_type, double_type, uint64_type, int64_type)
+signed_numeric_types = (int_type, float_type, double_type, int64_type)
+integer_types = (uint_type, int_type, uint64_type, int64_type)
 real_types = (float_type, double_type)
 
 # This template is for operations that can have operands of a several
@@ -420,8 +420,8 @@ ir_expression_operation = [
    operation("bit_not", 1, printable_name="~", source_types=integer_types, c_expression="~ {src0}"),
    operation("logic_not", 1, printable_name="!", source_types=(bool_type,), c_expression="!{src0}"),
    operation("neg", 1, source_types=numeric_types, c_expression={'u': "-((int) {src0})", 'default': "-{src0}"}),
-   operation("abs", 1, source_types=signed_numeric_types, c_expression={'i': "{src0} < 0 ? -{src0} : {src0}", 'f': "fabsf({src0})", 'd': "fabs({src0})"}),
-   operation("sign", 1, source_types=signed_numeric_types, c_expression={'i': "({src0} > 0) - ({src0} < 0)", 'f': "float(({src0} > 0.0F) - ({src0} < 0.0F))", 'd': "double(({src0} > 0.0) - ({src0} < 0.0))"}),
+   operation("abs", 1, source_types=signed_numeric_types, c_expression={'i': "{src0} < 0 ? -{src0} : {src0}", 'f': "fabsf({src0})", 'd': "fabs({src0})", 'i64': "{src0} < 0 ? -{src0} : {src0}"}),
+   operation("sign", 1, source_types=signed_numeric_types, c_expression={'i': "({src0} > 0) - ({src0} < 0)", 'f': "float(({src0} > 0.0F) - ({src0} < 0.0F))", 'd': "double(({src0} > 0.0) - ({src0} < 0.0))", 'i64': "({src0} > 0) - ({src0} < 0)"}),
    operation("rcp", 1, source_types=real_types, c_expression={'f': "{src0} != 0.0F ? 1.0F / {src0} : 0.0F", 'd': "{src0} != 0.0 ? 1.0 / {src0} : 0.0"}),
    operation("rsq", 1, source_types=real_types, c_expression={'f': "1.0F / sqrtf({src0})", 'd': "1.0 / sqrt({src0})"}),
    operation("sqrt", 1, source_types=real_types, c_expression={'f': "sqrtf({src0})", 'd': "sqrt({src0})"}),
@@ -441,7 +441,7 @@ ir_expression_operation = [
    # Boolean-to-float conversion
    operation("b2f", 1, source_types=(bool_type,), dest_type=float_type, c_expression="{src0} ? 1.0F : 0.0F"),
    # int-to-boolean conversion
-   operation("i2b", 1, source_types=integer_types, dest_type=bool_type, c_expression="{src0} ? true : false"),
+   operation("i2b", 1, source_types=(uint_type, int_type), dest_type=bool_type, c_expression="{src0} ? true : false"),
    # Boolean-to-int conversion
    operation("b2i", 1, source_types=(bool_type,), dest_type=int_type, c_expression="{src0} ? 1 : 0"),
    # Unsigned-to-float conversion.
@@ -473,35 +473,35 @@ ir_expression_operation = [
    # 'Bit-identical float-to-uint "conversion"
    operation("bitcast_f2u", 1, source_types=(float_type,), dest_type=uint_type, c_expression="bitcast_f2u({src0})"),
    # Bit-identical u64-to-double "conversion"
-   operation("bitcast_u642d", 1, source_types=(uint64_type,), dest_type=double_type),
+   operation("bitcast_u642d", 1, source_types=(uint64_type,), dest_type=double_type, c_expression="bitcast_u642d({src0})"),
    # Bit-identical i64-to-double "conversion"
-   operation("bitcast_i642d", 1, source_types=(int64_type,), dest_type=double_type),
+   operation("bitcast_i642d", 1, source_types=(int64_type,), dest_type=double_type, c_expression="bitcast_i642d({src0})"),
    # Bit-identical double-to_u64 "conversion"
-   operation("bitcast_d2u64", 1, source_types=(double_type,), dest_type=uint64_type),
+   operation("bitcast_d2u64", 1, source_types=(double_type,), dest_type=uint64_type, c_expression="bitcast_d2u64({src0})"),
    # Bit-identical double-to-i64 "conversion"
-   operation("bitcast_d2i64", 1, source_types=(double_type,), dest_type=int64_type),
+   operation("bitcast_d2i64", 1, source_types=(double_type,), dest_type=int64_type, c_expression="bitcast_d2i64({src0})"),
    # i64-to-i32 conversion
-   operation("i642i", 1, source_types=(int64_type,), dest_type=int_type),
+   operation("i642i", 1, source_types=(int64_type,), dest_type=int_type, c_expression="{src0}"),
    # ui64-to-i32 conversion
-   operation("u642i", 1, source_types=(uint64_type,), dest_type=int_type),
-   operation("i642u", 1, source_types=(int64_type,), dest_type=uint_type),
-   operation("u642u", 1, source_types=(uint64_type,), dest_type=uint_type),
-   operation("i642b", 1, source_types=(int64_type,), dest_type=bool_type),
-   operation("i642f", 1, source_types=(int64_type,), dest_type=float_type),
-   operation("u642f", 1, source_types=(uint64_type,), dest_type=float_type),
-   operation("i642d", 1, source_types=(int64_type,), dest_type=double_type),
-   operation("u642d", 1, source_types=(uint64_type,), dest_type=double_type),
-   operation("i2i64", 1, source_types=(int_type,), dest_type=int64_type),
-   operation("u2i64", 1, source_types=(uint_type,), dest_type=int64_type),
-   operation("b2i64", 1, source_types=(bool_type,), dest_type=int64_type),
-   operation("f2i64", 1, source_types=(float_type,), dest_type=int64_type),
-   operation("d2i64", 1, source_types=(double_type,), dest_type=int64_type),
-   operation("i2u64", 1, source_types=(int_type,), dest_type=uint64_type),
-   operation("u2u64", 1, source_types=(uint_type,), dest_type=uint64_type),
-   operation("f2u64", 1, source_types=(float_type,), dest_type=uint64_type),
-   operation("d2u64", 1, source_types=(double_type,), dest_type=uint64_type),
-   operation("u642i64", 1, source_types=(uint_type,), dest_type=int64_type),
-   operation("i642u64", 1, source_types=(int_type,), dest_type=uint64_type),
+   operation("u642i", 1, source_types=(uint64_type,), dest_type=int_type, c_expression="{src0}"),
+   operation("i642u", 1, source_types=(int64_type,), dest_type=uint_type, c_expression="{src0}"),
+   operation("u642u", 1, source_types=(uint64_type,), dest_type=uint_type, c_expression="{src0}"),
+   operation("i642b", 1, source_types=(int64_type,), dest_type=bool_type, c_expression="{src0} != 0"),
+   operation("i642f", 1, source_types=(int64_type,), dest_type=float_type, c_expression="{src0}"),
+   operation("u642f", 1, source_types=(uint64_type,), dest_type=float_type, c_expression="{src0}"),
+   operation("i642d", 1, source_types=(int64_type,), dest_type=double_type, c_expression="{src0}"),
+   operation("u642d", 1, source_types=(uint64_type,), dest_type=double_type, c_expression="{src0}"),
+   operation("i2i64", 1, source_types=(int_type,), dest_type=int64_type, c_expression="{src0}"),
+   operation("u2i64", 1, source_types=(uint_type,), dest_type=int64_type, c_expression="{src0}"),
+   operation("b2i64", 1, source_types=(bool_type,), dest_type=int64_type, c_expression="{src0}"),
+   operation("f2i64", 1, source_types=(float_type,), dest_type=int64_type, c_expression="{src0}"),
+   operation("d2i64", 1, source_types=(double_type,), dest_type=int64_type, c_expression="{src0}"),
+   operation("i2u64", 1, source_types=(int_type,), dest_type=uint64_type, c_expression="{src0}"),
+   operation("u2u64", 1, source_types=(uint_type,), dest_type=uint64_type, c_expression="{src0}"),
+   operation("f2u64", 1, source_types=(float_type,), dest_type=uint64_type, c_expression="{src0}"),
+   operation("d2u64", 1, source_types=(double_type,), dest_type=uint64_type, c_expression="{src0}"),
+   operation("u642i64", 1, source_types=(uint64_type,), dest_type=int64_type, c_expression="{src0}"),
+   operation("i642u64", 1, source_types=(int64_type,), dest_type=uint64_type, c_expression="{src0}"),
 
 
    # Unary floating-point rounding operations.
@@ -536,10 +536,10 @@ ir_expression_operation = [
    operation("unpack_half_2x16", 1, printable_name="unpackHalf2x16", source_types=(uint_type,), dest_type=float_type, c_expression="unpack_2x16(unpack_half_1x16, op[0]->value.u[0], &data.f[0], &data.f[1])", flags=frozenset((horizontal_operation, non_assign_operation))),
 
    # Bit operations, part of ARB_gpu_shader5.
-   operation("bitfield_reverse", 1, source_types=integer_types, c_expression="bitfield_reverse({src0})"),
-   operation("bit_count", 1, source_types=integer_types, dest_type=int_type, c_expression="_mesa_bitcount({src0})"),
-   operation("find_msb", 1, source_types=integer_types, dest_type=int_type, c_expression={'u': "find_msb_uint({src0})", 'i': "find_msb_int({src0})"}),
-   operation("find_lsb", 1, source_types=integer_types, dest_type=int_type, c_expression="find_msb_uint({src0} & -{src0})"),
+   operation("bitfield_reverse", 1, source_types=(uint_type, int_type), c_expression="bitfield_reverse({src0})"),
+   operation("bit_count", 1, source_types=(uint_type, int_type), dest_type=int_type, c_expression="_mesa_bitcount({src0})"),
+   operation("find_msb", 1, source_types=(uint_type, int_type), dest_type=int_type, c_expression={'u': "find_msb_uint({src0})", 'i': "find_msb_int({src0})"}),
+   operation("find_lsb", 1, source_types=(uint_type, int_type), dest_type=int_type, c_expression="find_msb_uint({src0} & -{src0})"),
 
    operation("saturate", 1, printable_name="sat", source_types=(float_type,), c_expression="CLAMP({src0}, 0.0f, 1.0f)"),
 
@@ -577,17 +577,17 @@ ir_expression_operation = [
    operation("vote_eq", 1),
 
    # 64-bit integer packing ops.
-   operation("pack_int_2x32", 1, printable_name="packInt2x32", source_types=(int_type,), dest_type=int64_type, flags=frozenset((horizontal_operation, non_assign_operation))),
-   operation("pack_uint_2x32", 1, printable_name="packUint2x32", source_types=(uint_type,), dest_type=uint64_type, flags=frozenset((horizontal_operation, non_assign_operation))),
-   operation("unpack_int_2x32", 1, printable_name="unpackInt2x32", source_types=(int64_type,), dest_type=int_type, flags=frozenset((horizontal_operation, non_assign_operation))),
-   operation("unpack_uint_2x32", 1, printable_name="unpackUint2x32", source_types=(uint64_type,), dest_type=uint_type, flags=frozenset((horizontal_operation, non_assign_operation))),
+   operation("pack_int_2x32", 1, printable_name="packInt2x32", source_types=(int_type,), dest_type=int64_type, c_expression="memcpy(&data.i64[0], &op[0]->value.i[0], sizeof(int64_t))", flags=frozenset((horizontal_operation, non_assign_operation))),
+   operation("pack_uint_2x32", 1, printable_name="packUint2x32", source_types=(uint_type,), dest_type=uint64_type, c_expression="memcpy(&data.u64[0], &op[0]->value.u[0], sizeof(uint64_t))", flags=frozenset((horizontal_operation, non_assign_operation))),
+   operation("unpack_int_2x32", 1, printable_name="unpackInt2x32", source_types=(int64_type,), dest_type=int_type, c_expression="memcpy(&data.i[0], &op[0]->value.i64[0], sizeof(int64_t))", flags=frozenset((horizontal_operation, non_assign_operation))),
+   operation("unpack_uint_2x32", 1, printable_name="unpackUint2x32", source_types=(uint64_type,), dest_type=uint_type, c_expression="memcpy(&data.u[0], &op[0]->value.u64[0], sizeof(uint64_t))", flags=frozenset((horizontal_operation, non_assign_operation))),
 
    operation("add", 2, printable_name="+", source_types=numeric_types, c_expression="{src0} + {src1}", flags=vector_scalar_operation),
    operation("sub", 2, printable_name="-", source_types=numeric_types, c_expression="{src0} - {src1}", flags=vector_scalar_operation),
    # "Floating-point or low 32-bit integer multiply."
    operation("mul", 2, printable_name="*", source_types=numeric_types, c_expression="{src0} * {src1}"),
    operation("imul_high", 2),       # Calculates the high 32-bits of a 64-bit multiply.
-   operation("div", 2, printable_name="/", source_types=numeric_types, c_expression={'u': "{src1} == 0 ? 0 : {src0} / {src1}", 'i': "{src1} == 0 ? 0 : {src0} / {src1}", 'default': "{src0} / {src1}"}, flags=vector_scalar_operation),
+   operation("div", 2, printable_name="/", source_types=numeric_types, c_expression={'u': "{src1} == 0 ? 0 : {src0} / {src1}", 'i': "{src1} == 0 ? 0 : {src0} / {src1}", 'u64': "{src1} == 0 ? 0 : {src0} / {src1}", 'i64': "{src1} == 0 ? 0 : {src0} / {src1}", 'default': "{src0} / {src1}"}, flags=vector_scalar_operation),
 
    # Returns the carry resulting from the addition of the two arguments.
    operation("carry", 2),
@@ -600,7 +600,7 @@ ir_expression_operation = [
    #
    # We don't use fmod because it rounds toward zero; GLSL specifies the use
    # of floor.
-   operation("mod", 2, printable_name="%", source_types=numeric_types, c_expression={'u': "{src1} == 0 ? 0 : {src0} % {src1}", 'i': "{src1} == 0 ? 0 : {src0} % {src1}", 'f': "{src0} - {src1} * floorf({src0} / {src1})", 'd': "{src0} - {src1} * floor({src0} / {src1})"}, flags=vector_scalar_operation),
+   operation("mod", 2, printable_name="%", source_types=numeric_types, c_expression={'u': "{src1} == 0 ? 0 : {src0} % {src1}", 'i': "{src1} == 0 ? 0 : {src0} % {src1}", 'f': "{src0} - {src1} * floorf({src0} / {src1})", 'd': "{src0} - {src1} * floor({src0} / {src1})", 'u64': "{src1} == 0 ? 0 : {src0} % {src1}", 'i64': "{src1} == 0 ? 0 : {src0} % {src1}"}, flags=vector_scalar_operation),
 
    # Binary comparison operators which return a boolean vector.
    # The type of both operands must be equal.