From 01b9e84eb15daf5a420fa956d3289f30a08884e3 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Thu, 27 Jan 2000 02:17:37 -0800 Subject: [PATCH] alpha.c (alpha_emit_conditional_move): Use VOIDmode when testing for a signed comparison. * alpha.c (alpha_emit_conditional_move): Use VOIDmode when testing for a signed comparison. (alpha_emit_floatuns): New. * alpha-protos.h: Declare it. * alpha.md (floatunsdisf2, floatunsdidf2): New. (extendsfdf2): Tidy. From-SVN: r31643 --- gcc/ChangeLog | 9 +++++ gcc/config/alpha/alpha-protos.h | 1 + gcc/config/alpha/alpha.c | 84 ++++++++++++++++++++++++++++++++++++++++- gcc/config/alpha/alpha.md | 34 ++++++++++------- 4 files changed, 113 insertions(+), 15 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 41f8f7b..fca0d65 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2000-01-27 Richard Henderson + + * alpha.c (alpha_emit_conditional_move): Use VOIDmode when + testing for a signed comparison. + (alpha_emit_floatuns): New. + * alpha-protos.h: Declare it. + * alpha.md (floatunsdisf2, floatunsdidf2): New. + (extendsfdf2): Tidy. + 2000-01-27 Jakub Jelinek * config/sparc/linux64.h (CC1_SPEC): If compiling -m32 with -g but diff --git a/gcc/config/alpha/alpha-protos.h b/gcc/config/alpha/alpha-protos.h index fafe17b..d4a6b65 100644 --- a/gcc/config/alpha/alpha-protos.h +++ b/gcc/config/alpha/alpha-protos.h @@ -79,6 +79,7 @@ extern rtx alpha_emit_set_const PARAMS ((rtx, enum machine_mode, HOST_WIDE_INT, int)); extern rtx alpha_emit_set_long_const PARAMS ((rtx, HOST_WIDE_INT, HOST_WIDE_INT)); +extern void alpha_emit_floatuns PARAMS ((rtx[])); extern rtx alpha_emit_conditional_branch PARAMS ((enum rtx_code)); extern rtx alpha_emit_conditional_move PARAMS ((rtx, enum machine_mode)); extern void alpha_emit_xfloating_arith PARAMS ((enum rtx_code, rtx[])); diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c index d430033..6e4ddde 100644 --- a/gcc/config/alpha/alpha.c +++ b/gcc/config/alpha/alpha.c @@ -1464,6 +1464,88 @@ alpha_emit_set_long_const (target, c1, c2) return target; } +/* Generate an unsigned DImode to FP conversion. This is the same code + optabs would emit if we didn't have TFmode patterns. + + For SFmode, this is the only construction I've found that can pass + gcc.c-torture/execute/ieee/rbug.c. No scenario that uses DFmode + intermediates will work, because you'll get intermediate rounding + that ruins the end result. Some of this could be fixed by turning + on round-to-positive-infinity, but that requires diddling the fpsr, + which kills performance. I tried turning this around and converting + to a negative number, so that I could turn on /m, but either I did + it wrong or there's something else cause I wound up with the exact + same single-bit error. There is a branch-less form of this same code: + + srl $16,1,$1 + and $16,1,$2 + cmplt $16,0,$3 + or $1,$2,$2 + cmovge $16,$16,$2 + itoft $3,$f10 + itoft $2,$f11 + cvtqs $f11,$f11 + adds $f11,$f11,$f0 + fcmoveq $f10,$f11,$f0 + + I'm not using it because it's the same number of instructions as + this branch-full form, and it has more serialized long latency + instructions on the critical path. + + For DFmode, we can avoid rounding errors by breaking up the word + into two pieces, converting them separately, and adding them back: + + LC0: .long 0,0x5f800000 + + itoft $16,$f11 + lda $2,LC0 + cpyse $f11,$f31,$f10 + cpyse $f31,$f11,$f11 + s4addq $1,$2,$1 + lds $f12,0($1) + cvtqt $f10,$f10 + cvtqt $f11,$f11 + addt $f12,$f10,$f0 + addt $f0,$f11,$f0 + + This doesn't seem to be a clear-cut win over the optabs form. + It probably all depends on the distribution of numbers being + converted -- in the optabs form, all but high-bit-set has a + much lower minimum execution time. */ + +void +alpha_emit_floatuns (operands) + rtx operands[2]; +{ + rtx neglab, donelab, i0, i1, f0, in, out; + enum machine_mode mode; + + out = operands[0]; + in = operands[1]; + mode = GET_MODE (out); + neglab = gen_label_rtx (); + donelab = gen_label_rtx (); + i0 = gen_reg_rtx (DImode); + i1 = gen_reg_rtx (DImode); + f0 = gen_reg_rtx (mode); + + emit_cmp_and_jump_insns (in, const0_rtx, LT, const0_rtx, DImode, 0, + 8, neglab); + + emit_insn (gen_rtx_SET (VOIDmode, out, gen_rtx_FLOAT (mode, in))); + emit_jump_insn (gen_jump (donelab)); + + emit_label (neglab); + + emit_insn (gen_lshrdi3 (i0, in, const1_rtx)); + emit_insn (gen_anddi3 (i1, in, const1_rtx)); + emit_insn (gen_iordi3 (i0, i0, i1)); + emit_insn (gen_rtx_SET (VOIDmode, f0, gen_rtx_FLOAT (mode, i0))); + emit_insn (gen_rtx_SET (VOIDmode, out, gen_rtx_PLUS (mode, f0, f0))); + + emit_label (donelab); +} + /* Generate the comparison for a conditional branch. */ rtx @@ -1676,7 +1758,7 @@ alpha_emit_conditional_move (cmp, mode) /* We may be able to use a conditional move directly. This avoids emitting spurious compares. */ - if (signed_comparison_operator (cmp, cmp_op_mode) + if (signed_comparison_operator (cmp, VOIDmode) && (!fp_p || local_fast_math) && (op0 == CONST0_RTX (cmp_mode) || op1 == CONST0_RTX (cmp_mode))) return gen_rtx_fmt_ee (code, VOIDmode, op0, op1); diff --git a/gcc/config/alpha/alpha.md b/gcc/config/alpha/alpha.md index 0202642..4fa6e56 100644 --- a/gcc/config/alpha/alpha.md +++ b/gcc/config/alpha/alpha.md @@ -2133,6 +2133,18 @@ "TARGET_HAS_XFLOATING_LIBS" "alpha_emit_xfloating_cvt (FLOAT, operands); DONE;") +(define_expand "floatunsdisf2" + [(use (match_operand:SF 0 "register_operand" "")) + (use (match_operand:DI 1 "register_operand" ""))] + "" + "alpha_emit_floatuns (operands); DONE;") + +(define_expand "floatunsdidf2" + [(use (match_operand:DF 0 "register_operand" "")) + (use (match_operand:DI 1 "register_operand" ""))] + "" + "alpha_emit_floatuns (operands); DONE;") + (define_expand "floatunsditf2" [(use (match_operand:TF 0 "register_operand" "")) (use (match_operand:DI 1 "general_operand" ""))] @@ -2140,21 +2152,16 @@ "alpha_emit_xfloating_cvt (UNSIGNED_FLOAT, operands); DONE;") (define_expand "extendsfdf2" - [(use (match_operand:DF 0 "register_operand" "")) - (use (match_operand:SF 1 "nonimmediate_operand" ""))] + [(set (match_operand:DF 0 "register_operand" "") + (float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "")))] "TARGET_FP" -" + " { if (alpha_fptm >= ALPHA_FPTM_SU) - emit_insn (gen_extendsfdf2_tp (operands[0], - force_reg (SFmode, operands[1]))); - else - emit_insn (gen_extendsfdf2_no_tp (operands[0], operands[1])); - - DONE; + operands[1] = force_reg (SFmode, operands[1]); }") -;; FIXME -(define_insn "extendsfdf2_tp" + +(define_insn "" [(set (match_operand:DF 0 "register_operand" "=&f") (float_extend:DF (match_operand:SF 1 "register_operand" "f")))] "TARGET_FP && alpha_fptm >= ALPHA_FPTM_SU" @@ -2162,7 +2169,7 @@ [(set_attr "type" "fadd") (set_attr "trap" "yes")]) -(define_insn "extendsfdf2_no_tp" +(define_insn "" [(set (match_operand:DF 0 "register_operand" "=f,f,m") (float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "f,m,f")))] "TARGET_FP && alpha_fptm < ALPHA_FPTM_SU" @@ -2170,8 +2177,7 @@ fmov %1,%0 ld%, %0,%1 st%- %1,%0" - [(set_attr "type" "fcpys,fld,fst") - (set_attr "trap" "yes")]) + [(set_attr "type" "fcpys,fld,fst")]) (define_expand "extenddftf2" [(use (match_operand:TF 0 "register_operand" "")) -- 2.7.4