nir: Add more modulus and remainder opcodes

SPIR-V makes a distinction between "modulus" and "remainder" for both
floating-point and signed integer variants.  The difference is primarily
one of which source they take their sign from.  The "remainder" opcode for
integers is equivalent to the C/C++ "%" operation while the "modulus"
opcode is more mathematically correct (at least for an unsigned divisor).
This commit adds corresponding opcodes to NIR.
This commit is contained in:
Jason Ekstrand
2016-01-13 15:05:39 -08:00
parent 0079523a0d
commit cac99fffdb
2 changed files with 16 additions and 1 deletions
+15 -1
View File
@@ -369,9 +369,23 @@ binop_convert("uadd_carry", tuint, tuint, commutative, "src0 + src1 < src0")
binop_convert("usub_borrow", tuint, tuint, "", "src0 < src1")
binop("fmod", tfloat, "", "src0 - src1 * floorf(src0 / src1)")
binop("umod", tuint, "", "src1 == 0 ? 0 : src0 % src1")
# For signed integers, there are several different possible definitions of
# "modulus" or "remainder". We follow the conventions used by LLVM and
# SPIR-V. The irem opcode implements the standard C/C++ signed "%"
# operation while the imod opcode implements the more mathematical
# "modulus" operation. For details on the difference, see
#
# http://mathforum.org/library/drmath/view/52343.html
binop("irem", tint, "", "src1 == 0 ? 0 : src0 % src1")
binop("imod", tint, "",
"src1 == 0 ? 0 : ((src0 % src1 == 0 || (src0 >= 0) == (src1 >= 0)) ?"
" src0 % src1 : src0 % src1 + src1)")
binop("fmod", tfloat, "", "src0 - src1 * floorf(src0 / src1)")
binop("frem", tfloat, "", "src0 - src1 * truncf(src0 / src1)")
#
# Comparisons
#
+1
View File
@@ -226,6 +226,7 @@ optimizations = [
# Misc. lowering
(('fmod', a, b), ('fsub', a, ('fmul', b, ('ffloor', ('fdiv', a, b)))), 'options->lower_fmod'),
(('frem', a, b), ('fsub', a, ('fmul', b, ('ftrunc', ('fdiv', a, b)))), 'options->lower_fmod'),
(('bitfield_insert', a, b, c, d), ('bfi', ('bfm', d, c), b, a), 'options->lower_bitfield_insert'),
(('uadd_carry', a, b), ('b2i', ('ult', ('iadd', a, b), a)), 'options->lower_uadd_carry'),
(('usub_borrow', a, b), ('b2i', ('ult', a, b)), 'options->lower_usub_borrow'),