expr.c (compress_float_constant): New.

* expr.c (compress_float_constant): New.
        (emit_move_insn): Use it.
        (float_extend_from_mem): New.
        (init_expr_once): Initialize it.
        * real.c (exact_real_truncate): New.

        * config/i386/i386.h (CONST_COSTS): Assume CONST_DOUBLE gets
        dropped into memory; penalize for size.
        (RTX_COSTS): FLOAT_EXTEND is free.
        * config/i386/i386.md (extendsfdf2, extendsfxf2, extendsftf2,
        extenddfxf2, extenddftf2): Accept constants and drop them to memory.

From-SVN: r53401
This commit is contained in:
Richard Henderson 2002-05-12 10:09:24 -07:00 committed by Richard Henderson
parent 6412341ec9
commit 51286de650
5 changed files with 169 additions and 18 deletions

View File

@ -1,3 +1,17 @@
2002-05-12 Richard Henderson <rth@redhat.com>
* expr.c (compress_float_constant): New.
(emit_move_insn): Use it.
(float_extend_from_mem): New.
(init_expr_once): Initialize it.
* real.c (exact_real_truncate): New.
* config/i386/i386.h (CONST_COSTS): Assume CONST_DOUBLE gets
dropped into memory; penalize for size.
(RTX_COSTS): FLOAT_EXTEND is free.
* config/i386/i386.md (extendsfdf2, extendsfxf2, extendsftf2,
extenddfxf2, extenddftf2): Accept constants and drop them to memory.
2002-05-12 Richard Henderson <rth@redhat.com>
* profile.h (profile_info): Add missing extern to declaration.

View File

@ -2595,16 +2595,21 @@ do { \
return flag_pic && SYMBOLIC_CONST (RTX) ? 1 : 0; \
\
case CONST_DOUBLE: \
{ \
int code; \
if (GET_MODE (RTX) == VOIDmode) \
return 0; \
\
code = standard_80387_constant_p (RTX); \
return code == 1 ? 1 : \
code == 2 ? 2 : \
3; \
}
if (GET_MODE (RTX) == VOIDmode) \
return 0; \
switch (standard_80387_constant_p (RTX)) \
{ \
case 1: /* 0.0 */ \
return 1; \
case 2: /* 1.0 */ \
return 2; \
default: \
/* Start with (MEM (SYMBOL_REF)), since that's where \
it'll probably end up. Add a penalty for size. */ \
return (COSTS_N_INSNS (1) + (flag_pic != 0) \
+ (GET_MODE (RTX) == SFmode ? 0 \
: GET_MODE (RTX) == DFmode ? 1 : 2)); \
}
/* Delete the definition here when TOPLEVEL_COSTS_N_INSNS gets added to cse.c */
#define TOPLEVEL_COSTS_N_INSNS(N) \
@ -2766,6 +2771,9 @@ do { \
TOPLEVEL_COSTS_N_INSNS (ix86_cost->add * 2); \
TOPLEVEL_COSTS_N_INSNS (ix86_cost->add); \
\
case FLOAT_EXTEND: \
TOPLEVEL_COSTS_N_INSNS (0); \
\
egress_rtx_costs: \
break;

View File

@ -3367,9 +3367,13 @@
(define_expand "extendsfdf2"
[(set (match_operand:DF 0 "nonimmediate_operand" "")
(float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "")))]
(float_extend:DF (match_operand:SF 1 "general_operand" "")))]
"TARGET_80387 || TARGET_SSE2"
{
/* ??? Needed for compress_float_constant since all fp constants
are LEGITIMATE_CONSTANT_P. */
if (GET_CODE (operands[1]) == CONST_DOUBLE)
operands[1] = validize_mem (force_const_mem (SFmode, operands[1]));
if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
operands[1] = force_reg (SFmode, operands[1]);
})
@ -3418,9 +3422,13 @@
(define_expand "extendsfxf2"
[(set (match_operand:XF 0 "nonimmediate_operand" "")
(float_extend:XF (match_operand:SF 1 "nonimmediate_operand" "")))]
(float_extend:XF (match_operand:SF 1 "general_operand" "")))]
"!TARGET_64BIT && TARGET_80387"
{
/* ??? Needed for compress_float_constant since all fp constants
are LEGITIMATE_CONSTANT_P. */
if (GET_CODE (operands[1]) == CONST_DOUBLE)
operands[1] = validize_mem (force_const_mem (SFmode, operands[1]));
if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
operands[1] = force_reg (SFmode, operands[1]);
})
@ -3459,9 +3467,13 @@
(define_expand "extendsftf2"
[(set (match_operand:TF 0 "nonimmediate_operand" "")
(float_extend:TF (match_operand:SF 1 "nonimmediate_operand" "")))]
(float_extend:TF (match_operand:SF 1 "general_operand" "")))]
"TARGET_80387"
{
/* ??? Needed for compress_float_constant since all fp constants
are LEGITIMATE_CONSTANT_P. */
if (GET_CODE (operands[1]) == CONST_DOUBLE)
operands[1] = validize_mem (force_const_mem (SFmode, operands[1]));
if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
operands[1] = force_reg (SFmode, operands[1]);
})
@ -3500,9 +3512,13 @@
(define_expand "extenddfxf2"
[(set (match_operand:XF 0 "nonimmediate_operand" "")
(float_extend:XF (match_operand:DF 1 "nonimmediate_operand" "")))]
(float_extend:XF (match_operand:DF 1 "general_operand" "")))]
"!TARGET_64BIT && TARGET_80387"
{
/* ??? Needed for compress_float_constant since all fp constants
are LEGITIMATE_CONSTANT_P. */
if (GET_CODE (operands[1]) == CONST_DOUBLE)
operands[1] = validize_mem (force_const_mem (SFmode, operands[1]));
if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
operands[1] = force_reg (DFmode, operands[1]);
})
@ -3541,9 +3557,13 @@
(define_expand "extenddftf2"
[(set (match_operand:TF 0 "nonimmediate_operand" "")
(float_extend:TF (match_operand:DF 1 "nonimmediate_operand" "")))]
(float_extend:TF (match_operand:DF 1 "general_operand" "")))]
"TARGET_80387"
{
/* ??? Needed for compress_float_constant since all fp constants
are LEGITIMATE_CONSTANT_P. */
if (GET_CODE (operands[1]) == CONST_DOUBLE)
operands[1] = validize_mem (force_const_mem (SFmode, operands[1]));
if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
operands[1] = force_reg (DFmode, operands[1]);
})

View File

@ -134,6 +134,7 @@ static void store_by_pieces_1 PARAMS ((struct store_by_pieces *,
static void store_by_pieces_2 PARAMS ((rtx (*) (rtx, ...),
enum machine_mode,
struct store_by_pieces *));
static rtx compress_float_constant PARAMS ((rtx, rtx));
static rtx get_subtarget PARAMS ((rtx));
static int is_zeros_p PARAMS ((tree));
static int mostly_zeros_p PARAMS ((tree));
@ -167,6 +168,10 @@ static void do_tablejump PARAMS ((rtx, enum machine_mode, rtx, rtx, rtx));
static char direct_load[NUM_MACHINE_MODES];
static char direct_store[NUM_MACHINE_MODES];
/* Record for each mode whether we can float-extend from memory. */
static bool float_extend_from_mem[NUM_MACHINE_MODES][NUM_MACHINE_MODES];
/* If a memory-to-memory move would take MOVE_RATIO or more simple
move-instruction sequences, we will do a movstr or libcall instead. */
@ -265,6 +270,28 @@ init_expr_once ()
}
}
mem = gen_rtx_MEM (VOIDmode, gen_rtx_raw_REG (Pmode, 10000));
for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT); mode != VOIDmode;
mode = GET_MODE_WIDER_MODE (mode))
{
enum machine_mode srcmode;
for (srcmode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT); srcmode != mode;
srcmode = GET_MODE_WIDER_MODE (srcmode))
{
enum insn_code ic;
ic = can_extend_p (mode, srcmode, 0);
if (ic == CODE_FOR_nothing)
continue;
PUT_MODE (mem, srcmode);
if ((*insn_data[ic].operand[1].predicate) (mem, srcmode))
float_extend_from_mem[mode][srcmode] = true;
}
}
end_sequence ();
}
@ -2771,10 +2798,18 @@ emit_move_insn (x, y)
/* Never force constant_p_rtx to memory. */
if (GET_CODE (y) == CONSTANT_P_RTX)
;
else if (CONSTANT_P (y) && ! LEGITIMATE_CONSTANT_P (y))
else if (CONSTANT_P (y))
{
y_cst = y;
y = force_const_mem (mode, y);
if (optimize
&& FLOAT_MODE_P (GET_MODE (x))
&& (last_insn = compress_float_constant (x, y)))
return last_insn;
if (!LEGITIMATE_CONSTANT_P (y))
{
y_cst = y;
y = force_const_mem (mode, y);
}
}
/* If X or Y are memory references, verify that their addresses are valid
@ -3100,6 +3135,64 @@ emit_move_insn_1 (x, y)
else
abort ();
}
/* If Y is representable exactly in a narrower mode, and the target can
perform the extension directly from constant or memory, then emit the
move as an extension. */
static rtx
compress_float_constant (x, y)
rtx x, y;
{
enum machine_mode dstmode = GET_MODE (x);
enum machine_mode orig_srcmode = GET_MODE (y);
enum machine_mode srcmode;
REAL_VALUE_TYPE r;
REAL_VALUE_FROM_CONST_DOUBLE (r, y);
for (srcmode = GET_CLASS_NARROWEST_MODE (GET_MODE_CLASS (orig_srcmode));
srcmode != orig_srcmode;
srcmode = GET_MODE_WIDER_MODE (srcmode))
{
enum insn_code ic;
rtx trunc_y, last_insn;
/* Skip if the target can't extend this way. */
ic = can_extend_p (dstmode, srcmode, 0);
if (ic == CODE_FOR_nothing)
continue;
/* Skip if the narrowed value isn't exact. */
if (! exact_real_truncate (srcmode, &r))
continue;
trunc_y = CONST_DOUBLE_FROM_REAL_VALUE (r, srcmode);
if (LEGITIMATE_CONSTANT_P (trunc_y))
{
/* Skip if the target needs extra instructions to perform
the extension. */
if (! (*insn_data[ic].operand[1].predicate) (trunc_y, srcmode))
continue;
}
else if (float_extend_from_mem[dstmode][srcmode])
trunc_y = validize_mem (force_const_mem (srcmode, trunc_y));
else
continue;
emit_unop_insn (ic, x, trunc_y, UNKNOWN);
last_insn = get_last_insn ();
if (GET_CODE (x) == REG)
REG_NOTES (last_insn)
= gen_rtx_EXPR_LIST (REG_EQUAL, y, REG_NOTES (last_insn));
return last_insn;
}
return NULL_RTX;
}
/* Pushing data onto the stack. */

View File

@ -1066,6 +1066,22 @@ real_value_truncate (mode, arg)
return (r);
}
/* Return true if ARG can be represented exactly in MODE. */
bool
exact_real_truncate (mode, arg)
enum machine_mode mode;
REAL_VALUE_TYPE *arg;
{
REAL_VALUE_TYPE trunc;
if (target_isnan (*arg))
return false;
trunc = real_value_truncate (mode, *arg);
return ereal_cmp (*arg, trunc) == 0;
}
/* Try to change R into its exact multiplicative inverse in machine mode
MODE. Return nonzero function value if successful. */