X-Git-Url: http://git.sourceforge.jp/view?p=pf3gnuchains%2Fgcc-fork.git;a=blobdiff_plain;f=gcc%2Foptabs.c;h=2b366ad61f0aac3db6bc3b05259a2d74b852e33f;hp=0db33ca06679d99a456d05a989dc10320247492e;hb=1f3233d13f58417984cb2239d328b65e8d172744;hpb=4268f174a342afb4108ba0718c302c349d53128f diff --git a/gcc/optabs.c b/gcc/optabs.c index 0db33ca0667..2b366ad61f0 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -108,6 +108,8 @@ static rtx ftruncify PARAMS ((rtx)); static optab new_optab PARAMS ((void)); static inline optab init_optab PARAMS ((enum rtx_code)); static inline optab init_optabv PARAMS ((enum rtx_code)); +static inline int complex_part_zero_p PARAMS ((rtx, enum mode_class, + enum machine_mode)); static void init_libfuncs PARAMS ((optab, int, int, const char *, int)); static void init_integral_libfuncs PARAMS ((optab, const char *, int)); static void init_floating_libfuncs PARAMS ((optab, const char *, int)); @@ -212,6 +214,22 @@ widen_operand (op, mode, oldmode, unsignedp, no_extend) return result; } +/* Test whether either the real or imaginary part of a complex floating + point number is 0.0, so that it can be ignored (when compiling + with -funsafe-math-optimizations). */ + +static inline int +complex_part_zero_p (part, class, submode) + rtx part; + enum mode_class class; + enum machine_mode submode; +{ + return part == 0 || + (flag_unsafe_math_optimizations + && class == MODE_COMPLEX_FLOAT + && part == CONST0_RTX (submode)); +} + /* Generate code to perform a straightforward complex divide. */ static int @@ -265,7 +283,7 @@ expand_cmplxdiv_straight (real0, real1, imag0, imag1, realr, imagr, submode, if (divisor == 0) return 0; - if (imag0 == 0) + if (complex_part_zero_p (imag0, class, submode)) { /* Mathematically, ((a)(c-id))/divisor. */ /* Computationally, (a+i0) / (c+id) = (ac/(cc+dd)) + i(-ad/(cc+dd)). */ @@ -431,7 +449,7 @@ expand_cmplxdiv_wide (real0, real1, imag0, imag1, realr, imagr, submode, /* Calculate dividend. */ - if (imag0 == 0) + if (complex_part_zero_p (imag0, class, submode)) { real_t = real0; @@ -536,7 +554,7 @@ expand_cmplxdiv_wide (real0, real1, imag0, imag1, realr, imagr, submode, /* Calculate dividend. */ - if (imag0 == 0) + if (complex_part_zero_p (imag0, class, submode)) { /* Compute a / (c+id) as a(c/d) / (c(c/d)+d) + i (-a) / (c(c/d)+d). */ @@ -1190,11 +1208,11 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods) && GET_MODE_SIZE (mode) >= 2 * UNITS_PER_WORD && binoptab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing) { - int i; + unsigned int i; optab otheroptab = binoptab == add_optab ? sub_optab : add_optab; - unsigned int nwords = GET_MODE_BITSIZE (mode) / BITS_PER_WORD; + int nwords = GET_MODE_BITSIZE (mode) / BITS_PER_WORD; rtx carry_in = NULL_RTX, carry_out = NULL_RTX; - rtx xop0, xop1; + rtx xop0, xop1, xtarget; /* We can handle either a 1 or -1 value for the carry. If STORE_FLAG value is one of those, use it. Otherwise, use 1 since it is the @@ -1209,19 +1227,20 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods) xop0 = force_reg (mode, op0); xop1 = force_reg (mode, op1); - if (target == 0 || GET_CODE (target) != REG - || target == xop0 || target == xop1) - target = gen_reg_rtx (mode); + xtarget = gen_reg_rtx (mode); + + if (target == 0 || GET_CODE (target) != REG) + target = xtarget; /* Indicate for flow that the entire target reg is being set. */ if (GET_CODE (target) == REG) - emit_insn (gen_rtx_CLOBBER (VOIDmode, target)); + emit_insn (gen_rtx_CLOBBER (VOIDmode, xtarget)); /* Do the actual arithmetic. */ for (i = 0; i < nwords; i++) { int index = (WORDS_BIG_ENDIAN ? nwords - i - 1 : i); - rtx target_piece = operand_subword (target, index, 1, mode); + rtx target_piece = operand_subword (xtarget, index, 1, mode); rtx op0_piece = operand_subword_force (xop0, index, mode); rtx op1_piece = operand_subword_force (xop1, index, mode); rtx x; @@ -1277,11 +1296,11 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods) carry_in = carry_out; } - if (i == GET_MODE_BITSIZE (mode) / BITS_PER_WORD) + if (i == GET_MODE_BITSIZE (mode) / (unsigned) BITS_PER_WORD) { if (mov_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing) { - rtx temp = emit_move_insn (target, target); + rtx temp = emit_move_insn (target, xtarget); set_unique_reg_note (temp, REG_EQUAL, @@ -1443,6 +1462,9 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods) rtx temp = expand_binop (word_mode, binoptab, op0_low, op1_xhigh, NULL_RTX, 0, OPTAB_DIRECT); + if (!REG_P (product_high)) + product_high = force_reg (word_mode, product_high); + if (temp != 0) temp = expand_binop (word_mode, add_optab, temp, product_high, product_high, 0, next_methods); @@ -1462,6 +1484,8 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods) if (temp != 0 && temp != product_high) emit_move_insn (product_high, temp); + emit_move_insn (operand_subword (product, high, 1, mode), product_high); + if (temp != 0) { if (mov_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing) @@ -1535,7 +1559,7 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods) else real1 = op1; - if (real0 == 0 || real1 == 0 || ! (imag0 != 0|| imag1 != 0)) + if (real0 == 0 || real1 == 0 || ! (imag0 != 0 || imag1 != 0)) abort (); switch (binoptab->code) @@ -1552,10 +1576,11 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods) else if (res != realr) emit_move_insn (realr, res); - if (imag0 && imag1) + if (!complex_part_zero_p (imag0, class, submode) + && !complex_part_zero_p (imag1, class, submode)) res = expand_binop (submode, binoptab, imag0, imag1, imagr, unsignedp, methods); - else if (imag0) + else if (!complex_part_zero_p (imag0, class, submode)) res = imag0; else if (binoptab->code == MINUS) res = expand_unop (submode, @@ -1575,7 +1600,8 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods) case MULT: /* (a+ib) * (c+id) = (ac-bd) + i(ad+cb) */ - if (imag0 && imag1) + if (!complex_part_zero_p (imag0, class, submode) + && !complex_part_zero_p (imag1, class, submode)) { rtx temp1, temp2; @@ -1638,7 +1664,7 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods) else if (res != realr) emit_move_insn (realr, res); - if (imag0 != 0) + if (!complex_part_zero_p (imag0, class, submode)) res = expand_binop (submode, binoptab, real1, imag0, imagr, unsignedp, methods); else @@ -1657,7 +1683,7 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods) case DIV: /* (a+ib) / (c+id) = ((ac+bd)/(cc+dd)) + i((bc-ad)/(cc+dd)) */ - if (imag1 == 0) + if (complex_part_zero_p (imag1, class, submode)) { /* (a+ib) / (c+i0) = (a/c) + i(b/c) */ @@ -2739,11 +2765,18 @@ emit_no_conflict_block (insns, target, op0, op1, equiv) these from the list. */ for (insn = insns; insn; insn = next) { - rtx set = 0; + rtx set = 0, note; int i; next = NEXT_INSN (insn); + /* Some ports (cris) create an libcall regions at their own. We must + avoid any potential nesting of LIBCALLs. */ + if ((note = find_reg_note (insn, REG_LIBCALL, NULL)) != NULL) + remove_note (insn, note); + if ((note = find_reg_note (insn, REG_RETVAL, NULL)) != NULL) + remove_note (insn, note); + if (GET_CODE (PATTERN (insn)) == SET || GET_CODE (PATTERN (insn)) == USE || GET_CODE (PATTERN (insn)) == CLOBBER) set = PATTERN (insn); @@ -2906,6 +2939,14 @@ emit_libcall_block (insns, target, result, equiv) for (insn = insns; insn; insn = next) { rtx set = single_set (insn); + rtx note; + + /* Some ports (cris) create an libcall regions at their own. We must + avoid any potential nesting of LIBCALLs. */ + if ((note = find_reg_note (insn, REG_LIBCALL, NULL)) != NULL) + remove_note (insn, note); + if ((note = find_reg_note (insn, REG_RETVAL, NULL)) != NULL) + remove_note (insn, note); next = NEXT_INSN (insn); @@ -3399,6 +3440,7 @@ prepare_float_lib_cmp (px, py, pcomparison, pmode, punsignedp) int *punsignedp; { enum rtx_code comparison = *pcomparison; + rtx tmp; rtx x = *px = protect_from_queue (*px, 0); rtx y = *py = protect_from_queue (*py, 0); enum machine_mode mode = GET_MODE (x); @@ -3418,18 +3460,42 @@ prepare_float_lib_cmp (px, py, pcomparison, pmode, punsignedp) case GT: libfunc = gthf2_libfunc; + if (libfunc == NULL_RTX) + { + tmp = x; x = y; y = tmp; + *pcomparison = LT; + libfunc = lthf2_libfunc; + } break; case GE: libfunc = gehf2_libfunc; + if (libfunc == NULL_RTX) + { + tmp = x; x = y; y = tmp; + *pcomparison = LE; + libfunc = lehf2_libfunc; + } break; case LT: libfunc = lthf2_libfunc; + if (libfunc == NULL_RTX) + { + tmp = x; x = y; y = tmp; + *pcomparison = GT; + libfunc = gthf2_libfunc; + } break; case LE: libfunc = lehf2_libfunc; + if (libfunc == NULL_RTX) + { + tmp = x; x = y; y = tmp; + *pcomparison = GE; + libfunc = gehf2_libfunc; + } break; case UNORDERED: @@ -3452,18 +3518,42 @@ prepare_float_lib_cmp (px, py, pcomparison, pmode, punsignedp) case GT: libfunc = gtsf2_libfunc; + if (libfunc == NULL_RTX) + { + tmp = x; x = y; y = tmp; + *pcomparison = LT; + libfunc = ltsf2_libfunc; + } break; case GE: libfunc = gesf2_libfunc; + if (libfunc == NULL_RTX) + { + tmp = x; x = y; y = tmp; + *pcomparison = LE; + libfunc = lesf2_libfunc; + } break; case LT: libfunc = ltsf2_libfunc; + if (libfunc == NULL_RTX) + { + tmp = x; x = y; y = tmp; + *pcomparison = GT; + libfunc = gtsf2_libfunc; + } break; case LE: libfunc = lesf2_libfunc; + if (libfunc == NULL_RTX) + { + tmp = x; x = y; y = tmp; + *pcomparison = GE; + libfunc = gesf2_libfunc; + } break; case UNORDERED: @@ -3486,18 +3576,42 @@ prepare_float_lib_cmp (px, py, pcomparison, pmode, punsignedp) case GT: libfunc = gtdf2_libfunc; + if (libfunc == NULL_RTX) + { + tmp = x; x = y; y = tmp; + *pcomparison = LT; + libfunc = ltdf2_libfunc; + } break; case GE: libfunc = gedf2_libfunc; + if (libfunc == NULL_RTX) + { + tmp = x; x = y; y = tmp; + *pcomparison = LE; + libfunc = ledf2_libfunc; + } break; case LT: libfunc = ltdf2_libfunc; + if (libfunc == NULL_RTX) + { + tmp = x; x = y; y = tmp; + *pcomparison = GT; + libfunc = gtdf2_libfunc; + } break; case LE: libfunc = ledf2_libfunc; + if (libfunc == NULL_RTX) + { + tmp = x; x = y; y = tmp; + *pcomparison = GE; + libfunc = gedf2_libfunc; + } break; case UNORDERED: @@ -3520,18 +3634,42 @@ prepare_float_lib_cmp (px, py, pcomparison, pmode, punsignedp) case GT: libfunc = gtxf2_libfunc; + if (libfunc == NULL_RTX) + { + tmp = x; x = y; y = tmp; + *pcomparison = LT; + libfunc = ltxf2_libfunc; + } break; case GE: libfunc = gexf2_libfunc; + if (libfunc == NULL_RTX) + { + tmp = x; x = y; y = tmp; + *pcomparison = LE; + libfunc = lexf2_libfunc; + } break; case LT: libfunc = ltxf2_libfunc; + if (libfunc == NULL_RTX) + { + tmp = x; x = y; y = tmp; + *pcomparison = GT; + libfunc = gtxf2_libfunc; + } break; case LE: libfunc = lexf2_libfunc; + if (libfunc == NULL_RTX) + { + tmp = x; x = y; y = tmp; + *pcomparison = GE; + libfunc = gexf2_libfunc; + } break; case UNORDERED: @@ -3554,18 +3692,42 @@ prepare_float_lib_cmp (px, py, pcomparison, pmode, punsignedp) case GT: libfunc = gttf2_libfunc; + if (libfunc == NULL_RTX) + { + tmp = x; x = y; y = tmp; + *pcomparison = LT; + libfunc = lttf2_libfunc; + } break; case GE: libfunc = getf2_libfunc; + if (libfunc == NULL_RTX) + { + tmp = x; x = y; y = tmp; + *pcomparison = LE; + libfunc = letf2_libfunc; + } break; case LT: libfunc = lttf2_libfunc; + if (libfunc == NULL_RTX) + { + tmp = x; x = y; y = tmp; + *pcomparison = GT; + libfunc = gttf2_libfunc; + } break; case LE: libfunc = letf2_libfunc; + if (libfunc == NULL_RTX) + { + tmp = x; x = y; y = tmp; + *pcomparison = GE; + libfunc = getf2_libfunc; + } break; case UNORDERED: @@ -4439,9 +4601,9 @@ expand_fix (to, from, unsignedp) NULL_RTX, 0, OPTAB_LIB_WIDEN); expand_fix (to, target, 0); target = expand_binop (GET_MODE (to), xor_optab, to, - GEN_INT (trunc_int_for_mode - ((HOST_WIDE_INT) 1 << (bitsize - 1), - GET_MODE (to))), + gen_int_mode + ((HOST_WIDE_INT) 1 << (bitsize - 1), + GET_MODE (to)), to, 1, OPTAB_LIB_WIDEN); if (target != to) @@ -4571,7 +4733,7 @@ static optab new_optab () { int i; - optab op = (optab) xmalloc (sizeof (struct optab)); + optab op = (optab) ggc_alloc (sizeof (struct optab)); for (i = 0; i < NUM_MACHINE_MODES; i++) { op->handlers[i].insn_code = CODE_FOR_nothing; @@ -4689,7 +4851,8 @@ rtx init_one_libfunc (name) const char *name; { - /* Create a FUNCTION_DECL that can be passed to ENCODE_SECTION_INFO. */ + /* Create a FUNCTION_DECL that can be passed to + targetm.encode_section_info. */ /* ??? We don't have any type information except for this is a function. Pretend this is "int foo()". */ tree decl = build_decl (FUNCTION_DECL, get_identifier (name), @@ -4702,19 +4865,6 @@ init_one_libfunc (name) return XEXP (DECL_RTL (decl), 0); } -/* Mark ARG (which is really an OPTAB *) for GC. */ - -void -mark_optab (arg) - void *arg; -{ - optab o = *(optab *) arg; - int i; - - for (i = 0; i < NUM_MACHINE_MODES; ++i) - ggc_mark_rtx (o->handlers[i].libfunc); -} - /* Call this once to initialize the contents of the optabs appropriately for the current target machine. */ @@ -4940,6 +5090,7 @@ init_optabs () truncxfdf2_libfunc = init_one_libfunc ("__truncxfdf2"); trunctfdf2_libfunc = init_one_libfunc ("__trunctfdf2"); + abort_libfunc = init_one_libfunc ("abort"); memcpy_libfunc = init_one_libfunc ("memcpy"); memmove_libfunc = init_one_libfunc ("memmove"); bcopy_libfunc = init_one_libfunc ("bcopy"); @@ -5064,18 +5215,15 @@ init_optabs () /* Allow the target to add more libcalls or rename some, etc. */ INIT_TARGET_OPTABS; #endif - - /* Add these GC roots. */ - ggc_add_root (optab_table, OTI_MAX, sizeof(optab), mark_optab); - ggc_add_rtx_root (libfunc_table, LTI_MAX); } +static GTY(()) rtx trap_rtx; + #ifdef HAVE_conditional_trap /* The insn generating function can not take an rtx_code argument. TRAP_RTX is used as an rtx argument. Its code is replaced with the code to be used in the trap insn and all other fields are ignored. */ -static rtx trap_rtx; static void init_traps () @@ -5083,7 +5231,6 @@ init_traps () if (HAVE_conditional_trap) { trap_rtx = gen_rtx_fmt_ee (EQ, VOIDmode, NULL_RTX, NULL_RTX); - ggc_add_rtx_root (&trap_rtx, 1); } } #endif @@ -5122,3 +5269,5 @@ gen_cond_trap (code, op1, op2, tcode) return 0; } + +#include "gt-optabs.h"