This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Patch to improve x86 extend FP patterns
- To: egcs-patches at egcs dot cygnus dot com
- Subject: Patch to improve x86 extend FP patterns
- From: John Wehle <john at feith dot com>
- Date: Sat, 10 Apr 1999 03:05:59 -0400 (EDT)
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 | |
-------------------------------------------------------------------------