diff options
author | rth <rth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2002-05-12 17:09:24 +0000 |
---|---|---|
committer | rth <rth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2002-05-12 17:09:24 +0000 |
commit | c0c4a46db805208f56509f85123d31e8255234ca (patch) | |
tree | e7f07bf40bf4b1b2030898085fdd52bd0243b374 /gcc/expr.c | |
parent | f21e12549ddb05d16bb9818a5c77bad2ff0433b8 (diff) | |
download | gcc-c0c4a46db805208f56509f85123d31e8255234ca.tar.gz |
* 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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@53401 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/expr.c')
-rw-r--r-- | gcc/expr.c | 99 |
1 files changed, 96 insertions, 3 deletions
diff --git a/gcc/expr.c b/gcc/expr.c index 84443e014e6..1a8d0518323 100644 --- a/gcc/expr.c +++ b/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. */ |