From bb7f04236c6c8c1f248f27eb86d9eb486a93c64b Mon Sep 17 00:00:00 2001 From: Richard Guenther Date: Wed, 25 Oct 2006 13:01:14 +0000 Subject: [PATCH] optabs.h (enum optab_index): Remove OTI_lrint. 2006-10-25 Richard Guenther * optabs.h (enum optab_index): Remove OTI_lrint. (enum convert_optab_index): Add COI_lrint. (lrint_optab): Adjust. (expand_sfix_optab): Declare. * optabs.c (expand_sfix_optab): New function. (init_optabs): Init lrint_optab as conversion optab. * genopinit.c (lrint_optab): Change to a conversion optab. * builtins.c (expand_builtin_int_roundingfn_2): Adjust to expansion via conversion optab. * config/i386/i386.md (*fistdi2_1): Remove flag_unsafe_math_optimizations guard. (fistdi2, fistdi2_with_temp, *fist2_1, fist2, fist2_with_temp): Likewise. (lrint2): Split into... (lrintxf2): ... x87 part (lrintdi2, lrintsi2): ... and SSE parts. * config/i386/sse.md (sse_cvtss2si_2, sse_cvtss2_siq_2, sse2_cvtsd2si_2, sse2_cvtsd2siq_2): New insns for UNSPEC_FIX_NOTRUNC matching non-vector float modes. * doc/md.texi (lrintMN2): Document. From-SVN: r118029 --- gcc/ChangeLog | 24 +++++++++++++++ gcc/builtins.c | 66 ++++++++++++++++++----------------------- gcc/config/i386/i386.md | 38 ++++++++++++++---------- gcc/config/i386/sse.md | 40 +++++++++++++++++++++++++ gcc/doc/md.texi | 6 ++++ gcc/genopinit.c | 2 +- gcc/optabs.c | 44 ++++++++++++++++++++++++++- gcc/optabs.h | 8 +++-- 8 files changed, 171 insertions(+), 57 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a4ffc2d9eb3..3db23d45429 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,27 @@ +2006-10-25 Richard Guenther + + PR target/28803 + * optabs.h (enum optab_index): Remove OTI_lrint. + (enum convert_optab_index): Add COI_lrint. + (lrint_optab): Adjust. + (expand_sfix_optab): Declare. + * optabs.c (expand_sfix_optab): New function. + (init_optabs): Init lrint_optab as conversion optab. + * genopinit.c (lrint_optab): Change to a conversion optab. + * builtins.c (expand_builtin_int_roundingfn_2): Adjust to + expansion via conversion optab. + * config/i386/i386.md (*fistdi2_1): Remove + flag_unsafe_math_optimizations guard. + (fistdi2, fistdi2_with_temp, *fist2_1, fist2, + fist2_with_temp): Likewise. + (lrint2): Split into... + (lrintxf2): ... x87 part + (lrintdi2, lrintsi2): ... and SSE parts. + * config/i386/sse.md (sse_cvtss2si_2, sse_cvtss2_siq_2, + sse2_cvtsd2si_2, sse2_cvtsd2siq_2): New insns for + UNSPEC_FIX_NOTRUNC matching non-vector float modes. + * doc/md.texi (lrintMN2): Document. + 2006-10-25 Uros Bizjak PR target/28909 diff --git a/gcc/builtins.c b/gcc/builtins.c index 6955cda2a83..1dcda03920a 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -2320,7 +2320,7 @@ expand_builtin_int_roundingfn (tree exp, rtx target, rtx subtarget) static rtx expand_builtin_int_roundingfn_2 (tree exp, rtx target, rtx subtarget) { - optab builtin_optab; + convert_optab builtin_optab; rtx op0, insns; tree fndecl = get_callee_fndecl (exp); tree arglist = TREE_OPERAND (exp, 1); @@ -2348,45 +2348,37 @@ expand_builtin_int_roundingfn_2 (tree exp, rtx target, rtx subtarget) /* Make a suitable register to place result in. */ mode = TYPE_MODE (TREE_TYPE (exp)); - /* Before working hard, check whether the instruction is available. */ - if (builtin_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing) + target = gen_reg_rtx (mode); + + /* Wrap the computation of the argument in a SAVE_EXPR, as we may + need to expand the argument again. This way, we will not perform + side-effects more the once. */ + narg = builtin_save_expr (arg); + if (narg != arg) { - target = gen_reg_rtx (mode); - - /* Wrap the computation of the argument in a SAVE_EXPR, as we may - need to expand the argument again. This way, we will not perform - side-effects more the once. */ - narg = builtin_save_expr (arg); - if (narg != arg) - { - arg = narg; - arglist = build_tree_list (NULL_TREE, arg); - exp = build_function_call_expr (fndecl, arglist); - } - - op0 = expand_expr (arg, subtarget, VOIDmode, 0); - - start_sequence (); - - /* Compute into TARGET. - Set TARGET to wherever the result comes back. */ - target = expand_unop (mode, builtin_optab, op0, target, 0); - - if (target != 0) - { - /* Output the entire sequence. */ - insns = get_insns (); - end_sequence (); - emit_insn (insns); - return target; - } - - /* If we were unable to expand via the builtin, stop the sequence - (without outputting the insns) and call to the library function - with the stabilized argument list. */ - end_sequence (); + arg = narg; + arglist = build_tree_list (NULL_TREE, arg); + exp = build_function_call_expr (fndecl, arglist); } + op0 = expand_expr (arg, subtarget, VOIDmode, 0); + + start_sequence (); + + if (expand_sfix_optab (target, op0, builtin_optab)) + { + /* Output the entire sequence. */ + insns = get_insns (); + end_sequence (); + emit_insn (insns); + return target; + } + + /* If we were unable to expand via the builtin, stop the sequence + (without outputting the insns) and call to the library function + with the stabilized argument list. */ + end_sequence (); + target = expand_call (exp, target, target == const0_rtx); return target; diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index aadf2ff8f85..5e691672467 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -17205,7 +17205,6 @@ (unspec:DI [(match_operand:XF 1 "register_operand" "f,f")] UNSPEC_FIST))] "TARGET_USE_FANCY_MATH_387 - && flag_unsafe_math_optimizations && !(reload_completed || reload_in_progress)" "#" "&& 1" @@ -17229,8 +17228,7 @@ (unspec:DI [(match_operand:XF 1 "register_operand" "f")] UNSPEC_FIST)) (clobber (match_scratch:XF 2 "=&1f"))] - "TARGET_USE_FANCY_MATH_387 - && flag_unsafe_math_optimizations" + "TARGET_USE_FANCY_MATH_387" "* return output_fix_trunc (insn, operands, 0);" [(set_attr "type" "fpspc") (set_attr "mode" "DI")]) @@ -17241,8 +17239,7 @@ UNSPEC_FIST)) (clobber (match_operand:DI 2 "memory_operand" "=m,m")) (clobber (match_scratch:XF 3 "=&1f,&1f"))] - "TARGET_USE_FANCY_MATH_387 - && flag_unsafe_math_optimizations" + "TARGET_USE_FANCY_MATH_387" "#" [(set_attr "type" "fpspc") (set_attr "mode" "DI")]) @@ -17275,7 +17272,6 @@ (unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "f")] UNSPEC_FIST))] "TARGET_USE_FANCY_MATH_387 - && flag_unsafe_math_optimizations && !(reload_completed || reload_in_progress)" "#" "&& 1" @@ -17293,8 +17289,7 @@ [(set (match_operand:X87MODEI12 0 "memory_operand" "=m") (unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "f")] UNSPEC_FIST))] - "TARGET_USE_FANCY_MATH_387 - && flag_unsafe_math_optimizations" + "TARGET_USE_FANCY_MATH_387" "* return output_fix_trunc (insn, operands, 0);" [(set_attr "type" "fpspc") (set_attr "mode" "")]) @@ -17304,8 +17299,7 @@ (unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "f")] UNSPEC_FIST)) (clobber (match_operand:X87MODEI12 2 "memory_operand" "=m"))] - "TARGET_USE_FANCY_MATH_387 - && flag_unsafe_math_optimizations" + "TARGET_USE_FANCY_MATH_387" "#" [(set_attr "type" "fpspc") (set_attr "mode" "")]) @@ -17331,13 +17325,25 @@ UNSPEC_FIST))] "") -(define_expand "lrint2" +(define_expand "lrintxf2" [(set (match_operand:X87MODEI 0 "nonimmediate_operand" "") - (unspec:X87MODEI [(match_operand:XF 1 "register_operand" "")] - UNSPEC_FIST))] - "TARGET_USE_FANCY_MATH_387 - && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387) - && flag_unsafe_math_optimizations" + (unspec:X87MODEI [(match_operand:XF 1 "register_operand" "")] + UNSPEC_FIST))] + "TARGET_USE_FANCY_MATH_387" + "") + +(define_expand "lrintdi2" + [(set (match_operand:DI 0 "nonimmediate_operand" "") + (unspec:DI [(match_operand:SSEMODEF 1 "register_operand" "")] + UNSPEC_FIX_NOTRUNC))] + "SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH && TARGET_64BIT" + "") + +(define_expand "lrintsi2" + [(set (match_operand:SI 0 "nonimmediate_operand" "") + (unspec:SI [(match_operand:SSEMODEF 1 "register_operand" "")] + UNSPEC_FIX_NOTRUNC))] + "SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH" "") ;; Rounding mode control word calculation could clobber FLAGS_REG. diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md index 1424149c1ab..8f5786a6659 100644 --- a/gcc/config/i386/sse.md +++ b/gcc/config/i386/sse.md @@ -974,6 +974,16 @@ (set_attr "athlon_decode" "double,vector") (set_attr "mode" "SI")]) +(define_insn "sse_cvtss2si_2" + [(set (match_operand:SI 0 "register_operand" "=r,r") + (unspec:SI [(match_operand:SF 1 "nonimmediate_operand" "x,m")] + UNSPEC_FIX_NOTRUNC))] + "TARGET_SSE" + "cvtss2si\t{%1, %0|%0, %1}" + [(set_attr "type" "sseicvt") + (set_attr "athlon_decode" "double,vector") + (set_attr "mode" "SI")]) + (define_insn "sse_cvtss2siq" [(set (match_operand:DI 0 "register_operand" "=r,r") (unspec:DI @@ -987,6 +997,16 @@ (set_attr "athlon_decode" "double,vector") (set_attr "mode" "DI")]) +(define_insn "sse_cvtss2siq_2" + [(set (match_operand:DI 0 "register_operand" "=r,r") + (unspec:DI [(match_operand:SF 1 "nonimmediate_operand" "x,m")] + UNSPEC_FIX_NOTRUNC))] + "TARGET_SSE && TARGET_64BIT" + "cvtss2siq\t{%1, %0|%0, %1}" + [(set_attr "type" "sseicvt") + (set_attr "athlon_decode" "double,vector") + (set_attr "mode" "DI")]) + (define_insn "sse_cvttss2si" [(set (match_operand:SI 0 "register_operand" "=r,r") (fix:SI @@ -1932,6 +1952,16 @@ (set_attr "athlon_decode" "double,vector") (set_attr "mode" "SI")]) +(define_insn "sse2_cvtsd2si_2" + [(set (match_operand:SI 0 "register_operand" "=r,r") + (unspec:SI [(match_operand:DF 1 "nonimmediate_operand" "x,m")] + UNSPEC_FIX_NOTRUNC))] + "TARGET_SSE2" + "cvtsd2si\t{%1, %0|%0, %1}" + [(set_attr "type" "sseicvt") + (set_attr "athlon_decode" "double,vector") + (set_attr "mode" "SI")]) + (define_insn "sse2_cvtsd2siq" [(set (match_operand:DI 0 "register_operand" "=r,r") (unspec:DI @@ -1945,6 +1975,16 @@ (set_attr "athlon_decode" "double,vector") (set_attr "mode" "DI")]) +(define_insn "sse2_cvtsd2siq_2" + [(set (match_operand:DI 0 "register_operand" "=r,r") + (unspec:DI [(match_operand:DF 1 "nonimmediate_operand" "x,m")] + UNSPEC_FIX_NOTRUNC))] + "TARGET_SSE2 && TARGET_64BIT" + "cvtsd2siq\t{%1, %0|%0, %1}" + [(set_attr "type" "sseicvt") + (set_attr "athlon_decode" "double,vector") + (set_attr "mode" "DI")]) + (define_insn "sse2_cvttsd2si" [(set (match_operand:SI 0 "register_operand" "=r,r") (fix:SI diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi index a05f9d04a9e..a41391c140d 100644 --- a/gcc/doc/md.texi +++ b/gcc/doc/md.texi @@ -3702,6 +3702,12 @@ corresponds to the C data type @code{double} and the @code{rintf} built-in function uses the mode which corresponds to the C data type @code{float}. +@cindex @code{lrint@var{m}@var{n}2} +@item @samp{lrint@var{m}@var{n}2} +Convert operand 1 (valid for floating point mode @var{m}) to fixed +point mode @var{n} as a signed number according to the current +rounding mode and store in operand 0 (which has mode @var{n}). + @cindex @code{copysign@var{m}3} instruction pattern @item @samp{copysign@var{m}3} Store a value with the magnitude of operand 1 and the sign of operand diff --git a/gcc/genopinit.c b/gcc/genopinit.c index 4f7bd46595c..15757353a00 100644 --- a/gcc/genopinit.c +++ b/gcc/genopinit.c @@ -127,7 +127,7 @@ static const char * const optabs[] = "btrunc_optab->handlers[$A].insn_code = CODE_FOR_$(btrunc$a2$)", "nearbyint_optab->handlers[$A].insn_code = CODE_FOR_$(nearbyint$a2$)", "rint_optab->handlers[$A].insn_code = CODE_FOR_$(rint$a2$)", - "lrint_optab->handlers[$A].insn_code = CODE_FOR_$(lrint$a2$)", + "lrint_optab->handlers[$B][$A].insn_code = CODE_FOR_$(lrint$F$a$I$b2$)", "sincos_optab->handlers[$A].insn_code = CODE_FOR_$(sincos$a3$)", "sin_optab->handlers[$A].insn_code = CODE_FOR_$(sin$a2$)", "asin_optab->handlers[$A].insn_code = CODE_FOR_$(asin$a2$)", diff --git a/gcc/optabs.c b/gcc/optabs.c index 12fd34e5da2..11cacae31f1 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -4861,6 +4861,46 @@ expand_fix (rtx to, rtx from, int unsignedp) convert_move (to, target, 0); } } + +/* Generate code to convert FROM to fixed point and store in TO. FROM + must be floating point, TO must be signed. Use the conversion optab + TAB to do the conversion. */ + +bool +expand_sfix_optab (rtx to, rtx from, convert_optab tab) +{ + enum insn_code icode; + rtx target = to; + enum machine_mode fmode, imode; + + /* 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 + this conversion. If the integer mode is wider than the mode of TO, + we can do the conversion either signed or unsigned. */ + + for (fmode = GET_MODE (from); fmode != VOIDmode; + fmode = GET_MODE_WIDER_MODE (fmode)) + for (imode = GET_MODE (to); imode != VOIDmode; + imode = GET_MODE_WIDER_MODE (imode)) + { + icode = tab->handlers[imode][fmode].insn_code; + if (icode != CODE_FOR_nothing) + { + if (fmode != GET_MODE (from)) + from = convert_to_mode (fmode, from, 0); + + if (imode != GET_MODE (to)) + target = gen_reg_rtx (imode); + + emit_unop_insn (icode, target, from, UNKNOWN); + if (target != to) + convert_move (to, target, 0); + return true; + } + } + + return false; +} /* Report whether we have an instruction to perform the operation specified by CODE on operands of mode MODE. */ @@ -5266,7 +5306,6 @@ init_optabs (void) btrunc_optab = init_optab (UNKNOWN); nearbyint_optab = init_optab (UNKNOWN); rint_optab = init_optab (UNKNOWN); - lrint_optab = init_optab (UNKNOWN); sincos_optab = init_optab (UNKNOWN); sin_optab = init_optab (UNKNOWN); asin_optab = init_optab (UNKNOWN); @@ -5325,6 +5364,7 @@ init_optabs (void) ufixtrunc_optab = init_convert_optab (UNKNOWN); sfloat_optab = init_convert_optab (FLOAT); ufloat_optab = init_convert_optab (UNSIGNED_FLOAT); + lrint_optab = init_convert_optab (UNKNOWN); for (i = 0; i < NUM_MACHINE_MODES; i++) { @@ -5444,6 +5484,8 @@ init_optabs (void) MODE_DECIMAL_FLOAT, MODE_INT); init_interclass_conv_libfuncs (ufloat_optab, "floatuns", MODE_INT, MODE_DECIMAL_FLOAT); + init_interclass_conv_libfuncs (lrint_optab, "lrint", + MODE_INT, MODE_FLOAT); /* sext_optab is also used for FLOAT_EXTEND. */ init_intraclass_conv_libfuncs (sext_optab, "extend", MODE_FLOAT, true); diff --git a/gcc/optabs.h b/gcc/optabs.h index 69dcbe11b91..4670b5b7fb2 100644 --- a/gcc/optabs.h +++ b/gcc/optabs.h @@ -196,7 +196,6 @@ enum optab_index OTI_round, OTI_nearbyint, OTI_rint, - OTI_lrint, /* Tangent */ OTI_tan, /* Inverse tangent */ @@ -345,7 +344,6 @@ extern GTY(()) optab optab_table[OTI_MAX]; #define round_optab (optab_table[OTI_round]) #define nearbyint_optab (optab_table[OTI_nearbyint]) #define rint_optab (optab_table[OTI_rint]) -#define lrint_optab (optab_table[OTI_lrint]) #define tan_optab (optab_table[OTI_tan]) #define atan_optab (optab_table[OTI_atan]) #define copysign_optab (optab_table[OTI_copysign]) @@ -407,6 +405,8 @@ enum convert_optab_index COI_sfloat, COI_ufloat, + COI_lrint, + COI_MAX }; @@ -421,6 +421,7 @@ extern GTY(()) convert_optab convert_optab_table[COI_MAX]; #define ufixtrunc_optab (convert_optab_table[COI_ufixtrunc]) #define sfloat_optab (convert_optab_table[COI_sfloat]) #define ufloat_optab (convert_optab_table[COI_ufloat]) +#define lrint_optab (convert_optab_table[COI_lrint]) /* These arrays record the insn_code of insns that may be needed to perform input and output reloads of special objects. They provide a @@ -597,6 +598,9 @@ extern void expand_float (rtx, rtx, int); /* Generate code for a FIX_EXPR. */ extern void expand_fix (rtx, rtx, int); +/* Generate code for float to integral conversion. */ +extern bool expand_sfix_optab (rtx, rtx, convert_optab); + /* Return tree if target supports vector operations for COND_EXPR. */ bool expand_vec_cond_expr_p (tree, enum machine_mode);