compiler/nir: add an is_conversion field to nir_op_info
This is set to True only for numeric conversion opcodes. Reviewed-by: Jason Ekstrand <jason@jlekstrand.net> Reviewed-by: Matt Turner <mattst88@gmail.com> Reviewed-by: Jordan Justen <jordan.l.justen@intel.com> Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
This commit is contained in:

committed by
Jason Ekstrand

parent
55e6454d5e
commit
ca2b5e9069
@@ -918,6 +918,9 @@ typedef struct {
|
|||||||
nir_alu_type input_types[NIR_MAX_VEC_COMPONENTS];
|
nir_alu_type input_types[NIR_MAX_VEC_COMPONENTS];
|
||||||
|
|
||||||
nir_op_algebraic_property algebraic_properties;
|
nir_op_algebraic_property algebraic_properties;
|
||||||
|
|
||||||
|
/* Whether this represents a numeric conversion opcode */
|
||||||
|
bool is_conversion;
|
||||||
} nir_op_info;
|
} nir_op_info;
|
||||||
|
|
||||||
extern const nir_op_info nir_op_infos[nir_num_opcodes];
|
extern const nir_op_info nir_op_infos[nir_num_opcodes];
|
||||||
|
@@ -33,12 +33,13 @@ class Opcode(object):
|
|||||||
NOTE: this must be kept in sync with nir_op_info
|
NOTE: this must be kept in sync with nir_op_info
|
||||||
"""
|
"""
|
||||||
def __init__(self, name, output_size, output_type, input_sizes,
|
def __init__(self, name, output_size, output_type, input_sizes,
|
||||||
input_types, algebraic_properties, const_expr):
|
input_types, is_conversion, algebraic_properties, const_expr):
|
||||||
"""Parameters:
|
"""Parameters:
|
||||||
|
|
||||||
- name is the name of the opcode (prepend nir_op_ for the enum name)
|
- name is the name of the opcode (prepend nir_op_ for the enum name)
|
||||||
- all types are strings that get nir_type_ prepended to them
|
- all types are strings that get nir_type_ prepended to them
|
||||||
- input_types is a list of types
|
- input_types is a list of types
|
||||||
|
- is_conversion is true if this opcode represents a type conversion
|
||||||
- algebraic_properties is a space-seperated string, where nir_op_is_ is
|
- algebraic_properties is a space-seperated string, where nir_op_is_ is
|
||||||
prepended before each entry
|
prepended before each entry
|
||||||
- const_expr is an expression or series of statements that computes the
|
- const_expr is an expression or series of statements that computes the
|
||||||
@@ -70,6 +71,7 @@ class Opcode(object):
|
|||||||
assert isinstance(input_sizes[0], int)
|
assert isinstance(input_sizes[0], int)
|
||||||
assert isinstance(input_types, list)
|
assert isinstance(input_types, list)
|
||||||
assert isinstance(input_types[0], str)
|
assert isinstance(input_types[0], str)
|
||||||
|
assert isinstance(is_conversion, bool)
|
||||||
assert isinstance(algebraic_properties, str)
|
assert isinstance(algebraic_properties, str)
|
||||||
assert isinstance(const_expr, str)
|
assert isinstance(const_expr, str)
|
||||||
assert len(input_sizes) == len(input_types)
|
assert len(input_sizes) == len(input_types)
|
||||||
@@ -84,6 +86,7 @@ class Opcode(object):
|
|||||||
self.output_type = output_type
|
self.output_type = output_type
|
||||||
self.input_sizes = input_sizes
|
self.input_sizes = input_sizes
|
||||||
self.input_types = input_types
|
self.input_types = input_types
|
||||||
|
self.is_conversion = is_conversion
|
||||||
self.algebraic_properties = algebraic_properties
|
self.algebraic_properties = algebraic_properties
|
||||||
self.const_expr = const_expr
|
self.const_expr = const_expr
|
||||||
|
|
||||||
@@ -138,21 +141,22 @@ associative = "associative "
|
|||||||
opcodes = {}
|
opcodes = {}
|
||||||
|
|
||||||
def opcode(name, output_size, output_type, input_sizes, input_types,
|
def opcode(name, output_size, output_type, input_sizes, input_types,
|
||||||
algebraic_properties, const_expr):
|
is_conversion, algebraic_properties, const_expr):
|
||||||
assert name not in opcodes
|
assert name not in opcodes
|
||||||
opcodes[name] = Opcode(name, output_size, output_type, input_sizes,
|
opcodes[name] = Opcode(name, output_size, output_type, input_sizes,
|
||||||
input_types, algebraic_properties, const_expr)
|
input_types, is_conversion, algebraic_properties,
|
||||||
|
const_expr)
|
||||||
|
|
||||||
def unop_convert(name, out_type, in_type, const_expr):
|
def unop_convert(name, out_type, in_type, const_expr):
|
||||||
opcode(name, 0, out_type, [0], [in_type], "", const_expr)
|
opcode(name, 0, out_type, [0], [in_type], False, "", const_expr)
|
||||||
|
|
||||||
def unop(name, ty, const_expr):
|
def unop(name, ty, const_expr):
|
||||||
opcode(name, 0, ty, [0], [ty], "", const_expr)
|
opcode(name, 0, ty, [0], [ty], False, "", const_expr)
|
||||||
|
|
||||||
def unop_horiz(name, output_size, output_type, input_size, input_type,
|
def unop_horiz(name, output_size, output_type, input_size, input_type,
|
||||||
const_expr):
|
const_expr):
|
||||||
opcode(name, output_size, output_type, [input_size], [input_type], "",
|
opcode(name, output_size, output_type, [input_size], [input_type],
|
||||||
const_expr)
|
False, "", const_expr)
|
||||||
|
|
||||||
def unop_reduce(name, output_size, output_type, input_type, prereduce_expr,
|
def unop_reduce(name, output_size, output_type, input_type, prereduce_expr,
|
||||||
reduce_expr, final_expr):
|
reduce_expr, final_expr):
|
||||||
@@ -173,6 +177,8 @@ def unop_reduce(name, output_size, output_type, input_type, prereduce_expr,
|
|||||||
unop_horiz(name + "4", output_size, output_type, 4, input_type,
|
unop_horiz(name + "4", output_size, output_type, 4, input_type,
|
||||||
final(reduce_(reduce_(src0, src1), reduce_(src2, src3))))
|
final(reduce_(reduce_(src0, src1), reduce_(src2, src3))))
|
||||||
|
|
||||||
|
def unop_numeric_convert(name, out_type, in_type, const_expr):
|
||||||
|
opcode(name, 0, out_type, [0], [in_type], True, "", const_expr)
|
||||||
|
|
||||||
# These two move instructions differ in what modifiers they support and what
|
# These two move instructions differ in what modifiers they support and what
|
||||||
# the negate modifier means. Otherwise, they are identical.
|
# the negate modifier means. Otherwise, they are identical.
|
||||||
@@ -215,13 +221,13 @@ for src_t in [tint, tuint, tfloat, tbool]:
|
|||||||
if bit_size == 16 and dst_t == tfloat and src_t == tfloat:
|
if bit_size == 16 and dst_t == tfloat and src_t == tfloat:
|
||||||
rnd_modes = ['_rtne', '_rtz', '']
|
rnd_modes = ['_rtne', '_rtz', '']
|
||||||
for rnd_mode in rnd_modes:
|
for rnd_mode in rnd_modes:
|
||||||
unop_convert("{0}2{1}{2}{3}".format(src_t[0], dst_t[0],
|
unop_numeric_convert("{0}2{1}{2}{3}".format(src_t[0], dst_t[0],
|
||||||
bit_size, rnd_mode),
|
bit_size, rnd_mode),
|
||||||
dst_t + str(bit_size), src_t, "src0")
|
dst_t + str(bit_size), src_t, "src0")
|
||||||
else:
|
else:
|
||||||
conv_expr = "src0 != 0" if dst_t == tbool else "src0"
|
conv_expr = "src0 != 0" if dst_t == tbool else "src0"
|
||||||
unop_convert("{0}2{1}{2}".format(src_t[0], dst_t[0], bit_size),
|
unop_numeric_convert("{0}2{1}{2}".format(src_t[0], dst_t[0], bit_size),
|
||||||
dst_t + str(bit_size), src_t, conv_expr)
|
dst_t + str(bit_size), src_t, conv_expr)
|
||||||
|
|
||||||
|
|
||||||
# Unary floating-point rounding operations.
|
# Unary floating-point rounding operations.
|
||||||
@@ -426,7 +432,8 @@ if (src0.z < 0 && absZ >= absX && absZ >= absY) dst.x = 5;
|
|||||||
|
|
||||||
|
|
||||||
def binop_convert(name, out_type, in_type, alg_props, const_expr):
|
def binop_convert(name, out_type, in_type, alg_props, const_expr):
|
||||||
opcode(name, 0, out_type, [0, 0], [in_type, in_type], alg_props, const_expr)
|
opcode(name, 0, out_type, [0, 0], [in_type, in_type],
|
||||||
|
False, alg_props, const_expr)
|
||||||
|
|
||||||
def binop(name, ty, alg_props, const_expr):
|
def binop(name, ty, alg_props, const_expr):
|
||||||
binop_convert(name, ty, ty, alg_props, const_expr)
|
binop_convert(name, ty, ty, alg_props, const_expr)
|
||||||
@@ -440,7 +447,7 @@ def binop_compare32(name, ty, alg_props, const_expr):
|
|||||||
def binop_horiz(name, out_size, out_type, src1_size, src1_type, src2_size,
|
def binop_horiz(name, out_size, out_type, src1_size, src1_type, src2_size,
|
||||||
src2_type, const_expr):
|
src2_type, const_expr):
|
||||||
opcode(name, out_size, out_type, [src1_size, src2_size], [src1_type, src2_type],
|
opcode(name, out_size, out_type, [src1_size, src2_size], [src1_type, src2_type],
|
||||||
"", const_expr)
|
False, "", const_expr)
|
||||||
|
|
||||||
def binop_reduce(name, output_size, output_type, src_type, prereduce_expr,
|
def binop_reduce(name, output_size, output_type, src_type, prereduce_expr,
|
||||||
reduce_expr, final_expr):
|
reduce_expr, final_expr):
|
||||||
@@ -455,13 +462,13 @@ def binop_reduce(name, output_size, output_type, src_type, prereduce_expr,
|
|||||||
src2 = prereduce("src0.z", "src1.z")
|
src2 = prereduce("src0.z", "src1.z")
|
||||||
src3 = prereduce("src0.w", "src1.w")
|
src3 = prereduce("src0.w", "src1.w")
|
||||||
opcode(name + "2", output_size, output_type,
|
opcode(name + "2", output_size, output_type,
|
||||||
[2, 2], [src_type, src_type], commutative,
|
[2, 2], [src_type, src_type], False, commutative,
|
||||||
final(reduce_(src0, src1)))
|
final(reduce_(src0, src1)))
|
||||||
opcode(name + "3", output_size, output_type,
|
opcode(name + "3", output_size, output_type,
|
||||||
[3, 3], [src_type, src_type], commutative,
|
[3, 3], [src_type, src_type], False, commutative,
|
||||||
final(reduce_(reduce_(src0, src1), src2)))
|
final(reduce_(reduce_(src0, src1), src2)))
|
||||||
opcode(name + "4", output_size, output_type,
|
opcode(name + "4", output_size, output_type,
|
||||||
[4, 4], [src_type, src_type], commutative,
|
[4, 4], [src_type, src_type], False, commutative,
|
||||||
final(reduce_(reduce_(src0, src1), reduce_(src2, src3))))
|
final(reduce_(reduce_(src0, src1), reduce_(src2, src3))))
|
||||||
|
|
||||||
binop("fadd", tfloat, commutative + associative, "src0 + src1")
|
binop("fadd", tfloat, commutative + associative, "src0 + src1")
|
||||||
@@ -657,9 +664,12 @@ binop("sne", tfloat32, commutative, "(src0 != src1) ? 1.0f : 0.0f") # Set on Not
|
|||||||
# SPIRV shifts are undefined for shift-operands >= bitsize,
|
# SPIRV shifts are undefined for shift-operands >= bitsize,
|
||||||
# but SM5 shifts are defined to use the least significant bits, only
|
# but SM5 shifts are defined to use the least significant bits, only
|
||||||
# The NIR definition is according to the SM5 specification.
|
# The NIR definition is according to the SM5 specification.
|
||||||
opcode("ishl", 0, tint, [0, 0], [tint, tuint32], "", "src0 << (src1 & (sizeof(src0) * 8 - 1))")
|
opcode("ishl", 0, tint, [0, 0], [tint, tuint32], False, "",
|
||||||
opcode("ishr", 0, tint, [0, 0], [tint, tuint32], "", "src0 >> (src1 & (sizeof(src0) * 8 - 1))")
|
"src0 << (src1 & (sizeof(src0) * 8 - 1))")
|
||||||
opcode("ushr", 0, tuint, [0, 0], [tuint, tuint32], "", "src0 >> (src1 & (sizeof(src0) * 8 - 1))")
|
opcode("ishr", 0, tint, [0, 0], [tint, tuint32], False, "",
|
||||||
|
"src0 >> (src1 & (sizeof(src0) * 8 - 1))")
|
||||||
|
opcode("ushr", 0, tuint, [0, 0], [tuint, tuint32], False, "",
|
||||||
|
"src0 >> (src1 & (sizeof(src0) * 8 - 1))")
|
||||||
|
|
||||||
# bitwise logic operators
|
# bitwise logic operators
|
||||||
#
|
#
|
||||||
@@ -690,9 +700,9 @@ binop_reduce("fdot", 1, tfloat, tfloat, "{src0} * {src1}", "{src0} + {src1}",
|
|||||||
binop_reduce("fdot_replicated", 4, tfloat, tfloat,
|
binop_reduce("fdot_replicated", 4, tfloat, tfloat,
|
||||||
"{src0} * {src1}", "{src0} + {src1}", "{src}")
|
"{src0} * {src1}", "{src0} + {src1}", "{src}")
|
||||||
|
|
||||||
opcode("fdph", 1, tfloat, [3, 4], [tfloat, tfloat], "",
|
opcode("fdph", 1, tfloat, [3, 4], [tfloat, tfloat], False, "",
|
||||||
"src0.x * src1.x + src0.y * src1.y + src0.z * src1.z + src1.w")
|
"src0.x * src1.x + src0.y * src1.y + src0.z * src1.z + src1.w")
|
||||||
opcode("fdph_replicated", 4, tfloat, [3, 4], [tfloat, tfloat], "",
|
opcode("fdph_replicated", 4, tfloat, [3, 4], [tfloat, tfloat], False, "",
|
||||||
"src0.x * src1.x + src0.y * src1.y + src0.z * src1.z + src1.w")
|
"src0.x * src1.x + src0.y * src1.y + src0.z * src1.z + src1.w")
|
||||||
|
|
||||||
binop("fmin", tfloat, "", "fminf(src0, src1)")
|
binop("fmin", tfloat, "", "fminf(src0, src1)")
|
||||||
@@ -769,7 +779,7 @@ else
|
|||||||
dst = ((1u << bits) - 1) << offset;
|
dst = ((1u << bits) - 1) << offset;
|
||||||
""")
|
""")
|
||||||
|
|
||||||
opcode("ldexp", 0, tfloat, [0, 0], [tfloat, tint32], "", """
|
opcode("ldexp", 0, tfloat, [0, 0], [tfloat, tint32], False, "", """
|
||||||
dst = (bit_size == 64) ? ldexp(src0, src1) : ldexpf(src0, src1);
|
dst = (bit_size == 64) ? ldexp(src0, src1) : ldexpf(src0, src1);
|
||||||
/* flush denormals to zero. */
|
/* flush denormals to zero. */
|
||||||
if (!isnormal(dst))
|
if (!isnormal(dst))
|
||||||
@@ -793,11 +803,11 @@ binop("extract_i16", tint, "", "(int16_t)(src0 >> (src1 * 16))")
|
|||||||
|
|
||||||
|
|
||||||
def triop(name, ty, const_expr):
|
def triop(name, ty, const_expr):
|
||||||
opcode(name, 0, ty, [0, 0, 0], [ty, ty, ty], "", const_expr)
|
opcode(name, 0, ty, [0, 0, 0], [ty, ty, ty], False, "", const_expr)
|
||||||
def triop_horiz(name, output_size, src1_size, src2_size, src3_size, const_expr):
|
def triop_horiz(name, output_size, src1_size, src2_size, src3_size, const_expr):
|
||||||
opcode(name, output_size, tuint,
|
opcode(name, output_size, tuint,
|
||||||
[src1_size, src2_size, src3_size],
|
[src1_size, src2_size, src3_size],
|
||||||
[tuint, tuint, tuint], "", const_expr)
|
[tuint, tuint, tuint], False, "", const_expr)
|
||||||
|
|
||||||
triop("ffma", tfloat, "src0 * src1 + src2")
|
triop("ffma", tfloat, "src0 * src1 + src2")
|
||||||
|
|
||||||
@@ -826,9 +836,9 @@ triop("imed3", tint, "MAX2(MIN2(MAX2(src0, src1), src2), MIN2(src0, src1))")
|
|||||||
triop("umed3", tuint, "MAX2(MIN2(MAX2(src0, src1), src2), MIN2(src0, src1))")
|
triop("umed3", tuint, "MAX2(MIN2(MAX2(src0, src1), src2), MIN2(src0, src1))")
|
||||||
|
|
||||||
opcode("bcsel", 0, tuint, [0, 0, 0],
|
opcode("bcsel", 0, tuint, [0, 0, 0],
|
||||||
[tbool1, tuint, tuint], "", "src0 ? src1 : src2")
|
[tbool1, tuint, tuint], False, "", "src0 ? src1 : src2")
|
||||||
opcode("b32csel", 0, tuint, [0, 0, 0],
|
opcode("b32csel", 0, tuint, [0, 0, 0],
|
||||||
[tbool32, tuint, tuint], "", "src0 ? src1 : src2")
|
[tbool32, tuint, tuint], False, "", "src0 ? src1 : src2")
|
||||||
|
|
||||||
# SM5 bfi assembly
|
# SM5 bfi assembly
|
||||||
triop("bfi", tuint32, """
|
triop("bfi", tuint32, """
|
||||||
@@ -847,7 +857,7 @@ if (mask == 0) {
|
|||||||
|
|
||||||
# SM5 ubfe/ibfe assembly
|
# SM5 ubfe/ibfe assembly
|
||||||
opcode("ubfe", 0, tuint32,
|
opcode("ubfe", 0, tuint32,
|
||||||
[0, 0, 0], [tuint32, tint32, tint32], "", """
|
[0, 0, 0], [tuint32, tint32, tint32], False, "", """
|
||||||
unsigned base = src0;
|
unsigned base = src0;
|
||||||
int offset = src1, bits = src2;
|
int offset = src1, bits = src2;
|
||||||
if (bits == 0) {
|
if (bits == 0) {
|
||||||
@@ -861,7 +871,7 @@ if (bits == 0) {
|
|||||||
}
|
}
|
||||||
""")
|
""")
|
||||||
opcode("ibfe", 0, tint32,
|
opcode("ibfe", 0, tint32,
|
||||||
[0, 0, 0], [tint32, tint32, tint32], "", """
|
[0, 0, 0], [tint32, tint32, tint32], False, "", """
|
||||||
int base = src0;
|
int base = src0;
|
||||||
int offset = src1, bits = src2;
|
int offset = src1, bits = src2;
|
||||||
if (bits == 0) {
|
if (bits == 0) {
|
||||||
@@ -877,7 +887,7 @@ if (bits == 0) {
|
|||||||
|
|
||||||
# GLSL bitfieldExtract()
|
# GLSL bitfieldExtract()
|
||||||
opcode("ubitfield_extract", 0, tuint32,
|
opcode("ubitfield_extract", 0, tuint32,
|
||||||
[0, 0, 0], [tuint32, tint32, tint32], "", """
|
[0, 0, 0], [tuint32, tint32, tint32], False, "", """
|
||||||
unsigned base = src0;
|
unsigned base = src0;
|
||||||
int offset = src1, bits = src2;
|
int offset = src1, bits = src2;
|
||||||
if (bits == 0) {
|
if (bits == 0) {
|
||||||
@@ -889,7 +899,7 @@ if (bits == 0) {
|
|||||||
}
|
}
|
||||||
""")
|
""")
|
||||||
opcode("ibitfield_extract", 0, tint32,
|
opcode("ibitfield_extract", 0, tint32,
|
||||||
[0, 0, 0], [tint32, tint32, tint32], "", """
|
[0, 0, 0], [tint32, tint32, tint32], False, "", """
|
||||||
int base = src0;
|
int base = src0;
|
||||||
int offset = src1, bits = src2;
|
int offset = src1, bits = src2;
|
||||||
if (bits == 0) {
|
if (bits == 0) {
|
||||||
@@ -914,10 +924,10 @@ def quadop_horiz(name, output_size, src1_size, src2_size, src3_size,
|
|||||||
opcode(name, output_size, tuint,
|
opcode(name, output_size, tuint,
|
||||||
[src1_size, src2_size, src3_size, src4_size],
|
[src1_size, src2_size, src3_size, src4_size],
|
||||||
[tuint, tuint, tuint, tuint],
|
[tuint, tuint, tuint, tuint],
|
||||||
"", const_expr)
|
False, "", const_expr)
|
||||||
|
|
||||||
opcode("bitfield_insert", 0, tuint32, [0, 0, 0, 0],
|
opcode("bitfield_insert", 0, tuint32, [0, 0, 0, 0],
|
||||||
[tuint32, tuint32, tint32, tint32], "", """
|
[tuint32, tuint32, tint32, tint32], False, "", """
|
||||||
unsigned base = src0, insert = src1;
|
unsigned base = src0, insert = src1;
|
||||||
int offset = src2, bits = src3;
|
int offset = src2, bits = src3;
|
||||||
if (bits == 0) {
|
if (bits == 0) {
|
||||||
|
@@ -117,6 +117,7 @@ const nir_op_info nir_op_infos[nir_num_opcodes] = {
|
|||||||
.input_types = {
|
.input_types = {
|
||||||
${ ", ".join("nir_type_" + type for type in opcode.input_types) }
|
${ ", ".join("nir_type_" + type for type in opcode.input_types) }
|
||||||
},
|
},
|
||||||
|
.is_conversion = ${"true" if opcode.is_conversion else "false"},
|
||||||
.algebraic_properties =
|
.algebraic_properties =
|
||||||
${ "0" if opcode.algebraic_properties == "" else " | ".join(
|
${ "0" if opcode.algebraic_properties == "" else " | ".join(
|
||||||
"NIR_OP_IS_" + prop.upper() for prop in
|
"NIR_OP_IS_" + prop.upper() for prop in
|
||||||
|
Reference in New Issue
Block a user