diff options
Diffstat (limited to 'gcc/config/mips/mips.md')
-rw-r--r-- | gcc/config/mips/mips.md | 265 |
1 files changed, 170 insertions, 95 deletions
diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md index f6912e11c2d..4f5692ce662 100644 --- a/gcc/config/mips/mips.md +++ b/gcc/config/mips/mips.md @@ -2475,164 +2475,239 @@ ;; Floating point multiply accumulate instructions. -;; The various multiply accumulate instructions can be used even when -;; HONOR_NANS is true because while IEEE 754-2008 requires the negate -;; operation to negate the sign of a NAN and the MIPS neg instruction does -;; not do this, the multiply and add (or minus) parts of these instructions -;; have no requirement on how the sign of a NAN is handled and so the final -;; sign bit of the entire operation is undefined. +(define_expand "fma<mode>4" + [(set (match_operand:ANYF 0 "register_operand") + (fma:ANYF (match_operand:ANYF 1 "register_operand") + (match_operand:ANYF 2 "register_operand") + (match_operand:ANYF 3 "register_operand")))] + "ISA_HAS_FUSED_MADDF || ISA_HAS_FUSED_MADD3 || ISA_HAS_FUSED_MADD4") -(define_insn "*madd4<mode>" +(define_insn "*fma<mode>4_madd3" [(set (match_operand:ANYF 0 "register_operand" "=f") - (plus:ANYF (mult:ANYF (match_operand:ANYF 1 "register_operand" "f") - (match_operand:ANYF 2 "register_operand" "f")) - (match_operand:ANYF 3 "register_operand" "f")))] - "ISA_HAS_FP_MADD4_MSUB4 && TARGET_FUSED_MADD" + (fma:ANYF (match_operand:ANYF 1 "register_operand" "f") + (match_operand:ANYF 2 "register_operand" "f") + (match_operand:ANYF 3 "register_operand" "0")))] + "ISA_HAS_FUSED_MADD3" + "madd.<fmt>\t%0,%1,%2" + [(set_attr "type" "fmadd") + (set_attr "mode" "<UNITMODE>")]) + +(define_insn "*fma<mode>4_madd4" + [(set (match_operand:ANYF 0 "register_operand" "=f") + (fma:ANYF (match_operand:ANYF 1 "register_operand" "f") + (match_operand:ANYF 2 "register_operand" "f") + (match_operand:ANYF 3 "register_operand" "f")))] + "ISA_HAS_FUSED_MADD4" "madd.<fmt>\t%0,%3,%1,%2" [(set_attr "type" "fmadd") (set_attr "mode" "<UNITMODE>")]) -(define_insn "fma<mode>4" +(define_insn "*fma<mode>4_maddf" [(set (match_operand:ANYF 0 "register_operand" "=f") (fma:ANYF (match_operand:ANYF 1 "register_operand" "f") (match_operand:ANYF 2 "register_operand" "f") (match_operand:ANYF 3 "register_operand" "0")))] - "ISA_HAS_FP_MADDF_MSUBF" + "ISA_HAS_FUSED_MADDF" "maddf.<fmt>\t%0,%1,%2" [(set_attr "type" "fmadd") (set_attr "mode" "<UNITMODE>")]) -(define_insn "*madd3<mode>" +;; The fms, fnma, and fnms instructions can be used even when HONOR_NANS +;; is true because while IEEE 754-2008 requires the negate operation to +;; negate the sign of a NAN and the MIPS neg instruction does not do this, +;; the fma part of the instruction has no requirement on how the sign of +;; a NAN is handled and so the final sign bit of the entire operation is +;; undefined. + +(define_expand "fms<mode>4" + [(set (match_operand:ANYF 0 "register_operand") + (fma:ANYF (match_operand:ANYF 1 "register_operand") + (match_operand:ANYF 2 "register_operand") + (neg:ANYF (match_operand:ANYF 3 "register_operand"))))] + "(ISA_HAS_FUSED_MADD3 || ISA_HAS_FUSED_MADD4)") + +(define_insn "*fms<mode>4_msub3" [(set (match_operand:ANYF 0 "register_operand" "=f") - (plus:ANYF (mult:ANYF (match_operand:ANYF 1 "register_operand" "f") - (match_operand:ANYF 2 "register_operand" "f")) - (match_operand:ANYF 3 "register_operand" "0")))] - "ISA_HAS_FP_MADD3_MSUB3 && TARGET_FUSED_MADD" - "madd.<fmt>\t%0,%1,%2" + (fma:ANYF (match_operand:ANYF 1 "register_operand" "f") + (match_operand:ANYF 2 "register_operand" "f") + (neg:ANYF (match_operand:ANYF 3 "register_operand" "0"))))] + "ISA_HAS_FUSED_MADD3" + "msub.<fmt>\t%0,%1,%2" [(set_attr "type" "fmadd") (set_attr "mode" "<UNITMODE>")]) -(define_insn "*msub4<mode>" +(define_insn "*fms<mode>4_msub4" [(set (match_operand:ANYF 0 "register_operand" "=f") - (minus:ANYF (mult:ANYF (match_operand:ANYF 1 "register_operand" "f") - (match_operand:ANYF 2 "register_operand" "f")) - (match_operand:ANYF 3 "register_operand" "f")))] - "ISA_HAS_FP_MADD4_MSUB4 && TARGET_FUSED_MADD" + (fma:ANYF (match_operand:ANYF 1 "register_operand" "f") + (match_operand:ANYF 2 "register_operand" "f") + (neg:ANYF (match_operand:ANYF 3 "register_operand" "f"))))] + "ISA_HAS_FUSED_MADD4" "msub.<fmt>\t%0,%3,%1,%2" [(set_attr "type" "fmadd") (set_attr "mode" "<UNITMODE>")]) -(define_insn "*msub3<mode>" +;; fnma is defined in GCC as (fma (neg op1) op2 op3) +;; (-op1 * op2) + op3 ==> -(op1 * op2) + op3 ==> -((op1 * op2) - op3) +;; The mips nmsub instructions implement -((op1 * op2) - op3) +;; This transformation means we may return the wrong signed zero +;; so we check HONOR_SIGNED_ZEROS. + +(define_expand "fnma<mode>4" + [(set (match_operand:ANYF 0 "register_operand") + (fma:ANYF (neg:ANYF (match_operand:ANYF 1 "register_operand")) + (match_operand:ANYF 2 "register_operand") + (match_operand:ANYF 3 "register_operand")))] + "(ISA_HAS_FUSED_MADD3 || ISA_HAS_FUSED_MADD4) + && !HONOR_SIGNED_ZEROS (<MODE>mode)") + +(define_insn "*fnma<mode>4_nmsub3" [(set (match_operand:ANYF 0 "register_operand" "=f") - (minus:ANYF (mult:ANYF (match_operand:ANYF 1 "register_operand" "f") - (match_operand:ANYF 2 "register_operand" "f")) - (match_operand:ANYF 3 "register_operand" "0")))] - "ISA_HAS_FP_MADD3_MSUB3 && TARGET_FUSED_MADD" - "msub.<fmt>\t%0,%1,%2" + (fma:ANYF (neg:ANYF (match_operand:ANYF 1 "register_operand" "f")) + (match_operand:ANYF 2 "register_operand" "f") + (match_operand:ANYF 3 "register_operand" "0")))] + "ISA_HAS_FUSED_MADD3 && !HONOR_SIGNED_ZEROS (<MODE>mode)" + "nmsub.<fmt>\t%0,%1,%2" [(set_attr "type" "fmadd") (set_attr "mode" "<UNITMODE>")]) -(define_insn "*nmadd4<mode>" +(define_insn "*fnma<mode>4_nmsub4" [(set (match_operand:ANYF 0 "register_operand" "=f") - (neg:ANYF (plus:ANYF - (mult:ANYF (match_operand:ANYF 1 "register_operand" "f") - (match_operand:ANYF 2 "register_operand" "f")) - (match_operand:ANYF 3 "register_operand" "f"))))] - "ISA_HAS_NMADD4_NMSUB4 - && TARGET_FUSED_MADD - && HONOR_SIGNED_ZEROS (<MODE>mode)" - "nmadd.<fmt>\t%0,%3,%1,%2" + (fma:ANYF (neg:ANYF (match_operand:ANYF 1 "register_operand" "f")) + (match_operand:ANYF 2 "register_operand" "f") + (match_operand:ANYF 3 "register_operand" "f")))] + "ISA_HAS_FUSED_MADD4 && !HONOR_SIGNED_ZEROS (<MODE>mode)" + "nmsub.<fmt>\t%0,%3,%1,%2" [(set_attr "type" "fmadd") (set_attr "mode" "<UNITMODE>")]) -(define_insn "*nmadd3<mode>" +;; fnms is defined as: (fma (neg op1) op2 (neg op3)) +;; ((-op1) * op2) - op3 ==> -(op1 * op2) - op3 ==> -((op1 * op2) + op3) +;; The mips nmadd instructions implement -((op1 * op2) + op3) +;; This transformation means we may return the wrong signed zero +;; so we check HONOR_SIGNED_ZEROS. + +(define_expand "fnms<mode>4" + [(set (match_operand:ANYF 0 "register_operand") + (fma:ANYF + (neg:ANYF (match_operand:ANYF 1 "register_operand")) + (match_operand:ANYF 2 "register_operand") + (neg:ANYF (match_operand:ANYF 3 "register_operand"))))] + "(ISA_HAS_FUSED_MADD3 || ISA_HAS_FUSED_MADD4) + && !HONOR_SIGNED_ZEROS (<MODE>mode)") + +(define_insn "*fnms<mode>4_nmadd3" [(set (match_operand:ANYF 0 "register_operand" "=f") - (neg:ANYF (plus:ANYF - (mult:ANYF (match_operand:ANYF 1 "register_operand" "f") - (match_operand:ANYF 2 "register_operand" "f")) - (match_operand:ANYF 3 "register_operand" "0"))))] - "ISA_HAS_NMADD3_NMSUB3 - && TARGET_FUSED_MADD - && HONOR_SIGNED_ZEROS (<MODE>mode)" + (fma:ANYF + (neg:ANYF (match_operand:ANYF 1 "register_operand" "f")) + (match_operand:ANYF 2 "register_operand" "f") + (neg:ANYF (match_operand:ANYF 3 "register_operand" "0"))))] + "ISA_HAS_FUSED_MADD3 && !HONOR_SIGNED_ZEROS (<MODE>mode)" "nmadd.<fmt>\t%0,%1,%2" [(set_attr "type" "fmadd") (set_attr "mode" "<UNITMODE>")]) -(define_insn "*nmadd4<mode>_fastmath" +(define_insn "*fnms<mode>4_nmadd4" [(set (match_operand:ANYF 0 "register_operand" "=f") - (minus:ANYF - (mult:ANYF (neg:ANYF (match_operand:ANYF 1 "register_operand" "f")) - (match_operand:ANYF 2 "register_operand" "f")) - (match_operand:ANYF 3 "register_operand" "f")))] - "ISA_HAS_NMADD4_NMSUB4 - && TARGET_FUSED_MADD - && !HONOR_SIGNED_ZEROS (<MODE>mode)" + (fma:ANYF + (neg:ANYF (match_operand:ANYF 1 "register_operand" "f")) + (match_operand:ANYF 2 "register_operand" "f") + (neg:ANYF (match_operand:ANYF 3 "register_operand" "f"))))] + "ISA_HAS_FUSED_MADD4 && !HONOR_SIGNED_ZEROS (<MODE>mode)" "nmadd.<fmt>\t%0,%3,%1,%2" [(set_attr "type" "fmadd") (set_attr "mode" "<UNITMODE>")]) -(define_insn "*nmadd3<mode>_fastmath" +;; Non-fused Floating point multiply accumulate instructions. + +;; These instructions are not fused and round in between the multiply +;; and the add (or subtract) so they are equivalent to the separate +;; multiply and add/sub instructions. + +(define_insn "*madd4<mode>" [(set (match_operand:ANYF 0 "register_operand" "=f") - (minus:ANYF - (mult:ANYF (neg:ANYF (match_operand:ANYF 1 "register_operand" "f")) - (match_operand:ANYF 2 "register_operand" "f")) - (match_operand:ANYF 3 "register_operand" "0")))] - "ISA_HAS_NMADD3_NMSUB3 - && TARGET_FUSED_MADD - && !HONOR_SIGNED_ZEROS (<MODE>mode)" - "nmadd.<fmt>\t%0,%1,%2" + (plus:ANYF (mult:ANYF (match_operand:ANYF 1 "register_operand" "f") + (match_operand:ANYF 2 "register_operand" "f")) + (match_operand:ANYF 3 "register_operand" "f")))] + "ISA_HAS_UNFUSED_MADD4" + "madd.<fmt>\t%0,%3,%1,%2" [(set_attr "type" "fmadd") (set_attr "mode" "<UNITMODE>")]) -(define_insn "*nmsub4<mode>" +(define_insn "*msub4<mode>" [(set (match_operand:ANYF 0 "register_operand" "=f") - (neg:ANYF (minus:ANYF - (mult:ANYF (match_operand:ANYF 2 "register_operand" "f") - (match_operand:ANYF 3 "register_operand" "f")) - (match_operand:ANYF 1 "register_operand" "f"))))] - "ISA_HAS_NMADD4_NMSUB4 - && TARGET_FUSED_MADD - && HONOR_SIGNED_ZEROS (<MODE>mode)" - "nmsub.<fmt>\t%0,%1,%2,%3" + (minus:ANYF (mult:ANYF (match_operand:ANYF 1 "register_operand" "f") + (match_operand:ANYF 2 "register_operand" "f")) + (match_operand:ANYF 3 "register_operand" "f")))] + "ISA_HAS_UNFUSED_MADD4" + "msub.<fmt>\t%0,%3,%1,%2" [(set_attr "type" "fmadd") (set_attr "mode" "<UNITMODE>")]) -(define_insn "*nmsub3<mode>" +;; Like with the fused fms, fnma, and fnms instructions, these unfused +;; instructions can be used even if HONOR_NANS is set because while +;; IEEE 754-2008 requires the negate operation to negate the sign of a +;; NAN and the MIPS neg instruction does not do this, the multiply and +;; add (or subtract) part of the instruction has no requirement on how +;; the sign of a NAN is handled and so the final sign bit of the entire +;; operation is undefined. + +(define_insn "*nmadd4<mode>" + [(set (match_operand:ANYF 0 "register_operand" "=f") + (neg:ANYF (plus:ANYF + (mult:ANYF (match_operand:ANYF 1 "register_operand" "f") + (match_operand:ANYF 2 "register_operand" "f")) + (match_operand:ANYF 3 "register_operand" "f"))))] + "ISA_HAS_UNFUSED_MADD4" + "nmadd.<fmt>\t%0,%3,%1,%2" + [(set_attr "type" "fmadd") + (set_attr "mode" "<UNITMODE>")]) + +(define_insn "*nmsub4<mode>" [(set (match_operand:ANYF 0 "register_operand" "=f") (neg:ANYF (minus:ANYF - (mult:ANYF (match_operand:ANYF 2 "register_operand" "f") - (match_operand:ANYF 3 "register_operand" "f")) - (match_operand:ANYF 1 "register_operand" "0"))))] - "ISA_HAS_NMADD3_NMSUB3 - && TARGET_FUSED_MADD - && HONOR_SIGNED_ZEROS (<MODE>mode)" - "nmsub.<fmt>\t%0,%1,%2" + (mult:ANYF (match_operand:ANYF 1 "register_operand" "f") + (match_operand:ANYF 2 "register_operand" "f")) + (match_operand:ANYF 3 "register_operand" "f"))))] + "ISA_HAS_UNFUSED_MADD4" + "nmsub.<fmt>\t%0,%3,%1,%2" [(set_attr "type" "fmadd") (set_attr "mode" "<UNITMODE>")]) -(define_insn "*nmsub4<mode>_fastmath" +;; Fast-math Non-fused Floating point multiply accumulate instructions. + +;; These instructions are not fused but the expressions they match are +;; not exactly what the instruction implements in the sense that they +;; may not generate the properly signed zeros. + +;; This instruction recognizes ((-op1) * op2) - op3 and generates an +;; nmadd which is really -((op1 * op2) + op3). They are equivalent +;; except for the sign bit when the result is zero or NaN. + +(define_insn "*nmadd4<mode>_fastmath" [(set (match_operand:ANYF 0 "register_operand" "=f") (minus:ANYF - (match_operand:ANYF 1 "register_operand" "f") - (mult:ANYF (match_operand:ANYF 2 "register_operand" "f") - (match_operand:ANYF 3 "register_operand" "f"))))] - "ISA_HAS_NMADD4_NMSUB4 - && TARGET_FUSED_MADD + (mult:ANYF (neg:ANYF (match_operand:ANYF 1 "register_operand" "f")) + (match_operand:ANYF 2 "register_operand" "f")) + (match_operand:ANYF 3 "register_operand" "f")))] + "ISA_HAS_UNFUSED_MADD4 && !HONOR_SIGNED_ZEROS (<MODE>mode)" - "nmsub.<fmt>\t%0,%1,%2,%3" + "nmadd.<fmt>\t%0,%3,%1,%2" [(set_attr "type" "fmadd") (set_attr "mode" "<UNITMODE>")]) -(define_insn "*nmsub3<mode>_fastmath" +;; This instruction recognizes (op1 - (op2 * op3) and generates an +;; nmsub which is really -((op2 * op3) - op1). They are equivalent +;; except for the sign bit when the result is zero or NaN. + +(define_insn "*nmsub4<mode>_fastmath" [(set (match_operand:ANYF 0 "register_operand" "=f") (minus:ANYF - (match_operand:ANYF 1 "register_operand" "f") - (mult:ANYF (match_operand:ANYF 2 "register_operand" "f") - (match_operand:ANYF 3 "register_operand" "0"))))] - "ISA_HAS_NMADD3_NMSUB3 - && TARGET_FUSED_MADD + (match_operand:ANYF 1 "register_operand" "f") + (mult:ANYF (match_operand:ANYF 2 "register_operand" "f") + (match_operand:ANYF 3 "register_operand" "f"))))] + "ISA_HAS_UNFUSED_MADD4 && !HONOR_SIGNED_ZEROS (<MODE>mode)" - "nmsub.<fmt>\t%0,%1,%2" + "nmsub.<fmt>\t%0,%1,%2,%3" [(set_attr "type" "fmadd") (set_attr "mode" "<UNITMODE>")]) |