]> gcc.gnu.org Git - gcc.git/commitdiff
alpha.c (alpha_emit_conditional_move): Use VOIDmode when testing for a signed comparison.
authorRichard Henderson <rth@cygnus.com>
Thu, 27 Jan 2000 10:17:37 +0000 (02:17 -0800)
committerRichard Henderson <rth@gcc.gnu.org>
Thu, 27 Jan 2000 10:17:37 +0000 (02:17 -0800)
        * 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
gcc/config/alpha/alpha-protos.h
gcc/config/alpha/alpha.c
gcc/config/alpha/alpha.md

index 41f8f7bb4d775c95b6741332cbbc49eace9df88f..fca0d65572b8830df97ac9d0c5850e11d5e99ba6 100644 (file)
@@ -1,3 +1,12 @@
+2000-01-27  Richard Henderson  <rth@cygnus.com>
+
+       * 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  <jakub@redhat.com>
 
        * config/sparc/linux64.h (CC1_SPEC): If compiling -m32 with -g but
index fafe17b3e134f4c310e26bc6f492c744ab53e299..d4a6b65fe870eec184e283d07077efc231fd69ee 100644 (file)
@@ -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[]));
index d4300334b16e441188b97439da4cf239be56939f..6e4dddeb4f61c5a34154254a87e7a7c821524c0d 100644 (file)
@@ -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);
index 0202642f02f4420bf5df2f98822ba5aa4edde28b..4fa6e563b1c057d94bc54220412a9a3c1e629393 100644 (file)
   "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" ""))]
   "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"
   [(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"
    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" ""))
This page took 0.091468 seconds and 5 git commands to generate.