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]

[PATCH, i386]: Implement lrint and llrint as x87 intrinsic function


Hello!

This is follow-up patch to http://gcc.gnu.org/ml/gcc-patches/2005-03/msg01970.html. Attached patch implements call to lrint and llrint with x87 insn. The testcase:

long int test11(double x)
{
 return lrint(x);
}

Will produce (-O2 -ffast-math):

test11:
   pushl    %ebp
   movl    %esp, %ebp
   subl    $4, %esp
   fldl    8(%ebp)
   fistpl    -4(%ebp)
   movl    -4(%ebp), %eax
   leave
   ret

Patch was regtested and bootstrapped on i686-pc-linux-gnu, for c and c++, together with http://gcc.gnu.org/ml/gcc-patches/2005-03/msg01970.html and http://gcc.gnu.org/ml/gcc-patches/2005-03/msg01523.html.
OK for mainline? (I would like to commit a fix for target PR/20421 before commiting this patch...)


2005-03-21 Uros Bizjak <uros@kss-loka.si>

* reg-stack.c (subst_stack_regs_pat): Handle <UNSPEC_FIST> case.

   * config/i386/i386.c (output_fix_trunc): Add new round_mode
   variable.  Output "fldcw" depending on round_mode.
   * config/i386/i386.md (UNSPEC_FIST): New.
   (fistdi2, fistdi2_with_temp, fist<mode>2, fist<mode>2_with_temp):
   New isns patterns to implement lrint and llrint built-ins as x87
   intrinsic function.
   (fistdi2, fist<mode>2 splitters): New splitters.
   (lrintsi2, llrintdi2): New expanders.

BTW: It is very hard ATM for me to split i386.md to different patches (because of mgs01523.html), so the patch includes only minimal diff to i386.md. The patterns themselves are:

(define_insn "fistdi2"
 [(set (match_operand:DI 0 "memory_operand" "=m")
   (unspec:DI [(match_operand:XF 1 "register_operand" "f")]
    UNSPEC_FIST))
  (clobber (match_scratch:XF 2 "=&1f"))]
 "TARGET_USE_FANCY_MATH_387
  && flag_unsafe_math_optimizations"
 "* return output_fix_trunc (insn, operands, 0);"
 [(set_attr "type" "fpspc")
  (set_attr "mode" "DI")])

(define_insn "fistdi2_with_temp"
 [(set (match_operand:DI 0 "nonimmediate_operand" "=m,?r")
   (unspec:DI [(match_operand:XF 1 "register_operand" "f,f")]
    UNSPEC_FIST))
  (clobber (match_operand:DI 2 "memory_operand" "=m,m"))
  (clobber (match_scratch:XF 3 "=&1f,&1f"))]
 "TARGET_USE_FANCY_MATH_387
  && flag_unsafe_math_optimizations"
 "#"
 [(set_attr "type" "fpspc")
  (set_attr "mode" "DI")])

(define_split
 [(set (match_operand:DI 0 "register_operand" "")
   (unspec:DI [(match_operand:XF 1 "register_operand" "")]
    UNSPEC_FIST))
  (clobber (match_operand:DI 2 "memory_operand" ""))
  (clobber (match_scratch 3 ""))]
 "reload_completed"
 [(parallel [(set (match_dup 2) (unspec:DI [(match_dup 1)] UNSPEC_FIST))
         (clobber (match_dup 3))])
  (set (match_dup 0) (match_dup 2))]
 "")

(define_split
 [(set (match_operand:DI 0 "memory_operand" "")
   (unspec:DI [(match_operand:XF 1 "register_operand" "")]
    UNSPEC_FIST))
  (clobber (match_operand:DI 2 "memory_operand" ""))
  (clobber (match_scratch 3 ""))]
 "reload_completed"
 [(parallel [(set (match_dup 0) (unspec:DI [(match_dup 1)] UNSPEC_FIST))
         (clobber (match_dup 3))])]
 "")

(define_insn "fist<mode>2"
 [(set (match_operand:X87MODEI12 0 "memory_operand" "=m")
   (unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "f")]
    UNSPEC_FIST))]
 "TARGET_USE_FANCY_MATH_387
  && flag_unsafe_math_optimizations"
 "* return output_fix_trunc (insn, operands, 0);"
 [(set_attr "type" "fpspc")
  (set_attr "mode" "<MODE>")])

(define_insn "fist<mode>2_with_temp"
 [(set (match_operand:X87MODEI12 0 "nonimmediate_operand" "=m,?r")
   (unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "f,f")]
    UNSPEC_FIST))
  (clobber (match_operand:X87MODEI12 2 "memory_operand" "=m,m"))]
 "TARGET_USE_FANCY_MATH_387
  && flag_unsafe_math_optimizations"
 "#"
 [(set_attr "type" "fpspc")
  (set_attr "mode" "<MODE>")])

(define_split
 [(set (match_operand:X87MODEI12 0 "register_operand" "")
   (unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "")]
    UNSPEC_FIST))
  (clobber (match_operand:X87MODEI12 2 "memory_operand" ""))]
 "reload_completed"
 [(set (match_dup 2) (unspec:X87MODEI12 [(match_dup 1)]
              UNSPEC_FIST))
  (set (match_dup 0) (match_dup 2))]
 "")

(define_split
 [(set (match_operand:X87MODEI12 0 "memory_operand" "")
   (unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "")]
    UNSPEC_FIST))
  (clobber (match_scratch 2 ""))]
 "reload_completed"
 [(set (match_dup 0) (unspec:X87MODEI12 [(match_dup 1)]
              UNSPEC_FIST))]
 "")

(define_expand "lrintsi2"
 [(use (match_operand:SI 0 "nonimmediate_operand" ""))
  (use (match_operand:XF 1 "register_operand" ""))]
 "TARGET_USE_FANCY_MATH_387
  && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
  && flag_unsafe_math_optimizations"
{
 if (memory_operand (operands[0], VOIDmode))
   emit_insn (gen_fistsi2 (operands[0], operands[1]));
 else
   {
     operands[2] = assign_386_stack_local (SImode, 0);
     emit_insn (gen_fistsi2_with_temp (operands[0], operands[1],
                   operands[2]));
   }
 DONE;
})

(define_expand "llrintdi2"
 [(use (match_operand:DI 0 "nonimmediate_operand" ""))
  (use (match_operand:XF 1 "register_operand" ""))]
 "TARGET_USE_FANCY_MATH_387
  && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
  && flag_unsafe_math_optimizations"
{
 if (memory_operand (operands[0], VOIDmode))
   emit_insn (gen_fistdi2 (operands[0], operands[1]));
 else
   {
     operands[2] = assign_386_stack_local (DImode, 0);
     emit_insn (gen_fistdi2_with_temp (operands[0], operands[1],
                   operands[2]));
   }
 DONE;
})

Uros.
Index: reg-stack.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/reg-stack.c,v
retrieving revision 1.173
diff -u -p -r1.173 reg-stack.c
--- reg-stack.c	13 Mar 2005 14:06:47 -0000	1.173
+++ reg-stack.c	21 Mar 2005 10:49:20 -0000
@@ -1672,6 +1672,27 @@ subst_stack_regs_pat (rtx insn, stack re
 	  case UNSPEC:
 	    switch (XINT (pat_src, 1))
 	      {
+	      case UNSPEC_FIST:
+		/* These insns only operate on the top of the stack.  */
+
+		src1 = get_true_reg (&XVECEXP (pat_src, 0, 0));
+		emit_swap_insn (insn, regstack, *src1);
+
+		src1_note = find_regno_note (insn, REG_DEAD, REGNO (*src1));
+
+		if (STACK_REG_P (*dest))
+		  replace_reg (dest, FIRST_STACK_REG);
+
+		if (src1_note)
+		  {
+		    replace_reg (&XEXP (src1_note, 0), FIRST_STACK_REG);
+		    regstack->top--;
+		    CLEAR_HARD_REG_BIT (regstack->reg_set, REGNO (*src1));
+		  }
+
+		replace_reg (src1, FIRST_STACK_REG);
+		break;
+
 	      case UNSPEC_SIN:
 	      case UNSPEC_COS:
 	      case UNSPEC_FRNDINT:
Index: config/i386/i386.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/i386.c,v
retrieving revision 1.798
diff -u -p -r1.798 i386.c
--- config/i386/i386.c	15 Mar 2005 14:44:08 -0000	1.798
+++ config/i386/i386.c	21 Mar 2005 10:49:23 -0000
@@ -7287,6 +7286,7 @@ output_fix_trunc (rtx insn, rtx *operand
 {
   int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
   int dimode_p = GET_MODE (operands[0]) == DImode;
+  int round_mode = get_attr_i387_cw (insn);
 
   /* Jump through a hoop or two for DImode, since the hardware has no
      non-popping instruction.  We used to do this a different way, but
@@ -7304,12 +7304,14 @@ output_fix_trunc (rtx insn, rtx *operand
       output_asm_insn ("fisttp%z0\t%0", operands);
   else
     {
-      output_asm_insn ("fldcw\t%3", operands);
+      if (round_mode != I387_CW_ANY)
+	output_asm_insn ("fldcw\t%3", operands);
       if (stack_top_dies || dimode_p)
 	output_asm_insn ("fistp%z0\t%0", operands);
       else
 	output_asm_insn ("fist%z0\t%0", operands);
-      output_asm_insn ("fldcw\t%2", operands);
+      if (round_mode != I387_CW_ANY)
+	output_asm_insn ("fldcw\t%2", operands);
     }
 
   return "";
Index: config/i386/i386.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/i386.md,v
retrieving revision 1.620
diff -u -p -r1.620 i386.md
--- config/i386/i386.md	15 Mar 2005 14:44:09 -0000	1.620
+++ config/i386/i386.md	21 Mar 2005 10:49:26 -0000
@@ -119,7 +119,8 @@
    (UNSPEC_FYL2X		66)
    (UNSPEC_FYL2XP1		67)
    (UNSPEC_FRNDINT		68)
-   (UNSPEC_F2XM1		69)
+   (UNSPEC_FIST			69)
+   (UNSPEC_F2XM1		70)
 
    ; x87 Double output FP
    (UNSPEC_SINCOS_COS		80)

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]