aboutsummaryrefslogtreecommitdiff
path: root/gcc/optabs.c
diff options
context:
space:
mode:
authorRichard Stallman <rms@gnu.org>1992-10-02 01:42:33 +0000
committerRichard Stallman <rms@gnu.org>1992-10-02 01:42:33 +0000
commit139e5e08924a01bb85498a6eab33436c519ef78f (patch)
tree76508584099faa5ec5ef7660d8a8a3ce2042203c /gcc/optabs.c
parentaa59a86918dc12f7243acc74b7419d042bf08ddc (diff)
downloadgcc-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.c111
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)