summaryrefslogtreecommitdiff
path: root/util/bytecoderules.dat
diff options
context:
space:
mode:
Diffstat (limited to 'util/bytecoderules.dat')
-rw-r--r--util/bytecoderules.dat513
1 files changed, 513 insertions, 0 deletions
diff --git a/util/bytecoderules.dat b/util/bytecoderules.dat
new file mode 100644
index 0000000..6584c54
--- /dev/null
+++ b/util/bytecoderules.dat
@@ -0,0 +1,513 @@
+# This documents all the optimizations that are done to bytecode
+# by fparser.cc directly while parsing the input function
+# (excluding powi).
+
+# identifiers: lowercase=cImmeds, uppercase=opcodes
+# [bracketed expression in condition]: constraints to input immeds or opcodes
+# [bracketed expression in replacement]: function that produces an immed
+# {braceted expression in replacement}: function that produces an opcode
+
+#
+# The comment tag "#TEST pathlet" indicates the test(s) that apply
+# to this particular rule. Note that the tests only test that this
+# rule does not _break_ anything (they try to invoke the rule),
+# but they don't test whether the rule is actually applied
+# and that the rule has the intended effect.
+#
+
+#y [isEvenInteger(y)&&!isEvenInteger(x*y)] cExp x cPow -> cAbs [y*x] cExp
+#y [isEvenInteger(y)&&!isEvenInteger(x*y)] cExp2 x cPow -> cAbs [y*x] cExp2
+# ^ y cExp never occurs (already optimized to literal)
+IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) y [isEvenInteger(y)&&!isEvenInteger(x*y)] cPow x cPow -> cAbs [y*x] cPow #TEST 10/absyxpow_neg, 10/absyxpow_pos
+IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) cSqr x [!isEvenInteger(x+x)] cPow -> cAbs [x+x] cPow
+IF(FP_FLOAT_VERSION) cSqr cSqrt -> cAbs # TEST 10/sqrsqrt
+#IF(FP_FLOAT_VERSION) cSqr cRSqrt -> cAbs cInv
+
+ # (x^y)^1.5 is unacceptable,
+ # for y might be 2, resulting in x^3
+ # f(-2) = 8
+ # f'(-2) = -8
+ # (x^y)^5 is okay
+ # for y might be 1.2, resulting in x^6
+ # f(-2) = nan
+ # f'(-2) = 64
+ # (x^y)^2 is okay,
+ # for y might be 1.5, resulting in x^3
+ # f(-2) = nan <- ok because of this
+ # f'(-2) = -8
+ #
+#y [!isInteger(y)] cExp x [isInteger(x)] cPow -> [y*x] cExp
+#y [!isInteger(y)] cExp2 x [isInteger(x)] cPow -> [y*x] cExp2
+# ^ y cExp never occurs (already optimized to literal)
+IF(FP_FLOAT_VERSION) y [!isInteger(y)] cPow x [isInteger(x)] cPow -> [y*x] cPow # TEST 10/ypowxpow
+IF(FP_FLOAT_VERSION) cExp x [isInteger(x)] cPow -> [x] cMul cExp # TEST 10/expxpow
+IF(FP_FLOAT_VERSION) cExp2 x [isInteger(x)] cPow -> [x] cMul cExp2 # TEST 10/exp2xpow
+IF(FP_FLOAT_VERSION) cPow x [isInteger(x)] cPow -> [x] cMul cPow # TEST 10/powxpow
+IF(FP_FLOAT_VERSION) cSqr x cPow -> [x+x] cPow #TEST 10/sqrxpow, 10/sqrxpow_nonint
+
+# This rule does not speed up evaluation at all, but
+# it greatly simplifies the optimization rule set, when
+# we don't need to check for sequences of an immed and cSub.
+x cSub -> [-x] cAdd # TEST 10/immsub
+
+###### REMOVING IDLE OPERATIONS :
+
+x [x==Value_t(1)] cMul -> # TEST 10/mul1
+x [x==Value_t(1)] cDiv -> # TEST 10/div1
+x [x==Value_t()] cAdd -> # TEST 10/add0
+x [x==Value_t()] cSub -> # TEST 10/sub0
+cDup cMin -> # TEST 10/dupminmax
+cDup cMax -> # TEST 10/dupminmax
+cNeg cNeg -> # TEST 10/negneg
+IF(FP_FLOAT_VERSION) cInv cInv -> # TEST 10/invinv
+IF(FP_COMPLEX_VERSION) cConj cConj ->
+
+B [B==A] cDup A [IsVarOpcode(A)] cMin -> B cDup # TEST 10/dupminmax2
+B [B==A] cDup A [IsVarOpcode(A)] cMax -> B cDup # TEST 10/dupminmax2
+B [B==A] cMin A [IsVarOpcode(A)] cMin -> B cMin # TEST 10/dupminmax3
+B [B==A] cMax A [IsVarOpcode(A)] cMax -> B cMax # TEST 10/dupminmax3
+
+y [y*x==Value_t(1)] cMul x cMul -> # TEST 10/mul1b
+
+###### OPERATIONS WHICH PRODUCE A CONSTANT VALUE:
+###### An expression is turned into a constant value
+###### by multiplying it with zero and adding the constant.
+
+cDup cSub -> [Value_t()] cMul # TEST 10/subxx
+cDup cRSub -> [Value_t()] cMul # TEST 10/subxx
+cDup cDiv -> [Value_t()] cMul [Value_t(1)] cAdd # TEST 10/divxx
+
+IF(FP_COMPLEX_VERSION) cReal cImag -> [Value_t()] cMul
+IF(FP_COMPLEX_VERSION) cAbs cImag -> [Value_t()] cMul
+
+IF(FP_FLOAT_VERSION) x [x==Value_t()] cPow -> [Value_t()] cMul [Value_t(1)] cAdd
+IF(FP_FLOAT_VERSION) cSinCos cHypot -> [Value_t()] cMul [Value_t(1)] cAdd # TEST 99/59
+
+# Multiplications by zero: Undo as many operands as possible by peeling.
+# Some of these optimimizations can be disabled due to law of diminishing returns.
+A [IsVarOpcode(A)] x [x==Value_t()] cMul -> [x] # TEST 10/mul_zero VERIFY
+ A [IsUnaryOpcode(A)&&!HasInvalidRangesOpcode(A)] x [x==Value_t()] cMul -> [x] cMul # TEST 10/mul_zero VERIFY
+B [IsVarOpcode(B)] A [IsBinaryOpcode(A)&&!HasInvalidRangesOpcode(A)] x [x==Value_t()] cMul -> [x] cMul # TEST 10/mul_zero VERIFY
+B [IsUnaryOpcode(B)&&!HasInvalidRangesOpcode(B)] A [IsBinaryOpcode(A)&&!HasInvalidRangesOpcode(A)] x [x==Value_t()] cMul -> A [x] cMul # TEST 10/mul_zero VERIFY
+y A [IsBinaryOpcode(A)&&!HasInvalidRangesOpcode(A)] x [x==Value_t()] cMul -> [x] cMul # TEST 10/mul_zero VERIFY
+A [IsVarOpcode(A)] cMul x [x==Value_t()] cMul -> [x] cMul # TEST 10/mul_zero VERIFY
+C [IsVarOpcode(C)] B [IsBinaryOpcode(B)&&!HasInvalidRangesOpcode(B)] A[IsBinaryOpcode(A)&&!HasInvalidRangesOpcode(A)] x [x==Value_t()] cMul -> A [x] cMul # TEST 10/mul_zero VERIFY
+C [IsUnaryOpcode(C)&&!HasInvalidRangesOpcode(C)] B [IsBinaryOpcode(B)&&!HasInvalidRangesOpcode(B)] A[IsBinaryOpcode(A)&&!HasInvalidRangesOpcode(A)] x [x==Value_t()] cMul -> B A [x] cMul # TEST 10/mul_zero VERIFY
+y B [IsBinaryOpcode(B)&&!HasInvalidRangesOpcode(B)] A[IsBinaryOpcode(A)&&!HasInvalidRangesOpcode(A)] x [x==Value_t()] cMul -> A [x] cMul # TEST 10/mul_zero VERIFY
+
+###### INLINE EXPANSION OF BASIC OPERATORS :
+
+x cNeg -> [-x] # TEST 10/neg
+x [x!=Value_t()] cInv -> [Value_t(1)/x]
+y x cMul -> [y*x] # TEST 10/mul
+y x [x!=Value_t()] cDiv -> [y/x] # TEST 10/div
+y x [x!=Value_t()] cMod -> [fp_mod(y,x)] # TEST 10/mod
+y x cAdd -> [y+x] # TEST 10/add
+y x cSub -> [y-x] # TEST 10/sub
+x cNot -> [fp_not(x)] # TEST 10/not
+#y [y!=Value_t()] x cRDiv -> [x/y]
+#y x cRSub -> [x-y]
+
+y x cLess -> [fp_less(y,x)] # TEST 10/cmplt
+y x cLessOrEq -> [fp_lessOrEq(y,x)] # TEST 10/cmple
+y x cGreater -> [fp_less(x,y)] # TEST 10/cmpgt
+y x cGreaterOrEq -> [fp_lessOrEq(x,y)] # TEST 10/cmpge
+y x cEqual -> [fp_equal(y,x)] # TEST 10/cmpeq
+y x cNEqual -> [fp_nequal(y,x)] # TEST 10/cmpne
+y x cAnd -> [fp_and(x,y)] # TEST 10/and
+y x cOr -> [fp_or(x,y)] # TEST 10/or
+#y x cAbsAnd -> [fp_absAnd(x,y)]
+#y x cAbsOr -> [fp_absOr(x,y)]
+
+cNeg x cMul -> [-x] cMul # TEST 10/negmul
+x cMul cNeg -> [-x] cMul # TEST 10/mulneg
+x [x==Value_t(-1)] cMul -> cNeg # TEST 10/mulminus1
+cNeg x [x!=Value_t()] cDiv -> [-x] cDiv # TEST 10/negdiv
+
+y cAdd x cAdd -> [y+x] cAdd # TEST 11/42
+y cMul x cMul -> [y*x] cMul # TEST 11/43
+
+###### INLINE EXPANSION OF BASIC FUNCTIONS :
+
+x cAbs -> [fp_abs(x)] # TEST 10/abs
+IF(FP_FLOAT_VERSION) x cDeg -> [RadiansToDegrees(x)] # TEST 10/deg
+IF(FP_FLOAT_VERSION) x cRad -> [DegreesToRadians(x)] # TEST 10/rad
+IF(FP_FLOAT_VERSION) x cCeil -> [fp_ceil(x)] # TEST 10/ceil*
+IF(FP_FLOAT_VERSION) x cFloor -> [fp_floor(x)] # TEST 10/floor*
+IF(FP_FLOAT_VERSION) x cInt -> [fp_int(x)] # TEST 10/int
+IF(FP_FLOAT_VERSION) x cTrunc -> [fp_trunc(x)] # TEST 10/runc*
+IF(FP_FLOAT_VERSION) y x cAtan2 -> [fp_atan2(y,x)] # TEST 10/atan2*
+y x cMin -> [fp_min(x,y)] # TEST 10/min
+y x cMax -> [fp_max(x,y)] # TEST 10/max
+
+##### REAL VERSIONS:
+
+IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x [x>=Value_t(1)] cAcosh -> [fp_acosh(x)] # TEST 10/acosh*
+IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x cAsinh -> [fp_asinh(x)] # TEST 10/asinh*
+IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x [fp_abs(x)< Value_t(1)] cAtanh -> [fp_atanh(x)] # TEST 10/atanh*
+IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x [fp_abs(x)<=Value_t(1)] cAcos -> [fp_acos(x)] # TEST 10/acos*
+IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x [fp_abs(x)<=Value_t(1)] cAsin -> [fp_asin(x)] # TEST 10/asin*
+IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x cAtan -> [fp_atan(x)] # TEST 10/atan*
+IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x cCbrt -> [fp_cbrt(x)] # TEST 10/cbrt*
+IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x cCos -> [fp_cos(x)] # TEST 10/cos*
+IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x cCosh -> [fp_cosh(x)] # TEST 10/cosh*
+IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x cExp -> [fp_exp(x)] # TEST 10/exp*
+IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x cExp2 -> [fp_exp2(x)] # TEST 10/exp2*
+IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x [x> Value_t(0)] cLog -> [fp_log(x)] # TEST 10/log*
+IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x [x> Value_t(0)] cLog10 -> [fp_log10(x)] # TEST 10/log10*
+IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x [x> Value_t(0)] cLog2 -> [fp_log2(x)] # TEST 10/log2*
+IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x cSin -> [fp_sin(x)] # TEST 10/sin*
+IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x cSinh -> [fp_sinh(x)] # TEST 10/sinh*
+IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x [x>=Value_t(0)] cSqrt -> [fp_sqrt(x)] # TEST 10/sqr*
+#IF(FP_FLOAT_VERSION) x [x> Value_t()] cRSqrt -> [Value_t(1)/fp_sqrt(x)]
+IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x cTan -> [fp_tan(x)] # TEST 10/tan*
+IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x cTanh -> [fp_tanh(x)] # TEST 10/tanh*
+IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) y [ y!=Value_t(0) || x>=Value_t(0)] x cPow -> [fp_pow(y,x)] # TEST 10/pow*
+
+##### COMPLEX VERSIONS:
+
+IF(FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x cAcosh -> [fp_acosh(x)]
+IF(FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x cAsinh -> [fp_asinh(x)]
+IF(FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x [Value_t(fp_abs(x.real()),x.imag())!=Value_t(1,0)] cAtanh -> [fp_atanh(x)]
+IF(FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x cAcos -> [fp_acos(x)]
+IF(FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x cAsin -> [fp_asin(x)]
+IF(FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x [Value_t(x.real(),fp_abs(x.imag()))!=Value_t(0,1)] cAtan -> [fp_atan(x)]
+IF(FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x cCbrt -> [fp_cbrt(x)] # TEST 10/cbrt*
+IF(FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x cCos -> [fp_cos(x)] # TEST 10/cos*
+IF(FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x cCosh -> [fp_cosh(x)] # TEST 10/cosh*
+IF(FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x cExp -> [fp_exp(x)] # TEST 10/exp*
+IF(FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x cExp2 -> [fp_exp2(x)] # TEST 10/exp2*
+IF(FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x [x!=Value_t(0)] cLog -> [fp_log(x)]
+IF(FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x [x!=Value_t(0)] cLog10 -> [fp_log10(x)]
+IF(FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x [x!=Value_t(0)] cLog2 -> [fp_log2(x)]
+IF(FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x cSin -> [fp_sin(x)] # TEST 10/sin*
+IF(FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x cSinh -> [fp_sinh(x)] # TEST 10/sinh*
+IF(FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x cSqrt -> [fp_sqrt(x)]
+#IF(FP_FLOAT_VERSION) x [x> Value_t(0)] cRSqrt -> [Value_t(1)/fp_sqrt(x)]
+IF(FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x cTan -> [fp_tan(x)] # TEST 10/tan*
+IF(FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x cTanh -> [fp_tanh(x)] # TEST 10/tanh*
+IF(FP_COMPLEX_VERSION && FP_FLOAT_VERSION) y x cPow -> [fp_pow(y,x)]
+IF(FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x cArg -> [fp_arg(x)]
+IF(FP_COMPLEX_VERSION) x cReal -> [fp_real(x)]
+IF(FP_COMPLEX_VERSION) x cImag -> [fp_imag(x)]
+IF(FP_COMPLEX_VERSION) x cConj -> [fp_conj(x)]
+IF(FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x y cPolar -> [fp_polar(x,y)]
+
+###### SIMPLIFYING SOME OPCODE SEQUENCES :
+
+x [x==Value_t(2)] cMul -> cDup cAdd # TEST 10/mul2
+cNeg cAdd -> cSub # TEST 10/negadd
+cNeg cSub -> cAdd # TEST 10/negsub
+cNeg cAbs -> cAbs # TEST 10/negabs
+cDup cMul -> cSqr # TEST 10/sqr_xx
+cNeg cSqr -> cSqr # TEST 10/negsqr
+cAbs cSqr -> cSqr # TEST 10/abssqr
+
+IF(FP_FLOAT_VERSION) cSqrt cInv -> cRSqrt # TEST 10/rsqrt
+IF(FP_FLOAT_VERSION) x [x==fp_const_rad_to_deg<Value_t>()] cMul -> cDeg #TEST 10/deg
+IF(FP_FLOAT_VERSION) x [x==fp_const_deg_to_rad<Value_t>()] cMul -> cRad #TEST 10/rad
+IF(FP_FLOAT_VERSION) cDeg x cMul -> [RadiansToDegrees(x)] cMul # TEST 10/degxmul
+IF(FP_FLOAT_VERSION) cRad x cMul -> [DegreesToRadians(x)] cMul # TEST 10/radxmul VERIFY
+IF(FP_FLOAT_VERSION) x cMul cRad -> [DegreesToRadians(x)] cMul # TEST 10/xmulrad
+
+IF(FP_FLOAT_VERSION) cInv cDiv -> cMul # TEST 10/invdiv
+IF(FP_FLOAT_VERSION) cInv cMul -> cDiv # TEST 10/invmul (float-only, because: y*(1/x) vs y/x)
+
+cLess cNot -> cGreaterOrEq # TEST 10/not_lt
+cLessOrEq cNot -> cGreater # TEST 10/not_le
+cGreater cNot -> cLessOrEq # TEST 10/not_gt
+cGreaterOrEq cNot -> cLess # TEST 10/not_ge
+cEqual cNot -> cNEqual # TEST 10/not_eq
+cNEqual cNot -> cEqual # TEST 10/not_ne
+
+cDup cOr -> cNotNot # TEST 99/3
+cDup cAnd -> cNotNot # TEST 99/3
+
+IF(!FP_COMPLEX_VERSION) cNeg cNot -> cNot # TEST 10/negnot
+IF(!FP_COMPLEX_VERSION) cAbs cNot -> cNot # TEST 10/absnot
+
+cNot cNot -> cNotNot # TEST 10/notnot
+cNotNot cNot -> cNot # TEST 10/notnotnot
+cAbsNotNot cNot -> cAbsNot # TEST 10/absnotnotnot
+cNot cNotNot -> cNot # TEST 10/notnotnot2
+# ^ Impossible as it seems, it is triggered by (!x & !x) -> !!(!x)
+
+IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) cAbs cCos -> cCos # TEST 10/abscos
+IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) cAbs cCosh -> cCosh # TEST 10/abscosh
+
+IF(FP_FLOAT_VERSION) cNeg cCos -> cCos # TEST 10/negcos
+IF(FP_FLOAT_VERSION) cNeg cCosh -> cCosh # TEST 10/negcosh
+IF(FP_FLOAT_VERSION) cNeg cSin -> cSin cNeg # TEST 10/negsin
+IF(FP_FLOAT_VERSION) cNeg cSinh -> cSinh cNeg # TEST 10/negsinh
+IF(FP_FLOAT_VERSION) cNeg cTan -> cTan cNeg # TEST 10/negtan
+IF(FP_FLOAT_VERSION) cNeg cTanh -> cTanh cNeg # TEST 10/negtanh
+IF(FP_FLOAT_VERSION) x cMul cSin cNeg -> [-x] cMul cSin # TEST 10/xmulsinneg
+IF(FP_FLOAT_VERSION) x cMul cSinh cNeg -> [-x] cMul cSinh # TEST 10/xmulsinhneg
+IF(FP_FLOAT_VERSION) x cMul cTan cNeg -> [-x] cMul cTan # TEST 10/xmultanneg
+IF(FP_FLOAT_VERSION) x cMul cTanh cNeg -> [-x] cMul cTanh # TEST 10/xmultanhneg
+
+IF(FP_FLOAT_VERSION) cSin cDiv -> cCsc cMul # TEST 10/invsincostan
+IF(FP_FLOAT_VERSION) cCos cDiv -> cSec cMul # TEST 10/invsincostan
+IF(FP_FLOAT_VERSION) cTan cDiv -> cCot cMul # TEST 10/invsincostan
+IF(FP_FLOAT_VERSION) cCsc cDiv -> cSin cMul # TEST 10/invsincostan
+IF(FP_FLOAT_VERSION) cSec cDiv -> cCos cMul # TEST 10/invsincostan
+IF(FP_FLOAT_VERSION) cCot cDiv -> cTan cMul # TEST 10/invsincostan
+IF(FP_FLOAT_VERSION) cSin cInv -> cCsc # TEST 10/invsincostan
+IF(FP_FLOAT_VERSION) cCos cInv -> cSec # TEST 10/invsincostan
+IF(FP_FLOAT_VERSION) cTan cInv -> cCot # TEST 10/invsincostan
+IF(FP_FLOAT_VERSION) cCsc cInv -> cSin # TEST 10/invsincostan
+IF(FP_FLOAT_VERSION) cSec cInv -> cCos # TEST 10/invsincostan
+IF(FP_FLOAT_VERSION) cCot cInv -> cTan # TEST 10/invsincostan
+
+###################
+
+# rdiv(x,y)/z --> rdiv(x*z,y) (y/x/z = y/(x*z))
+IF(FP_FLOAT_VERSION) B [IsVarOpcode(B)] cRDiv A [IsVarOpcode(A)] cDiv -> A cMul B cRDiv #TEST 11/23
+IF(FP_FLOAT_VERSION) x cRDiv A [IsVarOpcode(A)] cDiv -> A cMul [x] cRDiv #TEST 11/24
+IF(FP_FLOAT_VERSION) x cRDiv A [IsVarOpcode(A)] cMul -> [DO_STACKPLUS1] A [x] cMul cRDiv #TEST 11/25
+x [x==Value_t(1)] cRDiv -> cInv
+
+# a/b/c = a/(b*c)
+IF(FP_FLOAT_VERSION) B [IsVarOpcode(B)] cDiv A [IsVarOpcode(A)] cDiv -> [DO_STACKPLUS1] B A cMul cDiv #TEST 11/26
+
+# a/b*c = a*b/c (increases chances of doing the div grouping if more divs come later)
+IF(FP_FLOAT_VERSION) B [IsVarOpcode(B)] cDiv A [IsVarOpcode(A)] cMul -> [DO_STACKPLUS1] A cMul B cDiv #TEST 11/27
+# The three rules below: same as above, but with immed instead of var A
+# (do only when there is an explicit optimization; otherwise we get an infinite loop)
+IF(FP_FLOAT_VERSION) y B [IsVarOpcode(B)] cDiv x cMul -> [y*x] B cDiv
+IF(FP_FLOAT_VERSION) y cMul B [IsVarOpcode(B)] cDiv x cMul -> [y*x] cMul B cDiv
+IF(FP_FLOAT_VERSION) cNeg B [IsVarOpcode(B)] cDiv x cMul -> [-x] cMul B cDiv #TEST 11/28
+
+IF(FP_FLOAT_VERSION) cRDiv A [IsVarOpcode(A)] cMul -> [DO_STACKPLUS1] A cMul cRDiv #TEST 11/29
+# The three rules below: same as above, but with immed instead of var A
+# (do only when there is an explicit optimization; otherwise we get an infinite loop)
+IF(FP_FLOAT_VERSION) y cRDiv x cMul -> [y*x] cRDiv #TEST 11/30
+IF(FP_FLOAT_VERSION) y cMul cRDiv x cMul -> [y*x] cMul cRDiv
+IF(FP_FLOAT_VERSION) cNeg cRDiv x cMul -> [-x] cMul cRDiv #TEST 11/31
+
+# These below are just Add/Sub analogies of the above rules.
+x cRSub A [IsVarOpcode(A)] cSub -> A cAdd [x] cRSub #TEST 11/32
+x cRSub A [IsVarOpcode(A)] cAdd -> [DO_STACKPLUS1] A [x] cAdd cRSub #TEST 11/33
+y B [IsVarOpcode(B)] cSub x cAdd -> [ y+x] B cSub
+y cAdd B [IsVarOpcode(B)] cSub x cAdd -> [ y+x] cAdd B cSub #TEST 11/34
+cNeg B [IsVarOpcode(B)] cSub x cAdd -> [-x] cAdd B cSub #TEST 11/35
+
+cRSub A [IsVarOpcode(A)] cAdd -> [DO_STACKPLUS1] A cAdd cRSub #TEST 11/32 (DUP)
+cRSub A [IsVarOpcode(A)] cSub -> [DO_STACKPLUS1] A cSub cRSub #TEST 11/33 (DUP)
+y cRSub x cAdd -> [ y+x] cRSub #TEST 11/36
+y cAdd cRSub x cAdd -> [ y+x] cAdd cRSub #TEST 11/37
+cNeg cRSub x cAdd -> [-x] cAdd cRSub
+
+A [IsNeverNegativeValueOpcode(A)] x [x==Value_t(0)] cLess -> A [x] cMul # TEST 10/lt0
+
+IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) cSqr cLog -> cAbs cLog cDup cAdd # TEST 10/sqrlog
+IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) cSqr cLog2 -> cAbs cLog2 cDup cAdd # TEST 10/sqrlog2
+IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) cSqr cLog10 -> cAbs cLog10 cDup cAdd # TEST 10/sqrlog10
+
+IF(FP_FLOAT_VERSION) y [(y*x)==fp_const_rad_to_deg<Value_t>()] cMul x cMul -> cDeg
+IF(FP_FLOAT_VERSION) y [(y*x)==fp_const_deg_to_rad<Value_t>()] cMul x cMul -> cRad
+
+cDup cAdd cDup cAdd -> [Value_t(4)] cMul # TEST 10/mul4
+cDup cAdd cMul cDup cAdd -> cMul [Value_t(4)] cMul # TEST 10/mul4
+
+cDup x cMul cAdd -> [x+Value_t(1)] cMul # TEST 10/dupxmuladd
+cDup x cPow cMul -> [x+Value_t(1)] cPow # TEST 10/dupxpowmul
+
+IF(FP_FLOAT_VERSION) cDup [x+x==Value_t(1)] cAdd x cMul -> # TEST 10/dupaddmulh
+ cDup cAdd x cMul -> [x+x] cMul # TEST 10/dupaddmul7
+IF(FP_FLOAT_VERSION) cDup [x+x==Value_t(1)] cAdd cMul x cMul -> cMul # TEST 10/dupaddmulmulh
+ cDup cAdd cMul x cMul -> cMul [x+x] cMul # TEST 10/dupaddmulmul7
+
+IF(FP_FLOAT_VERSION) y [(y/x)==fp_const_rad_to_deg<Value_t>()] cMul x [x!=Value_t(0)] cDiv -> cDeg
+IF(FP_FLOAT_VERSION) y [(y/x)==fp_const_deg_to_rad<Value_t>()] cMul x [x!=Value_t(0)] cDiv -> cRad
+IF(FP_FLOAT_VERSION) y cMul x [x!=Value_t(0)] cDiv -> [y/x] cMul
+
+IF(FP_FLOAT_VERSION) x [x!=Value_t(0)] cDiv -> [Value_t(1)/x] cMul # TEST 10/multodiv
+
+#IF(FP_FLOAT_VERSION) y cExp x cPow -> [y*x] cExp
+#IF(FP_FLOAT_VERSION) y cExp2 x cPow -> [y*x] cExp2
+# ^ y cExp never occurs (already optimized to literal)
+IF(FP_FLOAT_VERSION) y cPow x cPow -> [y*x] cPow # TEST 10/ypowxpow (maybe?)
+
+IF(FP_FLOAT_VERSION) x [x==Value_t(0.5)] cPow -> cSqrt # TEST 10/powhalf
+IF(FP_FLOAT_VERSION) x [x==Value_t(1)/Value_t(3)] cPow -> cCbrt # TEST 10/powthird
+IF(FP_FLOAT_VERSION) x [x==Value_t(1)/Value_t(-3)] cPow -> cCbrt cInv # TEST 10/powminusthird
+IF(FP_FLOAT_VERSION) x [x==Value_t(-0.5)] cPow -> cRSqrt # TEST 10/powminushalf
+IF(FP_FLOAT_VERSION) x [x==Value_t(-1)] cPow -> cInv # TEST 10/powminusone
+
+IF(FP_FLOAT_VERSION) A [IsNeverNegativeValueOpcode(A)] cSqrt cSqr -> A # TEST 10/sqrtsqr1, 10/sqrtsqr2
+# ^ Doable only if lhs > 0.
+IF(FP_FLOAT_VERSION) A [IsNeverNegativeValueOpcode(A)] cLog cExp -> A # TEST 10/logexp1, 10/logexp2
+IF(FP_FLOAT_VERSION) A [IsNeverNegativeValueOpcode(A)] cLog2 cExp2 -> A # TEST 10/log2exp1, 10/log2exp2
+# ^ Doable only if lhs > 0.
+IF(FP_FLOAT_VERSION) cExp cLog -> # TEST 10/explog
+IF(FP_FLOAT_VERSION) cExp2 cLog2 -> # TEST 12/exp2log2
+IF(FP_COMPLEX_VERSION && FP_FLOAT_VERSION) cAsin cSin ->
+IF(FP_COMPLEX_VERSION && FP_FLOAT_VERSION) cAcos cCos ->
+# ^ For real values, doable only if abs(x) <= 1
+#IF(FP_FLOAT_VERSION) cAtan cTan ->
+IF(FP_FLOAT_VERSION) cAsinh cSinh -> # TEST 10/asinhsinh
+#IF(FP_FLOAT_VERSION) cAcosh cCosh -> # TEST 10/acoshcosh
+# ^ Doable only if x >= 1
+IF(FP_COMPLEX_VERSION && FP_FLOAT_VERSION) cAtanh cTanh ->
+# ^ For real values, doable only if abs(x) < 1
+IF(FP_FLOAT_VERSION) cAtan2 cTan -> cDiv # TEST 10/atan2tan
+IF(FP_FLOAT_VERSION) cPow cInv -> cNeg cPow # TEST 10/powinv
+
+#IF(FP_FLOAT_VERSION) x [x<0] cPow cMul -> [-x] cPow cDiv
+
+cAbs x [x==Value_t(0)] cEqual -> [x] cEqual # TEST 10/abseq0
+cAbs x [x==Value_t(0)] cNEqual -> [x] cNEqual # TEST 10/absneq0
+cSqr x [x==Value_t(0)] cEqual -> [x] cEqual # TEST 10/sqreq0
+cSqr x [x==Value_t(0)] cNEqual -> [x] cNEqual # TEST 10/sqrneq0
+
+IF(!FP_COMPLEX_VERSION) y cAdd x A [IsComparisonOpcode(A)] -> [x-y] A # TEST 10/cmp_add
+IF(!FP_COMPLEX_VERSION) cNeg x A [IsComparisonOpcode(A)] -> [-x] {OppositeComparisonOpcode(A)} # TEST 10/cmp_neg
+IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) y [y>Value_t(0)] cMul x A [IsComparisonOpcode(A)] -> [x/y] A # TEST 10/cmp_mulpos
+IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) y [y<Value_t(0)] cMul x A [IsComparisonOpcode(A)] -> [x/y] {OppositeComparisonOpcode(A)} # TEST 10/cmp_mulneg
+IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) y [y>Value_t(0)] cPow [x>Value_t(0)] x A [IsComparisonOpcode(A)] -> [fp_pow(x,Value_t(1)/y)] A # TEST 10/cmp_powy_*
+IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) cSqr [x>Value_t(0)] x A [IsComparisonOpcode(A)] -> cAbs [fp_sqrt(x)] A # TEST 10/cmp_sqr, 10/cmp_sqr_neg
+IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) cExp [x>Value_t(0)] x A [IsComparisonOpcode(A)] -> [fp_log(x)] A # TEST 10/cmp_exp, 10/cmp_exp_neg
+IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) cExp2 [x>Value_t(0)] x A [IsComparisonOpcode(A)] -> [fp_log2(x)] A # TEST 10/cmp_exp2, 10/cmp_exp2_neg
+# ^ Always doable
+IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) B [IsNeverNegativeValueOpcode(B)] cLog x A [IsComparisonOpcode(A)] -> B [fp_exp(x)] A # TEST 10/cmp_log_*
+IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) B [IsNeverNegativeValueOpcode(B)] cLog2 x A [IsComparisonOpcode(A)] -> B [fp_exp2(x)] A # TEST 10/cmp_log2_*
+IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) B [IsNeverNegativeValueOpcode(B)] cLog10 x A [IsComparisonOpcode(A)] -> B [fp_pow(Value_t(10),x)] A # TEST 10/cmp_log10_*
+# ^ Doable only if lhs > 0.
+#IF(FP_FLOAT_VERSION) cAsin [fp_abs(x)<fp_const_pi<Value_t>()*Value_t(0.5)] x A [IsComparisonOpcode(A)] -> [fp_sin(x)] A # TEST 10/cmp_asin*
+#IF(FP_FLOAT_VERSION) cAcos [x>=Value_t(0)&&fp_abs(x)<fp_const_pi<Value_t>()] x A [IsComparisonOpcode(A)] -> [fp_cos(x)] {OppositeComparisonOpcode(A)} # TEST 10/cmp_acos*
+# ^ Doable only if abs(x) <= 1
+IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) cAtan [fp_abs(x)<fp_const_pi<Value_t>()*Value_t(0.5)] x A [IsComparisonOpcode(A)] -> [fp_tan(x)] A # TEST 10/cmp_atan*
+IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) cSinh x A [IsComparisonOpcode(A)] -> [fp_asinh(x)] A # TEST 10/cmp_sinh*
+IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) cTanh [fp_abs(x)<Value_t(1)] x A [IsComparisonOpcode(A)] -> [fp_atanh(x)] A # TEST 10/cmp_tanh*
+
+# (x+3)*4 -> x*4 + 12
+ y cAdd x cMul -> [x] cMul [y*x] cAdd #TEST 11/39
+A [IsVarOpcode(A)] y cMul cAdd x cMul -> [x] cMul A [y*x] cMul cAdd #TEST 11/40
+A [IsVarOpcode(A)] y cMul cSub x cMul -> [x] cMul A [y*x] cMul cSub #TEST 11/41
+
+IF(!FP_COMPLEX_VERSION) A [IsLogicalOpcode(A)] cAbsNot cNot -> A # TEST 10/absnot3
+IF(!FP_COMPLEX_VERSION) A [A!=cImmed] cAbsNot cNot -> A cAbsNotNot # TEST 10/absnot4
+IF(!FP_COMPLEX_VERSION) A [IsNeverNegativeValueOpcode(A)] cNot -> A cAbsNot # TEST 10/absnot2
+
+IF(!FP_COMPLEX_VERSION) A [IsNeverNegativeValueOpcode(A)] cAbs -> A # TEST 10/absneverneg
+IF(FP_FLOAT_VERSION) A [IsAlwaysIntegerOpcode(A)] cTrunc-> A # TEST 10/inttrunc
+IF(FP_FLOAT_VERSION) A [IsAlwaysIntegerOpcode(A)] cFloor-> A # TEST 10/intfloor
+IF(FP_FLOAT_VERSION) A [IsAlwaysIntegerOpcode(A)] cCeil -> A # TEST 10/intceil
+IF(FP_FLOAT_VERSION) A [IsAlwaysIntegerOpcode(A)] cInt -> A # TEST 10/intint
+
+#IF(FP_FLOAT_VERSION) x cMul cFloor cNeg -> [-x] cMul cCeil
+#IF(FP_FLOAT_VERSION) x cMul cCeil cNeg -> [-x] cMul cFloor
+IF(FP_FLOAT_VERSION) cNeg cFloor -> cCeil cNeg # TEST 10/negfloor, 10/floorneg
+IF(FP_FLOAT_VERSION) cNeg cCeil -> cFloor cNeg # TEST 10/negceil, 10/ceilneg
+
+IF(FP_FLOAT_VERSION) x cAdd cExp -> cExp [fp_exp(x)] cMul # TEST 10/addexp
+IF(FP_FLOAT_VERSION) x cAdd cExp2 -> cExp2 [fp_exp2(x)] cMul # TEST 10/addexp2
+
+IF(FP_FLOAT_VERSION) cPow cDiv -> cNeg cPow cMul # TEST 10/powdiv
+IF(FP_FLOAT_VERSION) cExp cDiv -> cNeg cExp cMul # TEST 10/expdiv
+IF(FP_FLOAT_VERSION) cExp2 cDiv -> cNeg cExp2 cMul # TEST 10/exp2div
+
+IF(!FP_FLOAT_VERSION) x [x==Value_t(0)] cEqual -> cNot # TEST 10/eq0
+IF(!FP_FLOAT_VERSION) x [x==Value_t(0)] cNEqual -> cNotNot # TEST 10/neq0
+IF(!FP_COMPLEX_VERSION && !FP_FLOAT_VERSION) cAbs x [x==Value_t(0)] cGreater -> cNotNot # TEST 10/gt0_abs
+IF(!FP_COMPLEX_VERSION && !FP_FLOAT_VERSION) cAbs x [x==Value_t(1)] cGreaterOrEq -> cNotNot # TEST 10/ge1_abs
+IF(!FP_COMPLEX_VERSION && !FP_FLOAT_VERSION) cAbs x [x==Value_t(1)] cLess -> cNot # TEST 10/gt1_abs
+IF(!FP_COMPLEX_VERSION && !FP_FLOAT_VERSION) cAbs x [x==Value_t(0)] cLessOrEq -> cNot # TEST 10/ge0_abs
+IF(!FP_COMPLEX_VERSION && !FP_FLOAT_VERSION) A [IsNeverNegativeValueOpcode(A)] x [x==Value_t(0)] cGreater -> A cNotNot # TEST 10/gt0_pos, 10/gt0_neg
+IF(!FP_COMPLEX_VERSION && !FP_FLOAT_VERSION) A [IsNeverNegativeValueOpcode(A)] x [x==Value_t(1)] cGreaterOrEq -> A cNotNot # TEST 10/ge1_pos, 10/ge1_neg
+IF(!FP_COMPLEX_VERSION && !FP_FLOAT_VERSION) A [IsNeverNegativeValueOpcode(A)] x [x==Value_t(1)] cLess -> A cNot # TEST 10/gt1_pos, 10/gt1_neg
+IF(!FP_COMPLEX_VERSION && !FP_FLOAT_VERSION) A [IsNeverNegativeValueOpcode(A)] x [x==Value_t(0)] cLessOrEq -> A cNot # TEST 10/ge0_pos, 10/ge0_neg
+IF(!FP_FLOAT_VERSION) A [IsLogicalOpcode(A)] x [x==Value_t(1)] cEqual -> A # TEST 10/eq1
+IF(!FP_FLOAT_VERSION) A [IsLogicalOpcode(A)] x [x==Value_t(1)] cNEqual -> A cNot # TEST 10/neq1
+IF(!FP_FLOAT_VERSION) x cAdd cNotNot -> [-x] cNEqual # TEST 10/xaddnotnot
+IF(!FP_FLOAT_VERSION) x cAdd cNot -> [-x] cEqual # TEST 10/xaddnot
+
+IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) cAbs x [x!=Value_t(0)] cLess -> [Value_t(0.5)/x] cMul cNot # TEST 10/absnzlt
+IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) cAbs x [x!=Value_t(0)] cGreaterOrEq -> [Value_t(0.5)/x] cMul cNotNot # TEST 10/absnzge
+
+IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x [x==Value_t(0.5)] cLess -> cAbsNot # TEST 10/lthalf
+IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x [x==Value_t(0.5)] cGreaterOrEq -> cAbsNotNot # TEST 10/gehalf
+IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x [x==Value_t(-0.5)] cGreater -> cNeg cAbsNot # TEST 10/gtminushalf
+IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x [x==Value_t(-0.5)] cLessOrEq -> cNeg cAbsNotNot # TEST 10/leminushalf
+
+IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) cAbs x [isEvenInteger(x)] cPow -> [x] cPow # TEST 10/absevenconstpow
+IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) cAbs cMul x [isEvenInteger(x)] cPow -> cMul [x] cPow # TEST 10/absmulevenconstpow
+
+IF(FP_FLOAT_VERSION) cAcosh cSinh -> [DO_STACKPLUS1] cSqr [Value_t(-1)] cAdd cSqrt # TEST 10/acoshsinh
+# sinh(x) = 0.5 * (exp(x) - exp(-x))
+# acosh(x) = log(x + sqrt(x*x - 1))
+# Thus,
+# sinh(acosh(x)) = 0.5 * (exp(log(x + sqrt(x*x - 1))) - exp(-log(x + sqrt(x*x - 1))))
+# sinh(acosh(x)) = 0.5 * ( ( (x + sqrt(x*x - 1))) - 1 / (x + sqrt(x*x - 1)) )
+# sinh(acosh(x)) = 0.5 * (x + sqrt(x*x - 1) - 1 / (x + sqrt(x*x - 1)))
+# sinh(acosh(x)) = 0.5*x + 0.5*sqrt(x*x - 1) - 0.5/(x + sqrt(x*x - 1))
+# Maxima gets a step further and says that:
+# sinh(acosh(x)) = sqrt(x-1)*sqrt(x+1)
+# Furthermore, Wikipedia gives us this:
+# sinh(acosh(x)) = sqrt(x*x-1) IF abs(x) > 1 or complex version
+
+IF(FP_FLOAT_VERSION) cAsinh cCosh -> [DO_STACKPLUS1] cSqr [Value_t(1)] cAdd cSqrt # TEST 10/asinhcosh
+# cosh(asinh(x)) = sqrt(x^2+1)
+
+# Hardcoded optimizations that are too complex or
+# impossible to convey using this rule file:
+IF(FP_FLOAT_VERSION) x cPow -> [DO_POWI]
+
+# x*x = x^2
+B [B==A] A [IsVarOpcode(A)] cMul -> B cSqr # TEST 10/sqr_xx
+
+# ...*x*x = ...*x^2
+B [B==A] cMul A [IsVarOpcode(A)] cMul -> B cSqr cMul # TEST 10/sqr_yxx
+
+# -x*x = -(x^2)
+B [B==A] cNeg A [IsVarOpcode(A)] cMul -> B cSqr cNeg # TEST 10/sqr_nxx
+
+# x*-x = -(x^2)
+cDup cNeg cMul -> cSqr cNeg # TEST 10/sqr_xnx
+
+# ...*-x*x = ...*-(x^2)
+B [B==A] cNeg cMul A [IsVarOpcode(A)] cMul -> B cSqr cMul cNeg # TEST 10/sqr_ynxx
+
+# ...*x*-x = ...*-(x^2)
+B [B==A] cMul A [IsVarOpcode(A)] cNeg cMul -> B cSqr cMul cNeg # TEST 10/sqr_yxnx
+
+B [B==A] A [IsVarOpcode(A) && mData->mByteCode.size() > 0] -> B cDup # TEST 10/xxdup
+D [D==B] C [C==A] B [IsVarOpcode(B) && mData->mByteCode.size() > 1] A [IsUnaryOpcode(A)] -> D C cDup # TEST 10/xxfdup
+D [D==B] C [C==A] cMul B [IsVarOpcode(B) && mData->mByteCode.size() > 1] A [IsUnaryOpcode(A)] cMul -> D C cSqr cMul # TEST 10/xxsqrdup
+
+IF(FP_FLOAT_VERSION) cExp2 -> [DO_STACKPLUS1] [fp_log(Value_t(2))] cMul cExp # TEST 02/exp2
+IF(FP_FLOAT_VERSION) cExp cLog2 -> [DO_STACKPLUS1] [fp_log2(fp_const_e<Value_t>())] cMul # TEST 10/explog2
+IF(FP_FLOAT_VERSION) cExp cLog10 -> [DO_STACKPLUS1] [fp_log10(fp_const_e<Value_t>())] cMul # TEST 10/explog10
+
+# expr0 expr1 cExp cMul cLog
+# -> expr0 cLog expr1 cAdd
+# could be done if expr1 is a var. Too special case. Not doing...
+# expr0 cLog expr1 cLog
+# -> expr0 expr1 cMul cLog
+# similar.
+
+IF(FP_FLOAT_VERSION) x [x>Value_t(0)] cMul cLog2 -> cLog2 [fp_log2(x)] cAdd # TEST 10/logmul2
+IF(FP_FLOAT_VERSION) x [x>Value_t(0)] cMul cLog -> cLog [fp_log(x)] cAdd # TEST 10/logmul
+IF(FP_FLOAT_VERSION) x [x>Value_t(0)] cMul cLog10 -> cLog10 [fp_log10(x)] cAdd # TEST 10/logmul10
+
+IF(FP_FLOAT_VERSION) B [B==A] cSin A [IsVarOpcode(A) && mData->mByteCode.size() > 2] cCos -> B cSinCos # TEST 10/sincos_sc
+IF(FP_FLOAT_VERSION) B [B==A] cSin A [IsVarOpcode(A) && mData->mByteCode.size() > 2] cSec -> B cSinCos cInv # TEST 10/sincos_sci
+IF(FP_FLOAT_VERSION) B [B==A] cSin A [IsVarOpcode(A) && mData->mByteCode.size() > 2] cCsc -> B cSin cDup cInv # TEST 10/sincos_ssi
+IF(FP_FLOAT_VERSION) B [B==A] cCos A [IsVarOpcode(A) && mData->mByteCode.size() > 2] cSec -> B cCos cDup cInv # TEST 10/sincos_cci
+IF(FP_FLOAT_VERSION) B [B==A] cTan A [IsVarOpcode(A) && mData->mByteCode.size() > 2] cCot -> B cTan cDup cInv # TEST 10/sincos_tti
+IF(FP_FLOAT_VERSION) B [B==A] cCsc A [IsVarOpcode(A) && mData->mByteCode.size() > 2] cSin -> B cCsc cDup cInv # TEST 10/sincos_sis
+IF(FP_FLOAT_VERSION) B [B==A] cSec A [IsVarOpcode(A) && mData->mByteCode.size() > 2] cCos -> B cSec cDup cInv # TEST 10/sincos_cic
+IF(FP_FLOAT_VERSION) B [B==A] cCot A [IsVarOpcode(A) && mData->mByteCode.size() > 2] cTan -> B cCot cDup cInv # TEST 10/sincos_tit
+IF(FP_FLOAT_VERSION) cSinCos cDiv -> cTan # TEST 10/sincos_tan
+IF(FP_FLOAT_VERSION) cSinCos cRDiv -> cCot
+
+IF(FP_FLOAT_VERSION) B [B==A] cCos A [IsVarOpcode(A) && mData->mByteCode.size() > 3] cSin C [IsCommutativeOrParamSwappableBinaryOpcode(C)] -> B cSinCos {GetParamSwappedBinaryOpcode(C)} # TEST 99/59
+IF(FP_FLOAT_VERSION) B [B==A] cCosh A [IsVarOpcode(A) && mData->mByteCode.size() > 3] cSinh C [IsCommutativeOrParamSwappableBinaryOpcode(C)] -> B cSinhCosh {GetParamSwappedBinaryOpcode(C)} # TEST 99/59
+IF(FP_FLOAT_VERSION) B [B==A] cSinh A [IsVarOpcode(A) && mData->mByteCode.size() > 2] cCosh -> B cSinhCosh
+IF(FP_FLOAT_VERSION) B [B==A] cCos A [IsVarOpcode(A) && mData->mByteCode.size() > 3] cCsc cMul -> B cCot
+IF(FP_FLOAT_VERSION) cSinhCosh cDiv -> cTanh
+IF(FP_FLOAT_VERSION) cSinhCosh cRDiv -> cTanh cInv
+
+IF(FP_FLOAT_VERSION) cSqr A [IsVarOpcode(A)] cSqr cAdd cSqrt -> A cHypot # TEST 10/xsqrysqrhypot
+IF(FP_FLOAT_VERSION) cSqr A [IsVarOpcode(A)] B [IsUnaryOpcode(B)] cSqr cAdd cSqrt -> A B cHypot # TEST 10/xsqryfsqrhypot