From d0c9d431524b7c1cb4991c01e45f527cb7e75932 Mon Sep 17 00:00:00 2001 From: Uros Bizjak Date: Sat, 21 Jul 2007 23:45:06 +0200 Subject: [PATCH] optabs.h (enum optab_index): Add new OTI_signbit. * optabs.h (enum optab_index): Add new OTI_signbit. (signbit_optab): Define corresponding macro. (enum insn_code signbit_optab[]): Remove array. * optabs.c (init_optabs): Initialize signbit_optab using init_optab. (expand_copysign_absneg): If back end provides signbit insn, use it instead of bit operations on floating point argument. * builtins.c (enum insn_code signbit_optab[]): Remove array. (expand_builtin_signbit): Check signbit_optab->handlers[].insn_code for availability of signbit insn. * config/i386/i386.md (signbit2): New insn pattern to implement signbitf, signbit and signbitl built-ins as inline x87 intrinsics when SSE mode is not active. (isinf2): Disable for mfpmath=sse,387. From-SVN: r126813 --- gcc/ChangeLog | 24 +++++++++-- gcc/builtins.c | 13 ++---- gcc/config/i386/i386.md | 17 +++++++- gcc/optabs.c | 92 ++++++++++++++++++++++++----------------- gcc/optabs.h | 8 ++-- 5 files changed, 96 insertions(+), 58 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 92579ec5f87..5d4982d47b7 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,20 @@ +2007-07-21 Uros Bizjak + + * optabs.h (enum optab_index): Add new OTI_signbit. + (signbit_optab): Define corresponding macro. + (enum insn_code signbit_optab[]): Remove array. + * optabs.c (init_optabs): Initialize signbit_optab using init_optab. + (expand_copysign_absneg): If back end provides signbit insn, use it + instead of bit operations on floating point argument. + * builtins.c (enum insn_code signbit_optab[]): Remove array. + (expand_builtin_signbit): Check signbit_optab->handlers[].insn_code for + availability of signbit insn. + + * config/i386/i386.md (signbit2): New insn pattern to implement + signbitf, signbit and signbitl built-ins as inline x87 intrinsics when + SSE mode is not active. + (isinf2): Disable for mfpmath=sse,387. + 2007-07-22 Ben Elliston * regclass.c (invalid_mode_change_p): Attach ATTRIBUTE_UNUSED to @@ -256,7 +273,6 @@ 2007-07-16 Paul Brook PR target/32753 - gcc/ * config/arm/cirrus.md (cirrus_arm_movsi_insn): Remove dead insn. (cirrus_thumb2_movsi_insn): Ditto. @@ -2753,7 +2769,7 @@ offsets->locals_base to avoid negative stack size. (thumb1_expand_prologue): Assert on negative stack size. -2007-04-19 Sebastian Pop +2007-06-19 Sebastian Pop PR tree-optimization/32367 * tree-chrec.h (build_polynomial_chrec): Verify that the left hand side @@ -6068,7 +6084,7 @@ float constant. (_m_to_float): Use C89 compatible assignment. -2007-04-20 Martin Michlmayr +2007-05-20 Martin Michlmayr PR target/32007 * config/arm/lib1funcs.asm: Define __ARM_ARCH__ on v2/v3 machines. @@ -7084,7 +7100,7 @@ size never inline functions increasing caller size. (cgraph_early_inlining): Inline for size when optimizing for size. -2007-04-18 Bernd Schmidt +2007-05-04 Bernd Schmidt * config/bfin/bfin.md (di3): Now a define_expand which expands logical operations piecewise. diff --git a/gcc/builtins.c b/gcc/builtins.c index d0e5db903bc..a2e4be874ea 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -240,11 +240,6 @@ static tree do_mpfr_remquo (tree, tree, tree); static tree do_mpfr_lgamma_r (tree, tree, tree); #endif -/* This array records the insn_code of insns to imlement the signbit - function. */ -enum insn_code signbit_optab[NUM_MACHINE_MODES]; - - /* Return true if NODE should be considered for inline expansion regardless of the optimization level. This means whenever a function is invoked with its "internal" name, which normally contains the prefix "__builtin". */ @@ -5725,7 +5720,7 @@ expand_builtin_signbit (tree exp, rtx target) HOST_WIDE_INT hi, lo; tree arg; int word, bitpos; - enum insn_code signbit_insn_code; + enum insn_code icode; rtx temp; if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE)) @@ -5743,11 +5738,11 @@ expand_builtin_signbit (tree exp, rtx target) /* Check if the back end provides an insn that handles signbit for the argument's mode. */ - signbit_insn_code = signbit_optab [(int) fmode]; - if (signbit_insn_code != CODE_FOR_nothing) + icode = signbit_optab->handlers [(int) fmode].insn_code; + if (icode != CODE_FOR_nothing) { target = gen_reg_rtx (TYPE_MODE (TREE_TYPE (exp))); - emit_unop_insn (signbit_insn_code, target, temp, UNKNOWN); + emit_unop_insn (icode, target, temp, UNKNOWN); return target; } diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index e258447c39e..037773541b9 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -17990,8 +17990,7 @@ (use (match_operand:X87MODEF 1 "register_operand" ""))] "TARGET_USE_FANCY_MATH_387 && TARGET_C99_FUNCTIONS - && (!(SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH) - || TARGET_MIX_SSE_I387)" + && !(SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH)" { rtx mask = GEN_INT (0x45); rtx val = GEN_INT (0x05); @@ -18012,6 +18011,20 @@ DONE; }) +(define_expand "signbit2" + [(use (match_operand:SI 0 "register_operand" "")) + (use (match_operand:X87MODEF 1 "register_operand" ""))] + "TARGET_USE_FANCY_MATH_387 + && !(SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH)" +{ + rtx mask = GEN_INT (0x0200); + + rtx scratch = gen_reg_rtx (HImode); + + emit_insn (gen_fxam2_i387 (scratch, operands[1])); + emit_insn (gen_andsi3 (operands[0], gen_lowpart (SImode, scratch), mask)); + DONE; +}) ;; Block operation instructions diff --git a/gcc/optabs.c b/gcc/optabs.c index 95b2ec9b232..c754544f10f 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -3112,13 +3112,62 @@ expand_copysign_absneg (enum machine_mode mode, rtx op0, rtx op1, rtx target, int bitpos, bool op0_is_abs) { enum machine_mode imode; - HOST_WIDE_INT hi, lo; - int word; - rtx label; + int icode; + rtx sign, label; if (target == op1) target = NULL_RTX; + /* Check if the back end provides an insn that handles signbit for the + argument's mode. */ + icode = (int) signbit_optab->handlers [(int) mode].insn_code; + if (icode != CODE_FOR_nothing) + { + imode = insn_data[icode].operand[0].mode; + sign = gen_reg_rtx (imode); + emit_unop_insn (icode, sign, op1, UNKNOWN); + } + else + { + HOST_WIDE_INT hi, lo; + + if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD) + { + imode = int_mode_for_mode (mode); + if (imode == BLKmode) + return NULL_RTX; + op1 = gen_lowpart (imode, op1); + } + else + { + int word; + + imode = word_mode; + if (FLOAT_WORDS_BIG_ENDIAN) + word = (GET_MODE_BITSIZE (mode) - bitpos) / BITS_PER_WORD; + else + word = bitpos / BITS_PER_WORD; + bitpos = bitpos % BITS_PER_WORD; + op1 = operand_subword_force (op1, word, mode); + } + + if (bitpos < HOST_BITS_PER_WIDE_INT) + { + hi = 0; + lo = (HOST_WIDE_INT) 1 << bitpos; + } + else + { + hi = (HOST_WIDE_INT) 1 << (bitpos - HOST_BITS_PER_WIDE_INT); + lo = 0; + } + + sign = gen_reg_rtx (imode); + sign = expand_binop (imode, and_optab, op1, + immed_double_const (lo, hi, imode), + NULL_RTX, 1, OPTAB_LIB_WIDEN); + } + if (!op0_is_abs) { op0 = expand_unop (mode, abs_optab, op0, target, 0); @@ -3134,41 +3183,8 @@ expand_copysign_absneg (enum machine_mode mode, rtx op0, rtx op1, rtx target, emit_move_insn (target, op0); } - if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD) - { - imode = int_mode_for_mode (mode); - if (imode == BLKmode) - return NULL_RTX; - op1 = gen_lowpart (imode, op1); - } - else - { - imode = word_mode; - if (FLOAT_WORDS_BIG_ENDIAN) - word = (GET_MODE_BITSIZE (mode) - bitpos) / BITS_PER_WORD; - else - word = bitpos / BITS_PER_WORD; - bitpos = bitpos % BITS_PER_WORD; - op1 = operand_subword_force (op1, word, mode); - } - - if (bitpos < HOST_BITS_PER_WIDE_INT) - { - hi = 0; - lo = (HOST_WIDE_INT) 1 << bitpos; - } - else - { - hi = (HOST_WIDE_INT) 1 << (bitpos - HOST_BITS_PER_WIDE_INT); - lo = 0; - } - - op1 = expand_binop (imode, and_optab, op1, - immed_double_const (lo, hi, imode), - NULL_RTX, 1, OPTAB_LIB_WIDEN); - label = gen_label_rtx (); - emit_cmp_and_jump_insns (op1, const0_rtx, EQ, NULL_RTX, imode, 1, label); + emit_cmp_and_jump_insns (sign, const0_rtx, EQ, NULL_RTX, imode, 1, label); if (GET_CODE (op0) == CONST_DOUBLE) op0 = simplify_unary_operation (NEG, mode, op0, mode); @@ -5585,6 +5601,7 @@ init_optabs (void) tan_optab = init_optab (UNKNOWN); atan_optab = init_optab (UNKNOWN); copysign_optab = init_optab (UNKNOWN); + signbit_optab = init_optab (UNKNOWN); isinf_optab = init_optab (UNKNOWN); @@ -5655,7 +5672,6 @@ init_optabs (void) for (i = 0; i < NUM_MACHINE_MODES; i++) { movmem_optab[i] = CODE_FOR_nothing; - signbit_optab[i] = CODE_FOR_nothing; cmpstr_optab[i] = CODE_FOR_nothing; cmpstrn_optab[i] = CODE_FOR_nothing; cmpmem_optab[i] = CODE_FOR_nothing; diff --git a/gcc/optabs.h b/gcc/optabs.h index aed7a5488a3..d8917ab5734 100644 --- a/gcc/optabs.h +++ b/gcc/optabs.h @@ -219,7 +219,8 @@ enum optab_index OTI_atan, /* Copy sign */ OTI_copysign, - + /* Signbit */ + OTI_signbit, /* Test for infinite value */ OTI_isinf, @@ -409,7 +410,7 @@ extern GTY(()) optab optab_table[OTI_MAX]; #define tan_optab (optab_table[OTI_tan]) #define atan_optab (optab_table[OTI_atan]) #define copysign_optab (optab_table[OTI_copysign]) - +#define signbit_optab (optab_table[OTI_signbit]) #define isinf_optab (optab_table[OTI_isinf]) #define cmp_optab (optab_table[OTI_cmp]) @@ -553,9 +554,6 @@ extern enum insn_code vcondu_gen_code[NUM_MACHINE_MODES]; /* This array records the insn_code of insns to perform block moves. */ extern enum insn_code movmem_optab[NUM_MACHINE_MODES]; -/* This array records the insn_code of insns to implement the signbit function. */ -extern enum insn_code signbit_optab[NUM_MACHINE_MODES]; - /* This array records the insn_code of insns to perform block sets. */ extern enum insn_code setmem_optab[NUM_MACHINE_MODES];