diff options
-rw-r--r-- | gcc/ChangeLog | 110 | ||||
-rw-r--r-- | gcc/combine.c | 3 | ||||
-rw-r--r-- | gcc/config/c4x/c4x.md | 22 | ||||
-rw-r--r-- | gcc/config/dsp16xx/dsp16xx.md | 2 | ||||
-rw-r--r-- | gcc/config/mips/mips.md | 8 | ||||
-rw-r--r-- | gcc/config/pa/pa.md | 6 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000-protos.h | 2 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000.c | 41 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000.md | 4 | ||||
-rw-r--r-- | gcc/config/sparc/sparc.c | 18 | ||||
-rw-r--r-- | gcc/config/sparc/sparc.md | 2 | ||||
-rw-r--r-- | gcc/emit-rtl.c | 206 | ||||
-rw-r--r-- | gcc/expr.c | 3 | ||||
-rw-r--r-- | gcc/gengenrtl.c | 22 | ||||
-rw-r--r-- | gcc/ggc-common.c | 3 | ||||
-rw-r--r-- | gcc/output.h | 5 | ||||
-rw-r--r-- | gcc/real.h | 26 | ||||
-rw-r--r-- | gcc/rtl.h | 12 | ||||
-rw-r--r-- | gcc/toplev.c | 4 | ||||
-rw-r--r-- | gcc/varasm.c | 191 |
20 files changed, 324 insertions, 366 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a6fffce694d..443aff9977b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,57 @@ +2002-05-12 Zack Weinberg <zack@codesourcery.com> + + * emit-rtl.c (global_rtl): Update comment. + (const_double_htab, const_double_htab_hash, + const_double_htab_hash, lookup_const_double): New. + (const_int_htab_hash, const_int_htab_eq): Remove const + qualifiers, which cause tons of warnings with RTL checking on. + (gen_rtx_CONST_DOUBLE): Deleted. + (const_double_from_real_value): New function - bears some + resemblance to the former immed_real_const_1. + (immed_double_const): Moved here from varasm.c and + simplified. + (gen_rtx_REG): Make REGNO unsigned to squelch warnings. + (gen_rtx_SUBREG): Use gen_rtx_raw_SUBREG. + (gen_rtx): Use immed_double_const. + (init_emit_once): Initialize the const_double_htab. Use + REAL_VALUE_FROM_INT where possible. Can now use + CONST_DOUBLE_FROM_REAL_VALUE when setting up const_tiny_rtx. + * varasm.c (struct varasm_status): Remove x_const_double_chain. + (const_double_chain, immed_real_const, clear_const_double_mem): Delete. + (immed_double_const, immed_real_const_1): Moved to emit-rtl.c. + (init_varasm_status, mark_varasm_status): Don't touch + x_const_double_chain. + + * output.h: Delete prototype for clear_const_double_mem. + * real.h: Make REAL_VALUE_TYPE a macro again. Remove leading + '0' slot from all CONST_DOUBLE_FORMAT definitions. Prototype + const_double_from_real_value, not immed_real_const_1, and use + it to define CONST_DOUBLE_FROM_REAL_VALUE. Define new macro + CONST_DOUBLE_ATOF. + * rtl.h (CONST_DOUBLE_CHAIN): Kill. + (CONST_DOUBLE_LOW, CONST_DOUBLE_HIGH): Adjust. + (gen_rtx_CONST_DOUBLE, immed_real_const): Delete prototypes. + (gen_rtx_REG): Second arg is unsigned. + + * gengenrtl.c (special_rtx): Take out CONST_DOUBLE. + (excluded_rtx): New, return true for CONST_DOUBLE. + (genmacro): Write nothing for excluded codes. + * combine.c (combine_simplify_rtx): Use CONST_DOUBLE_FROM_REAL_VALUE. + * expr.c (expand_expr): Likewise. + * ggc-common.c (ggc_mark_rtx_children_1): Don't mark the + CONST_DOUBLE_CHAIN. + * toplev.c (rest_of_compilation): Don't call + clear_const_double_mem. + + * config/rs6000/rs6000.c (rs6000_float_const): Delete. + (rs6000_hash_constant): Remove CONST_DOUBLE special case. + (toc_hash_eq): Remove CONST_DOUBLE and LABEL_REF special cases. + * config/rs6000/rs6000-protos.h: Don't prototype rs6000_float_const. + * config/c4x/c4x.md, config/rs6000/rs6000.md: Use CONST_DOUBLE_ATOF. + * config/dsp16xx/dsp16xx.md, config/mips/mips.md, + config/pa/pa.md: Use CONST_DOUBLE_FROM_REAL_VALUE. + * config/sparc/sparc.md, config/sparc/sparc.c: Use immed_double_const. + 2002-05-12 Kaveh R. Ghazi <ghazi@caip.rutgers.edu> * mips/iris6.h (CPLUSPLUS_CPP_SPEC): Define. @@ -313,38 +367,38 @@ Thu May 9 14:52:45 CEST 2002 Jan Hubicka <jh@suse.cz> * final.c (end_final): Use C trees to output data structures for profiling. * Makefile.in (LIBGCC_DEPS): Added missing dependency on gcov-io.h - (profile.o): New dependency profile.h - (final.o): New dependency profile.h - * profile.h: New file. New global structure profile_info. - * final.h (count_edges_instrumented_now): Declare. - (current_function_cfg_checksum): Declare. - (function_list): New structure. - (functions_head, functions_tail): New static variables. - (end_final): Emits more data, removed some -ax stuff. - (final): Stores function names and chcksums. - * gcov-io.h (__write_gcov_string): New function. - (__read_gcov_string): New function. - * gcov.c (read_profile): New function. - (create_program_flow_graph): Uses read_profile instead of reading + (profile.o): New dependency profile.h + (final.o): New dependency profile.h + * profile.h: New file. New global structure profile_info. + * final.h (count_edges_instrumented_now): Declare. + (current_function_cfg_checksum): Declare. + (function_list): New structure. + (functions_head, functions_tail): New static variables. + (end_final): Emits more data, removed some -ax stuff. + (final): Stores function names and chcksums. + * gcov-io.h (__write_gcov_string): New function. + (__read_gcov_string): New function. + * gcov.c (read_profile): New function. + (create_program_flow_graph): Uses read_profile instead of reading da_file. - (read_files): Removed da_file checking, it's done by read_profile now. - * libgcc2.c (bb_function_info): New structure. - (bb): New field in structure, removed some -ax stuff. - (__bb_exit_func): Changed structure of da_file. - * profile.c (count_edges_instrumented_now): New global variable. - (current_function_cfg_checksum): New global variable. - (max_counter_in_program): New global variable. - (get_exec_counts): New function. - (compute_checksum): New function. - (instrument_edges): Sets count_edges_instrumented_now. - (compute_branch_probabilities): Uses get_exec_counts instead of + (read_files): Removed da_file checking, it's done by read_profile now. + * libgcc2.c (bb_function_info): New structure. + (bb): New field in structure, removed some -ax stuff. + (__bb_exit_func): Changed structure of da_file. + * profile.c (count_edges_instrumented_now): New global variable. + (current_function_cfg_checksum): New global variable. + (max_counter_in_program): New global variable. + (get_exec_counts): New function. + (compute_checksum): New function. + (instrument_edges): Sets count_edges_instrumented_now. + (compute_branch_probabilities): Uses get_exec_counts instead of reading da_file. - (branch_prob): Calls compute_checksum and writes extra data to bbg_file. - (init_branch_prob): Removed da_file checking, done in get_exec_counts + (branch_prob): Calls compute_checksum and writes extra data to bbg_file. + (init_branch_prob): Removed da_file checking, done in get_exec_counts now. - (end_branch_prob): Removed da_file checking, done in get_exec_counts + (end_branch_prob): Removed da_file checking, done in get_exec_counts now. - * gcov.texi: Updated information about gcov file format. + * gcov.texi: Updated information about gcov file format. 2002-05-09 Kazu Hirata <kazu@cs.umass.edu> diff --git a/gcc/combine.c b/gcc/combine.c index f3d43c49509..9415728d630 100644 --- a/gcc/combine.c +++ b/gcc/combine.c @@ -3773,7 +3773,8 @@ combine_simplify_rtx (x, op0_mode, last, in_dest) if (temp == const0_rtx) temp = CONST0_RTX (mode); else - temp = immed_real_const_1 (FLOAT_STORE_FLAG_VALUE (mode), mode); + temp = CONST_DOUBLE_FROM_REAL_VALUE (FLOAT_STORE_FLAG_VALUE (mode), + mode); } #endif break; diff --git a/gcc/config/c4x/c4x.md b/gcc/config/c4x/c4x.md index f7e44b1c4ec..b9ac85cffe8 100644 --- a/gcc/config/c4x/c4x.md +++ b/gcc/config/c4x/c4x.md @@ -3714,8 +3714,7 @@ operands[4] = gen_reg_rtx (QFmode); operands[5] = gen_reg_rtx (QFmode); operands[6] = gen_reg_rtx (QFmode); - emit_move_insn (operands[5], - immed_real_const_1 (REAL_VALUE_ATOF (\"4294967296.0\", QFmode), QFmode));") + emit_move_insn (operands[5], CONST_DOUBLE_ATOF (\"4294967296.0\", QFmode));") (define_expand "floatunsqihf2" [(set (match_dup 2) (match_dup 3)) @@ -3737,8 +3736,7 @@ operands[4] = gen_reg_rtx (HFmode); operands[5] = gen_reg_rtx (HFmode); operands[6] = gen_reg_rtx (HFmode); - emit_move_insn (operands[5], - immed_real_const_1 (REAL_VALUE_ATOF (\"4294967296.0\", HFmode), HFmode));") + emit_move_insn (operands[5], CONST_DOUBLE_ATOF (\"4294967296.0\", HFmode));") (define_insn "floatqihf2" [(set (match_operand:HF 0 "reg_operand" "=h") @@ -3877,8 +3875,7 @@ operands[3] = gen_reg_rtx (QFmode); operands[4] = gen_reg_rtx (QImode); operands[5] = gen_reg_rtx (QFmode); - emit_move_insn (operands[5], - immed_real_const_1 (REAL_VALUE_ATOF (\"4294967296.0\", QFmode), QFmode));") + emit_move_insn (operands[5], CONST_DOUBLE_ATOF (\"4294967296.0\", QFmode));") (define_expand "fixuns_trunchfqi2" [(parallel [(set (match_dup 2) @@ -3900,8 +3897,7 @@ operands[3] = gen_reg_rtx (HFmode); operands[4] = gen_reg_rtx (QImode); operands[5] = gen_reg_rtx (HFmode); - emit_move_insn (operands[5], - immed_real_const_1 (REAL_VALUE_ATOF (\"4294967296.0\", HFmode), HFmode));") + emit_move_insn (operands[5], CONST_DOUBLE_ATOF (\"4294967296.0\", HFmode));") (define_expand "fixuns_truncqfhi2" [(parallel [(set (match_operand:HI 0 "reg_operand" "") @@ -3981,10 +3977,8 @@ operands[2] = gen_reg_rtx (QFmode); operands[3] = gen_reg_rtx (QFmode); operands[4] = gen_reg_rtx (QFmode); - operands[5] = immed_real_const_1 (REAL_VALUE_ATOF (\"0.5\", QFmode), - QFmode); - operands[6] = immed_real_const_1 (REAL_VALUE_ATOF (\"1.5\", QFmode), - QFmode);") + operands[5] = CONST_DOUBLE_ATOF (\"0.5\", QFmode); + operands[6] = CONST_DOUBLE_ATOF (\"1.5\", QFmode);") (define_expand "sqrtqf2" [(parallel [(set (match_operand:QF 0 "reg_operand" "") @@ -6197,8 +6191,8 @@ operands[2] = gen_reg_rtx (HFmode); operands[3] = gen_reg_rtx (HFmode); operands[4] = gen_reg_rtx (HFmode); - operands[5] = immed_real_const_1 (REAL_VALUE_ATOF (\"0.5\", HFmode), HFmode); - operands[6] = immed_real_const_1 (REAL_VALUE_ATOF (\"1.5\", HFmode), HFmode); + operands[5] = CONST_DOUBLE_ATOF (\"0.5\", HFmode); + operands[6] = CONST_DOUBLE_ATOF (\"1.5\", HFmode); ") diff --git a/gcc/config/dsp16xx/dsp16xx.md b/gcc/config/dsp16xx/dsp16xx.md index 31247ba38f8..fc506b975a4 100644 --- a/gcc/config/dsp16xx/dsp16xx.md +++ b/gcc/config/dsp16xx/dsp16xx.md @@ -1939,7 +1939,7 @@ if (reg1) /* turn off complaints about unreached code */ { - emit_move_insn (reg1, immed_real_const_1 (offset, HFmode)); + emit_move_insn (reg1, CONST_DOUBLE_FROM_REAL_VALUE (offset, HFmode)); do_pending_stack_adjust (); emit_insn (gen_cmphf (operands[1], reg1)); diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md index bbce30eb3bf..118c15984ed 100644 --- a/gcc/config/mips/mips.md +++ b/gcc/config/mips/mips.md @@ -4509,7 +4509,7 @@ move\\t%0,%z4\\n\\ if (reg1) /* turn off complaints about unreached code */ { - emit_move_insn (reg1, immed_real_const_1 (offset, DFmode)); + emit_move_insn (reg1, CONST_DOUBLE_FROM_REAL_VALUE (offset, DFmode)); do_pending_stack_adjust (); emit_insn (gen_cmpdf (operands[1], reg1)); @@ -4553,7 +4553,7 @@ move\\t%0,%z4\\n\\ if (reg1) /* turn off complaints about unreached code */ { - emit_move_insn (reg1, immed_real_const_1 (offset, DFmode)); + emit_move_insn (reg1, CONST_DOUBLE_FROM_REAL_VALUE (offset, DFmode)); do_pending_stack_adjust (); emit_insn (gen_cmpdf (operands[1], reg1)); @@ -4597,7 +4597,7 @@ move\\t%0,%z4\\n\\ if (reg1) /* turn off complaints about unreached code */ { - emit_move_insn (reg1, immed_real_const_1 (offset, SFmode)); + emit_move_insn (reg1, CONST_DOUBLE_FROM_REAL_VALUE (offset, SFmode)); do_pending_stack_adjust (); emit_insn (gen_cmpsf (operands[1], reg1)); @@ -4641,7 +4641,7 @@ move\\t%0,%z4\\n\\ if (reg1) /* turn off complaints about unreached code */ { - emit_move_insn (reg1, immed_real_const_1 (offset, SFmode)); + emit_move_insn (reg1, CONST_DOUBLE_FROM_REAL_VALUE (offset, SFmode)); do_pending_stack_adjust (); emit_insn (gen_cmpsf (operands[1], reg1)); diff --git a/gcc/config/pa/pa.md b/gcc/config/pa/pa.md index e1b952bfce8..a8145546548 100644 --- a/gcc/config/pa/pa.md +++ b/gcc/config/pa/pa.md @@ -4796,7 +4796,8 @@ emit_insn (gen_negdf2_fast (operands[0], operands[1])); else { - operands[2] = force_reg (DFmode, immed_real_const_1 (dconstm1, DFmode)); + operands[2] = force_reg (DFmode, + CONST_DOUBLE_FROM_REAL_VALUE (dconstm1, DFmode)); emit_insn (gen_muldf3 (operands[0], operands[1], operands[2])); } DONE; @@ -4826,7 +4827,8 @@ emit_insn (gen_negsf2_fast (operands[0], operands[1])); else { - operands[2] = force_reg (SFmode, immed_real_const_1 (dconstm1, SFmode)); + operands[2] = force_reg (SFmode, + CONST_DOUBLE_FROM_REAL_VALUE (dconstm1, SFmode)); emit_insn (gen_mulsf3 (operands[0], operands[1], operands[2])); } DONE; diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h index 26bb1e6cd13..954366334ba 100644 --- a/gcc/config/rs6000/rs6000-protos.h +++ b/gcc/config/rs6000/rs6000-protos.h @@ -160,8 +160,6 @@ extern enum direction function_arg_padding PARAMS ((enum machine_mode, tree)); extern void optimization_options PARAMS ((int, int)); extern void rs6000_override_options PARAMS ((const char *)); extern void rs6000_file_start PARAMS ((FILE *, const char *)); -extern struct rtx_def *rs6000_float_const PARAMS ((const char *, - enum machine_mode)); extern int direct_return PARAMS ((void)); extern union tree_node *rs6000_build_va_list PARAMS ((void)); extern int first_reg_to_save PARAMS ((void)); diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index c6b703bcc8a..44e70dbc384 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -702,19 +702,6 @@ rs6000_file_start (file, default_cpu) putc ('\n', file); } } - - -/* Create a CONST_DOUBLE from a string. */ - -struct rtx_def * -rs6000_float_const (string, mode) - const char *string; - enum machine_mode mode; -{ - REAL_VALUE_TYPE value; - value = REAL_VALUE_ATOF (string, mode); - return immed_real_const_1 (value, mode); -} /* Return non-zero if this function is known to have a null epilogue. */ @@ -10044,9 +10031,7 @@ rs6000_hash_constant (k) if (GET_CODE (k) == LABEL_REF) return result * 1231 + X0INT (XEXP (k, 0), 3); - if (GET_CODE (k) == CONST_DOUBLE) - fidx = 1; - else if (GET_CODE (k) == CODE_LABEL) + if (GET_CODE (k) == CODE_LABEL) fidx = 3; else fidx = 0; @@ -10112,29 +10097,7 @@ toc_hash_eq (h1, h2) != ((const struct toc_hash_struct *) h2)->key_mode) return 0; - /* Gotcha: One of these const_doubles will be in memory. - The other may be on the constant-pool chain. - So rtx_equal_p will think they are different... */ - if (r1 == r2) - return 1; - if (GET_CODE (r1) != GET_CODE (r2) - || GET_MODE (r1) != GET_MODE (r2)) - return 0; - if (GET_CODE (r1) == CONST_DOUBLE) - { - int format_len = strlen (GET_RTX_FORMAT (CONST_DOUBLE)); - int i; - for (i = 1; i < format_len; i++) - if (XWINT (r1, i) != XWINT (r2, i)) - return 0; - - return 1; - } - else if (GET_CODE (r1) == LABEL_REF) - return (CODE_LABEL_NUMBER (XEXP (r1, 0)) - == CODE_LABEL_NUMBER (XEXP (r2, 0))); - else - return rtx_equal_p (r1, r2); + return rtx_equal_p (r1, r2); } /* Mark the hash table-entry HASH_ENTRY. */ diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index 6b66c42e088..423ecfd2a96 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -5253,7 +5253,7 @@ " { operands[2] = force_reg (SImode, GEN_INT (0x43300000)); - operands[3] = force_reg (DFmode, rs6000_float_const (\"4503601774854144\", DFmode)); + operands[3] = force_reg (DFmode, CONST_DOUBLE_ATOF (\"4503601774854144\", DFmode)); operands[4] = assign_stack_temp (DFmode, GET_MODE_SIZE (DFmode), 0); operands[5] = gen_reg_rtx (DFmode); operands[6] = gen_reg_rtx (SImode); @@ -5320,7 +5320,7 @@ " { operands[2] = force_reg (SImode, GEN_INT (0x43300000)); - operands[3] = force_reg (DFmode, rs6000_float_const (\"4503599627370496\", DFmode)); + operands[3] = force_reg (DFmode, CONST_DOUBLE_ATOF (\"4503599627370496\", DFmode)); operands[4] = assign_stack_temp (DFmode, GET_MODE_SIZE (DFmode), 0); operands[5] = gen_reg_rtx (DFmode); }") diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c index 6219be324e5..ad1b3c0c65e 100644 --- a/gcc/config/sparc/sparc.c +++ b/gcc/config/sparc/sparc.c @@ -1379,9 +1379,8 @@ sparc_emit_set_const32 (op0, op1) && (INTVAL (op1) & 0x80000000) != 0) emit_insn (gen_rtx_SET (VOIDmode, temp, - gen_rtx_CONST_DOUBLE (VOIDmode, - INTVAL (op1) & ~(HOST_WIDE_INT)0x3ff, - 0))); + immed_double_const (INTVAL (op1) & ~(HOST_WIDE_INT)0x3ff, + 0, DImode))); else emit_insn (gen_rtx_SET (VOIDmode, temp, GEN_INT (INTVAL (op1) @@ -1559,11 +1558,10 @@ static rtx gen_safe_XOR64 PARAMS ((rtx, HOST_WIDE_INT)); #define GEN_INT64(__x) GEN_INT (__x) #else #define GEN_HIGHINT64(__x) \ - gen_rtx_CONST_DOUBLE (VOIDmode, (__x) & ~(HOST_WIDE_INT)0x3ff, 0) + immed_double_const ((__x) & ~(HOST_WIDE_INT)0x3ff, 0, DImode) #define GEN_INT64(__x) \ - gen_rtx_CONST_DOUBLE (VOIDmode, (__x) & 0xffffffff, \ - ((__x) & 0x80000000 \ - ? -1 : 0)) + immed_double_const ((__x) & 0xffffffff, \ + ((__x) & 0x80000000 ? -1 : 0), DImode) #endif /* The optimizer is not to assume anything about exactly @@ -2133,9 +2131,9 @@ sparc_emit_set_const64 (op0, op1) negated_const = GEN_INT (((~low_bits) & 0xfffffc00) | (((HOST_WIDE_INT)((~high_bits) & 0xffffffff))<<32)); #else - negated_const = gen_rtx_CONST_DOUBLE (DImode, - (~low_bits) & 0xfffffc00, - (~high_bits) & 0xffffffff); + negated_const = immed_double_const ((~low_bits) & 0xfffffc00, + (~high_bits) & 0xffffffff, + DImode); #endif sparc_emit_set_const64 (temp, negated_const); } diff --git a/gcc/config/sparc/sparc.md b/gcc/config/sparc/sparc.md index 37ab89916bc..34ec9de765f 100644 --- a/gcc/config/sparc/sparc.md +++ b/gcc/config/sparc/sparc.md @@ -3158,7 +3158,7 @@ emit_insn (gen_movdi (operands[0], GEN_INT (val))); #else emit_insn (gen_movdi (operands[0], - gen_rtx_CONST_DOUBLE (VOIDmode, l[1], l[0]))); + immed_double_const (l[1], l[0], DImode))); #endif } else diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c index adeabe9db0b..2e86dff09a4 100644 --- a/gcc/emit-rtl.c +++ b/gcc/emit-rtl.c @@ -87,8 +87,8 @@ static int no_line_numbers; /* Commonly used rtx's, so that we only need space for one copy. These are initialized once for the entire compilation. - All of these except perhaps the floating-point CONST_DOUBLEs - are unique; no other rtx-object will be equal to any of these. */ + All of these are unique; no other rtx-object will be equal to any + of these. */ rtx global_rtl[GR_MAX]; @@ -148,6 +148,9 @@ static htab_t const_int_htab; /* A hash table storing memory attribute structures. */ static htab_t mem_attrs_htab; +/* A hash table storing all CONST_DOUBLEs. */ +static htab_t const_double_htab; + /* start_sequence and gen_sequence can make a lot of rtx expressions which are shortly thrown away. We use two mechanisms to prevent this waste: @@ -188,6 +191,10 @@ static void mark_label_nuses PARAMS ((rtx)); static hashval_t const_int_htab_hash PARAMS ((const void *)); static int const_int_htab_eq PARAMS ((const void *, const void *)); +static hashval_t const_double_htab_hash PARAMS ((const void *)); +static int const_double_htab_eq PARAMS ((const void *, + const void *)); +static rtx lookup_const_double PARAMS ((rtx)); static hashval_t mem_attrs_htab_hash PARAMS ((const void *)); static int mem_attrs_htab_eq PARAMS ((const void *, const void *)); @@ -208,7 +215,7 @@ static hashval_t const_int_htab_hash (x) const void *x; { - return (hashval_t) INTVAL ((const struct rtx_def *) x); + return (hashval_t) INTVAL ((struct rtx_def *) x); } /* Returns non-zero if the value represented by X (which is really a @@ -220,7 +227,40 @@ const_int_htab_eq (x, y) const void *x; const void *y; { - return (INTVAL ((const struct rtx_def *) x) == *((const HOST_WIDE_INT *) y)); + return (INTVAL ((rtx) x) == *((const HOST_WIDE_INT *) y)); +} + +/* Returns a hash code for X (which is really a CONST_DOUBLE). */ +static hashval_t +const_double_htab_hash (x) + const void *x; +{ + hashval_t h = 0; + size_t i; + rtx value = (rtx) x; + + for (i = 0; i < sizeof(CONST_DOUBLE_FORMAT)-1; i++) + h ^= XWINT (value, i); + return h; +} + +/* Returns non-zero if the value represented by X (really a ...) + is the same as that represented by Y (really a ...) */ +static int +const_double_htab_eq (x, y) + const void *x; + const void *y; +{ + rtx a = (rtx)x, b = (rtx)y; + size_t i; + + if (GET_MODE (a) != GET_MODE (b)) + return 0; + for (i = 0; i < sizeof(CONST_DOUBLE_FORMAT)-1; i++) + if (XWINT (a, i) != XWINT (b, i)) + return 0; + + return 1; } /* Returns a hash code for X (which is a really a mem_attrs *). */ @@ -363,32 +403,130 @@ gen_int_mode (c, mode) return GEN_INT (trunc_int_for_mode (c, mode)); } -/* CONST_DOUBLEs needs special handling because their length is known - only at run-time. */ +/* CONST_DOUBLEs might be created from pairs of integers, or from + REAL_VALUE_TYPEs. Also, their length is known only at run time, + so we cannot use gen_rtx_raw_CONST_DOUBLE. */ + +/* Determine whether REAL, a CONST_DOUBLE, already exists in the + hash table. If so, return its counterpart; otherwise add it + to the hash table and return it. */ +static rtx +lookup_const_double (real) + rtx real; +{ + void **slot = htab_find_slot (const_double_htab, real, INSERT); + if (*slot == 0) + *slot = real; + + return (rtx) *slot; +} +/* Return a CONST_DOUBLE rtx for a floating-point value specified by + VALUE in mode MODE. */ rtx -gen_rtx_CONST_DOUBLE (mode, arg0, arg1) +const_double_from_real_value (value, mode) + REAL_VALUE_TYPE value; enum machine_mode mode; - HOST_WIDE_INT arg0, arg1; { - rtx r = rtx_alloc (CONST_DOUBLE); - int i; + rtx real = rtx_alloc (CONST_DOUBLE); + PUT_MODE (real, mode); + + memcpy (&CONST_DOUBLE_LOW (real), &value, sizeof (REAL_VALUE_TYPE)); + + return lookup_const_double (real); +} + +/* Return a CONST_DOUBLE or CONST_INT for a value specified as a pair + of ints: I0 is the low-order word and I1 is the high-order word. + Do not use this routine for non-integer modes; convert to + REAL_VALUE_TYPE and use CONST_DOUBLE_FROM_REAL_VALUE. */ + +rtx +immed_double_const (i0, i1, mode) + HOST_WIDE_INT i0, i1; + enum machine_mode mode; +{ + rtx value; + unsigned int i; + + if (mode != VOIDmode) + { + int width; + if (GET_MODE_CLASS (mode) != MODE_INT + && GET_MODE_CLASS (mode) != MODE_PARTIAL_INT) + abort (); + + /* We clear out all bits that don't belong in MODE, unless they and + our sign bit are all one. So we get either a reasonable negative + value or a reasonable unsigned value for this mode. */ + width = GET_MODE_BITSIZE (mode); + if (width < HOST_BITS_PER_WIDE_INT + && ((i0 & ((HOST_WIDE_INT) (-1) << (width - 1))) + != ((HOST_WIDE_INT) (-1) << (width - 1)))) + i0 &= ((HOST_WIDE_INT) 1 << width) - 1, i1 = 0; + else if (width == HOST_BITS_PER_WIDE_INT + && ! (i1 == ~0 && i0 < 0)) + i1 = 0; + else if (width > 2 * HOST_BITS_PER_WIDE_INT) + /* We cannot represent this value as a constant. */ + abort (); + + /* If this would be an entire word for the target, but is not for + the host, then sign-extend on the host so that the number will + look the same way on the host that it would on the target. + + For example, when building a 64 bit alpha hosted 32 bit sparc + targeted compiler, then we want the 32 bit unsigned value -1 to be + represented as a 64 bit value -1, and not as 0x00000000ffffffff. + The latter confuses the sparc backend. */ + + if (width < HOST_BITS_PER_WIDE_INT + && (i0 & ((HOST_WIDE_INT) 1 << (width - 1)))) + i0 |= ((HOST_WIDE_INT) (-1) << width); - PUT_MODE (r, mode); - X0EXP (r, 0) = NULL_RTX; - XWINT (r, 1) = arg0; - XWINT (r, 2) = arg1; + /* If MODE fits within HOST_BITS_PER_WIDE_INT, always use a + CONST_INT. - for (i = GET_RTX_LENGTH (CONST_DOUBLE) - 1; i > 2; --i) - XWINT (r, i) = 0; + ??? Strictly speaking, this is wrong if we create a CONST_INT for + a large unsigned constant with the size of MODE being + HOST_BITS_PER_WIDE_INT and later try to interpret that constant + in a wider mode. In that case we will mis-interpret it as a + negative number. - return r; + Unfortunately, the only alternative is to make a CONST_DOUBLE for + any constant in any mode if it is an unsigned constant larger + than the maximum signed integer in an int on the host. However, + doing this will break everyone that always expects to see a + CONST_INT for SImode and smaller. + + We have always been making CONST_INTs in this case, so nothing + new is being broken. */ + + if (width <= HOST_BITS_PER_WIDE_INT) + i1 = (i0 < 0) ? ~(HOST_WIDE_INT) 0 : 0; + } + + /* If this integer fits in one word, return a CONST_INT. */ + if ((i1 == 0 && i0 >= 0) || (i1 == ~0 && i0 < 0)) + return GEN_INT (i0); + + /* We use VOIDmode for integers. */ + value = rtx_alloc (CONST_DOUBLE); + PUT_MODE (value, VOIDmode); + + CONST_DOUBLE_LOW (value) = i0; + CONST_DOUBLE_HIGH (value) = i1; + + for (i = 2; i < (sizeof CONST_DOUBLE_FORMAT - 1); i++) + XWINT (value, i) = 0; + + return lookup_const_double (value); } rtx gen_rtx_REG (mode, regno) enum machine_mode mode; - int regno; + unsigned int regno; { /* In case the MD file explicitly references the frame pointer, have all such references point to the same frame pointer. This is @@ -463,7 +601,7 @@ gen_rtx_SUBREG (mode, reg, offset) if (offset >= GET_MODE_SIZE (GET_MODE (reg))) abort (); #endif - return gen_rtx_fmt_ei (SUBREG, mode, reg, offset); + return gen_rtx_raw_SUBREG (mode, reg, offset); } /* Generate a SUBREG representing the least-significant part of REG if MODE @@ -532,7 +670,7 @@ gen_rtx VPARAMS ((enum rtx_code code, enum machine_mode mode, ...)) HOST_WIDE_INT arg0 = va_arg (p, HOST_WIDE_INT); HOST_WIDE_INT arg1 = va_arg (p, HOST_WIDE_INT); - rt_val = gen_rtx_CONST_DOUBLE (mode, arg0, arg1); + rt_val = immed_double_const (arg0, arg1, mode); } break; @@ -4849,11 +4987,16 @@ init_emit_once (line_numbers) enum machine_mode mode; enum machine_mode double_mode; - /* Initialize the CONST_INT and memory attribute hash tables. */ + /* Initialize the CONST_INT, CONST_DOUBLE, and memory attribute hash + tables. */ const_int_htab = htab_create (37, const_int_htab_hash, const_int_htab_eq, NULL); ggc_add_deletable_htab (const_int_htab, 0, 0); + const_double_htab = htab_create (37, const_double_htab_hash, + const_double_htab_eq, NULL); + ggc_add_deletable_htab (const_double_htab, 0, 0); + mem_attrs_htab = htab_create (37, mem_attrs_htab_hash, mem_attrs_htab_eq, NULL); ggc_add_deletable_htab (mem_attrs_htab, 0, mem_attrs_mark); @@ -4937,10 +5080,10 @@ init_emit_once (line_numbers) else const_true_rtx = gen_rtx_CONST_INT (VOIDmode, STORE_FLAG_VALUE); - dconst0 = REAL_VALUE_ATOF ("0", double_mode); - dconst1 = REAL_VALUE_ATOF ("1", double_mode); - dconst2 = REAL_VALUE_ATOF ("2", double_mode); - dconstm1 = REAL_VALUE_ATOF ("-1", double_mode); + REAL_VALUE_FROM_INT (dconst0, 0, 0, double_mode); + REAL_VALUE_FROM_INT (dconst1, 1, 0, double_mode); + REAL_VALUE_FROM_INT (dconst2, 2, 0, double_mode); + REAL_VALUE_FROM_INT (dconstm1, -1, -1, double_mode); for (i = 0; i <= 2; i++) { @@ -4949,17 +5092,8 @@ init_emit_once (line_numbers) for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT); mode != VOIDmode; mode = GET_MODE_WIDER_MODE (mode)) - { - rtx tem = rtx_alloc (CONST_DOUBLE); - - /* Can't use CONST_DOUBLE_FROM_REAL_VALUE here; that uses the - tables we're setting up right now. */ - memcpy (&CONST_DOUBLE_LOW (tem), r, sizeof (REAL_VALUE_TYPE)); - CONST_DOUBLE_CHAIN (tem) = NULL_RTX; - PUT_MODE (tem, mode); - - const_tiny_rtx[i][(int) mode] = tem; - } + const_tiny_rtx[i][(int) mode] = + CONST_DOUBLE_FROM_REAL_VALUE (*r, mode); const_tiny_rtx[i][(int) VOIDmode] = GEN_INT (i); diff --git a/gcc/expr.c b/gcc/expr.c index 1a8d0518323..c40a6dfeed6 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -6486,7 +6486,8 @@ expand_expr (exp, target, tmode, modifier) many insns, so we'd end up copying it to a register in any case. Now, we do the copying in expand_binop, if appropriate. */ - return immed_real_const (exp); + return CONST_DOUBLE_FROM_REAL_VALUE (TREE_REAL_CST (exp), + TYPE_MODE (TREE_TYPE (exp))); case COMPLEX_CST: case STRING_CST: diff --git a/gcc/gengenrtl.c b/gcc/gengenrtl.c index 5795d32edb0..3da601b141b 100644 --- a/gcc/gengenrtl.c +++ b/gcc/gengenrtl.c @@ -132,21 +132,31 @@ special_format (fmt) || strchr (fmt, 'n') != 0); } -/* Return nonzero if the RTL code given by index IDX is one that we should not - generate a gen_RTX_FOO function foo (because that function is present - elsewhere in the compiler). */ +/* Return nonzero if the RTL code given by index IDX is one that we should + generate a gen_rtx_raw_FOO macro for, not gen_rtx_FOO (because gen_rtx_FOO + is a wrapper in emit-rtl.c). */ static int special_rtx (idx) int idx; { return (strcmp (defs[idx].enumname, "CONST_INT") == 0 - || strcmp (defs[idx].enumname, "CONST_DOUBLE") == 0 || strcmp (defs[idx].enumname, "REG") == 0 || strcmp (defs[idx].enumname, "SUBREG") == 0 || strcmp (defs[idx].enumname, "MEM") == 0); } +/* Return nonzero if the RTL code given by index IDX is one that we should + generate no macro for at all (because gen_rtx_FOO is never used or + cannot have the obvious interface). */ + +static int +excluded_rtx (idx) + int idx; +{ + return (strcmp (defs[idx].enumname, "CONST_DOUBLE") == 0); +} + /* Place a list of all format specifiers we use into the array FORMAT. */ static void @@ -213,6 +223,10 @@ genmacro (idx) /* We write a macro that defines gen_rtx_RTLCODE to be an equivalent to gen_rtx_fmt_FORMAT where FORMAT is the RTX_FORMAT of RTLCODE. */ + if (excluded_rtx (idx)) + /* Don't define a macro for this code. */ + return; + printf ("#define gen_rtx_%s%s(MODE", special_rtx (idx) ? "raw_" : "", defs[idx].enumname); diff --git a/gcc/ggc-common.c b/gcc/ggc-common.c index a90a01fb51a..57c193d5036 100644 --- a/gcc/ggc-common.c +++ b/gcc/ggc-common.c @@ -347,9 +347,6 @@ ggc_mark_rtx_children_1 (r) case ADDRESSOF: ggc_mark_tree (ADDRESSOF_DECL (r)); break; - case CONST_DOUBLE: - ggc_mark_rtx (CONST_DOUBLE_CHAIN (r)); - break; case NOTE: switch (NOTE_LINE_NUMBER (r)) { diff --git a/gcc/output.h b/gcc/output.h index 289bdc0a1ba..a33f15b2c16 100644 --- a/gcc/output.h +++ b/gcc/output.h @@ -357,11 +357,6 @@ extern void assemble_real PARAMS ((REAL_VALUE_TYPE, #endif #endif -/* At the end of a function, forget the memory-constants - previously made for CONST_DOUBLEs. Mark them as not on real_constant_chain. - Also clear out real_constant_chain and clear out all the chain-pointers. */ -extern void clear_const_double_mem PARAMS ((void)); - /* Start deferring output of subconstants. */ extern void defer_addressed_constants PARAMS ((void)); diff --git a/gcc/real.h b/gcc/real.h index b662089d51e..3de905dfddf 100644 --- a/gcc/real.h +++ b/gcc/real.h @@ -89,7 +89,10 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA + (REAL_VALUE_TYPE_SIZE%HOST_BITS_PER_WIDE_INT ? 1 : 0)) /* round up */ typedef struct { HOST_WIDE_INT r[REAL_WIDTH]; -} REAL_VALUE_TYPE; +} realvaluetype; +/* Various headers condition prototypes on #ifdef REAL_VALUE_TYPE, so it needs + to be a macro. */ +#define REAL_VALUE_TYPE realvaluetype /* Calculate the format for CONST_DOUBLE. We need as many slots as are necessary to overlay a REAL_VALUE_TYPE on them. This could be @@ -99,19 +102,19 @@ typedef struct { slots in a CONST_DOUBLE, so we provide them even if one would suffice. */ #if REAL_WIDTH == 1 -# define CONST_DOUBLE_FORMAT "0ww" +# define CONST_DOUBLE_FORMAT "ww" #else # if REAL_WIDTH == 2 -# define CONST_DOUBLE_FORMAT "0ww" +# define CONST_DOUBLE_FORMAT "ww" # else # if REAL_WIDTH == 3 -# define CONST_DOUBLE_FORMAT "0www" +# define CONST_DOUBLE_FORMAT "www" # else # if REAL_WIDTH == 4 -# define CONST_DOUBLE_FORMAT "0wwww" +# define CONST_DOUBLE_FORMAT "wwww" # else # if REAL_WIDTH == 5 -# define CONST_DOUBLE_FORMAT "0wwwww" +# define CONST_DOUBLE_FORMAT "wwwww" # else #error "REAL_WIDTH > 5 not supported" # endif @@ -265,9 +268,14 @@ REAL_VALUE_TYPE real_value_from_int_cst PARAMS ((union tree_node *, /* Return a CONST_DOUBLE with value R and mode M. */ -#define CONST_DOUBLE_FROM_REAL_VALUE(r, m) immed_real_const_1 (r, m) -extern struct rtx_def *immed_real_const_1 PARAMS ((REAL_VALUE_TYPE, - enum machine_mode)); +#define CONST_DOUBLE_FROM_REAL_VALUE(r, m) \ + const_double_from_real_value (r, m) +extern rtx const_double_from_real_value PARAMS ((REAL_VALUE_TYPE, + enum machine_mode)); + +/* Shorthand; can be handy in machine descriptions. */ +#define CONST_DOUBLE_ATOF(s, m) \ + CONST_DOUBLE_FROM_REAL_VALUE (REAL_VALUE_ATOF (s, m), m) /* Replace R by 1/R in the given machine mode, if the result is exact. */ extern int exact_real_inverse PARAMS ((enum machine_mode, REAL_VALUE_TYPE *)); diff --git a/gcc/rtl.h b/gcc/rtl.h index c164f743763..ebcbd4482d0 100644 --- a/gcc/rtl.h +++ b/gcc/rtl.h @@ -946,11 +946,8 @@ extern const char * const note_insn_name[NOTE_INSN_MAX - NOTE_INSN_BIAS]; For a float, the number of ints varies, and CONST_DOUBLE_LOW is the one that should come first *in memory*. So use &CONST_DOUBLE_LOW(r) as the address of an array of ints. */ -#define CONST_DOUBLE_LOW(r) XCWINT (r, 1, CONST_DOUBLE) -#define CONST_DOUBLE_HIGH(r) XCWINT (r, 2, CONST_DOUBLE) - -/* Link for chain of all CONST_DOUBLEs in use in current function. */ -#define CONST_DOUBLE_CHAIN(r) XCEXP (r, 0, CONST_DOUBLE) +#define CONST_DOUBLE_LOW(r) XCWINT (r, 0, CONST_DOUBLE) +#define CONST_DOUBLE_HIGH(r) XCWINT (r, 1, CONST_DOUBLE) /* For a CONST_VECTOR, return element #n. */ #define CONST_VECTOR_ELT(RTX, N) XCVECEXP (RTX, 0, N, CONST_VECTOR) @@ -1802,11 +1799,9 @@ extern rtx return_address_pointer_rtx; add to this list, modify special_rtx in gengenrtl.c as well. You should also modify gen_rtx to use the special function. */ -extern rtx gen_rtx_CONST_DOUBLE PARAMS ((enum machine_mode, - HOST_WIDE_INT, HOST_WIDE_INT)); extern rtx gen_rtx_CONST_INT PARAMS ((enum machine_mode, HOST_WIDE_INT)); extern rtx gen_raw_REG PARAMS ((enum machine_mode, int)); -extern rtx gen_rtx_REG PARAMS ((enum machine_mode, int)); +extern rtx gen_rtx_REG PARAMS ((enum machine_mode, unsigned)); extern rtx gen_rtx_SUBREG PARAMS ((enum machine_mode, rtx, int)); extern rtx gen_rtx_MEM PARAMS ((enum machine_mode, rtx)); @@ -1883,7 +1878,6 @@ extern rtx gen_lowpart_SUBREG PARAMS ((enum machine_mode, rtx)); extern rtx find_next_ref PARAMS ((rtx, rtx)); extern rtx output_constant_def PARAMS ((tree, int)); -extern rtx immed_real_const PARAMS ((tree)); /* Define a default value for STORE_FLAG_VALUE. */ diff --git a/gcc/toplev.c b/gcc/toplev.c index 4170afde8e8..9213730f629 100644 --- a/gcc/toplev.c +++ b/gcc/toplev.c @@ -3491,10 +3491,6 @@ rest_of_compilation (decl) longer valid. */ init_insn_lengths (); - /* Clear out the real_constant_chain before some of the rtx's - it runs through become garbage. */ - clear_const_double_mem (); - /* Show no temporary slots allocated. */ init_temp_slots (); diff --git a/gcc/varasm.c b/gcc/varasm.c index a463fb39cae..1d9522e7546 100644 --- a/gcc/varasm.c +++ b/gcc/varasm.c @@ -95,10 +95,6 @@ struct varasm_status /* Current offset in constant pool (does not include any machine-specific header). */ HOST_WIDE_INT x_pool_offset; - - /* Chain of all CONST_DOUBLE rtx's constructed for the current function. - They are chained through the CONST_DOUBLE_CHAIN. */ - rtx x_const_double_chain; }; #define const_rtx_hash_table (cfun->varasm->x_const_rtx_hash_table) @@ -106,7 +102,6 @@ struct varasm_status #define first_pool (cfun->varasm->x_first_pool) #define last_pool (cfun->varasm->x_last_pool) #define pool_offset (cfun->varasm->x_pool_offset) -#define const_double_chain (cfun->varasm->x_const_double_chain) /* Number for making the label on the next constant that is stored in memory. */ @@ -2104,190 +2099,6 @@ assemble_real (d, mode, align) } } -/* Here we combine duplicate floating constants to make - CONST_DOUBLE rtx's, and force those out to memory when necessary. */ - -/* Return a CONST_DOUBLE or CONST_INT for a value specified as a pair of ints. - For an integer, I0 is the low-order word and I1 is the high-order word. - For a real number, I0 is the word with the low address - and I1 is the word with the high address. */ - -rtx -immed_double_const (i0, i1, mode) - HOST_WIDE_INT i0, i1; - enum machine_mode mode; -{ - rtx r; - - if (GET_MODE_CLASS (mode) == MODE_INT - || GET_MODE_CLASS (mode) == MODE_PARTIAL_INT) - { - /* We clear out all bits that don't belong in MODE, unless they and our - sign bit are all one. So we get either a reasonable negative value - or a reasonable unsigned value for this mode. */ - int width = GET_MODE_BITSIZE (mode); - if (width < HOST_BITS_PER_WIDE_INT - && ((i0 & ((HOST_WIDE_INT) (-1) << (width - 1))) - != ((HOST_WIDE_INT) (-1) << (width - 1)))) - i0 &= ((HOST_WIDE_INT) 1 << width) - 1, i1 = 0; - else if (width == HOST_BITS_PER_WIDE_INT - && ! (i1 == ~0 && i0 < 0)) - i1 = 0; - else if (width > 2 * HOST_BITS_PER_WIDE_INT) - /* We cannot represent this value as a constant. */ - abort (); - - /* If this would be an entire word for the target, but is not for - the host, then sign-extend on the host so that the number will look - the same way on the host that it would on the target. - - For example, when building a 64 bit alpha hosted 32 bit sparc - targeted compiler, then we want the 32 bit unsigned value -1 to be - represented as a 64 bit value -1, and not as 0x00000000ffffffff. - The later confuses the sparc backend. */ - - if (width < HOST_BITS_PER_WIDE_INT - && (i0 & ((HOST_WIDE_INT) 1 << (width - 1)))) - i0 |= ((HOST_WIDE_INT) (-1) << width); - - /* If MODE fits within HOST_BITS_PER_WIDE_INT, always use a CONST_INT. - - ??? Strictly speaking, this is wrong if we create a CONST_INT - for a large unsigned constant with the size of MODE being - HOST_BITS_PER_WIDE_INT and later try to interpret that constant in a - wider mode. In that case we will mis-interpret it as a negative - number. - - Unfortunately, the only alternative is to make a CONST_DOUBLE - for any constant in any mode if it is an unsigned constant larger - than the maximum signed integer in an int on the host. However, - doing this will break everyone that always expects to see a CONST_INT - for SImode and smaller. - - We have always been making CONST_INTs in this case, so nothing new - is being broken. */ - - if (width <= HOST_BITS_PER_WIDE_INT) - i1 = (i0 < 0) ? ~(HOST_WIDE_INT) 0 : 0; - - /* If this integer fits in one word, return a CONST_INT. */ - if ((i1 == 0 && i0 >= 0) - || (i1 == ~0 && i0 < 0)) - return GEN_INT (i0); - - /* We use VOIDmode for integers. */ - mode = VOIDmode; - } - - /* Search the chain for an existing CONST_DOUBLE with the right value. - If one is found, return it. */ - if (cfun != 0) - for (r = const_double_chain; r; r = CONST_DOUBLE_CHAIN (r)) - if (CONST_DOUBLE_LOW (r) == i0 && CONST_DOUBLE_HIGH (r) == i1 - && GET_MODE (r) == mode) - return r; - - /* No; make a new one and add it to the chain. */ - r = gen_rtx_CONST_DOUBLE (mode, i0, i1); - - /* Don't touch const_double_chain if not inside any function. */ - if (current_function_decl != 0) - { - CONST_DOUBLE_CHAIN (r) = const_double_chain; - const_double_chain = r; - } - - return r; -} - -/* Return a CONST_DOUBLE for a specified `double' value - and machine mode. */ - -rtx -immed_real_const_1 (d, mode) - REAL_VALUE_TYPE d; - enum machine_mode mode; -{ - rtx r; - - /* Detect special cases. Check for NaN first, because some ports - (specifically the i386) do not emit correct ieee-fp code by default, and - thus will generate a core dump here if we pass a NaN to REAL_VALUES_EQUAL - and if REAL_VALUES_EQUAL does a floating point comparison. */ - if (! REAL_VALUE_ISNAN (d) && REAL_VALUES_IDENTICAL (dconst0, d)) - return CONST0_RTX (mode); - else if (! REAL_VALUE_ISNAN (d) && REAL_VALUES_EQUAL (dconst1, d)) - return CONST1_RTX (mode); - else if (! REAL_VALUE_ISNAN (d) && REAL_VALUES_EQUAL (dconst2, d)) - return CONST2_RTX (mode); - - if (sizeof (REAL_VALUE_TYPE) == sizeof (HOST_WIDE_INT)) - return immed_double_const (d.r[0], 0, mode); - if (sizeof (REAL_VALUE_TYPE) == 2 * sizeof (HOST_WIDE_INT)) - return immed_double_const (d.r[0], d.r[1], mode); - - /* The rest of this function handles the case where - a float value requires more than 2 ints of space. - It will be deleted as dead code on machines that don't need it. */ - - /* Search the chain for an existing CONST_DOUBLE with the right value. - If one is found, return it. */ - if (cfun != 0) - for (r = const_double_chain; r; r = CONST_DOUBLE_CHAIN (r)) - if (! memcmp ((char *) &CONST_DOUBLE_LOW (r), (char *) &d, sizeof d) - && GET_MODE (r) == mode) - return r; - - /* No; make a new one and add it to the chain. - - We may be called by an optimizer which may be discarding any memory - allocated during its processing (such as combine and loop). However, - we will be leaving this constant on the chain, so we cannot tolerate - freed memory. */ - r = rtx_alloc (CONST_DOUBLE); - PUT_MODE (r, mode); - memcpy ((char *) &CONST_DOUBLE_LOW (r), (char *) &d, sizeof d); - - /* If we aren't inside a function, don't put r on the - const_double_chain. */ - if (current_function_decl != 0) - { - CONST_DOUBLE_CHAIN (r) = const_double_chain; - const_double_chain = r; - } - else - CONST_DOUBLE_CHAIN (r) = NULL_RTX; - - return r; -} - -/* Return a CONST_DOUBLE rtx for a value specified by EXP, - which must be a REAL_CST tree node. */ - -rtx -immed_real_const (exp) - tree exp; -{ - return immed_real_const_1 (TREE_REAL_CST (exp), TYPE_MODE (TREE_TYPE (exp))); -} - -/* At the end of a function, forget the memory-constants - previously made for CONST_DOUBLEs. Mark them as not on real_constant_chain. - Also clear out real_constant_chain and clear out all the chain-pointers. */ - -void -clear_const_double_mem () -{ - rtx r, next; - - for (r = const_double_chain; r; r = next) - { - next = CONST_DOUBLE_CHAIN (r); - CONST_DOUBLE_CHAIN (r) = 0; - } - const_double_chain = 0; -} - /* Given an expression EXP with a constant value, reduce it to the sum of an assembler symbol and an integer. Store them both in the structure *VALUE. @@ -3470,7 +3281,6 @@ init_varasm_status (f) p->x_first_pool = p->x_last_pool = 0; p->x_pool_offset = 0; - p->x_const_double_chain = 0; } /* Mark PC for GC. */ @@ -3498,7 +3308,6 @@ mark_varasm_status (p) return; mark_pool_constant (p->x_first_pool); - ggc_mark_rtx (p->x_const_double_chain); } /* Clear out all parts of the state in F that can safely be discarded |