This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
i386 fp moves changes
- To: egcs-patches at egcs dot cygnus dot com, rth at cygnus dot com
- Subject: i386 fp moves changes
- From: Jan Hubicka <hubicka at atrey dot karlin dot mff dot cuni dot cz>
- Date: Thu, 30 Dec 1999 23:34:48 +0100
Hi
The LEGITIMATE_CONSTANT_P returns 0 for CONST_DOUBLES other than 0 and 1.
This results in suboptimal code when integer instructions are used (where
loads from constant pool are used at the place of immediates).
Making LEGITIMATE_CONSTANT_P return 1 results in bad code as well, because all
moves uses immediates in combine and thus immediates are never combined into
arithmetic oprations.
The best solution I was able to come with is to make the LEGITIMATE_CONSTANT_P
return 1 and let the move patterns accept immediates before reload only for
stores to memory. In other cases constant pool is used and post-reload
splitters converts them back to direct loads. The combiner works fine now even
for 0 and 1 and only problem I am aware of is that PIC register might be
initialized when it is not necesary in some cases.
This patch also fixes some other glitches in move patterns - the mem<->mem
pushes are alowed by expander (this results in better code when not optimizing),
and PREFERRED_RELOAD_CLASS is updated - it now allows loads of fp constants
to integer registers and don't change ALL_REGS to GENERAL_REGS, since the
integer fp fp moves are emited anyway (and fp register is used only
when no integer registers are available.)
Fri Dec 30 17:00:49 CET 1999 Jan Hubicka <hubicka@freesoft.cz>
* i386.c (ix86_expand_move): Allow pushes of memory, offload to memory
all FP constants for constant->reg moves.
(ix86_split_to_parts): Try to convert memory address into immediate
when available in the constant pool.
* i386.h (PREFERRED_RELOAD_CLASS): Allow CONST_DOUBLE->integer reg
moves.
(LEGITIMATE_CONSTANT_P): Return 1.
* i386.md (pushsf): New splitter to convert constant pool memory
reference to immediate.
(mov?f): Likewise; do not allow CONST_DOUBLE for reg moves before
reload.
*** i386.c.nod Thu Dec 30 12:07:00 1999
--- i386.c Thu Dec 30 14:16:31 1999
*************** ix86_expand_move (mode, operands)
*** 3709,3729 ****
}
else
{
! if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
operands[1] = force_reg (mode, operands[1]);
if (FLOAT_MODE_P (mode))
{
! /* If we are loading a floating point constant that isn't 0 or 1
! into a register, force the value to memory now, since we'll
! get better code out the back end. */
if (strict)
;
- else if (GET_CODE (operands[0]) == MEM)
- operands[1] = force_reg (mode, operands[1]);
else if (GET_CODE (operands[1]) == CONST_DOUBLE
! && ! standard_80387_constant_p (operands[1]))
operands[1] = validize_mem (force_const_mem (mode, operands[1]));
}
}
--- 3709,3728 ----
}
else
{
! if (GET_CODE (operands[0]) == MEM && !push_operand (operands[0], mode)
! && GET_CODE (operands[1]) == MEM)
operands[1] = force_reg (mode, operands[1]);
if (FLOAT_MODE_P (mode))
{
! /* If we are loading a floating point constant to a register,
! force the value to memory now, since we'll get better code
! out the back end. */
if (strict)
;
else if (GET_CODE (operands[1]) == CONST_DOUBLE
! && register_operand (operands[0], mode))
operands[1] = validize_mem (force_const_mem (mode, operands[1]));
}
}
*************** ix86_split_to_parts (operand, parts, mod
*** 4779,4784 ****
--- 4778,4790 ----
if (size < 2 || size > 3)
abort ();
+ /* Optimize constant pool reference to immediates. This is used by fp moves,
+ that force all constants to memory to allow combining. */
+
+ if (GET_CODE (operand) == MEM && GET_CODE (XEXP (operand, 0)) == SYMBOL_REF
+ && CONSTANT_POOL_ADDRESS_P (XEXP (operand, 0)))
+ operand = get_pool_constant (XEXP (operand, 0));
+
if (GET_CODE (operand) == MEM && !offsettable_memref_p (operand))
{
/* The only non-offsetable memories we handle are pushes. */
*** i386.h.nod Thu Dec 30 12:04:43 1999
--- i386.h Thu Dec 30 16:50:08 1999
*************** enum reg_class
*** 1035,1045 ****
#define PREFERRED_RELOAD_CLASS(X,CLASS) \
(GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) != VOIDmode \
? (standard_80387_constant_p (X) \
! ? reg_class_subset_p (CLASS, FLOAT_REGS) ? CLASS : FLOAT_REGS \
! : NO_REGS) \
: GET_MODE (X) == QImode && ! reg_class_subset_p (CLASS, Q_REGS) ? Q_REGS \
- : ((CLASS) == ALL_REGS \
- && GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT) ? GENERAL_REGS \
: (CLASS))
/* If we are copying between general and FP registers, we need a memory
--- 1035,1045 ----
#define PREFERRED_RELOAD_CLASS(X,CLASS) \
(GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) != VOIDmode \
? (standard_80387_constant_p (X) \
! ? CLASS \
! : (reg_class_subset_p (CLASS, FLOAT_REGS) \
! ? NO_REGS \
! : reg_class_subset_p (CLASS, GENERAL_REGS) ? CLASS : GENERAL_REGS)) \
: GET_MODE (X) == QImode && ! reg_class_subset_p (CLASS, Q_REGS) ? Q_REGS \
: (CLASS))
/* If we are copying between general and FP registers, we need a memory
*************** do { \
*** 1556,1563 ****
/* Nonzero if the constant value X is a legitimate general operand.
It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE. */
! #define LEGITIMATE_CONSTANT_P(X) \
! (GET_CODE (X) == CONST_DOUBLE ? standard_80387_constant_p (X) : 1)
#ifdef REG_OK_STRICT
#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
--- 1556,1562 ----
/* Nonzero if the constant value X is a legitimate general operand.
It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE. */
! #define LEGITIMATE_CONSTANT_P(X) 1
#ifdef REG_OK_STRICT
#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
*** i386.md.nod Thu Dec 30 12:32:30 1999
--- i386.md Thu Dec 30 14:19:40 1999
***************
*** 1721,1726 ****
--- 1721,1738 ----
}"
[(set_attr "type" "multi,push")])
+ (define_split
+ [(set (match_operand:SF 0 "push_operand" "")
+ (match_operand:SF 1 "memory_operand" ""))]
+ "reload_completed
+ && GET_CODE (operands[1]) == MEM
+ && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
+ && CONSTANT_POOL_ADDRESS_P (XEXP (operands[1], 0))"
+ [(set (match_dup 0)
+ (match_dup 1))]
+ "operands[1] = get_pool_constant (XEXP (operands[1], 0));")
+
+
;; %%% Kill this when call knows how to work this out.
(define_split
[(set (match_operand:SF 0 "push_operand" "")
***************
*** 1732,1738 ****
(define_insn "*movsf_1"
[(set (match_operand:SF 0 "nonimmediate_operand" "=f#r,m,f#r,r#f,m")
(match_operand:SF 1 "general_operand" "fm#r,f#r,G,rmF#f,Fr#f"))]
! "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM"
"*
{
switch (which_alternative)
--- 1744,1753 ----
(define_insn "*movsf_1"
[(set (match_operand:SF 0 "nonimmediate_operand" "=f#r,m,f#r,r#f,m")
(match_operand:SF 1 "general_operand" "fm#r,f#r,G,rmF#f,Fr#f"))]
! "(GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
! && (reload_in_progress || reload_completed
! || GET_CODE (operands[1]) != CONST_DOUBLE
! || memory_operand (operands[0], SFmode))"
"*
{
switch (which_alternative)
***************
*** 1772,1777 ****
--- 1787,1807 ----
}"
[(set_attr "type" "fmov,fmov,fmov,imov,imov")])
+ (define_split
+ [(set (match_operand:SF 0 "general_operand" "")
+ (match_operand:SF 1 "memory_operand" ""))]
+ "reload_completed
+ && GET_CODE (operands[1]) == MEM
+ && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
+ && CONSTANT_POOL_ADDRESS_P (XEXP (operands[1], 0))
+ && (!(FP_REG_P (operands[0]) ||
+ (GET_CODE (operands[0]) == SUBREG
+ && FP_REG_P (SUBREG_REG (operands[0]))))
+ || standard_80387_constant_p (get_pool_constant (XEXP (operands[1], 0))))"
+ [(set (match_dup 0)
+ (match_dup 1))]
+ "operands[1] = get_pool_constant (XEXP (operands[1], 0));")
+
(define_insn "swapsf"
[(set (match_operand:SF 0 "register_operand" "+f")
(match_operand:SF 1 "register_operand" "+f"))
***************
*** 1849,1855 ****
[(set (match_operand:DF 0 "nonimmediate_operand" "=f,m,f,*r,o")
(match_operand:DF 1 "general_operand" "fm,f,G,*roF,F*r"))]
"(GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
! && optimize_size"
"*
{
switch (which_alternative)
--- 1879,1888 ----
[(set (match_operand:DF 0 "nonimmediate_operand" "=f,m,f,*r,o")
(match_operand:DF 1 "general_operand" "fm,f,G,*roF,F*r"))]
"(GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
! && optimize_size
! && (reload_in_progress || reload_completed
! || GET_CODE (operands[1]) != CONST_DOUBLE
! || memory_operand (operands[0], DFmode))"
"*
{
switch (which_alternative)
***************
*** 1893,1899 ****
[(set (match_operand:DF 0 "nonimmediate_operand" "=f#r,m,f#r,r#f,o")
(match_operand:DF 1 "general_operand" "fm#r,f#r,G,roF#f,Fr#f"))]
"(GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
! && !optimize_size"
"*
{
switch (which_alternative)
--- 1926,1935 ----
[(set (match_operand:DF 0 "nonimmediate_operand" "=f#r,m,f#r,r#f,o")
(match_operand:DF 1 "general_operand" "fm#r,f#r,G,roF#f,Fr#f"))]
"(GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
! && !optimize_size
! && (reload_in_progress || reload_completed
! || GET_CODE (operands[1]) != CONST_DOUBLE
! || memory_operand (operands[0], DFmode))"
"*
{
switch (which_alternative)
***************
*** 1948,1953 ****
--- 1984,2001 ----
(set (match_dup 3) (match_dup 6))]
"if (ix86_split_long_move (operands)) DONE;")
+ (define_split
+ [(set (match_operand:DF 0 "register_operand" "")
+ (match_operand:DF 1 "memory_operand" ""))]
+ "reload_completed
+ && GET_CODE (operands[1]) == MEM
+ && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
+ && CONSTANT_POOL_ADDRESS_P (XEXP (operands[1], 0))
+ && standard_80387_constant_p (get_pool_constant (XEXP (operands[1], 0)))"
+ [(set (match_dup 0)
+ (match_dup 1))]
+ "operands[1] = get_pool_constant (XEXP (operands[1], 0));")
+
(define_insn "swapdf"
[(set (match_operand:DF 0 "register_operand" "+f")
(match_operand:DF 1 "register_operand" "+f"))
***************
*** 2051,2057 ****
[(set (match_operand:XF 0 "nonimmediate_operand" "=f,m,f,*r,o")
(match_operand:XF 1 "general_operand" "fm,f,G,*roF,F*r"))]
"(GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
! && optimize_size"
"*
{
switch (which_alternative)
--- 2099,2108 ----
[(set (match_operand:XF 0 "nonimmediate_operand" "=f,m,f,*r,o")
(match_operand:XF 1 "general_operand" "fm,f,G,*roF,F*r"))]
"(GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
! && optimize_size
! && (reload_in_progress || reload_completed
! || GET_CODE (operands[1]) != CONST_DOUBLE
! || memory_operand (operands[0], XFmode))"
"*
{
switch (which_alternative)
***************
*** 2094,2100 ****
[(set (match_operand:XF 0 "nonimmediate_operand" "=f#r,m,f#r,r#f,o")
(match_operand:XF 1 "general_operand" "fm#r,f#r,G,roF#f,Fr#f"))]
"(GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
! && !optimize_size"
"*
{
switch (which_alternative)
--- 2145,2154 ----
[(set (match_operand:XF 0 "nonimmediate_operand" "=f#r,m,f#r,r#f,o")
(match_operand:XF 1 "general_operand" "fm#r,f#r,G,roF#f,Fr#f"))]
"(GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
! && !optimize_size
! && (reload_in_progress || reload_completed
! || GET_CODE (operands[1]) != CONST_DOUBLE
! || memory_operand (operands[0], XFmode))"
"*
{
switch (which_alternative)
***************
*** 2149,2154 ****
--- 2203,2220 ----
(set (match_dup 4) (match_dup 7))]
"if (ix86_split_long_move (operands)) DONE;")
+ (define_split
+ [(set (match_operand:XF 0 "register_operand" "")
+ (match_operand:XF 1 "memory_operand" ""))]
+ "reload_completed
+ && GET_CODE (operands[1]) == MEM
+ && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
+ && CONSTANT_POOL_ADDRESS_P (XEXP (operands[1], 0))
+ && standard_80387_constant_p (get_pool_constant (XEXP (operands[1], 0)))"
+ [(set (match_dup 0)
+ (match_dup 1))]
+ "operands[1] = get_pool_constant (XEXP (operands[1], 0));")
+
(define_insn "swapxf"
[(set (match_operand:XF 0 "register_operand" "+f")
(match_operand:XF 1 "register_operand" "+f"))