diff options
Diffstat (limited to 'util/bytecoderules.dat')
-rw-r--r-- | util/bytecoderules.dat | 513 |
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 |