From: Zack Weinberg Date: Tue, 7 Oct 2003 02:23:42 +0000 (+0000) Subject: * libfuncs.h (LTI_extendsfdf2, LTI_extendsfxf2, LTI_extendsftf2) X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=85363ca0942f5f45334b2b2ee56dad289f0ebd27;p=platform%2Fupstream%2Fgcc.git * 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 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index cbd783f..a7a3b0c 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,65 @@ +2003-10-06 Zack Weinberg + + * 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. + 2003-10-06 Roger Sayle * config/i386/i386.c (ix86_expand_setcc): Annotate the floating @@ -18,9 +80,9 @@ 2003-10-06 Falk Hueffner - PR optimization/11974 - * optabs.c (expand_unop): Promote libcall outmode according to - hard_libcall_value. + PR optimization/11974 + * optabs.c (expand_unop): Promote libcall outmode according to + hard_libcall_value. 2003-10-06 Zack Weinberg diff --git a/gcc/builtins.c b/gcc/builtins.c index d7d7604..8aabaa7 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -1652,7 +1652,7 @@ expand_builtin_mathfn (tree exp, rtx target, rtx subtarget) case BUILT_IN_TRUNC: case BUILT_IN_TRUNCF: case BUILT_IN_TRUNCL: - builtin_optab = trunc_optab; break; + builtin_optab = btrunc_optab; break; case BUILT_IN_ROUND: case BUILT_IN_ROUNDF: case BUILT_IN_ROUNDL: diff --git a/gcc/config/frv/frv.c b/gcc/config/frv/frv.c index 0d83982..c9eab11 100644 --- a/gcc/config/frv/frv.c +++ b/gcc/config/frv/frv.c @@ -40,7 +40,6 @@ Boston, MA 02111-1307, USA. */ #include "except.h" #include "function.h" #include "optabs.h" -#include "libfuncs.h" #include "toplev.h" #include "basic-block.h" #include "tm_p.h" @@ -9145,20 +9144,23 @@ frv_init_libfuncs (void) set_optab_libfunc (smul_optab, DFmode, "__muld"); set_optab_libfunc (sdiv_optab, DFmode, "__divd"); - fixsfsi_libfunc = init_one_libfunc ("__ftoi"); - fixunssfsi_libfunc = init_one_libfunc ("__ftoui"); - fixsfdi_libfunc = init_one_libfunc ("__ftoll"); - fixunssfdi_libfunc = init_one_libfunc ("__ftoull"); - fixdfsi_libfunc = init_one_libfunc ("__dtoi"); - fixunsdfsi_libfunc = init_one_libfunc ("__dtoui"); - fixdfdi_libfunc = init_one_libfunc ("__dtoll"); - fixunsdfdi_libfunc = init_one_libfunc ("__dtoull"); - floatsisf_libfunc = init_one_libfunc ("__itof"); - floatdisf_libfunc = init_one_libfunc ("__lltof"); - floatsidf_libfunc = init_one_libfunc ("__itod"); - floatdidf_libfunc = init_one_libfunc ("__lltod"); - extendsfdf2_libfunc = init_one_libfunc ("__ftod"); - truncdfsf2_libfunc = init_one_libfunc ("__dtof"); + set_conv_libfunc (sext_optab, DFmode, SFmode, "__ftod"); + set_conv_libfunc (trunc_optab, SFmode, DFmode, "__dtof"); + + set_conv_libfunc (sfix_optab, SImode, SFmode, "__ftoi"); + set_conv_libfunc (sfix_optab, DImode, SFmode, "__ftoll"); + set_conv_libfunc (sfix_optab, SImode, DFmode, "__dtoi"); + set_conv_libfunc (sfix_optab, DImode, DFmode, "__dtoll"); + + set_conv_libfunc (ufix_optab, SImode, SFmode, "__ftoui"); + set_conv_libfunc (ufix_optab, SImode, SFmode, "__ftoull"); + set_conv_libfunc (ufix_optab, SImode, SFmode, "__dtoui"); + set_conv_libfunc (ufix_optab, SImode, SFmode, "__dtoull"); + + set_conv_libfunc (sfloat_optab, SFmode, SImode, "__itof"); + set_conv_libfunc (sfloat_optab, SFmode, DImode, "__lltof"); + set_conv_libfunc (sfloat_optab, DFmode, SImode, "__itod"); + set_conv_libfunc (sfloat_optab, DFmode, DImode, "__lltod"); } /* Convert an integer constant to an accumulator register. ICODE is the diff --git a/gcc/config/gofast.h b/gcc/config/gofast.h index 3b3efb9..91b0a65 100644 --- a/gcc/config/gofast.h +++ b/gcc/config/gofast.h @@ -66,14 +66,15 @@ gofast_maybe_init_libfuncs (void) set_optab_libfunc (lt_optab, DFmode, "dpcmp"); set_optab_libfunc (le_optab, DFmode, "dpcmp"); - extendsfdf2_libfunc = init_one_libfunc ("fptodp"); - truncdfsf2_libfunc = init_one_libfunc ("dptofp"); + set_conv_libfunc (sext_optab, DFmode, SFmode, "fptodp"); + set_conv_libfunc (trunc_optab, SFmode, DFmode, "dptofp"); - floatsisf_libfunc = init_one_libfunc ("sitofp"); - floatsidf_libfunc = init_one_libfunc ("litodp"); - fixsfsi_libfunc = init_one_libfunc ("fptosi"); - fixdfsi_libfunc = init_one_libfunc ("dptoli"); - fixunssfsi_libfunc = init_one_libfunc ("fptoui"); - fixunsdfsi_libfunc = init_one_libfunc ("dptoul"); + set_conv_libfunc (sfix_optab, SImode, SFmode, "fptosi"); + set_conv_libfunc (sfix_optab, SImode, DFmode, "dptoli"); + set_conv_libfunc (ufix_optab, SImode, SFmode, "fptoui"); + set_conv_libfunc (ufix_optab, SImode, DFmode, "dptoul"); + + set_conv_libfunc (sfloat_optab, SFmode, SImode, "sitofp"); + set_conv_libfunc (sfloat_optab, DFmode, DImode, "litodp"); #endif } diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c index b632d8b..75a2cb6 100644 --- a/gcc/config/ia64/ia64.c +++ b/gcc/config/ia64/ia64.c @@ -37,7 +37,6 @@ Boston, MA 02111-1307, USA. */ #include "recog.h" #include "expr.h" #include "optabs.h" -#include "libfuncs.h" #include "except.h" #include "function.h" #include "ggc.h" @@ -8327,16 +8326,18 @@ ia64_hpux_init_libfuncs (void) set_optab_libfunc (lt_optab, TFmode, "_U_Qflt"); set_optab_libfunc (le_optab, TFmode, "_U_Qfle"); - extendsftf2_libfunc = init_one_libfunc ("_U_Qfcnvff_sgl_to_quad"); - extenddftf2_libfunc = init_one_libfunc ("_U_Qfcnvff_dbl_to_quad"); - trunctfsf2_libfunc = init_one_libfunc ("_U_Qfcnvff_quad_to_sgl"); - trunctfdf2_libfunc = init_one_libfunc ("_U_Qfcnvff_quad_to_dbl"); - floatsitf_libfunc = init_one_libfunc ("_U_Qfcnvxf_sgl_to_quad"); - floatditf_libfunc = init_one_libfunc ("_U_Qfcnvxf_dbl_to_quad"); - fixtfsi_libfunc = init_one_libfunc ("_U_Qfcnvfxt_quad_to_sgl"); - fixtfdi_libfunc = init_one_libfunc ("_U_Qfcnvfxt_quad_to_dbl"); - fixunstfsi_libfunc = init_one_libfunc ("_U_Qfcnvfxut_quad_to_sgl"); - fixunstfdi_libfunc = init_one_libfunc ("_U_Qfcnvfxut_quad_to_dbl"); + set_conv_libfunc (sext_optab, TFmode, SFmode, "_U_Qfcnvff_sgl_to_quad"); + set_conv_libfunc (sext_optab, TFmode, DFmode, "_U_Qfcnvff_dbl_to_quad"); + set_conv_libfunc (trunc_optab, SFmode, TFmode, "_U_Qfcnvff_quad_to_sgl"); + set_conv_libfunc (trunc_optab, DFmode, TFmode, "_U_Qfcnvff_quad_to_dbl"); + + set_conv_libfunc (sfix_optab, SImode, TFmode, "_U_Qfcnvfxt_quad_to_sgl"); + set_conv_libfunc (sfix_optab, DImode, TFmode, "_U_Qfcnvfxt_quad_to_dbl"); + set_conv_libfunc (ufix_optab, SImode, TFmode, "_U_Qfcnvfxut_quad_to_sgl"); + set_conv_libfunc (ufix_optab, DImode, TFmode, "_U_Qfcnvfxut_quad_to_dbl"); + + set_conv_libfunc (sfloat_optab, TFmode, SImode, "_U_Qfcnvxf_sgl_to_quad"); + set_conv_libfunc (sfloat_optab, TFmode, DImode, "_U_Qfcnvxf_dbl_to_quad"); } /* Switch to the section to which we should output X. The only thing diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index 9478ec1..773d6a1 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -42,7 +42,6 @@ Boston, MA 02111-1307, USA. */ #include "function.h" #include "expr.h" #include "optabs.h" -#include "libfuncs.h" #include "flags.h" #include "reload.h" #include "tm_p.h" @@ -9043,8 +9042,8 @@ mips_init_libfuncs (void) set_optab_libfunc (lt_optab, SFmode, "__mips16_ltsf2"); set_optab_libfunc (le_optab, SFmode, "__mips16_lesf2"); - floatsisf_libfunc = init_one_libfunc ("__mips16_floatsisf"); - fixsfsi_libfunc = init_one_libfunc ("__mips16_fixsfsi"); + set_conv_libfunc (sfix_optab, SImode, SFmode, "__mips16_fixsfsi"); + set_conv_libfunc (sfloat_optab, SFmode, SImode, "__mips16_floatsisf"); if (TARGET_DOUBLE_FLOAT) { @@ -9060,11 +9059,11 @@ mips_init_libfuncs (void) set_optab_libfunc (lt_optab, DFmode, "__mips16_ltdf2"); set_optab_libfunc (le_optab, DFmode, "__mips16_ledf2"); - floatsidf_libfunc = init_one_libfunc ("__mips16_floatsidf"); - fixdfsi_libfunc = init_one_libfunc ("__mips16_fixdfsi"); + set_conv_libfunc (sext_optab, DFmode, SFmode, "__mips16_extendsfdf2"); + set_conv_libfunc (trunc_optab, SFmode, DFmode, "__mips16_truncdfsf2"); - extendsfdf2_libfunc = init_one_libfunc ("__mips16_extendsfdf2"); - truncdfsf2_libfunc = init_one_libfunc ("__mips16_truncdfsf2"); + set_conv_libfunc (sfix_optab, SImode, DFmode, "__mips16_fixdfsi"); + set_conv_libfunc (sfloat_optab, DFmode, SImode, "__mips16_floatsidf"); } } else diff --git a/gcc/config/pa/pa.c b/gcc/config/pa/pa.c index a5b9a4d..a438ac4 100644 --- a/gcc/config/pa/pa.c +++ b/gcc/config/pa/pa.c @@ -37,7 +37,6 @@ Boston, MA 02111-1307, USA. */ #include "except.h" #include "expr.h" #include "optabs.h" -#include "libfuncs.h" #include "reload.h" #include "integrate.h" #include "function.h" @@ -4980,18 +4979,20 @@ pa_hpux_init_libfuncs (void) set_optab_libfunc (lt_optab, TFmode, "_U_Qflt"); set_optab_libfunc (le_optab, TFmode, "_U_Qfle"); - extendsftf2_libfunc = init_one_libfunc ("_U_Qfcnvff_sgl_to_quad"); - extenddftf2_libfunc = init_one_libfunc ("_U_Qfcnvff_dbl_to_quad"); - trunctfsf2_libfunc = init_one_libfunc ("_U_Qfcnvff_quad_to_sgl"); - trunctfdf2_libfunc = init_one_libfunc ("_U_Qfcnvff_quad_to_dbl"); - floatsitf_libfunc = init_one_libfunc ("_U_Qfcnvxf_sgl_to_quad"); - floatditf_libfunc = init_one_libfunc ("_U_Qfcnvxf_dbl_to_quad"); - fixtfsi_libfunc = init_one_libfunc (TARGET_64BIT - ? "__U_Qfcnvfxt_quad_to_sgl" - : "_U_Qfcnvfxt_quad_to_sgl"); - fixtfdi_libfunc = init_one_libfunc ("_U_Qfcnvfxt_quad_to_dbl"); - fixunstfsi_libfunc = init_one_libfunc ("_U_Qfcnvfxt_quad_to_usgl"); - fixunstfdi_libfunc = init_one_libfunc ("_U_Qfcnvfxt_quad_to_udbl"); + set_conv_libfunc (sext_optab, TFmode, SFmode, "_U_Qfcnvff_sgl_to_quad"); + set_conv_libfunc (sext_optab, TFmode, DFmode, "_U_Qfcnvff_dbl_to_quad"); + set_conv_libfunc (trunc_optab, SFmode, TFmode, "_U_Qfcnvff_quad_to_sgl"); + set_conv_libfunc (trunc_optab, DFmode, TFmode, "_U_Qfcnvff_quad_to_dbl"); + + set_conv_libfunc (sfix_optab, SImode, TFmode, TARGET_64BIT + ? "__U_Qfcnvfxt_quad_to_sgl" + : "_U_Qfcnvfxt_quad_to_sgl"); + set_conv_libfunc (sfix_optab, DImode, TFmode, "_U_Qfcnvfxt_quad_to_dbl"); + set_conv_libfunc (ufix_optab, SImode, TFmode, "_U_Qfcnvfxt_quad_to_usgl"); + set_conv_libfunc (ufix_optab, DImode, TFmode, "_U_Qfcnvfxt_quad_to_udbl"); + + set_conv_libfunc (sfloat_optab, TFmode, SImode, "_U_Qfcnvxf_sgl_to_quad"); + set_conv_libfunc (sfloat_optab, TFmode, DImode, "_U_Qfcnvxf_dbl_to_quad"); } #endif diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 4316b23..be79acc 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -37,7 +37,6 @@ #include "tree.h" #include "expr.h" #include "optabs.h" -#include "libfuncs.h" #include "except.h" #include "function.h" #include "output.h" @@ -6784,8 +6783,8 @@ rs6000_init_libfuncs (void) if (TARGET_XCOFF && ! TARGET_POWER2 && ! TARGET_POWERPC) { /* AIX library routines for float->int conversion. */ - fixdfsi_libfunc = init_one_libfunc ("__itrunc"); - fixunsdfsi_libfunc = init_one_libfunc ("__uitrunc"); + set_conv_libfunc (sfix_optab, SImode, DFmode, "__itrunc"); + set_conv_libfunc (ufix_optab, SImode, DFmode, "__uitrunc"); } /* Standard AIX/Darwin/64-bit SVR4 quad floating point routines. */ @@ -6813,17 +6812,15 @@ rs6000_init_libfuncs (void) set_optab_libfunc (lt_optab, TFmode, "_q_flt"); set_optab_libfunc (le_optab, TFmode, "_q_fle"); - trunctfsf2_libfunc = init_one_libfunc ("_q_qtos"); - trunctfdf2_libfunc = init_one_libfunc ("_q_qtod"); - extendsftf2_libfunc = init_one_libfunc ("_q_stoq"); - extenddftf2_libfunc = init_one_libfunc ("_q_dtoq"); - floatsitf_libfunc = init_one_libfunc ("_q_itoq"); - fixtfsi_libfunc = init_one_libfunc ("_q_qtoi"); - fixunstfsi_libfunc = init_one_libfunc ("_q_qtou"); + set_conv_libfunc (sext_optab, TFmode, SFmode, "_q_stoq"); + set_conv_libfunc (sext_optab, TFmode, DFmode, "_q_dtoq"); + set_conv_libfunc (trunc_optab, SFmode, TFmode, "_q_qtos"); + set_conv_libfunc (trunc_optab, DFmode, TFmode, "_q_qtod"); + set_conv_libfunc (sfix_optab, SImode, TFmode, "_q_qtoi"); + set_conv_libfunc (ufix_optab, SImode, TFmode, "_q_qtou"); + set_conv_libfunc (sfloat_optab, TFmode, SImode, "_q_itoq"); } } - - /* Expand a block move operation, and return 1 if successful. Return 0 if we should let the compiler generate normal code. diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c index adea22f..96335c9 100644 --- a/gcc/config/sparc/sparc.c +++ b/gcc/config/sparc/sparc.c @@ -39,7 +39,6 @@ Boston, MA 02111-1307, USA. */ #include "function.h" #include "expr.h" #include "optabs.h" -#include "libfuncs.h" #include "recog.h" #include "toplev.h" #include "ggc.h" @@ -8431,20 +8430,21 @@ sparc_init_libfuncs (void) set_optab_libfunc (lt_optab, TFmode, "_Q_flt"); set_optab_libfunc (le_optab, TFmode, "_Q_fle"); - trunctfsf2_libfunc = init_one_libfunc ("_Q_qtos"); - trunctfdf2_libfunc = init_one_libfunc ("_Q_qtod"); - extendsftf2_libfunc = init_one_libfunc ("_Q_stoq"); - extenddftf2_libfunc = init_one_libfunc ("_Q_dtoq"); - floatsitf_libfunc = init_one_libfunc ("_Q_itoq"); - fixtfsi_libfunc = init_one_libfunc ("_Q_qtoi"); - fixunstfsi_libfunc = init_one_libfunc ("_Q_qtou"); + set_conv_libfunc (sext_optab, TFmode, SFmode, "_Q_stoq"); + set_conv_libfunc (sext_optab, TFmode, DFmode, "_Q_dtoq"); + set_conv_libfunc (trunc_optab, SFmode, TFmode, "_Q_qtos"); + set_conv_libfunc (trunc_optab, DFmode, TFmode, "_Q_qtod"); + + set_conv_libfunc (sfix_optab, SImode, TFmode, "_Q_qtoi"); + set_conv_libfunc (ufix_optab, SImode, TFmode, "_Q_qtou"); + set_conv_libfunc (sfloat_optab, TFmode, SImode, "_Q_itoq"); if (SUN_CONVERSION_LIBFUNCS) { - fixsfdi_libfunc = init_one_libfunc ("__ftoll"); - fixunssfdi_libfunc = init_one_libfunc ("__ftoull"); - fixdfdi_libfunc = init_one_libfunc ("__dtoll"); - fixunsdfdi_libfunc = init_one_libfunc ("__dtoull"); + set_conv_libfunc (sfix_optab, DImode, SFmode, "__ftoll"); + set_conv_libfunc (ufix_optab, DImode, SFmode, "__ftoull"); + set_conv_libfunc (sfix_optab, DImode, DFmode, "__dtoll"); + set_conv_libfunc (ufix_optab, DImode, DFmode, "__dtoull"); } } if (TARGET_ARCH64) @@ -8470,10 +8470,10 @@ sparc_init_libfuncs (void) if (SUN_CONVERSION_LIBFUNCS) { - fixsfdi_libfunc = init_one_libfunc ("__ftol"); - fixunssfdi_libfunc = init_one_libfunc ("__ftoul"); - fixdfdi_libfunc = init_one_libfunc ("__dtol"); - fixunsdfdi_libfunc = init_one_libfunc ("__dtoul"); + set_conv_libfunc (sfix_optab, DImode, SFmode, "__ftol"); + set_conv_libfunc (ufix_optab, DImode, SFmode, "__ftoul"); + set_conv_libfunc (sfix_optab, DImode, DFmode, "__dtol"); + set_conv_libfunc (ufix_optab, DImode, DFmode, "__dtoul"); } } diff --git a/gcc/expr.c b/gcc/expr.c index edc4290..015faaf 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -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)); diff --git a/gcc/genopinit.c b/gcc/genopinit.c index a0728fa..cded6e3 100644 --- a/gcc/genopinit.c +++ b/gcc/genopinit.c @@ -59,32 +59,33 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA upper-case forms of the comparison, respectively. */ static const char * const optabs[] = -{ "extendtab[$B][$A][0] = CODE_FOR_$(extend$a$b2$)", - "extendtab[$B][$A][1] = CODE_FOR_$(zero_extend$a$b2$)", - "fixtab[$A][$B][0] = CODE_FOR_$(fix$F$a$I$b2$)", - "fixtab[$A][$B][1] = CODE_FOR_$(fixuns$F$a$b2$)", - "fixtrunctab[$A][$B][0] = CODE_FOR_$(fix_trunc$F$a$I$b2$)", - "fixtrunctab[$A][$B][1] = CODE_FOR_$(fixuns_trunc$F$a$I$b2$)", - "floattab[$B][$A][0] = CODE_FOR_$(float$I$a$F$b2$)", - "floattab[$B][$A][1] = CODE_FOR_$(floatuns$I$a$F$b2$)", +{ "sext_optab->handlers[$B][$A].insn_code = CODE_FOR_$(extend$a$b2$)", + "zext_optab->handlers[$B][$A].insn_code = CODE_FOR_$(zero_extend$a$b2$)", + "sfix_optab->handlers[$B][$A].insn_code = CODE_FOR_$(fix$F$a$I$b2$)", + "ufix_optab->handlers[$B][$A].insn_code = CODE_FOR_$(fixuns$F$a$b2$)", + "sfixtrunc_optab->handlers[$B][$A].insn_code = CODE_FOR_$(fix_trunc$F$a$I$b2$)", + "ufixtrunc_optab->handlers[$B][$A].insn_code = CODE_FOR_$(fixuns_trunc$F$a$I$b2$)", + "sfloat_optab->handlers[$B][$A].insn_code = CODE_FOR_$(float$I$a$F$b2$)", + "ufloat_optab->handlers[$B][$A].insn_code = CODE_FOR_$(floatuns$I$a$F$b2$)", + "trunc_optab->handlers[$B][$A].insn_code = CODE_FOR_$(trunc$a$b2$)", "add_optab->handlers[$A].insn_code = CODE_FOR_$(add$P$a3$)", - "addv_optab->handlers[(int) $A].insn_code =\n\ - add_optab->handlers[(int) $A].insn_code = CODE_FOR_$(add$F$a3$)", - "addv_optab->handlers[(int) $A].insn_code = CODE_FOR_$(addv$I$a3$)", + "addv_optab->handlers[$A].insn_code =\n\ + add_optab->handlers[$A].insn_code = CODE_FOR_$(add$F$a3$)", + "addv_optab->handlers[$A].insn_code = CODE_FOR_$(addv$I$a3$)", "sub_optab->handlers[$A].insn_code = CODE_FOR_$(sub$P$a3$)", - "subv_optab->handlers[(int) $A].insn_code =\n\ - sub_optab->handlers[(int) $A].insn_code = CODE_FOR_$(sub$F$a3$)", - "subv_optab->handlers[(int) $A].insn_code = CODE_FOR_$(subv$I$a3$)", + "subv_optab->handlers[$A].insn_code =\n\ + sub_optab->handlers[$A].insn_code = CODE_FOR_$(sub$F$a3$)", + "subv_optab->handlers[$A].insn_code = CODE_FOR_$(subv$I$a3$)", "smul_optab->handlers[$A].insn_code = CODE_FOR_$(mul$P$a3$)", - "smulv_optab->handlers[(int) $A].insn_code =\n\ - smul_optab->handlers[(int) $A].insn_code = CODE_FOR_$(mul$F$a3$)", - "smulv_optab->handlers[(int) $A].insn_code = CODE_FOR_$(mulv$I$a3$)", + "smulv_optab->handlers[$A].insn_code =\n\ + smul_optab->handlers[$A].insn_code = CODE_FOR_$(mul$F$a3$)", + "smulv_optab->handlers[$A].insn_code = CODE_FOR_$(mulv$I$a3$)", "umul_highpart_optab->handlers[$A].insn_code = CODE_FOR_$(umul$a3_highpart$)", "smul_highpart_optab->handlers[$A].insn_code = CODE_FOR_$(smul$a3_highpart$)", "smul_widen_optab->handlers[$B].insn_code = CODE_FOR_$(mul$a$b3$)$N", "umul_widen_optab->handlers[$B].insn_code = CODE_FOR_$(umul$a$b3$)$N", "sdiv_optab->handlers[$A].insn_code = CODE_FOR_$(div$a3$)", - "sdivv_optab->handlers[(int) $A].insn_code = CODE_FOR_$(div$V$I$a3$)", + "sdivv_optab->handlers[$A].insn_code = CODE_FOR_$(div$V$I$a3$)", "udiv_optab->handlers[$A].insn_code = CODE_FOR_$(udiv$I$a3$)", "sdivmod_optab->handlers[$A].insn_code = CODE_FOR_$(divmod$a4$)", "udivmod_optab->handlers[$A].insn_code = CODE_FOR_$(udivmod$a4$)", @@ -108,13 +109,13 @@ static const char * const optabs[] = "pow_optab->handlers[$A].insn_code = CODE_FOR_$(pow$a3$)", "atan2_optab->handlers[$A].insn_code = CODE_FOR_$(atan2$a3$)", "neg_optab->handlers[$A].insn_code = CODE_FOR_$(neg$P$a2$)", - "negv_optab->handlers[(int) $A].insn_code =\n\ - neg_optab->handlers[(int) $A].insn_code = CODE_FOR_$(neg$F$a2$)", - "negv_optab->handlers[(int) $A].insn_code = CODE_FOR_$(negv$I$a2$)", + "negv_optab->handlers[$A].insn_code =\n\ + neg_optab->handlers[$A].insn_code = CODE_FOR_$(neg$F$a2$)", + "negv_optab->handlers[$A].insn_code = CODE_FOR_$(negv$I$a2$)", "abs_optab->handlers[$A].insn_code = CODE_FOR_$(abs$P$a2$)", - "absv_optab->handlers[(int) $A].insn_code =\n\ - abs_optab->handlers[(int) $A].insn_code = CODE_FOR_$(abs$F$a2$)", - "absv_optab->handlers[(int) $A].insn_code = CODE_FOR_$(absv$I$a2$)", + "absv_optab->handlers[$A].insn_code =\n\ + abs_optab->handlers[$A].insn_code = CODE_FOR_$(abs$F$a2$)", + "absv_optab->handlers[$A].insn_code = CODE_FOR_$(absv$I$a2$)", "sqrt_optab->handlers[$A].insn_code = CODE_FOR_$(sqrt$a2$)", "floor_optab->handlers[$A].insn_code = CODE_FOR_$(floor$a2$)", "ceil_optab->handlers[$A].insn_code = CODE_FOR_$(ceil$a2$)", @@ -229,7 +230,7 @@ gen_insn (rtx insn) look through the modes in reverse order, in case EXTRA_CC_MODES was used and CC is a prefix of the CC modes (as it should be). */ - for (i = ((int) MAX_MACHINE_MODE) - 1; i >= 0; i--) + for (i = (MAX_MACHINE_MODE) - 1; i >= 0; i--) { for (p = GET_MODE_NAME(i), q = np; *p; p++, q++) if (TOLOWER (*p) != *q) @@ -303,16 +304,15 @@ gen_insn (rtx insn) putchar (TOLOWER (*np)); break; case 'A': - printf ("(int) %smode", GET_MODE_NAME(m1)); + printf ("%smode", GET_MODE_NAME(m1)); break; case 'B': - printf ("(int) %smode", GET_MODE_NAME(m2)); + printf ("%smode", GET_MODE_NAME(m2)); break; case 'c': printf ("%s", GET_RTX_NAME(op)); break; case 'C': - printf ("(int) "); for (np = GET_RTX_NAME(op); *np; np++) putchar (TOUPPER (*np)); break; @@ -368,7 +368,17 @@ from the machine description file `md'. */\n\n"); gen_insn (desc); } - printf ("}\n"); + puts ("\ +\n\ +#ifdef FIXUNS_TRUNC_LIKE_FIX_TRUNC\n\ + /* This flag says the same insns that convert to a signed fixnum\n\ + also convert validly to an unsigned one. */\n\ + for (i = 0; i < NUM_MACHINE_MODES; i++)\n\ + for (j = 0; j < NUM_MACHINE_MODES; j++)\n\ + ufixtrunc_optab->handlers[i][j].insn_code\n\ + = sfixtrunc_optab->handlers[i][j].insn_code;\n\ +#endif\n\ +}"); fflush (stdout); return (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE); diff --git a/gcc/libfuncs.h b/gcc/libfuncs.h index d919ddf..d4bd644 100644 --- a/gcc/libfuncs.h +++ b/gcc/libfuncs.h @@ -24,18 +24,6 @@ Boston, MA 02111-1307, USA. */ /* Enumeration of indexes into libfunc_table. */ enum libfunc_index { - LTI_extendsfdf2, - LTI_extendsfxf2, - LTI_extendsftf2, - LTI_extenddfxf2, - LTI_extenddftf2, - - LTI_truncdfsf2, - LTI_truncxfsf2, - LTI_trunctfsf2, - LTI_truncxfdf2, - LTI_trunctfdf2, - LTI_abort, LTI_memcpy, LTI_memmove, @@ -53,54 +41,6 @@ enum libfunc_index LTI_unwind_sjlj_register, LTI_unwind_sjlj_unregister, - 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, - LTI_profile_function_entry, LTI_profile_function_exit, @@ -115,17 +55,6 @@ enum libfunc_index extern GTY(()) rtx libfunc_table[LTI_MAX]; /* Accessor macros for libfunc_table. */ -#define extendsfdf2_libfunc (libfunc_table[LTI_extendsfdf2]) -#define extendsfxf2_libfunc (libfunc_table[LTI_extendsfxf2]) -#define extendsftf2_libfunc (libfunc_table[LTI_extendsftf2]) -#define extenddfxf2_libfunc (libfunc_table[LTI_extenddfxf2]) -#define extenddftf2_libfunc (libfunc_table[LTI_extenddftf2]) - -#define truncdfsf2_libfunc (libfunc_table[LTI_truncdfsf2]) -#define truncxfsf2_libfunc (libfunc_table[LTI_truncxfsf2]) -#define trunctfsf2_libfunc (libfunc_table[LTI_trunctfsf2]) -#define truncxfdf2_libfunc (libfunc_table[LTI_truncxfdf2]) -#define trunctfdf2_libfunc (libfunc_table[LTI_trunctfdf2]) #define abort_libfunc (libfunc_table[LTI_abort]) #define memcpy_libfunc (libfunc_table[LTI_memcpy]) @@ -145,54 +74,6 @@ extern GTY(()) rtx libfunc_table[LTI_MAX]; #define unwind_sjlj_unregister_libfunc \ (libfunc_table[LTI_unwind_sjlj_unregister]) -#define floatsisf_libfunc (libfunc_table[LTI_floatsisf]) -#define floatdisf_libfunc (libfunc_table[LTI_floatdisf]) -#define floattisf_libfunc (libfunc_table[LTI_floattisf]) - -#define floatsidf_libfunc (libfunc_table[LTI_floatsidf]) -#define floatdidf_libfunc (libfunc_table[LTI_floatdidf]) -#define floattidf_libfunc (libfunc_table[LTI_floattidf]) - -#define floatsixf_libfunc (libfunc_table[LTI_floatsixf]) -#define floatdixf_libfunc (libfunc_table[LTI_floatdixf]) -#define floattixf_libfunc (libfunc_table[LTI_floattixf]) - -#define floatsitf_libfunc (libfunc_table[LTI_floatsitf]) -#define floatditf_libfunc (libfunc_table[LTI_floatditf]) -#define floattitf_libfunc (libfunc_table[LTI_floattitf]) - -#define fixsfsi_libfunc (libfunc_table[LTI_fixsfsi]) -#define fixsfdi_libfunc (libfunc_table[LTI_fixsfdi]) -#define fixsfti_libfunc (libfunc_table[LTI_fixsfti]) - -#define fixdfsi_libfunc (libfunc_table[LTI_fixdfsi]) -#define fixdfdi_libfunc (libfunc_table[LTI_fixdfdi]) -#define fixdfti_libfunc (libfunc_table[LTI_fixdfti]) - -#define fixxfsi_libfunc (libfunc_table[LTI_fixxfsi]) -#define fixxfdi_libfunc (libfunc_table[LTI_fixxfdi]) -#define fixxfti_libfunc (libfunc_table[LTI_fixxfti]) - -#define fixtfsi_libfunc (libfunc_table[LTI_fixtfsi]) -#define fixtfdi_libfunc (libfunc_table[LTI_fixtfdi]) -#define fixtfti_libfunc (libfunc_table[LTI_fixtfti]) - -#define fixunssfsi_libfunc (libfunc_table[LTI_fixunssfsi]) -#define fixunssfdi_libfunc (libfunc_table[LTI_fixunssfdi]) -#define fixunssfti_libfunc (libfunc_table[LTI_fixunssfti]) - -#define fixunsdfsi_libfunc (libfunc_table[LTI_fixunsdfsi]) -#define fixunsdfdi_libfunc (libfunc_table[LTI_fixunsdfdi]) -#define fixunsdfti_libfunc (libfunc_table[LTI_fixunsdfti]) - -#define fixunsxfsi_libfunc (libfunc_table[LTI_fixunsxfsi]) -#define fixunsxfdi_libfunc (libfunc_table[LTI_fixunsxfdi]) -#define fixunsxfti_libfunc (libfunc_table[LTI_fixunsxfti]) - -#define fixunstfsi_libfunc (libfunc_table[LTI_fixunstfsi]) -#define fixunstfdi_libfunc (libfunc_table[LTI_fixunstfdi]) -#define fixunstfti_libfunc (libfunc_table[LTI_fixunstfti]) - #define profile_function_entry_libfunc (libfunc_table[LTI_profile_function_entry]) #define profile_function_exit_libfunc (libfunc_table[LTI_profile_function_exit]) diff --git a/gcc/optabs.c b/gcc/optabs.c index b0953eb..bd1bf39 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -58,13 +58,8 @@ optab optab_table[OTI_MAX]; rtx libfunc_table[LTI_MAX]; -/* Tables of patterns for extending one integer mode to another. */ -enum insn_code extendtab[MAX_MACHINE_MODE][MAX_MACHINE_MODE][2]; - -/* Tables of patterns for converting between fixed and floating point. */ -enum insn_code fixtab[NUM_MACHINE_MODES][NUM_MACHINE_MODES][2]; -enum insn_code fixtrunctab[NUM_MACHINE_MODES][NUM_MACHINE_MODES][2]; -enum insn_code floattab[NUM_MACHINE_MODES][NUM_MACHINE_MODES][2]; +/* Tables of patterns for converting one mode to another. */ +convert_optab convert_optab_table[CTI_MAX]; /* Contains the optab used for each rtx code. */ optab code_to_optab[NUM_RTX_CODE + 1]; @@ -112,11 +107,17 @@ static enum insn_code can_fix_p (enum machine_mode, enum machine_mode, int, static enum insn_code can_float_p (enum machine_mode, enum machine_mode, int); static rtx ftruncify (rtx); static optab new_optab (void); +static convert_optab new_convert_optab (void); static inline optab init_optab (enum rtx_code); static inline optab init_optabv (enum rtx_code); +static inline convert_optab init_convert_optab (enum rtx_code); static void init_libfuncs (optab, int, int, const char *, int); static void init_integral_libfuncs (optab, const char *, int); static void init_floating_libfuncs (optab, const char *, int); +static void init_interclass_conv_libfuncs (convert_optab, const char *, + enum mode_class, enum mode_class); +static void init_intraclass_conv_libfuncs (convert_optab, const char *, + enum mode_class, bool); static void emit_cmp_and_jump_insn_1 (rtx, rtx, enum machine_mode, enum rtx_code, int, rtx); static void prepare_float_lib_cmp (rtx *, rtx *, enum rtx_code *, @@ -4421,12 +4422,14 @@ enum insn_code can_extend_p (enum machine_mode to_mode, enum machine_mode from_mode, int unsignedp) { + convert_optab tab; #ifdef HAVE_ptr_extend if (unsignedp < 0) return CODE_FOR_ptr_extend; - else #endif - return extendtab[(int) to_mode][(int) from_mode][unsignedp != 0]; + + tab = unsignedp ? zext_optab : sext_optab; + return tab->handlers[to_mode][from_mode].insn_code; } /* Generate the body of an insn to extend Y (with mode MFROM) @@ -4436,7 +4439,8 @@ rtx gen_extend_insn (rtx x, rtx y, enum machine_mode mto, enum machine_mode mfrom, int unsignedp) { - return (GEN_FCN (extendtab[(int) mto][(int) mfrom][unsignedp != 0]) (x, y)); + enum insn_code icode = can_extend_p (mto, mfrom, unsignedp); + return GEN_FCN (icode) (x, y); } /* can_fix_p and can_float_p say whether the target machine @@ -4452,16 +4456,27 @@ static enum insn_code can_fix_p (enum machine_mode fixmode, enum machine_mode fltmode, int unsignedp, int *truncp_ptr) { - *truncp_ptr = 0; - if (fixtrunctab[(int) fltmode][(int) fixmode][unsignedp != 0] - != CODE_FOR_nothing) - return fixtrunctab[(int) fltmode][(int) fixmode][unsignedp != 0]; + convert_optab tab; + enum insn_code icode; + + tab = unsignedp ? ufixtrunc_optab : sfixtrunc_optab; + icode = tab->handlers[fixmode][fltmode].insn_code; + if (icode != CODE_FOR_nothing) + { + *truncp_ptr = 0; + return icode; + } - if (ftrunc_optab->handlers[(int) fltmode].insn_code != CODE_FOR_nothing) + tab = unsignedp ? ufix_optab : sfix_optab; + icode = tab->handlers[fixmode][fltmode].insn_code; + if (icode != CODE_FOR_nothing + && ftrunc_optab->handlers[fltmode].insn_code != CODE_FOR_nothing) { *truncp_ptr = 1; - return fixtab[(int) fltmode][(int) fixmode][unsignedp != 0]; + return icode; } + + *truncp_ptr = 0; return CODE_FOR_nothing; } @@ -4469,7 +4484,10 @@ static enum insn_code can_float_p (enum machine_mode fltmode, enum machine_mode fixmode, int unsignedp) { - return floattab[(int) fltmode][(int) fixmode][unsignedp != 0]; + convert_optab tab; + + tab = unsignedp ? ufloat_optab : sfloat_optab; + return tab->handlers[fltmode][fixmode].insn_code; } /* Generate code to convert FROM to floating point @@ -4642,12 +4660,12 @@ expand_float (rtx to, rtx from, int unsignedp) goto done; } - /* No hardware instruction available; call a library routine to convert from - SImode, DImode, or TImode into SFmode, DFmode, XFmode, or TFmode. */ + /* No hardware instruction available; call a library routine. */ { - rtx libfcn; + rtx libfunc; rtx insns; rtx value; + convert_optab tab = unsignedp ? ufloat_optab : sfloat_optab; to = protect_from_queue (to, 1); from = protect_from_queue (from, 0); @@ -4658,56 +4676,13 @@ expand_float (rtx to, rtx from, int unsignedp) if (flag_force_mem) from = force_not_mem (from); - if (GET_MODE (to) == SFmode) - { - if (GET_MODE (from) == SImode) - libfcn = floatsisf_libfunc; - else if (GET_MODE (from) == DImode) - libfcn = floatdisf_libfunc; - else if (GET_MODE (from) == TImode) - libfcn = floattisf_libfunc; - else - abort (); - } - else if (GET_MODE (to) == DFmode) - { - if (GET_MODE (from) == SImode) - libfcn = floatsidf_libfunc; - else if (GET_MODE (from) == DImode) - libfcn = floatdidf_libfunc; - else if (GET_MODE (from) == TImode) - libfcn = floattidf_libfunc; - else - abort (); - } - else if (GET_MODE (to) == XFmode) - { - if (GET_MODE (from) == SImode) - libfcn = floatsixf_libfunc; - else if (GET_MODE (from) == DImode) - libfcn = floatdixf_libfunc; - else if (GET_MODE (from) == TImode) - libfcn = floattixf_libfunc; - else - abort (); - } - else if (GET_MODE (to) == TFmode) - { - if (GET_MODE (from) == SImode) - libfcn = floatsitf_libfunc; - else if (GET_MODE (from) == DImode) - libfcn = floatditf_libfunc; - else if (GET_MODE (from) == TImode) - libfcn = floattitf_libfunc; - else - abort (); - } - else + libfunc = tab->handlers[GET_MODE (to)][GET_MODE (from)].libfunc; + if (!libfunc) abort (); start_sequence (); - value = emit_library_call_value (libfcn, NULL_RTX, LCT_CONST, + value = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST, GET_MODE (to), 1, from, GET_MODE (from)); insns = get_insns (); @@ -4748,7 +4723,6 @@ expand_fix (rtx to, rtx from, int unsignedp) rtx target = to; enum machine_mode fmode, imode; int must_trunc = 0; - rtx libfcn = 0; /* We first try to find a pair of modes, one real and one integer, at least as wide as FROM and TO, respectively, in which we can open-code @@ -4889,57 +4863,16 @@ expand_fix (rtx to, rtx from, int unsignedp) expand_fix (target, from, unsignedp); } - else if (GET_MODE (from) == SFmode) - { - if (GET_MODE (to) == SImode) - libfcn = unsignedp ? fixunssfsi_libfunc : fixsfsi_libfunc; - else if (GET_MODE (to) == DImode) - libfcn = unsignedp ? fixunssfdi_libfunc : fixsfdi_libfunc; - else if (GET_MODE (to) == TImode) - libfcn = unsignedp ? fixunssfti_libfunc : fixsfti_libfunc; - else - abort (); - } - else if (GET_MODE (from) == DFmode) - { - if (GET_MODE (to) == SImode) - libfcn = unsignedp ? fixunsdfsi_libfunc : fixdfsi_libfunc; - else if (GET_MODE (to) == DImode) - libfcn = unsignedp ? fixunsdfdi_libfunc : fixdfdi_libfunc; - else if (GET_MODE (to) == TImode) - libfcn = unsignedp ? fixunsdfti_libfunc : fixdfti_libfunc; - else - abort (); - } - else if (GET_MODE (from) == XFmode) - { - if (GET_MODE (to) == SImode) - libfcn = unsignedp ? fixunsxfsi_libfunc : fixxfsi_libfunc; - else if (GET_MODE (to) == DImode) - libfcn = unsignedp ? fixunsxfdi_libfunc : fixxfdi_libfunc; - else if (GET_MODE (to) == TImode) - libfcn = unsignedp ? fixunsxfti_libfunc : fixxfti_libfunc; - else - abort (); - } - else if (GET_MODE (from) == TFmode) - { - if (GET_MODE (to) == SImode) - libfcn = unsignedp ? fixunstfsi_libfunc : fixtfsi_libfunc; - else if (GET_MODE (to) == DImode) - libfcn = unsignedp ? fixunstfdi_libfunc : fixtfdi_libfunc; - else if (GET_MODE (to) == TImode) - libfcn = unsignedp ? fixunstfti_libfunc : fixtfti_libfunc; - else - abort (); - } else - abort (); - - if (libfcn) { rtx insns; rtx value; + rtx libfunc; + + convert_optab tab = unsignedp ? ufix_optab : sfix_optab; + libfunc = tab->handlers[GET_MODE (to)][GET_MODE (from)].libfunc; + if (!libfunc) + abort (); to = protect_from_queue (to, 1); from = protect_from_queue (from, 0); @@ -4949,7 +4882,7 @@ expand_fix (rtx to, rtx from, int unsignedp) start_sequence (); - value = emit_library_call_value (libfcn, NULL_RTX, LCT_CONST, + value = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST, GET_MODE (to), 1, from, GET_MODE (from)); insns = get_insns (); @@ -4994,6 +4927,20 @@ new_optab (void) return op; } +static convert_optab +new_convert_optab (void) +{ + int i, j; + convert_optab op = ggc_alloc (sizeof (struct convert_optab)); + for (i = 0; i < NUM_MACHINE_MODES; i++) + for (j = 0; j < NUM_MACHINE_MODES; j++) + { + op->handlers[i][j].insn_code = CODE_FOR_nothing; + op->handlers[i][j].libfunc = 0; + } + return op; +} + /* Same, but fill in its code as CODE, and write it into the code_to_optab table. */ static inline optab @@ -5015,6 +4962,15 @@ init_optabv (enum rtx_code code) return op; } +/* Conversion optabs never go in the code_to_optab table. */ +static inline convert_optab +init_convert_optab (enum rtx_code code) +{ + convert_optab op = new_convert_optab (); + op->code = code; + return op; +} + /* Initialize the libfunc fields of an entire group of entries in some optab. Each entry is set equal to a string consisting of a leading pair of underscores followed by a generic operation name followed by @@ -5101,6 +5057,119 @@ init_floating_libfuncs (optab optable, const char *opname, int suffix) init_libfuncs (optable, lmode, lmode, opname, suffix); } +/* Initialize the libfunc fields of an entire group of entries of an + inter-mode-class conversion optab. The string formation rules are + similar to the ones for init_libfuncs, above, but instead of having + a mode name and an operand count these functions have two mode names + and no operand count. */ +static void +init_interclass_conv_libfuncs (convert_optab tab, const char *opname, + enum mode_class from_class, + enum mode_class to_class) +{ + enum machine_mode first_from_mode = GET_CLASS_NARROWEST_MODE (from_class); + enum machine_mode first_to_mode = GET_CLASS_NARROWEST_MODE (to_class); + size_t opname_len = strlen (opname); + size_t max_mname_len = 0; + + enum machine_mode fmode, tmode; + const char *fname, *tname; + const char *q; + char *libfunc_name, *suffix; + char *p; + + for (fmode = first_from_mode; + fmode != VOIDmode; + fmode = GET_MODE_WIDER_MODE (fmode)) + max_mname_len = MAX (max_mname_len, strlen (GET_MODE_NAME (fmode))); + + for (tmode = first_to_mode; + tmode != VOIDmode; + tmode = GET_MODE_WIDER_MODE (tmode)) + max_mname_len = MAX (max_mname_len, strlen (GET_MODE_NAME (tmode))); + + libfunc_name = alloca (2 + opname_len + 2*max_mname_len + 1 + 1); + libfunc_name[0] = '_'; + libfunc_name[1] = '_'; + memcpy (&libfunc_name[2], opname, opname_len); + suffix = libfunc_name + opname_len + 2; + + for (fmode = first_from_mode; fmode != VOIDmode; + fmode = GET_MODE_WIDER_MODE (fmode)) + for (tmode = first_to_mode; tmode != VOIDmode; + tmode = GET_MODE_WIDER_MODE (tmode)) + { + fname = GET_MODE_NAME (fmode); + tname = GET_MODE_NAME (tmode); + + p = suffix; + for (q = fname; *q; p++, q++) + *p = TOLOWER (*q); + for (q = tname; *q; p++, q++) + *p = TOLOWER (*q); + + *p = '\0'; + + tab->handlers[tmode][fmode].libfunc + = init_one_libfunc (ggc_alloc_string (libfunc_name, + p - libfunc_name)); + } +} + +/* Initialize the libfunc fields of an entire group of entries of an + intra-mode-class conversion optab. The string formation rules are + similar to the ones for init_libfunc, above. WIDENING says whether + the optab goes from narrow to wide modes or vice versa. These functions + have two mode names _and_ an operand count. */ +static void +init_intraclass_conv_libfuncs (convert_optab tab, const char *opname, + enum mode_class class, bool widening) +{ + enum machine_mode first_mode = GET_CLASS_NARROWEST_MODE (class); + size_t opname_len = strlen (opname); + size_t max_mname_len = 0; + + enum machine_mode nmode, wmode; + const char *nname, *wname; + const char *q; + char *libfunc_name, *suffix; + char *p; + + for (nmode = first_mode; nmode != VOIDmode; + nmode = GET_MODE_WIDER_MODE (nmode)) + max_mname_len = MAX (max_mname_len, strlen (GET_MODE_NAME (nmode))); + + libfunc_name = alloca (2 + opname_len + 2*max_mname_len + 1 + 1); + libfunc_name[0] = '_'; + libfunc_name[1] = '_'; + memcpy (&libfunc_name[2], opname, opname_len); + suffix = libfunc_name + opname_len + 2; + + for (nmode = first_mode; nmode != VOIDmode; + nmode = GET_MODE_WIDER_MODE (nmode)) + for (wmode = GET_MODE_WIDER_MODE (nmode); wmode != VOIDmode; + wmode = GET_MODE_WIDER_MODE (wmode)) + { + nname = GET_MODE_NAME (nmode); + wname = GET_MODE_NAME (wmode); + + p = suffix; + for (q = widening ? nname : wname; *q; p++, q++) + *p = TOLOWER (*q); + for (q = widening ? wname : nname; *q; p++, q++) + *p = TOLOWER (*q); + + *p++ = '2'; + *p = '\0'; + + tab->handlers[widening ? nmode : wmode] + [widening ? wmode : nmode].libfunc + = init_one_libfunc (ggc_alloc_string (libfunc_name, + p - libfunc_name)); + } +} + + rtx init_one_libfunc (const char *name) { @@ -5136,36 +5205,29 @@ set_optab_libfunc (optab optable, enum machine_mode mode, const char *name) optable->handlers[mode].libfunc = 0; } +/* Call this to reset the function entry for one conversion optab + (OPTABLE) from mode FMODE to mode TMODE to NAME, which should be + either 0 or a string constant. */ +void +set_conv_libfunc (convert_optab optable, enum machine_mode tmode, + enum machine_mode fmode, const char *name) +{ + if (name) + optable->handlers[tmode][fmode].libfunc = init_one_libfunc (name); + else + optable->handlers[tmode][fmode].libfunc = 0; +} + /* Call this once to initialize the contents of the optabs appropriately for the current target machine. */ void init_optabs (void) { - unsigned int i, j, k; + unsigned int i; /* Start by initializing all tables to contain CODE_FOR_nothing. */ - for (i = 0; i < ARRAY_SIZE (fixtab); i++) - for (j = 0; j < ARRAY_SIZE (fixtab[0]); j++) - for (k = 0; k < ARRAY_SIZE (fixtab[0][0]); k++) - fixtab[i][j][k] = CODE_FOR_nothing; - - for (i = 0; i < ARRAY_SIZE (fixtrunctab); i++) - for (j = 0; j < ARRAY_SIZE (fixtrunctab[0]); j++) - for (k = 0; k < ARRAY_SIZE (fixtrunctab[0][0]); k++) - fixtrunctab[i][j][k] = CODE_FOR_nothing; - - for (i = 0; i < ARRAY_SIZE (floattab); i++) - for (j = 0; j < ARRAY_SIZE (floattab[0]); j++) - for (k = 0; k < ARRAY_SIZE (floattab[0][0]); k++) - floattab[i][j][k] = CODE_FOR_nothing; - - for (i = 0; i < ARRAY_SIZE (extendtab); i++) - for (j = 0; j < ARRAY_SIZE (extendtab[0]); j++) - for (k = 0; k < ARRAY_SIZE (extendtab[0][0]); k++) - extendtab[i][j][k] = CODE_FOR_nothing; - for (i = 0; i < NUM_RTX_CODE; i++) setcc_gen_code[i] = CODE_FOR_nothing; @@ -5239,7 +5301,7 @@ init_optabs (void) floor_optab = init_optab (UNKNOWN); ceil_optab = init_optab (UNKNOWN); round_optab = init_optab (UNKNOWN); - trunc_optab = init_optab (UNKNOWN); + btrunc_optab = init_optab (UNKNOWN); nearbyint_optab = init_optab (UNKNOWN); sin_optab = init_optab (UNKNOWN); cos_optab = init_optab (UNKNOWN); @@ -5253,6 +5315,17 @@ init_optabs (void) cstore_optab = init_optab (UNKNOWN); push_optab = init_optab (UNKNOWN); + /* Conversions. */ + sext_optab = init_convert_optab (SIGN_EXTEND); + zext_optab = init_convert_optab (ZERO_EXTEND); + trunc_optab = init_convert_optab (TRUNCATE); + sfix_optab = init_convert_optab (FIX); + ufix_optab = init_convert_optab (UNSIGNED_FIX); + sfixtrunc_optab = init_convert_optab (UNKNOWN); + ufixtrunc_optab = init_convert_optab (UNKNOWN); + sfloat_optab = init_convert_optab (FLOAT); + ufloat_optab = init_convert_optab (UNSIGNED_FLOAT); + for (i = 0; i < NUM_MACHINE_MODES; i++) { movstr_optab[i] = CODE_FOR_nothing; @@ -5266,14 +5339,6 @@ init_optabs (void) /* Fill in the optabs with the insns we support. */ init_all_optabs (); -#ifdef FIXUNS_TRUNC_LIKE_FIX_TRUNC - /* This flag says the same insns that convert to a signed fixnum - also convert validly to an unsigned one. */ - for (i = 0; i < NUM_MACHINE_MODES; i++) - for (j = 0; j < NUM_MACHINE_MODES; j++) - fixtrunctab[i][j][1] = fixtrunctab[i][j][0]; -#endif - /* Initialize the optabs with the names of the library functions. */ init_integral_libfuncs (add_optab, "add", '3'); init_floating_libfuncs (add_optab, "add", '3'); @@ -5333,26 +5398,24 @@ init_optabs (void) init_floating_libfuncs (le_optab, "le", '2'); init_floating_libfuncs (unord_optab, "unord", '2'); - /* Use cabs for DC complex abs, since systems generally have cabs. - Don't define any libcall for SCmode, so that cabs will be used. */ - abs_optab->handlers[(int) DCmode].libfunc - = init_one_libfunc ("cabs"); + /* Conversions. */ + init_interclass_conv_libfuncs (sfloat_optab, "float", MODE_INT, MODE_FLOAT); + init_interclass_conv_libfuncs (sfix_optab, "fix", MODE_FLOAT, MODE_INT); + init_interclass_conv_libfuncs (ufix_optab, "fixuns", MODE_FLOAT, MODE_INT); - /* The ffs function operates on `int'. */ - ffs_optab->handlers[(int) mode_for_size (INT_TYPE_SIZE, MODE_INT, 0)].libfunc - = init_one_libfunc ("ffs"); + /* sext_optab is also used for FLOAT_EXTEND. */ + init_intraclass_conv_libfuncs (sext_optab, "extend", MODE_FLOAT, true); + init_intraclass_conv_libfuncs (trunc_optab, "trunc", MODE_FLOAT, false); - extendsfdf2_libfunc = init_one_libfunc ("__extendsfdf2"); - extendsfxf2_libfunc = init_one_libfunc ("__extendsfxf2"); - extendsftf2_libfunc = init_one_libfunc ("__extendsftf2"); - extenddfxf2_libfunc = init_one_libfunc ("__extenddfxf2"); - extenddftf2_libfunc = init_one_libfunc ("__extenddftf2"); + /* Use cabs for double complex abs, since systems generally have cabs. + Don't define any libcall for float complex, so that cabs will be used. */ + if (complex_double_type_node) + abs_optab->handlers[TYPE_MODE (complex_double_type_node)].libfunc + = init_one_libfunc ("cabs"); - truncdfsf2_libfunc = init_one_libfunc ("__truncdfsf2"); - truncxfsf2_libfunc = init_one_libfunc ("__truncxfsf2"); - trunctfsf2_libfunc = init_one_libfunc ("__trunctfsf2"); - truncxfdf2_libfunc = init_one_libfunc ("__truncxfdf2"); - trunctfdf2_libfunc = init_one_libfunc ("__trunctfdf2"); + /* The ffs function op[1erates on `int'. */ + ffs_optab->handlers[(int) mode_for_size (INT_TYPE_SIZE, MODE_INT, 0)].libfunc + = init_one_libfunc ("ffs"); abort_libfunc = init_one_libfunc ("abort"); memcpy_libfunc = init_one_libfunc ("memcpy"); @@ -5378,54 +5441,6 @@ init_optabs (void) unwind_sjlj_unregister_libfunc = init_one_libfunc ("_Unwind_SjLj_Unregister"); - floatsisf_libfunc = init_one_libfunc ("__floatsisf"); - floatdisf_libfunc = init_one_libfunc ("__floatdisf"); - floattisf_libfunc = init_one_libfunc ("__floattisf"); - - floatsidf_libfunc = init_one_libfunc ("__floatsidf"); - floatdidf_libfunc = init_one_libfunc ("__floatdidf"); - floattidf_libfunc = init_one_libfunc ("__floattidf"); - - floatsixf_libfunc = init_one_libfunc ("__floatsixf"); - floatdixf_libfunc = init_one_libfunc ("__floatdixf"); - floattixf_libfunc = init_one_libfunc ("__floattixf"); - - floatsitf_libfunc = init_one_libfunc ("__floatsitf"); - floatditf_libfunc = init_one_libfunc ("__floatditf"); - floattitf_libfunc = init_one_libfunc ("__floattitf"); - - fixsfsi_libfunc = init_one_libfunc ("__fixsfsi"); - fixsfdi_libfunc = init_one_libfunc ("__fixsfdi"); - fixsfti_libfunc = init_one_libfunc ("__fixsfti"); - - fixdfsi_libfunc = init_one_libfunc ("__fixdfsi"); - fixdfdi_libfunc = init_one_libfunc ("__fixdfdi"); - fixdfti_libfunc = init_one_libfunc ("__fixdfti"); - - fixxfsi_libfunc = init_one_libfunc ("__fixxfsi"); - fixxfdi_libfunc = init_one_libfunc ("__fixxfdi"); - fixxfti_libfunc = init_one_libfunc ("__fixxfti"); - - fixtfsi_libfunc = init_one_libfunc ("__fixtfsi"); - fixtfdi_libfunc = init_one_libfunc ("__fixtfdi"); - fixtfti_libfunc = init_one_libfunc ("__fixtfti"); - - fixunssfsi_libfunc = init_one_libfunc ("__fixunssfsi"); - fixunssfdi_libfunc = init_one_libfunc ("__fixunssfdi"); - fixunssfti_libfunc = init_one_libfunc ("__fixunssfti"); - - fixunsdfsi_libfunc = init_one_libfunc ("__fixunsdfsi"); - fixunsdfdi_libfunc = init_one_libfunc ("__fixunsdfdi"); - fixunsdfti_libfunc = init_one_libfunc ("__fixunsdfti"); - - fixunsxfsi_libfunc = init_one_libfunc ("__fixunsxfsi"); - fixunsxfdi_libfunc = init_one_libfunc ("__fixunsxfdi"); - fixunsxfti_libfunc = init_one_libfunc ("__fixunsxfti"); - - fixunstfsi_libfunc = init_one_libfunc ("__fixunstfsi"); - fixunstfdi_libfunc = init_one_libfunc ("__fixunstfdi"); - fixunstfti_libfunc = init_one_libfunc ("__fixunstfti"); - /* For function entry/exit instrumentation. */ profile_function_entry_libfunc = init_one_libfunc ("__cyg_profile_func_enter"); diff --git a/gcc/optabs.h b/gcc/optabs.h index 02c0af5..d8448af 100644 --- a/gcc/optabs.h +++ b/gcc/optabs.h @@ -38,19 +38,32 @@ Boston, MA 02111-1307, USA. */ A few optabs, such as move_optab and cmp_optab, are used by special code. */ +struct optab_handlers GTY(()) +{ + enum insn_code insn_code; + rtx libfunc; +}; + struct optab GTY(()) { enum rtx_code code; - struct optab_handlers { - enum insn_code insn_code; - rtx libfunc; - } handlers [NUM_MACHINE_MODES]; + struct optab_handlers handlers[NUM_MACHINE_MODES]; }; typedef struct optab * optab; +/* A convert_optab is for some sort of conversion operation between + modes. The first array index is the destination mode, the second + is the source mode. */ +struct convert_optab GTY(()) +{ + enum rtx_code code; + struct optab_handlers handlers[NUM_MACHINE_MODES][NUM_MACHINE_MODES]; +}; +typedef struct convert_optab *convert_optab; + /* Given an enum insn_code, access the function to construct the body of that kind of insn. */ -#define GEN_FCN(CODE) (*insn_data[(int) (CODE)].genfun) +#define GEN_FCN(CODE) (insn_data[CODE].genfun) /* Enumeration of valid indexes into optab_table. */ enum optab_index @@ -242,7 +255,7 @@ extern GTY(()) optab optab_table[OTI_MAX]; #define log_optab (optab_table[OTI_log]) #define floor_optab (optab_table[OTI_floor]) #define ceil_optab (optab_table[OTI_ceil]) -#define trunc_optab (optab_table[OTI_trunc]) +#define btrunc_optab (optab_table[OTI_trunc]) #define round_optab (optab_table[OTI_round]) #define nearbyint_optab (optab_table[OTI_nearbyint]) #define tan_optab (optab_table[OTI_tan]) @@ -268,13 +281,36 @@ extern GTY(()) optab optab_table[OTI_MAX]; #define push_optab (optab_table[OTI_push]) #define addcc_optab (optab_table[OTI_addcc]) -/* Tables of patterns for extending one integer mode to another. */ -extern enum insn_code extendtab[MAX_MACHINE_MODE][MAX_MACHINE_MODE][2]; +/* Conversion optabs have their own table and indexes. */ +enum convert_optab_index +{ + CTI_sext, + CTI_zext, + CTI_trunc, + + CTI_sfix, + CTI_ufix, + + CTI_sfixtrunc, + CTI_ufixtrunc, + + CTI_sfloat, + CTI_ufloat, + + CTI_MAX +}; + +extern GTY(()) convert_optab convert_optab_table[CTI_MAX]; -/* Tables of patterns for converting between fixed and floating point. */ -extern enum insn_code fixtab[NUM_MACHINE_MODES][NUM_MACHINE_MODES][2]; -extern enum insn_code fixtrunctab[NUM_MACHINE_MODES][NUM_MACHINE_MODES][2]; -extern enum insn_code floattab[NUM_MACHINE_MODES][NUM_MACHINE_MODES][2]; +#define sext_optab (convert_optab_table[CTI_sext]) +#define zext_optab (convert_optab_table[CTI_zext]) +#define trunc_optab (convert_optab_table[CTI_trunc]) +#define sfix_optab (convert_optab_table[CTI_sfix]) +#define ufix_optab (convert_optab_table[CTI_ufix]) +#define sfixtrunc_optab (convert_optab_table[CTI_sfixtrunc]) +#define ufixtrunc_optab (convert_optab_table[CTI_ufixtrunc]) +#define sfloat_optab (convert_optab_table[CTI_sfloat]) +#define ufloat_optab (convert_optab_table[CTI_ufloat]) /* These arrays record the insn_code of insns that may be needed to perform input and output reloads of special objects. They provide a @@ -385,6 +421,8 @@ extern void init_floattab (void); /* Call this to reset the function entry for one optab. */ extern void set_optab_libfunc (optab, enum machine_mode, const char *); +extern void set_conv_libfunc (convert_optab, enum machine_mode, + enum machine_mode, const char *); /* Generate code for a FLOAT_EXPR. */ extern void expand_float (rtx, rtx, int);