diff options
author | Uros Bizjak <uros@gcc.gnu.org> | 2007-07-21 23:45:06 +0200 |
---|---|---|
committer | Uros Bizjak <uros@gcc.gnu.org> | 2007-07-21 23:45:06 +0200 |
commit | d0c9d431524b7c1cb4991c01e45f527cb7e75932 (patch) | |
tree | 2e34198e0e1a0497de165774678adb850f5fdf36 /gcc/optabs.c | |
parent | 21a772278801d5143e385999c692da9457db5552 (diff) | |
download | gcc-d0c9d431524b7c1cb4991c01e45f527cb7e75932.tar.gz |
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 (signbit<mode>2): New insn pattern to implement
signbitf, signbit and signbitl built-ins as inline x87 intrinsics when
SSE mode is not active.
(isinf<mode>2): Disable for mfpmath=sse,387.
From-SVN: r126813
Diffstat (limited to 'gcc/optabs.c')
-rw-r--r-- | gcc/optabs.c | 92 |
1 files changed, 54 insertions, 38 deletions
diff --git a/gcc/optabs.c b/gcc/optabs.c index 95b2ec9b232..c754544f10f 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -3112,63 +3112,79 @@ 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; - if (!op0_is_abs) + /* 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) { - op0 = expand_unop (mode, abs_optab, op0, target, 0); - if (op0 == NULL) - return NULL_RTX; - target = op0; + imode = insn_data[icode].operand[0].mode; + sign = gen_reg_rtx (imode); + emit_unop_insn (icode, sign, op1, UNKNOWN); } else { - if (target == NULL_RTX) - target = copy_to_reg (op0); + 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 - emit_move_insn (target, op0); - } + { + int word; - 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; + 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 - word = bitpos / BITS_PER_WORD; - bitpos = bitpos % BITS_PER_WORD; - op1 = operand_subword_force (op1, word, mode); + { + 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 (bitpos < HOST_BITS_PER_WIDE_INT) + if (!op0_is_abs) { - hi = 0; - lo = (HOST_WIDE_INT) 1 << bitpos; + op0 = expand_unop (mode, abs_optab, op0, target, 0); + if (op0 == NULL) + return NULL_RTX; + target = op0; } else { - hi = (HOST_WIDE_INT) 1 << (bitpos - HOST_BITS_PER_WIDE_INT); - lo = 0; + if (target == NULL_RTX) + target = copy_to_reg (op0); + else + emit_move_insn (target, op0); } - 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; |