From 139e5e08924a01bb85498a6eab33436c519ef78f Mon Sep 17 00:00:00 2001 From: Richard Stallman Date: Fri, 2 Oct 1992 01:42:33 +0000 Subject: [PATCH] (expand_unop): Handle complex negate and abs val. (init_optabs): Set up libcalls for complex abs. (init_complex_libcalls): New function. From-SVN: r2305 --- gcc/optabs.c | 111 ++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 97 insertions(+), 14 deletions(-) diff --git a/gcc/optabs.c b/gcc/optabs.c index 82f10780e40..22c3b28c18e 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)