diff options
author | Richard Stallman <rms@gnu.org> | 1992-10-02 01:42:33 +0000 |
---|---|---|
committer | Richard Stallman <rms@gnu.org> | 1992-10-02 01:42:33 +0000 |
commit | 139e5e08924a01bb85498a6eab33436c519ef78f (patch) | |
tree | 76508584099faa5ec5ef7660d8a8a3ce2042203c /gcc/optabs.c | |
parent | aa59a86918dc12f7243acc74b7419d042bf08ddc (diff) | |
download | gcc-139e5e08924a01bb85498a6eab33436c519ef78f.zip gcc-139e5e08924a01bb85498a6eab33436c519ef78f.tar.gz gcc-139e5e08924a01bb85498a6eab33436c519ef78f.tar.bz2 |
(expand_unop): Handle complex negate and abs val.
(init_optabs): Set up libcalls for complex abs.
(init_complex_libcalls): New function.
From-SVN: r2305
Diffstat (limited to 'gcc/optabs.c')
-rw-r--r-- | gcc/optabs.c | 111 |
1 files changed, 97 insertions, 14 deletions
diff --git a/gcc/optabs.c b/gcc/optabs.c index 82f1078..22c3b28 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -180,10 +180,8 @@ rtx fixunstfsi_libfunc; rtx fixunstfdi_libfunc; rtx fixunstfti_libfunc; -#ifdef GPC /* from emit-rtl.c */ -extern rtx gen_highpart(); -#endif +extern rtx gen_highpart (); /* Indexed by the rtx-code for a conditional (eg. EQ, LT,...) gives the gen_function to make a branch to test that condition. */ @@ -1386,19 +1384,9 @@ expand_unop (mode, unoptab, op0, target, unsignedp) register rtx temp; rtx last = get_last_insn (); rtx pat; -#ifdef GPC - enum machine_mode submode; -#endif class = GET_MODE_CLASS (mode); -#ifdef GPC - if (class == MODE_COMPLEX_FLOAT || class == MODE_COMPLEX_INT) - submode = mode_for_size (GET_MODE_UNIT_SIZE (mode) * BITS_PER_UNIT, - class == MODE_COMPLEX_INT ? - MODE_INT : MODE_FLOAT, 0); -#endif /* GPC */ - op0 = protect_from_queue (op0, 0); if (flag_force_mem) @@ -1527,6 +1515,86 @@ expand_unop (mode, unoptab, op0, target, unsignedp) return target; } + /* Open-code the complex negation operation. */ + else if (unoptab == neg_optab + && (class == MODE_COMPLEX_FLOAT || class == MODE_COMPLEX_INT)) + { + rtx target_piece; + rtx x; + rtx seq; + + /* Find the correct mode for the real and imaginary parts */ + enum machine_mode submode + = mode_for_size (GET_MODE_UNIT_SIZE (mode) * BITS_PER_UNIT, + class == MODE_COMPLEX_INT ? MODE_INT : MODE_FLOAT, + 0); + + if (submode == BLKmode) + abort (); + + if (target == 0) + target = gen_reg_rtx (mode); + + start_sequence (); + + target_piece = gen_highpart (submode, target); + x = expand_unop (submode, unoptab, + gen_highpart (submode, op0), + target_piece, unsignedp); + if (target_piece != x) + emit_move_insn (target_piece, x); + + target_piece = gen_lowpart (submode, target); + x = expand_unop (submode, unoptab, + gen_lowpart (submode, op0), + target_piece, unsignedp); + if (target_piece != x) + emit_move_insn (target_piece, x); + + seq = gen_sequence (); + end_sequence (); + + emit_no_conflict_block (seq, target, op0, 0, + gen_rtx (unoptab->code, mode, op0)); + return target; + } + + /* Open-code the complex absolute-value operation + if we can open-code sqrt. Otherwise it's not worth while. */ + else if (unoptab == abs_optab + && (class == MODE_COMPLEX_FLOAT || class == MODE_COMPLEX_INT)) + { + /* Find the correct mode for the real and imaginary parts */ + enum machine_mode submode + = mode_for_size (GET_MODE_UNIT_SIZE (mode) * BITS_PER_UNIT, + class == MODE_COMPLEX_INT ? MODE_INT : MODE_FLOAT, + 0); + + if (submode == BLKmode) + abort (); + + if (sqrt_optab->handlers[(int) submode].insn_code != CODE_FOR_nothing) + { + rtx real, imag, total; + + real = gen_highpart (submode, op0); + imag = gen_lowpart (submode, op0); + /* Square both parts. */ + real = expand_mult (mode, real, real, NULL_RTX, 0); + imag = expand_mult (mode, imag, imag, NULL_RTX, 0); + /* Sum the parts. */ + total = expand_binop (submode, add_optab, real, imag, 0, + 0, OPTAB_LIB_WIDEN); + /* Get sqrt in TARGET. Set TARGET to where the result is. */ + target = expand_unop (submode, sqrt_optab, total, target, 0); + if (target == 0) + delete_insns_since (last); + else + return target; + } + } + + /* Now try a library call in this mode. */ if (unoptab->handlers[(int) mode].libfunc) { rtx insns; @@ -3574,6 +3642,20 @@ init_floating_libfuncs (optable, opname, suffix) init_libfuncs (optable, SFmode, TFmode, opname, suffix); } +/* Initialize the libfunc fields of an entire group of entries in some + optab which correspond to all complex floating modes. The parameters + have the same meaning as similarly named ones for the `init_libfuncs' + routine. (See above). */ + +static void +init_complex_libfuncs (optable, opname, suffix) + register optab optable; + register char *opname; + register char suffix; +{ + init_libfuncs (optable, SCmode, TCmode, opname, suffix); +} + /* Call this once to initialize the contents of the optabs appropriately for the current target machine. */ @@ -4477,8 +4559,9 @@ init_optabs () if (HAVE_abstf2) abs_optab->handlers[(int) TFmode].insn_code = CODE_FOR_abstf2; #endif - /* No library calls here! If there is no abs instruction, + /* No library calls here for real types. If there is no abs instruction, expand_expr will generate a conditional negation. */ + init_complex_libfuncs (abs_optab, "abs", '2'); #ifdef HAVE_sqrtqi2 if (HAVE_sqrtqi2) |