diff options
author | Zack Weinberg <zack@gcc.gnu.org> | 2003-10-07 02:23:42 +0000 |
---|---|---|
committer | Zack Weinberg <zack@gcc.gnu.org> | 2003-10-07 02:23:42 +0000 |
commit | 85363ca0942f5f45334b2b2ee56dad289f0ebd27 (patch) | |
tree | 272ff451c0f5e3b65cd727409933c9d1f5119570 /gcc/expr.c | |
parent | 1f1dc5bb85d601f26249deecb9bf77390d674f3d (diff) | |
download | gcc-85363ca0942f5f45334b2b2ee56dad289f0ebd27.zip gcc-85363ca0942f5f45334b2b2ee56dad289f0ebd27.tar.gz gcc-85363ca0942f5f45334b2b2ee56dad289f0ebd27.tar.bz2 |
* libfuncs.h (LTI_extendsfdf2, LTI_extendsfxf2, LTI_extendsftf2)
(LTI_extenddfxf2, LTI_extenddftf2, LTI_truncdfsf2, LTI_truncxfsf2)
(LTI_trunctfsf2, LTI_truncxfdf2, LTI_trunctfdf2, LTI_floatsisf)
(LTI_floatdisf, LTI_floattisf, LTI_floatsidf, LTI_floatdidf)
(LTI_floattidf, LTI_floatsixf, LTI_floatdixf, LTI_floattixf)
(LTI_floatsitf, LTI_floatditf, LTI_floattitf, LTI_fixsfsi, LTI_fixsfdi)
(LTI_fixsfti, LTI_fixdfsi, LTI_fixdfdi, LTI_fixdfti, LTI_fixxfsi)
(LTI_fixxfdi, LTI_fixxfti, LTI_fixtfsi, LTI_fixtfdi, LTI_fixtfti)
(LTI_fixunssfsi, LTI_fixunssfdi, LTI_fixunssfti, LTI_fixunsdfsi)
(LTI_fixunsdfdi, LTI_fixunsdfti, LTI_fixunsxfsi, LTI_fixunsxfdi)
(LTI_fixunsxfti, LTI_fixunstfsi, LTI_fixunstfdi, LTI_fixunstfti)
(extendsfdf2_libfunc, extendsfxf2_libfunc, extendsftf2_libfunc)
(extenddfxf2_libfunc, extenddftf2_libfunc, truncdfsf2_libfunc)
(truncxfsf2_libfunc, trunctfsf2_libfunc, truncxfdf2_libfunc)
(trunctfdf2_libfunc, floatsisf_libfunc, floatdisf_libfunc)
(floattisf_libfunc, floatsidf_libfunc, floatdidf_libfunc)
(floattidf_libfunc, floatsixf_libfunc, floatdixf_libfunc)
(floattixf_libfunc, floatsitf_libfunc, floatditf_libfunc)
(floattitf_libfunc, fixsfsi_libfunc, fixsfdi_libfunc, fixsfti_libfunc)
(fixdfsi_libfunc, fixdfdi_libfunc, fixdfti_libfunc, fixxfsi_libfunc)
(fixxfdi_libfunc, fixxfti_libfunc, fixtfsi_libfunc, fixtfdi_libfunc)
(fixtfti_libfunc, fixunssfsi_libfunc, fixunssfdi_libfunc)
(fixunssfti_libfunc, fixunsdfsi_libfunc, fixunsdfdi_libfunc)
(fixunsdfti_libfunc, fixunsxfsi_libfunc, fixunsxfdi_libfunc)
(fixunsxfti_libfunc, fixunstfsi_libfunc, fixunstfdi_libfunc)
(fixunstfti_libfunc): Delete.
* optabs.h (struct optab_handlers): Break out of struct optab.
(struct convert_optab, convert_optab, enum convert_optab_index,
convert_optab_table, sext_optab, zext_optab, trunc_optab,
sfix_optab, ufix_optab, sfixtrunc_optab, ufixtrunc_optab,
sfloat_optab, ufloat_optab): New.
(set_conv_libfunc): Prototype.
(GEN_FCN): Use C90 indirect call syntax, remove unnecessary cast.
(trunc_optab): Renamed btrunc_optab.
* builtins.c (expand_builtin_mathfn): Update to match.
* optabs.c (extendtab, fixtab, fixtrunctab, floattab): Delete.
(convert_optab_table, new_convert_optab, init_convert_optab)
(init_interclass_conv_libfuncs, init_intraclass_conv_libfuncs)
(set_conv_libfunc): New.
(can_extend_p, gen_extend_insn, can_fix_p, can_float_p)
(expand_float, expand_fix): Use new conversion optabs,
not old insn code tables or long chains of ifs.
(init_optabs): No need to clear old insn code tables.
Initialize the new optabs, not the old libfunc array entries.
Don't handle FIXUNS_TRUNC_LIKE_FIX_TRUNC here.
* genopinit.c: Initialize conversion optabs, not the
former insn code tables. Remove unnecessary casts.
Handle FIXUNS_TRUNC_LIKE_FIX_TRUNC here.
* expr.c (convert_move): Remove redundant check that
to_real==from_real. Use the conversion optabs instead
of long chains of tests of modes. Move partial-integer-mode
interconversion above all integer conversion. Do not recurse
on a value forced into a register in the original mode.
* config/gofast.h, config/frv/frv.c, config/ia64/ia64.c
* config/mips/mips.c, config/pa/pa.c, config/rs6000/rs6000.c
* config/sparc/sparc.c: Use set_conv_libfunc to adjust entries
in new conversion optabs; do not reference the old libfunc
array entries. No need to include libfuncs.h.
From-SVN: r72178
Diffstat (limited to 'gcc/expr.c')
-rw-r--r-- | gcc/expr.c | 529 |
1 files changed, 58 insertions, 471 deletions
@@ -595,248 +595,32 @@ convert_move (rtx to, rtx from, int unsignedp) return; } - if (to_real != from_real) - abort (); - if (to_real) { rtx value, insns; + convert_optab tab; if (GET_MODE_BITSIZE (from_mode) < GET_MODE_BITSIZE (to_mode)) - { - /* Try converting directly if the insn is supported. */ - if ((code = can_extend_p (to_mode, from_mode, 0)) - != CODE_FOR_nothing) - { - emit_unop_insn (code, to, from, UNKNOWN); - return; - } - } + tab = sext_optab; + else if (GET_MODE_BITSIZE (from_mode) > GET_MODE_BITSIZE (to_mode)) + tab = trunc_optab; + else + abort (); -#ifdef HAVE_trunchfqf2 - if (HAVE_trunchfqf2 && from_mode == HFmode && to_mode == QFmode) - { - emit_unop_insn (CODE_FOR_trunchfqf2, to, from, UNKNOWN); - return; - } -#endif -#ifdef HAVE_trunctqfqf2 - if (HAVE_trunctqfqf2 && from_mode == TQFmode && to_mode == QFmode) - { - emit_unop_insn (CODE_FOR_trunctqfqf2, to, from, UNKNOWN); - return; - } -#endif -#ifdef HAVE_truncsfqf2 - if (HAVE_truncsfqf2 && from_mode == SFmode && to_mode == QFmode) - { - emit_unop_insn (CODE_FOR_truncsfqf2, to, from, UNKNOWN); - return; - } -#endif -#ifdef HAVE_truncdfqf2 - if (HAVE_truncdfqf2 && from_mode == DFmode && to_mode == QFmode) - { - emit_unop_insn (CODE_FOR_truncdfqf2, to, from, UNKNOWN); - return; - } -#endif -#ifdef HAVE_truncxfqf2 - if (HAVE_truncxfqf2 && from_mode == XFmode && to_mode == QFmode) - { - emit_unop_insn (CODE_FOR_truncxfqf2, to, from, UNKNOWN); - return; - } -#endif -#ifdef HAVE_trunctfqf2 - if (HAVE_trunctfqf2 && from_mode == TFmode && to_mode == QFmode) - { - emit_unop_insn (CODE_FOR_trunctfqf2, to, from, UNKNOWN); - return; - } -#endif + /* Try converting directly if the insn is supported. */ -#ifdef HAVE_trunctqfhf2 - if (HAVE_trunctqfhf2 && from_mode == TQFmode && to_mode == HFmode) - { - emit_unop_insn (CODE_FOR_trunctqfhf2, to, from, UNKNOWN); - return; - } -#endif -#ifdef HAVE_truncsfhf2 - if (HAVE_truncsfhf2 && from_mode == SFmode && to_mode == HFmode) - { - emit_unop_insn (CODE_FOR_truncsfhf2, to, from, UNKNOWN); - return; - } -#endif -#ifdef HAVE_truncdfhf2 - if (HAVE_truncdfhf2 && from_mode == DFmode && to_mode == HFmode) - { - emit_unop_insn (CODE_FOR_truncdfhf2, to, from, UNKNOWN); - return; - } -#endif -#ifdef HAVE_truncxfhf2 - if (HAVE_truncxfhf2 && from_mode == XFmode && to_mode == HFmode) - { - emit_unop_insn (CODE_FOR_truncxfhf2, to, from, UNKNOWN); - return; - } -#endif -#ifdef HAVE_trunctfhf2 - if (HAVE_trunctfhf2 && from_mode == TFmode && to_mode == HFmode) + code = tab->handlers[to_mode][from_mode].insn_code; + if (code != CODE_FOR_nothing) { - emit_unop_insn (CODE_FOR_trunctfhf2, to, from, UNKNOWN); + emit_unop_insn (code, to, from, + tab == sext_optab ? FLOAT_EXTEND : FLOAT_TRUNCATE); return; } -#endif -#ifdef HAVE_truncsftqf2 - if (HAVE_truncsftqf2 && from_mode == SFmode && to_mode == TQFmode) - { - emit_unop_insn (CODE_FOR_truncsftqf2, to, from, UNKNOWN); - return; - } -#endif -#ifdef HAVE_truncdftqf2 - if (HAVE_truncdftqf2 && from_mode == DFmode && to_mode == TQFmode) - { - emit_unop_insn (CODE_FOR_truncdftqf2, to, from, UNKNOWN); - return; - } -#endif -#ifdef HAVE_truncxftqf2 - if (HAVE_truncxftqf2 && from_mode == XFmode && to_mode == TQFmode) - { - emit_unop_insn (CODE_FOR_truncxftqf2, to, from, UNKNOWN); - return; - } -#endif -#ifdef HAVE_trunctftqf2 - if (HAVE_trunctftqf2 && from_mode == TFmode && to_mode == TQFmode) - { - emit_unop_insn (CODE_FOR_trunctftqf2, to, from, UNKNOWN); - return; - } -#endif + /* Otherwise use a libcall. */ + libcall = tab->handlers[to_mode][from_mode].libfunc; -#ifdef HAVE_truncdfsf2 - if (HAVE_truncdfsf2 && from_mode == DFmode && to_mode == SFmode) - { - emit_unop_insn (CODE_FOR_truncdfsf2, to, from, UNKNOWN); - return; - } -#endif -#ifdef HAVE_truncxfsf2 - if (HAVE_truncxfsf2 && from_mode == XFmode && to_mode == SFmode) - { - emit_unop_insn (CODE_FOR_truncxfsf2, to, from, UNKNOWN); - return; - } -#endif -#ifdef HAVE_trunctfsf2 - if (HAVE_trunctfsf2 && from_mode == TFmode && to_mode == SFmode) - { - emit_unop_insn (CODE_FOR_trunctfsf2, to, from, UNKNOWN); - return; - } -#endif -#ifdef HAVE_truncxfdf2 - if (HAVE_truncxfdf2 && from_mode == XFmode && to_mode == DFmode) - { - emit_unop_insn (CODE_FOR_truncxfdf2, to, from, UNKNOWN); - return; - } -#endif -#ifdef HAVE_trunctfdf2 - if (HAVE_trunctfdf2 && from_mode == TFmode && to_mode == DFmode) - { - emit_unop_insn (CODE_FOR_trunctfdf2, to, from, UNKNOWN); - return; - } -#endif - - libcall = (rtx) 0; - switch (from_mode) - { - case SFmode: - switch (to_mode) - { - case DFmode: - libcall = extendsfdf2_libfunc; - break; - - case XFmode: - libcall = extendsfxf2_libfunc; - break; - - case TFmode: - libcall = extendsftf2_libfunc; - break; - - default: - break; - } - break; - - case DFmode: - switch (to_mode) - { - case SFmode: - libcall = truncdfsf2_libfunc; - break; - - case XFmode: - libcall = extenddfxf2_libfunc; - break; - - case TFmode: - libcall = extenddftf2_libfunc; - break; - - default: - break; - } - break; - - case XFmode: - switch (to_mode) - { - case SFmode: - libcall = truncxfsf2_libfunc; - break; - - case DFmode: - libcall = truncxfdf2_libfunc; - break; - - default: - break; - } - break; - - case TFmode: - switch (to_mode) - { - case SFmode: - libcall = trunctfsf2_libfunc; - break; - - case DFmode: - libcall = trunctfdf2_libfunc; - break; - - default: - break; - } - break; - - default: - break; - } - - if (libcall == (rtx) 0) + if (!libcall) /* This conversion is not implemented yet. */ abort (); @@ -850,6 +634,42 @@ convert_move (rtx to, rtx from, int unsignedp) return; } + /* Handle pointer conversion. */ /* SPEE 900220. */ + /* Targets are expected to provide conversion insns between PxImode and + xImode for all MODE_PARTIAL_INT modes they use, but no others. */ + if (GET_MODE_CLASS (to_mode) == MODE_PARTIAL_INT) + { + enum machine_mode full_mode + = smallest_mode_for_size (GET_MODE_BITSIZE (to_mode), MODE_INT); + + if (trunc_optab->handlers[to_mode][full_mode].insn_code + == CODE_FOR_nothing) + abort (); + + if (full_mode != from_mode) + from = convert_to_mode (full_mode, from, unsignedp); + emit_unop_insn (trunc_optab->handlers[to_mode][full_mode].insn_code, + to, from, UNKNOWN); + return; + } + if (GET_MODE_CLASS (from_mode) == MODE_PARTIAL_INT) + { + enum machine_mode full_mode + = smallest_mode_for_size (GET_MODE_BITSIZE (from_mode), MODE_INT); + + if (sext_optab->handlers[full_mode][from_mode].insn_code + == CODE_FOR_nothing) + abort (); + + emit_unop_insn (sext_optab->handlers[full_mode][from_mode].insn_code, + to, from, UNKNOWN); + if (to_mode == full_mode) + return; + + /* else proceed to integer conversions below */ + from_mode = full_mode; + } + /* Now both modes are integers. */ /* Handle expanding beyond a word. */ @@ -972,119 +792,6 @@ convert_move (rtx to, rtx from, int unsignedp) return; } - /* Handle pointer conversion. */ /* SPEE 900220. */ - if (to_mode == PQImode) - { - if (from_mode != QImode) - from = convert_to_mode (QImode, from, unsignedp); - -#ifdef HAVE_truncqipqi2 - if (HAVE_truncqipqi2) - { - emit_unop_insn (CODE_FOR_truncqipqi2, to, from, UNKNOWN); - return; - } -#endif /* HAVE_truncqipqi2 */ - abort (); - } - - if (from_mode == PQImode) - { - if (to_mode != QImode) - { - from = convert_to_mode (QImode, from, unsignedp); - from_mode = QImode; - } - else - { -#ifdef HAVE_extendpqiqi2 - if (HAVE_extendpqiqi2) - { - emit_unop_insn (CODE_FOR_extendpqiqi2, to, from, UNKNOWN); - return; - } -#endif /* HAVE_extendpqiqi2 */ - abort (); - } - } - - if (to_mode == PSImode) - { - if (from_mode != SImode) - from = convert_to_mode (SImode, from, unsignedp); - -#ifdef HAVE_truncsipsi2 - if (HAVE_truncsipsi2) - { - emit_unop_insn (CODE_FOR_truncsipsi2, to, from, UNKNOWN); - return; - } -#endif /* HAVE_truncsipsi2 */ - abort (); - } - - if (from_mode == PSImode) - { - if (to_mode != SImode) - { - from = convert_to_mode (SImode, from, unsignedp); - from_mode = SImode; - } - else - { -#ifdef HAVE_extendpsisi2 - if (! unsignedp && HAVE_extendpsisi2) - { - emit_unop_insn (CODE_FOR_extendpsisi2, to, from, UNKNOWN); - return; - } -#endif /* HAVE_extendpsisi2 */ -#ifdef HAVE_zero_extendpsisi2 - if (unsignedp && HAVE_zero_extendpsisi2) - { - emit_unop_insn (CODE_FOR_zero_extendpsisi2, to, from, UNKNOWN); - return; - } -#endif /* HAVE_zero_extendpsisi2 */ - abort (); - } - } - - if (to_mode == PDImode) - { - if (from_mode != DImode) - from = convert_to_mode (DImode, from, unsignedp); - -#ifdef HAVE_truncdipdi2 - if (HAVE_truncdipdi2) - { - emit_unop_insn (CODE_FOR_truncdipdi2, to, from, UNKNOWN); - return; - } -#endif /* HAVE_truncdipdi2 */ - abort (); - } - - if (from_mode == PDImode) - { - if (to_mode != DImode) - { - from = convert_to_mode (DImode, from, unsignedp); - from_mode = DImode; - } - else - { -#ifdef HAVE_extendpdidi2 - if (HAVE_extendpdidi2) - { - emit_unop_insn (CODE_FOR_extendpdidi2, to, from, UNKNOWN); - return; - } -#endif /* HAVE_extendpdidi2 */ - abort (); - } - } - /* Now follow all the conversions between integers no more than a word long. */ @@ -1158,140 +865,20 @@ convert_move (rtx to, rtx from, int unsignedp) } /* Support special truncate insns for certain modes. */ - - if (from_mode == DImode && to_mode == SImode) + if (trunc_optab->handlers[to_mode][from_mode].insn_code != CODE_FOR_nothing) { -#ifdef HAVE_truncdisi2 - if (HAVE_truncdisi2) - { - emit_unop_insn (CODE_FOR_truncdisi2, to, from, UNKNOWN); - return; - } -#endif - convert_move (to, force_reg (from_mode, from), unsignedp); - return; - } - - if (from_mode == DImode && to_mode == HImode) - { -#ifdef HAVE_truncdihi2 - if (HAVE_truncdihi2) - { - emit_unop_insn (CODE_FOR_truncdihi2, to, from, UNKNOWN); - return; - } -#endif - convert_move (to, force_reg (from_mode, from), unsignedp); - return; - } - - if (from_mode == DImode && to_mode == QImode) - { -#ifdef HAVE_truncdiqi2 - if (HAVE_truncdiqi2) - { - emit_unop_insn (CODE_FOR_truncdiqi2, to, from, UNKNOWN); - return; - } -#endif - convert_move (to, force_reg (from_mode, from), unsignedp); - return; - } - - if (from_mode == SImode && to_mode == HImode) - { -#ifdef HAVE_truncsihi2 - if (HAVE_truncsihi2) - { - emit_unop_insn (CODE_FOR_truncsihi2, to, from, UNKNOWN); - return; - } -#endif - convert_move (to, force_reg (from_mode, from), unsignedp); - return; - } - - if (from_mode == SImode && to_mode == QImode) - { -#ifdef HAVE_truncsiqi2 - if (HAVE_truncsiqi2) - { - emit_unop_insn (CODE_FOR_truncsiqi2, to, from, UNKNOWN); - return; - } -#endif - convert_move (to, force_reg (from_mode, from), unsignedp); - return; - } - - if (from_mode == HImode && to_mode == QImode) - { -#ifdef HAVE_trunchiqi2 - if (HAVE_trunchiqi2) - { - emit_unop_insn (CODE_FOR_trunchiqi2, to, from, UNKNOWN); - return; - } -#endif - convert_move (to, force_reg (from_mode, from), unsignedp); - return; - } - - if (from_mode == TImode && to_mode == DImode) - { -#ifdef HAVE_trunctidi2 - if (HAVE_trunctidi2) - { - emit_unop_insn (CODE_FOR_trunctidi2, to, from, UNKNOWN); - return; - } -#endif - convert_move (to, force_reg (from_mode, from), unsignedp); - return; - } - - if (from_mode == TImode && to_mode == SImode) - { -#ifdef HAVE_trunctisi2 - if (HAVE_trunctisi2) - { - emit_unop_insn (CODE_FOR_trunctisi2, to, from, UNKNOWN); - return; - } -#endif - convert_move (to, force_reg (from_mode, from), unsignedp); - return; - } - - if (from_mode == TImode && to_mode == HImode) - { -#ifdef HAVE_trunctihi2 - if (HAVE_trunctihi2) - { - emit_unop_insn (CODE_FOR_trunctihi2, to, from, UNKNOWN); - return; - } -#endif - convert_move (to, force_reg (from_mode, from), unsignedp); - return; - } - - if (from_mode == TImode && to_mode == QImode) - { -#ifdef HAVE_trunctiqi2 - if (HAVE_trunctiqi2) - { - emit_unop_insn (CODE_FOR_trunctiqi2, to, from, UNKNOWN); - return; - } -#endif - convert_move (to, force_reg (from_mode, from), unsignedp); + emit_unop_insn (trunc_optab->handlers[to_mode][from_mode].insn_code, + to, from, UNKNOWN); return; } /* Handle truncation of volatile memrefs, and so on; the things that couldn't be truncated directly, - and for which there was no special instruction. */ + and for which there was no special instruction. + + ??? Code above formerly short-circuited this, for most integer + mode pairs, with a force_reg in from_mode followed by a recursive + call to this routine. Appears always to have been wrong. */ if (GET_MODE_BITSIZE (to_mode) < GET_MODE_BITSIZE (from_mode)) { rtx temp = force_reg (to_mode, gen_lowpart (to_mode, from)); |