glsl: Add new expressions for INTEL_shader_integer_functions2
v2: Re-write iadd64_saturate and isub64_saturate to avoid undefined overflow behavior. Also fix copy-and-paste bug in isub64_saturate. Suggested by Caio. v3: Avoid signed integer overflow for abs_sub(0, INT_MIN). Noticed by Caio. v4: Alternate fix for signed integer overflow for abs_sub(0, INT_MIN). I tried the previous methon in a small test program with -ftrapv, and it failed. Reviewed-by: Caio Marcelo de Oliveira Filho <caio.oliveira@intel.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/merge_requests/767>
This commit is contained in:
@@ -257,6 +257,7 @@ ir_expression::ir_expression(int op, ir_rvalue *op0)
|
||||
case ir_unop_dFdy_fine:
|
||||
case ir_unop_bitfield_reverse:
|
||||
case ir_unop_interpolate_at_centroid:
|
||||
case ir_unop_clz:
|
||||
case ir_unop_saturate:
|
||||
case ir_unop_atan:
|
||||
this->type = op0->type;
|
||||
@@ -500,6 +501,7 @@ ir_expression::ir_expression(int op, ir_rvalue *op0, ir_rvalue *op1)
|
||||
break;
|
||||
|
||||
case ir_binop_imul_high:
|
||||
case ir_binop_mul_32x16:
|
||||
case ir_binop_carry:
|
||||
case ir_binop_borrow:
|
||||
case ir_binop_lshift:
|
||||
@@ -510,6 +512,44 @@ ir_expression::ir_expression(int op, ir_rvalue *op0, ir_rvalue *op1)
|
||||
this->type = op0->type;
|
||||
break;
|
||||
|
||||
case ir_binop_add_sat:
|
||||
case ir_binop_sub_sat:
|
||||
case ir_binop_avg:
|
||||
case ir_binop_avg_round:
|
||||
assert(op0->type == op1->type);
|
||||
this->type = op0->type;
|
||||
break;
|
||||
|
||||
case ir_binop_abs_sub: {
|
||||
enum glsl_base_type base;
|
||||
|
||||
assert(op0->type == op1->type);
|
||||
|
||||
switch (op0->type->base_type) {
|
||||
case GLSL_TYPE_UINT:
|
||||
case GLSL_TYPE_INT:
|
||||
base = GLSL_TYPE_UINT;
|
||||
break;
|
||||
case GLSL_TYPE_UINT8:
|
||||
case GLSL_TYPE_INT8:
|
||||
base = GLSL_TYPE_UINT8;
|
||||
break;
|
||||
case GLSL_TYPE_UINT16:
|
||||
case GLSL_TYPE_INT16:
|
||||
base = GLSL_TYPE_UINT16;
|
||||
break;
|
||||
case GLSL_TYPE_UINT64:
|
||||
case GLSL_TYPE_INT64:
|
||||
base = GLSL_TYPE_UINT64;
|
||||
break;
|
||||
default:
|
||||
unreachable(!"Invalid base type.");
|
||||
}
|
||||
|
||||
this->type = glsl_type::get_instance(base, op0->type->vector_elements, 1);
|
||||
break;
|
||||
}
|
||||
|
||||
case ir_binop_vector_extract:
|
||||
this->type = op0->type->get_scalar_type();
|
||||
break;
|
||||
|
@@ -416,6 +416,42 @@ unpack_half_1x16(uint16_t u)
|
||||
return _mesa_half_to_float(u);
|
||||
}
|
||||
|
||||
static int32_t
|
||||
iadd_saturate(int32_t a, int32_t b)
|
||||
{
|
||||
return CLAMP(int64_t(a) + int64_t(b), INT32_MIN, INT32_MAX);
|
||||
}
|
||||
|
||||
static int64_t
|
||||
iadd64_saturate(int64_t a, int64_t b)
|
||||
{
|
||||
if (a < 0 && b < INT64_MIN - a)
|
||||
return INT64_MIN;
|
||||
|
||||
if (a > 0 && b > INT64_MAX - a)
|
||||
return INT64_MAX;
|
||||
|
||||
return a + b;
|
||||
}
|
||||
|
||||
static int32_t
|
||||
isub_saturate(int32_t a, int32_t b)
|
||||
{
|
||||
return CLAMP(int64_t(a) - int64_t(b), INT32_MIN, INT32_MAX);
|
||||
}
|
||||
|
||||
static int64_t
|
||||
isub64_saturate(int64_t a, int64_t b)
|
||||
{
|
||||
if (b > 0 && a < INT64_MIN + b)
|
||||
return INT64_MIN;
|
||||
|
||||
if (b < 0 && a > INT64_MAX + b)
|
||||
return INT64_MAX;
|
||||
|
||||
return a - b;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the constant that is ultimately referenced by an r-value, in a constant
|
||||
* expression evaluation context.
|
||||
|
@@ -539,6 +539,7 @@ ir_expression_operation = [
|
||||
operation("bit_count", 1, source_types=(uint_type, int_type), dest_type=int_type, c_expression="util_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("clz", 1, source_types=(uint_type,), dest_type=uint_type, c_expression="(unsigned)(31 - find_msb_uint({src0}))"),
|
||||
|
||||
operation("saturate", 1, printable_name="sat", source_types=(float_type,), c_expression="CLAMP({src0}, 0.0f, 1.0f)"),
|
||||
|
||||
@@ -584,8 +585,33 @@ ir_expression_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),
|
||||
operation("add_sat", 2, printable_name="add_sat", source_types=integer_types, c_expression={
|
||||
'u': "({src0} + {src1}) < {src0} ? UINT32_MAX : ({src0} + {src1})",
|
||||
'i': "iadd_saturate({src0}, {src1})",
|
||||
'u64': "({src0} + {src1}) < {src0} ? UINT64_MAX : ({src0} + {src1})",
|
||||
'i64': "iadd64_saturate({src0}, {src1})"
|
||||
}),
|
||||
operation("sub_sat", 2, printable_name="sub_sat", source_types=integer_types, c_expression={
|
||||
'u': "({src1} > {src0}) ? 0 : {src0} - {src1}",
|
||||
'i': "isub_saturate({src0}, {src1})",
|
||||
'u64': "({src1} > {src0}) ? 0 : {src0} - {src1}",
|
||||
'i64': "isub64_saturate({src0}, {src1})"
|
||||
}),
|
||||
operation("abs_sub", 2, printable_name="abs_sub", source_types=integer_types, c_expression={
|
||||
'u': "({src1} > {src0}) ? {src1} - {src0} : {src0} - {src1}",
|
||||
'i': "({src1} > {src0}) ? (unsigned){src1} - (unsigned){src0} : (unsigned){src0} - (unsigned){src1}",
|
||||
'u64': "({src1} > {src0}) ? {src1} - {src0} : {src0} - {src1}",
|
||||
'i64': "({src1} > {src0}) ? (uint64_t){src1} - (uint64_t){src0} : (uint64_t){src0} - (uint64_t){src1}",
|
||||
}),
|
||||
operation("avg", 2, printable_name="average", source_types=integer_types, c_expression="({src0} >> 1) + ({src1} >> 1) + (({src0} & {src1}) & 1)"),
|
||||
operation("avg_round", 2, printable_name="average_rounded", source_types=integer_types, c_expression="({src0} >> 1) + ({src1} >> 1) + (({src0} | {src1}) & 1)"),
|
||||
|
||||
# "Floating-point or low 32-bit integer multiply."
|
||||
operation("mul", 2, printable_name="*", source_types=numeric_types, c_expression="{src0} * {src1}"),
|
||||
operation("mul_32x16", 2, printable_name="*", source_types=(uint_type, int_type), c_expression={
|
||||
'u': "{src0} * (uint16_t){src1}",
|
||||
'i': "{src0} * (int16_t){src0}"
|
||||
}),
|
||||
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}", 'u64': "{src1} == 0 ? 0 : {src0} / {src1}", 'i64': "{src1} == 0 ? 0 : {src0} / {src1}", 'default': "{src0} / {src1}"}, flags=vector_scalar_operation),
|
||||
|
||||
|
@@ -546,6 +546,11 @@ ir_validate::visit_leave(ir_expression *ir)
|
||||
assert(ir->type->base_type == GLSL_TYPE_INT);
|
||||
break;
|
||||
|
||||
case ir_unop_clz:
|
||||
assert(ir->operands[0]->type == ir->type);
|
||||
assert(ir->type->base_type == GLSL_TYPE_UINT);
|
||||
break;
|
||||
|
||||
case ir_unop_noise:
|
||||
/* XXX what can we assert here? */
|
||||
break;
|
||||
@@ -649,6 +654,25 @@ ir_validate::visit_leave(ir_expression *ir)
|
||||
}
|
||||
break;
|
||||
|
||||
case ir_binop_abs_sub:
|
||||
assert(ir->operands[0]->type == ir->operands[1]->type);
|
||||
assert(ir->operands[0]->type->is_integer_32_64());
|
||||
assert(ir->operands[0]->type->vector_elements ==
|
||||
ir->type->vector_elements);
|
||||
assert(ir->type->base_type == GLSL_TYPE_UINT ||
|
||||
ir->type->base_type == GLSL_TYPE_UINT64);
|
||||
break;
|
||||
|
||||
case ir_binop_add_sat:
|
||||
case ir_binop_sub_sat:
|
||||
case ir_binop_avg:
|
||||
case ir_binop_avg_round:
|
||||
assert(ir->type == ir->operands[0]->type);
|
||||
assert(ir->type == ir->operands[1]->type);
|
||||
assert(ir->type->is_integer_32_64());
|
||||
break;
|
||||
|
||||
case ir_binop_mul_32x16:
|
||||
case ir_binop_imul_high:
|
||||
assert(ir->type == ir->operands[0]->type);
|
||||
assert(ir->type == ir->operands[1]->type);
|
||||
|
@@ -1296,6 +1296,12 @@ ir_to_mesa_visitor::visit(ir_expression *ir)
|
||||
case ir_binop_ldexp:
|
||||
case ir_binop_carry:
|
||||
case ir_binop_borrow:
|
||||
case ir_binop_abs_sub:
|
||||
case ir_binop_add_sat:
|
||||
case ir_binop_sub_sat:
|
||||
case ir_binop_avg:
|
||||
case ir_binop_avg_round:
|
||||
case ir_binop_mul_32x16:
|
||||
case ir_binop_imul_high:
|
||||
case ir_unop_interpolate_at_centroid:
|
||||
case ir_binop_interpolate_at_offset:
|
||||
@@ -1340,6 +1346,7 @@ ir_to_mesa_visitor::visit(ir_expression *ir)
|
||||
case ir_unop_unpack_image_2x32:
|
||||
case ir_unop_atan:
|
||||
case ir_binop_atan2:
|
||||
case ir_unop_clz:
|
||||
assert(!"not supported");
|
||||
break;
|
||||
|
||||
|
Reference in New Issue
Block a user