diff options
author | Alan Modra <amodra@bigpond.net.au> | 2002-09-18 23:27:29 +0000 |
---|---|---|
committer | Alan Modra <amodra@gcc.gnu.org> | 2002-09-19 08:57:29 +0930 |
commit | 678b77333a389968633c420123f579414c0f1911 (patch) | |
tree | fb8b6f627c043a74d86eb9f7b254aaabcfe12012 /gcc | |
parent | c402b6bfbdeb1e95750bff205e441e597f1c47a6 (diff) | |
download | gcc-678b77333a389968633c420123f579414c0f1911.zip gcc-678b77333a389968633c420123f579414c0f1911.tar.gz gcc-678b77333a389968633c420123f579414c0f1911.tar.bz2 |
rs6000.md: (floatdisf2): Rename to floatdisf2_internal1.
* config/rs6000/rs6000.md: (floatdisf2): Rename to
floatdisf2_internal1.
(floatdisf2): New define_expand.
(floatdisf2_internal2): Likewise.
From-SVN: r57288
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000.md | 52 |
2 files changed, 55 insertions, 4 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index fec1110..80846d7 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2002-09-19 Alan Modra <amodra@bigpond.net.au> + + * config/rs6000/rs6000.md: (floatdisf2): Rename to + floatdisf2_internal1. + (floatdisf2): New define_expand. + (floatdisf2_internal2): Likewise. + 2002-09-18 Richard Henderson <rth@redhat.com> * real.c (sticky_rshift_significand): Collect sticky as diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index 270d82e..8bfec08 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -5890,13 +5890,30 @@ "fctidz %0,%1" [(set_attr "type" "fp")]) -;; This only is safe if rounding mode set appropriately. -(define_insn_and_split "floatdisf2" +(define_expand "floatdisf2" + [(set (match_operand:SF 0 "gpc_reg_operand" "") + (float:SF (match_operand:DI 1 "gpc_reg_operand" "")))] + "TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS" + " +{ + if (!flag_unsafe_math_optimizations) + { + rtx label = gen_label_rtx (); + emit_insn (gen_floatdisf2_internal2 (operands[1], label)); + emit_label (label); + } + emit_insn (gen_floatdisf2_internal1 (operands[0], operands[1])); + DONE; +}") + +;; This is not IEEE compliant if rounding mode is "round to nearest". +;; If the DI->DF conversion is inexact, then it's possible to suffer +;; from double rounding. +(define_insn_and_split "floatdisf2_internal1" [(set (match_operand:SF 0 "gpc_reg_operand" "=f") (float:SF (match_operand:DI 1 "gpc_reg_operand" "*f"))) (clobber (match_scratch:DF 2 "=f"))] - "TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS - && flag_unsafe_math_optimizations" + "TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS" "#" "&& reload_completed" [(set (match_dup 2) @@ -5904,6 +5921,33 @@ (set (match_dup 0) (float_truncate:SF (match_dup 2)))] "") + +;; Twiddles bits to avoid double rounding. +;; Bits that might be trucated when converting to DFmode are replaced +;; by a bit that won't be lost at that stage, but is below the SFmode +;; rounding position. +(define_expand "floatdisf2_internal2" + [(set (match_dup 2) (and:DI (match_operand:DI 0 "" "") (const_int 2047))) + (set (match_dup 4) (compare:CC (match_dup 2) (const_int 0))) + (set (match_dup 3) (ashiftrt:DI (match_dup 0) (const_int 53))) + (set (match_dup 3) (plus:DI (match_dup 3) (const_int 1))) + (set (pc) (if_then_else (eq (match_dup 4) (const_int 0)) + (label_ref (match_operand:DI 1 "" "")) + (pc))) + (set (match_dup 5) (compare:CCUNS (match_dup 3) (const_int 2))) + (set (pc) (if_then_else (ltu (match_dup 5) (const_int 0)) + (label_ref (match_dup 1)) + (pc))) + (set (match_dup 0) (xor:DI (match_dup 0) (match_dup 2))) + (set (match_dup 0) (ior:DI (match_dup 0) (const_int 2048)))] + "TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS" + " +{ + operands[2] = gen_reg_rtx (DImode); + operands[3] = gen_reg_rtx (DImode); + operands[4] = gen_reg_rtx (CCmode); + operands[5] = gen_reg_rtx (CCUNSmode); +}") ;; Define the DImode operations that can be done in a small number ;; of instructions. The & constraints are to prevent the register |