This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |
Other format: | [Raw text] |
This is a followup to http://gcc.gnu.org/ml/gcc/2002-09/msg00681.html I've done some testing using the attached test program, so I'd like to apply the following to rs6000.md. rth's solution may be better for libgcc2.c, but I've only tested the rs6000.md change. ;) * config/rs6000/rs6000.md (floatdisf2): Rename to floatdisf2_int1. (floatdisf2): New define_expand. (floatdisf2_int2): Likewise. Index: gcc/config/rs6000/rs6000.md =================================================================== RCS file: /cvs/gcc/gcc/gcc/config/rs6000/rs6000.md,v retrieving revision 1.206 diff -u -p -r1.206 rs6000.md --- gcc/config/rs6000/rs6000.md 13 Sep 2002 01:40:44 -0000 1.206 +++ gcc/config/rs6000/rs6000.md 18 Sep 2002 07:26:06 -0000 @@ -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_int2 (operands[1], label)); + emit_label (label); + } + emit_insn (gen_floatdisf2_int1 (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_int1" [(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_int2" + [(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 -- Alan Modra IBM OzLabs - Linux Technology Centre
Attachment:
round.c
Description: Text document
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |