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]

Patch to improve x86 extend FP patterns


This patch is a rewrite of the extend FP patterns using a splitter.
This avoids using output_op_from_reg and output_to_reg which output
instructions behind the scenes thus intefering with scheduling.
The output_op_from_reg and output_to_reg functions also don't take any
steps to ensure the proper alignment of the stack slot used.

The effect of this patch can be seen by compiling:

  union a {
    float b;
    long c;
    };

  long double
  func (union a a, float d)
    {
    union a b;

    b = a;
    b.c -= 3;

    return b.b;
    }

with -O2 -S.

ChangeLog:

Fri Apr  9 22:24:08 EDT 1999  John Wehle  (john@feith.com)

	* reg-stack.c (delete_insn_for_stacker): Ensure that
	the only side effects of a PARALLEL are clobbers.
	(subst_stack_regs): Handle subst_stack_regs_pat deleting
	a PARALLEL.
	* i386.md (extendsfdf2, extenddfxf2,
	extendsfxf2): Rewrite using a splitter.
	* i386.c (output_op_from_reg): Remove.
	* i386.h: Likewise.

Enjoy!

-- John Wehle
------------------8<------------------------8<------------------------
*** gcc/reg-stack.c.ORIGINAL	Tue Mar  9 21:21:31 1999
--- gcc/reg-stack.c	Thu Apr  8 20:23:54 1999
*************** static void
*** 1405,1410 ****
--- 1405,1418 ----
  delete_insn_for_stacker (insn)
       rtx insn;
  {
+   int i;
+ 
+   /* Ensure that the side effects were clobbers when deleting a PARALLEL.  */
+   if (GET_CODE (PATTERN (insn)) == PARALLEL)
+     for (i = 1; i < XVECLEN (PATTERN (insn), 0); i++)
+       if (GET_CODE (XVECEXP (PATTERN (insn), 0, i)) != CLOBBER)
+ 	abort ();
+ 
    PUT_CODE (insn, NOTE);
    NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
    NOTE_SOURCE_FILE (insn) = 0;
*************** subst_stack_regs (insn, regstack)
*** 2478,2485 ****
  	for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
  	  {
  	    if (stack_regs_mentioned_p (XVECEXP (PATTERN (insn), 0, i)))
! 	      subst_stack_regs_pat (insn, regstack,
! 				    XVECEXP (PATTERN (insn), 0, i));
  	  }
        else
  	subst_stack_regs_pat (insn, regstack, PATTERN (insn));
--- 2486,2499 ----
  	for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
  	  {
  	    if (stack_regs_mentioned_p (XVECEXP (PATTERN (insn), 0, i)))
! 	      {
! 		subst_stack_regs_pat (insn, regstack,
! 				      XVECEXP (PATTERN (insn), 0, i));
! 
! 		/* subst_stack_regs_pat may have deleted a no-op insn.  */
! 		if (GET_CODE (insn) == NOTE)
! 		  break;
! 	      }
  	  }
        else
  	subst_stack_regs_pat (insn, regstack, PATTERN (insn));
*** gcc/config/i386/i386.md.ORIGINAL	Thu Apr  8 18:40:36 1999
--- gcc/config/i386/i386.md	Fri Apr  9 17:29:09 1999
***************
*** 2171,2280 ****
  
  ;; Conversions between float and double.
  
! (define_insn "extendsfdf2"
!   [(set (match_operand:DF 0 "nonimmediate_operand" "=fm,f")
! 	(float_extend:DF
! 	 (match_operand:SF 1 "nonimmediate_operand" "f,fm")))]
    "TARGET_80387"
    "*
  {
    int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
  
!   if (NON_STACK_REG_P (operands[1]))
!     {
!       output_op_from_reg (operands[1], AS1 (fld%z0,%y1));
!       RET;
!     }
! 
!   if (NON_STACK_REG_P (operands[0]))
!     {
!       output_to_reg (operands[0], stack_top_dies, 0);
!       RET;
!     }
  
    if (STACK_TOP_P (operands[0]))
      return AS1 (fld%z1,%y1);
  
!   if (GET_CODE (operands[0]) == MEM)
!     {
!       if (stack_top_dies)
! 	return AS1 (fstp%z0,%y0);
!       else
!         return AS1 (fst%z0,%y0);
!     }
  
!   abort ();
  }")
  
! (define_insn "extenddfxf2"
!   [(set (match_operand:XF 0 "nonimmediate_operand" "=fm,f,f,!*r")
  	(float_extend:XF
! 	 (match_operand:DF 1 "nonimmediate_operand" "f,fm,!*r,f")))]
!   "TARGET_80387"
    "*
  {
    int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
  
!   if (NON_STACK_REG_P (operands[1]))
!     {
!       output_op_from_reg (operands[1], AS1 (fld%z0,%y1));
!       RET;
!     }
! 
!   if (NON_STACK_REG_P (operands[0]))
!     {
!       output_to_reg (operands[0], stack_top_dies, 0);
!       RET;
!     }
  
    if (STACK_TOP_P (operands[0]))
      return AS1 (fld%z1,%y1);
  
!   if (GET_CODE (operands[0]) == MEM)
!     {
!       output_asm_insn (AS1 (fstp%z0,%y0), operands);
!       if (! stack_top_dies)
! 	return AS1 (fld%z0,%y0);
!       RET;
!     }
  
!   abort ();
  }")
  
! (define_insn "extendsfxf2"
!   [(set (match_operand:XF 0 "nonimmediate_operand" "=fm,f,f,!*r")
  	(float_extend:XF
! 	 (match_operand:SF 1 "nonimmediate_operand" "f,fm,!*r,f")))]
!   "TARGET_80387"
    "*
  {
    int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
  
!   if (NON_STACK_REG_P (operands[1]))
!     {
!       output_op_from_reg (operands[1], AS1 (fld%z0,%y1));
!       RET;
!     }
! 
!   if (NON_STACK_REG_P (operands[0]))
!     {
!       output_to_reg (operands[0], stack_top_dies, 0);
!       RET;
!     }
  
    if (STACK_TOP_P (operands[0]))
      return AS1 (fld%z1,%y1);
  
!   if (GET_CODE (operands[0]) == MEM)
!     {
!       output_asm_insn (AS1 (fstp%z0,%y0), operands);
!       if (! stack_top_dies)
! 	return AS1 (fld%z0,%y0);
!       RET;
!     }
! 
!   abort ();
! }")
  
  (define_expand "truncdfsf2"
    [(parallel [(set (match_operand:SF 0 "nonimmediate_operand" "")
--- 2171,2441 ----
  
  ;; Conversions between float and double.
  
! (define_expand "extendsfdf2"
!   [(parallel [(set (match_operand:DF 0 "nonimmediate_operand" "")
! 		   (float_extend:DF
! 		     (match_operand:SF 1 "nonimmediate_operand" "")))
!      (clobber (match_dup 2))
!      (clobber (match_dup 3))])]
    "TARGET_80387"
+   "
+ {
+   if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
+     operands[1] = force_reg (SFmode, operands[1]);
+ 
+   operands[2] = assign_386_stack_local (SFmode, 0);
+   operands[3] = assign_386_stack_local (DFmode, 0);
+ }")
+ 
+ (define_insn ""
+   [(set (match_operand:DF 0 "nonimmediate_operand" "=f,m,!f,!*r")
+ 	(float_extend:DF
+ 	  (match_operand:SF 1 "nonimmediate_operand" "fm,f,*r,f")))
+    (clobber (match_operand:SF 2 "memory_operand" "m,m,m,m"))
+    (clobber (match_operand:DF 3 "memory_operand" "m,m,m,o"))]
+   "TARGET_80387 && (GET_CODE (operands[0]) != MEM
+ 		    || GET_CODE (operands[1]) != MEM)"
+   "#")
+ 
+ (define_split
+   [(set (match_operand:DF 0 "register_operand" "")
+ 	(float_extend:DF (match_operand:SF 1 "register_operand" "")))
+    (clobber (match_operand:SF 2 "memory_operand" ""))
+    (clobber (match_operand:DF 3 "memory_operand" ""))]
+   "TARGET_80387 && reload_completed && NON_STACK_REG_P (operands[1])"
+   [(set (match_dup 2)
+ 	(match_dup 1))
+    (set (match_dup 0)
+ 	(float_extend:DF (match_dup 2)))]
+   "")
+ 
+ (define_split
+   [(set (match_operand:DF 0 "register_operand" "")
+ 	(float_extend:DF (match_operand:SF 1 "register_operand" "")))
+    (clobber (match_operand:SF 2 "memory_operand" ""))
+    (clobber (match_operand:DF 3 "memory_operand" ""))]
+   "TARGET_80387 && reload_completed && NON_STACK_REG_P (operands[0])"
+   [(set (match_dup 3)
+ 	(float_extend:DF (match_dup 1)))
+    (set (match_dup 0)
+ 	(match_dup 3))]
+   "")
+ 
+ (define_split
+   [(set (match_operand:DF 0 "nonimmediate_operand" "")
+ 	(float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "")))
+    (clobber (match_operand:SF 2 "memory_operand" ""))
+    (clobber (match_operand:DF 3 "memory_operand" ""))]
+   "TARGET_80387 && reload_completed"
+   [(set (match_dup 0)
+ 	(float_extend:DF (match_dup 1)))]
+   "")
+ 
+ (define_insn ""
+   [(set (match_operand:DF 0 "nonimmediate_operand" "=f,m")
+ 	(float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "fm,f")))]
+   "TARGET_80387 && (GET_CODE (operands[0]) != MEM
+ 		    || GET_CODE (operands[1]) != MEM)"
    "*
  {
    int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
  
!   if (! STACK_TOP_P (operands[0]) && ! STACK_TOP_P (operands[1]))
!     abort ();
! 
!   if (STACK_TOP_P (operands[0]) && STACK_TOP_P (operands[1]))
!     return \"\";
  
    if (STACK_TOP_P (operands[0]))
      return AS1 (fld%z1,%y1);
  
!   if (stack_top_dies)
!     return AS1 (fstp%z0,%y0);
!   else
!     return AS1 (fst%z0,%y0);
! }"
!   [(set_attr "type" "fld,fpop")])
! 
! (define_expand "extenddfxf2"
!   [(parallel [(set (match_operand:XF 0 "nonimmediate_operand" "")
! 		   (float_extend:XF
! 		     (match_operand:DF 1 "nonimmediate_operand" "")))
!      (clobber (match_dup 2))
!      (clobber (match_dup 3))])]
!   "TARGET_80387"
!   "
! {
!   if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
!     operands[1] = force_reg (DFmode, operands[1]);
  
!   operands[2] = assign_386_stack_local (DFmode, 0);
!   operands[3] = assign_386_stack_local (XFmode, 0);
  }")
  
! (define_insn ""
!   [(set (match_operand:XF 0 "nonimmediate_operand" "=f,m,!f,!*r")
  	(float_extend:XF
! 	  (match_operand:DF 1 "nonimmediate_operand" "fm,f,*r,f")))
!    (clobber (match_operand:DF 2 "memory_operand" "m,m,o,m"))
!    (clobber (match_operand:XF 3 "memory_operand" "m,m,m,o"))]
!   "TARGET_80387 && (GET_CODE (operands[0]) != MEM
! 		    || GET_CODE (operands[1]) != MEM)"
!   "#")
! 
! (define_split
!   [(set (match_operand:XF 0 "register_operand" "")
! 	(float_extend:XF (match_operand:DF 1 "register_operand" "")))
!    (clobber (match_operand:DF 2 "memory_operand" ""))
!    (clobber (match_operand:XF 3 "memory_operand" ""))]
!   "TARGET_80387 && reload_completed && NON_STACK_REG_P (operands[1])"
!   [(set (match_dup 2)
! 	(match_dup 1))
!    (set (match_dup 0)
! 	(float_extend:XF (match_dup 2)))]
!   "")
! 
! (define_split
!   [(set (match_operand:XF 0 "register_operand" "")
! 	(float_extend:XF (match_operand:DF 1 "register_operand" "")))
!    (clobber (match_operand:DF 2 "memory_operand" ""))
!    (clobber (match_operand:XF 3 "memory_operand" ""))]
!   "TARGET_80387 && reload_completed && NON_STACK_REG_P (operands[0])"
!   [(set (match_dup 3)
! 	(float_extend:XF (match_dup 1)))
!    (set (match_dup 0)
! 	(match_dup 3))]
!   "")
! 
! (define_split
!   [(set (match_operand:XF 0 "nonimmediate_operand" "")
! 	(float_extend:XF (match_operand:DF 1 "nonimmediate_operand" "")))
!    (clobber (match_operand:DF 2 "memory_operand" ""))
!    (clobber (match_operand:XF 3 "memory_operand" ""))]
!   "TARGET_80387 && reload_completed"
!   [(set (match_dup 0)
! 	(float_extend:XF (match_dup 1)))]
!   "")
! 
! (define_insn ""
!   [(set (match_operand:XF 0 "nonimmediate_operand" "=f,m")
! 	(float_extend:XF (match_operand:DF 1 "nonimmediate_operand" "fm,f")))]
!   "TARGET_80387 && (GET_CODE (operands[0]) != MEM
! 		    || GET_CODE (operands[1]) != MEM)"
    "*
  {
    int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
  
!   if (! STACK_TOP_P (operands[0]) && ! STACK_TOP_P (operands[1]))
!     abort ();
! 
!   if (STACK_TOP_P (operands[0]) && STACK_TOP_P (operands[1]))
!     return \"\";
  
    if (STACK_TOP_P (operands[0]))
      return AS1 (fld%z1,%y1);
  
!   if (stack_top_dies || GET_CODE (operands[0]) == MEM)
!     output_asm_insn (AS1 (fstp%z0,%y0), operands);
!   else
!     return AS1 (fst%z0,%y0);
! 
!   if (! stack_top_dies)
!     return AS1 (fld%z0,%y0);
! 
!   return \"\";
! }"
!   [(set_attr "type" "fld,fpop")])
! 
! (define_expand "extendsfxf2"
!   [(parallel [(set (match_operand:XF 0 "nonimmediate_operand" "")
! 		   (float_extend:XF
! 		     (match_operand:SF 1 "nonimmediate_operand" "")))
!      (clobber (match_dup 2))
!      (clobber (match_dup 3))])]
!   "TARGET_80387"
!   "
! {
!   if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
!     operands[1] = force_reg (SFmode, operands[1]);
  
!   operands[2] = assign_386_stack_local (SFmode, 0);
!   operands[3] = assign_386_stack_local (XFmode, 0);
  }")
  
! (define_insn ""
!   [(set (match_operand:XF 0 "nonimmediate_operand" "=f,m,!f,!*r")
  	(float_extend:XF
! 	  (match_operand:SF 1 "nonimmediate_operand" "fm,f,*r,f")))
!    (clobber (match_operand:SF 2 "memory_operand" "m,m,m,m"))
!    (clobber (match_operand:XF 3 "memory_operand" "m,m,m,o"))]
!   "TARGET_80387 && (GET_CODE (operands[0]) != MEM
! 		    || GET_CODE (operands[1]) != MEM)"
!   "#")
! 
! (define_split
!   [(set (match_operand:XF 0 "register_operand" "")
! 	(float_extend:XF (match_operand:SF 1 "register_operand" "")))
!    (clobber (match_operand:SF 2 "memory_operand" ""))
!    (clobber (match_operand:XF 3 "memory_operand" ""))]
!   "TARGET_80387 && reload_completed && NON_STACK_REG_P (operands[1])"
!   [(set (match_dup 2)
! 	(match_dup 1))
!    (set (match_dup 0)
! 	(float_extend:XF (match_dup 2)))]
!   "")
! 
! (define_split
!   [(set (match_operand:XF 0 "register_operand" "")
! 	(float_extend:XF (match_operand:SF 1 "register_operand" "")))
!    (clobber (match_operand:SF 2 "memory_operand" ""))
!    (clobber (match_operand:XF 3 "memory_operand" ""))]
!   "TARGET_80387 && reload_completed && NON_STACK_REG_P (operands[0])"
!   [(set (match_dup 3)
! 	(float_extend:XF (match_dup 1)))
!    (set (match_dup 0)
! 	(match_dup 3))]
!   "")
! 
! (define_split
!   [(set (match_operand:XF 0 "nonimmediate_operand" "")
! 	(float_extend:XF (match_operand:SF 1 "nonimmediate_operand" "")))
!    (clobber (match_operand:SF 2 "memory_operand" ""))
!    (clobber (match_operand:XF 3 "memory_operand" ""))]
!   "TARGET_80387 && reload_completed"
!   [(set (match_dup 0)
! 	(float_extend:XF (match_dup 1)))]
!   "")
! 
! (define_insn ""
!   [(set (match_operand:XF 0 "nonimmediate_operand" "=f,m")
! 	(float_extend:XF
! 	 (match_operand:SF 1 "nonimmediate_operand" "fm,f")))]
!   "TARGET_80387 && (GET_CODE (operands[0]) != MEM
! 		    || GET_CODE (operands[1]) != MEM)"
    "*
  {
    int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
  
!   if (! STACK_TOP_P (operands[0]) && ! STACK_TOP_P (operands[1]))
!     abort ();
! 
!   if (STACK_TOP_P (operands[0]) && STACK_TOP_P (operands[1]))
!     return \"\";
  
    if (STACK_TOP_P (operands[0]))
      return AS1 (fld%z1,%y1);
  
!   if (stack_top_dies || GET_CODE (operands[0]) == MEM)
!     output_asm_insn (AS1 (fstp%z0,%y0), operands);
!   else
!     return AS1 (fst%z0,%y0);
! 
!   if (! stack_top_dies)
!     return AS1 (fld%z0,%y0);
! 
!   return \"\";
! }"
!   [(set_attr "type" "fld,fpop")])
  
  (define_expand "truncdfsf2"
    [(parallel [(set (match_operand:SF 0 "nonimmediate_operand" "")
*** gcc/config/i386/i386.c.ORIGINAL	Thu Apr  8 18:36:42 1999
--- gcc/config/i386/i386.c	Thu Apr  8 19:03:53 1999
*************** function_arg_partial_nregs (cum, mode, t
*** 854,907 ****
    return 0;
  }
  
- /* Output an insn whose source is a 386 integer register.  SRC is the
-    rtx for the register, and TEMPLATE is the op-code template.  SRC may
-    be either SImode or DImode.
- 
-    The template will be output with operands[0] as SRC, and operands[1]
-    as a pointer to the top of the 386 stack.  So a call from floatsidf2
-    would look like this:
- 
-       output_op_from_reg (operands[1], AS1 (fild%z0,%1));
- 
-    where %z0 corresponds to the caller's operands[1], and is used to
-    emit the proper size suffix.
- 
-    ??? Extend this to handle HImode - a 387 can load and store HImode
-    values directly. */
- 
- void
- output_op_from_reg (src, template)
-      rtx src;
-      char *template;
- {
-   rtx xops[4];
-   int size = GET_MODE_SIZE (GET_MODE (src));
- 
-   xops[0] = src;
-   xops[1] = AT_SP (Pmode);
-   xops[2] = GEN_INT (size);
-   xops[3] = stack_pointer_rtx;
- 
-   if (size > UNITS_PER_WORD)
-     {
-       rtx high;
- 
-       if (size > 2 * UNITS_PER_WORD)
- 	{
- 	  high = gen_rtx_REG (SImode, REGNO (src) + 2);
- 	  output_asm_insn (AS1 (push%L0,%0), &high);
- 	}
- 
-       high = gen_rtx_REG (SImode, REGNO (src) + 1);
-       output_asm_insn (AS1 (push%L0,%0), &high);
-     }
- 
-   output_asm_insn (AS1 (push%L0,%0), &src);
-   output_asm_insn (template, xops);
-   output_asm_insn (AS2 (add%L3,%2,%3), xops);
- }
- 
  /* Output an insn to pop an value from the 387 top-of-stack to 386
     register DEST. The 387 register stack is popped if DIES is true.  If
     the mode of DEST is an integer mode, a `fist' integer store is done,
--- 854,859 ----
*** gcc/config/i386/i386.h.ORIGINAL	Thu Apr  8 18:36:43 1999
--- gcc/config/i386/i386.h	Thu Apr  8 19:05:17 1999
*************** extern void function_arg_advance ();
*** 2713,2719 ****
  extern struct rtx_def *function_arg ();
  extern int function_arg_partial_nregs ();
  extern char *output_strlen_unroll ();
- extern void output_op_from_reg ();
  extern void output_to_reg ();
  extern char *singlemove_string ();
  extern char *output_move_double ();
--- 2713,2718 ----
-------------------------------------------------------------------------
|   Feith Systems  |   Voice: 1-215-646-8000  |  Email: john@feith.com  |
|    John Wehle    |     Fax: 1-215-540-5495  |                         |
-------------------------------------------------------------------------



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