Patch to improve x86 trunc FP patterns

John Wehle john@feith.com
Wed Apr 7 00:09:00 GMT 1999


This patch is a rewrite of the trunc FP patterns using a splitter.
This avoids using output_to_reg which outputs instructions behind
the scenes thus intefering with scheduling.  The original patterns
also used fld followed by fstp when the top of the stack didn't
died which is strange since the x86 has perfectly good instructions
for storing SFmode and DFmode memory values without killing the
top of the stack.

The effect of this patch can be seen by compiling:

  float a;

  double
  func (double b)
    {
    double c;

    c = b;
    a = c;
    return c + 2.0;
    }

with -O2 -S.

ChangeLog:

Wed Apr  7 03:02:50 EDT 1999  John Wehle  (john@feith.com)

	* i386.md (truncdfsf2, truncxfsf2,
	truncxfdf2): Rewrite using a splitter.

Enjoy!

-- John Wehle
------------------8<------------------------8<------------------------
*** gcc/config/i386/i386.md.ORIGINAL	Mon Apr  5 12:25:52 1999
--- gcc/config/i386/i386.md	Wed Apr  7 00:33:25 1999
***************
*** 2287,2389 ****
    operands[2] = (rtx) assign_386_stack_local (SFmode, 0);
  }")
  
! ;; This cannot output into an f-reg because there is no way to be sure
! ;; of truncating in that case.  Otherwise this is just like a simple move
! ;; insn.  So we pretend we can output to a reg in order to get better
! ;; register preferencing, but we really use a stack slot.
  
  (define_insn ""
!   [(set (match_operand:SF 0 "nonimmediate_operand" "=f,m")
  	(float_truncate:SF
! 	 (match_operand:DF 1 "register_operand" "0,f")))
     (clobber (match_operand:SF 2 "memory_operand" "m,m"))]
    "TARGET_80387"
    "*
  {
    int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
  
!   if (GET_CODE (operands[0]) == MEM)
!     {
!       if (stack_top_dies)
! 	return AS1 (fstp%z0,%0);
!       else
!         return AS1 (fst%z0,%0);
!     }
!   else if (STACK_TOP_P (operands[0]))
!     {
!       output_asm_insn (AS1 (fstp%z2,%y2), operands);
!       return AS1 (fld%z2,%y2);
!     }
    else
!     abort ();
  }")
  
! (define_insn "truncxfsf2"
!   [(set (match_operand:SF 0 "nonimmediate_operand" "=m,!*r")
  	(float_truncate:SF
! 	 (match_operand:XF 1 "register_operand" "f,f")))]
    "TARGET_80387"
    "*
  {
    int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
  
!   if (NON_STACK_REG_P (operands[0]))
!     {
!       if (stack_top_dies == 0)
! 	{
! 	  output_asm_insn (AS1 (fld,%y1), operands);
! 	  stack_top_dies = 1;
! 	}
!       output_to_reg (operands[0], stack_top_dies, 0);
!       RET;
!     }
!   else if (GET_CODE (operands[0]) == MEM)
!     {
!       if (stack_top_dies)
! 	return AS1 (fstp%z0,%0);
!       else
! 	{
! 	  output_asm_insn (AS1 (fld,%y1), operands);
! 	  return AS1 (fstp%z0,%0);
! 	}
!     }
    else
!     abort ();
  }")
  
! (define_insn "truncxfdf2"
!   [(set (match_operand:DF 0 "nonimmediate_operand" "=m,!*r")
  	(float_truncate:DF
! 	 (match_operand:XF 1 "register_operand" "f,f")))]
!   "TARGET_80387"
    "*
  {
    int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
  
!   if (NON_STACK_REG_P (operands[0]))
!     {
!       if (stack_top_dies == 0)
! 	{
! 	  output_asm_insn (AS1 (fld,%y1), operands);
! 	  stack_top_dies = 1;
! 	}
!       output_to_reg (operands[0], stack_top_dies, 0);
!       RET;
!     }
!   else if (GET_CODE (operands[0]) == MEM)
      {
!       if (stack_top_dies)
! 	return AS1 (fstp%z0,%0);
!       else
! 	{
! 	  output_asm_insn (AS1 (fld,%y1), operands);
! 	  return AS1 (fstp%z0,%0);
! 	}
      }
-   else
-     abort ();
- }")
  
  
  ;; The 387 requires that the stack top dies after converting to DImode.
  
--- 2287,2530 ----
    operands[2] = (rtx) assign_386_stack_local (SFmode, 0);
  }")
  
! (define_insn ""
!   [(set (match_operand:SF 0 "nonimmediate_operand" "=f,m,!*r")
! 	(float_truncate:SF
! 	  (match_operand:DF 1 "register_operand" "0,f,f")))
!    (clobber (match_operand:SF 2 "memory_operand" "m,m,m"))]
!   "TARGET_80387 && ! flag_schedule_insns_after_reload"
!   "*
! {
!   int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
!   rtx xops[1];
! 
!   xops[0] = GET_CODE (operands[0]) == MEM ? operands[0] : operands[2];
! 
!   if (stack_top_dies || STACK_REG_P (operands[0]))
!     output_asm_insn (AS1 (fstp%z0,%0), xops);
!   else
!     output_asm_insn (AS1 (fst%z0,%0), xops);
! 
!   if (STACK_REG_P (operands[0]))
!     return AS1 (fld%z2,%2);
!   else if (NON_STACK_REG_P (operands[0]))
!     return AS2 (mov%L0,%2,%0);
! 
!   return \"\";
! }"
!   [(set_attr "type" "fpop")])
  
  (define_insn ""
!   [(set (match_operand:SF 0 "nonimmediate_operand" "=f,m,!*r")
  	(float_truncate:SF
! 	  (match_operand:DF 1 "register_operand" "0,f,f")))
!    (clobber (match_operand:SF 2 "memory_operand" "m,m,m"))]
!   "TARGET_80387 && flag_schedule_insns_after_reload"
!   "#")
! 
! (define_split
!   [(set (match_operand:SF 0 "register_operand" "=f,!*r")
! 	(float_truncate:SF (match_operand:DF 1 "register_operand" "0,f")))
     (clobber (match_operand:SF 2 "memory_operand" "m,m"))]
+   "TARGET_80387 && reload_completed"
+   [(set (match_dup 2)
+ 	(float_truncate:SF (match_dup 1)))
+    (set (match_dup 0)
+ 	(match_dup 2))]
+   "")
+ 
+ (define_split
+   [(set (match_operand:SF 0 "memory_operand" "=m")
+ 	(float_truncate:SF (match_operand:DF 1 "register_operand" "f")))
+    (clobber (match_operand:SF 2 "memory_operand" "m"))]
+   "TARGET_80387 && reload_completed"
+   [(set (match_dup 0)
+ 	(float_truncate:SF (match_dup 1)))]
+   "")
+ 
+ ;; This cannot output into an f-reg because there is no way to be sure
+ ;; of truncating in that case.
+ 
+ (define_insn ""
+   [(set (match_operand:SF 0 "memory_operand" "=m")
+ 	(float_truncate:SF (match_operand:DF 1 "register_operand" "f")))]
    "TARGET_80387"
    "*
  {
    int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
  
!   if (stack_top_dies)
!     return AS1 (fstp%z0,%0);
    else
!     return AS1 (fst%z0,%0);
! }"
!   [(set_attr "type" "fpop")])
! 
! (define_expand "truncxfsf2"
!   [(parallel [(set (match_operand:SF 0 "nonimmediate_operand" "")
! 		   (float_truncate:SF
! 		    (match_operand:XF 1 "register_operand" "")))
! 	      (clobber (match_dup 2))])]
!   "TARGET_80387"
!   "
! {
!   operands[2] = (rtx) assign_386_stack_local (SFmode, 0);
  }")
  
! (define_insn ""
!   [(set (match_operand:SF 0 "nonimmediate_operand" "=f,m,!*r")
! 	(float_truncate:SF
! 	  (match_operand:XF 1 "register_operand" "0,f,f")))
!    (clobber (match_operand:SF 2 "memory_operand" "m,m,m"))]
!   "TARGET_80387 && ! flag_schedule_insns_after_reload"
!   "*
! {
!   int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
!   rtx xops[1];
! 
!   xops[0] = GET_CODE (operands[0]) == MEM ? operands[0] : operands[2];
! 
!   if (stack_top_dies || STACK_REG_P (operands[0]))
!     output_asm_insn (AS1 (fstp%z0,%0), xops);
!   else
!     output_asm_insn (AS1 (fst%z0,%0), xops);
! 
!   if (STACK_REG_P (operands[0]))
!     return AS1 (fld%z2,%2);
!   else if (NON_STACK_REG_P (operands[0]))
!     return AS2 (mov%L0,%2,%0);
! 
!   return \"\";
! }"
!   [(set_attr "type" "fpop")])
! 
! (define_insn ""
!   [(set (match_operand:SF 0 "nonimmediate_operand" "=f,m,!*r")
  	(float_truncate:SF
! 	  (match_operand:XF 1 "register_operand" "0,f,f")))
!    (clobber (match_operand:SF 2 "memory_operand" "m,m,m"))]
!   "TARGET_80387 && flag_schedule_insns_after_reload"
!   "#")
! 
! (define_split
!   [(set (match_operand:SF 0 "register_operand" "=f,!*r")
! 	(float_truncate:SF (match_operand:XF 1 "register_operand" "0,f")))
!    (clobber (match_operand:SF 2 "memory_operand" "m,m"))]
!   "TARGET_80387 && reload_completed"
!   [(set (match_dup 2)
! 	(float_truncate:SF (match_dup 1)))
!    (set (match_dup 0)
! 	(match_dup 2))]
!   "")
! 
! (define_split
!   [(set (match_operand:SF 0 "memory_operand" "=m")
! 	(float_truncate:SF (match_operand:XF 1 "register_operand" "f")))
!    (clobber (match_operand:SF 2 "memory_operand" "m"))]
!   "TARGET_80387 && reload_completed"
!   [(set (match_dup 0)
! 	(float_truncate:SF (match_dup 1)))]
!   "")
! 
! (define_insn ""
!   [(set (match_operand:SF 0 "memory_operand" "=m")
! 	(float_truncate:SF (match_operand:XF 1 "register_operand" "f")))]
    "TARGET_80387"
    "*
  {
    int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
  
!   if (stack_top_dies)
!     return AS1 (fstp%z0,%0);
    else
!     return AS1 (fst%z0,%0);
! }"
!   [(set_attr "type" "fpop")])
! 
! (define_expand "truncxfdf2"
!   [(parallel [(set (match_operand:DF 0 "nonimmediate_operand" "")
! 		   (float_truncate:DF
! 		    (match_operand:XF 1 "register_operand" "")))
! 	      (clobber (match_dup 2))])]
!   "TARGET_80387"
!   "
! {
!   operands[2] = (rtx) assign_386_stack_local (DFmode, 0);
  }")
  
! (define_insn ""
!   [(set (match_operand:DF 0 "nonimmediate_operand" "=f,m,!*r")
  	(float_truncate:DF
! 	  (match_operand:XF 1 "register_operand" "0,f,f")))
!    (clobber (match_operand:DF 2 "memory_operand" "m,m,o"))]
!   "TARGET_80387 && ! flag_schedule_insns_after_reload"
    "*
  {
    int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
+   rtx xops[2];
  
!   xops[0] = GET_CODE (operands[0]) == MEM ? operands[0] : operands[2];
! 
!   if (stack_top_dies || STACK_REG_P (operands[0]))
!     output_asm_insn (AS1 (fstp%z0,%0), xops);
!   else
!     output_asm_insn (AS1 (fst%z0,%0), xops);
! 
!   if (STACK_REG_P (operands[0]))
!     return AS1 (fld%z2,%2);
!   else if (NON_STACK_REG_P (operands[0]))
      {
!     xops[0] = operands[0];
!     xops[1] = operands[2];
!     return output_move_double (xops);
      }
  
+   return \"\";
+ }"
+   [(set_attr "type" "fpop")])
+ 
+ (define_insn ""
+   [(set (match_operand:DF 0 "nonimmediate_operand" "=f,m,!*r")
+ 	(float_truncate:DF
+ 	  (match_operand:XF 1 "register_operand" "0,f,f")))
+    (clobber (match_operand:DF 2 "memory_operand" "m,m,o"))]
+   "TARGET_80387 && flag_schedule_insns_after_reload"
+   "#")
+ 
+ (define_split
+   [(set (match_operand:DF 0 "register_operand" "=f,!*r")
+ 	(float_truncate:DF (match_operand:XF 1 "register_operand" "0,f")))
+    (clobber (match_operand:DF 2 "memory_operand" "m,o"))]
+   "TARGET_80387 && reload_completed"
+   [(set (match_dup 2)
+ 	(float_truncate:DF (match_dup 1)))
+    (set (match_dup 0)
+ 	(match_dup 2))]
+   "")
+ 
+ (define_split
+   [(set (match_operand:DF 0 "memory_operand" "=m")
+ 	(float_truncate:DF (match_operand:XF 1 "register_operand" "f")))
+    (clobber (match_operand:DF 2 "memory_operand" "m"))]
+   "TARGET_80387 && reload_completed"
+   [(set (match_dup 0)
+ 	(float_truncate:DF (match_dup 1)))]
+   "")
+ 
+ (define_insn ""
+   [(set (match_operand:DF 0 "memory_operand" "=m")
+ 	(float_truncate:DF (match_operand:XF 1 "register_operand" "f")))]
+   "TARGET_80387"
+   "*
+ {
+   int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
+ 
+   if (stack_top_dies)
+     return AS1 (fstp%z0,%0);
+   else
+     return AS1 (fst%z0,%0);
+ }"
+   [(set_attr "type" "fpop")])
  
  ;; The 387 requires that the stack top dies after converting to DImode.
  
-------------------------------------------------------------------------
|   Feith Systems  |   Voice: 1-215-646-8000  |  Email: john@feith.com  |
|    John Wehle    |     Fax: 1-215-540-5495  |                         |
-------------------------------------------------------------------------



More information about the Gcc-patches mailing list