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:
parent
6412341ec9
commit
51286de650
5 changed files with 169 additions and 18 deletions
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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]);
|
||||
})
|
||||
|
|
99
gcc/expr.c
99
gcc/expr.c
|
@ -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. */
|
||||
|
||||
|
|
16
gcc/real.c
16
gcc/real.c
|
@ -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. */
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue