summaryrefslogtreecommitdiff
path: root/gcc/optabs.c
diff options
context:
space:
mode:
authoruros <uros@138bc75d-0d04-0410-961f-82ee72b054a4>2007-07-21 21:45:06 +0000
committeruros <uros@138bc75d-0d04-0410-961f-82ee72b054a4>2007-07-21 21:45:06 +0000
commit27eda24040c703c6ecd3eadc44c78eb80098b995 (patch)
tree2e34198e0e1a0497de165774678adb850f5fdf36 /gcc/optabs.c
parentba9293d743480d445cf092990fc04951477c5871 (diff)
downloadgcc-27eda24040c703c6ecd3eadc44c78eb80098b995.tar.gz
* 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@126813 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/optabs.c')
-rw-r--r--gcc/optabs.c92
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;