diff options
-rw-r--r-- | gcc/ChangeLog | 20 | ||||
-rw-r--r-- | gcc/config/i386/i386.c | 62 | ||||
-rw-r--r-- | gcc/config/i386/xmmintrin.h | 8 | ||||
-rw-r--r-- | gcc/doc/md.texi | 7 | ||||
-rw-r--r-- | gcc/genopinit.c | 1 | ||||
-rw-r--r-- | gcc/ifcvt.c | 88 | ||||
-rw-r--r-- | gcc/optabs.c | 129 | ||||
-rw-r--r-- | gcc/optabs.h | 4 | ||||
-rw-r--r-- | gcc/reload1.c | 5 |
9 files changed, 262 insertions, 62 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 3a887366a47..7de2cb006f8 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,23 @@ +Tue Jan 7 21:46:57 CET 2003 Jan Hubicka <jh@suse.cz> + + * genopinit.c (optabs): Add addc_optab. + * ifcvt.c (noce_try_store_flag): Rename to ... + (noce_try_addcc): ... this one; handle generic conditional increment. + (noce_process_if_block): Update noce_try_addcc call. + * optabs.c (emit_conditional_add): New. + (init_obtabs): Initialize addc_optab. + * optabs.h (optab_index): Add OTI_addcc. + (addcc_optab): New macro. + * md.texi: Document addMcc + + PR target/8322 + * i386.c (ix86_init_mmx_sse_builtins): Constify arguments of loads. + * xmmintrin.h (_mm_load*_si128. _mm_store*_si128): Add casts. + * xmmintrin.h (_mm_load*_si128. _mm_store*_si128): Add casts. + + * reload1.c (delete_output_reload): Avoid repeated attempts + to delete insn. + 2003-01-07 Andreas Schwab <schwab@suse.de> * configure.in: Restore CFLAGS before gcc_AC_INITFINI_ARRAY. diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 63d8a010941..c1a760b6358 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -9584,11 +9584,11 @@ ix86_expand_int_movcc (operands) /* On x86_64 the lea instruction operates on Pmode, so we need to get arithmetics done in proper mode to match. */ if (diff == 1) - tmp = out; + tmp = copy_rtx (out); else { rtx out1; - out1 = out; + out1 = copy_rtx (out); tmp = gen_rtx_MULT (mode, out1, GEN_INT (diff & ~1)); nops++; if (diff & 1) @@ -12590,7 +12590,11 @@ ix86_init_mmx_sse_builtins () size_t i; tree pchar_type_node = build_pointer_type (char_type_node); + tree pcchar_type_node = build_pointer_type ( + build_type_variant (char_type_node, 1, 0)); tree pfloat_type_node = build_pointer_type (float_type_node); + tree pcfloat_type_node = build_pointer_type ( + build_type_variant (float_type_node, 1, 0)); tree pv2si_type_node = build_pointer_type (V2SI_type_node); tree pv2di_type_node = build_pointer_type (V2DI_type_node); tree pdi_type_node = build_pointer_type (long_long_unsigned_type_node); @@ -12663,8 +12667,8 @@ ix86_init_mmx_sse_builtins () = build_function_type_list (void_type_node, V8QI_type_node, V8QI_type_node, pchar_type_node, NULL_TREE); - tree v4sf_ftype_pfloat - = build_function_type_list (V4SF_type_node, pfloat_type_node, NULL_TREE); + tree v4sf_ftype_pcfloat + = build_function_type_list (V4SF_type_node, pcfloat_type_node, NULL_TREE); /* @@@ the type is bogus */ tree v4sf_ftype_v4sf_pv2si = build_function_type_list (V4SF_type_node, @@ -12719,7 +12723,11 @@ ix86_init_mmx_sse_builtins () = build_function_type_list (V2SI_type_node, V2SF_type_node, V2SF_type_node, NULL_TREE); tree pint_type_node = build_pointer_type (integer_type_node); + tree pcint_type_node = build_pointer_type ( + build_type_variant (integer_type_node, 1, 0)); tree pdouble_type_node = build_pointer_type (double_type_node); + tree pcdouble_type_node = build_pointer_type ( + build_type_variant (double_type_node, 1, 0)); tree int_ftype_v2df_v2df = build_function_type_list (integer_type_node, V2DF_type_node, V2DF_type_node, NULL_TREE); @@ -12731,8 +12739,8 @@ ix86_init_mmx_sse_builtins () tree ti_ftype_ti_ti = build_function_type_list (intTI_type_node, intTI_type_node, intTI_type_node, NULL_TREE); - tree void_ftype_pvoid - = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE); + tree void_ftype_pcvoid + = build_function_type_list (void_type_node, const_ptr_type_node, NULL_TREE); tree v2di_ftype_di = build_function_type_list (V2DI_type_node, long_long_unsigned_type_node, NULL_TREE); @@ -12787,8 +12795,8 @@ ix86_init_mmx_sse_builtins () = build_function_type_list (void_type_node, V16QI_type_node, V16QI_type_node, pchar_type_node, NULL_TREE); - tree v2df_ftype_pdouble - = build_function_type_list (V2DF_type_node, pdouble_type_node, NULL_TREE); + tree v2df_ftype_pcdouble + = build_function_type_list (V2DF_type_node, pcdouble_type_node, NULL_TREE); tree v2df_ftype_v2df_v2df = build_function_type_list (V2DF_type_node, V2DF_type_node, V2DF_type_node, NULL_TREE); @@ -12847,16 +12855,16 @@ ix86_init_mmx_sse_builtins () V16QI_type_node, V16QI_type_node, NULL_TREE); tree int_ftype_v16qi = build_function_type_list (integer_type_node, V16QI_type_node, NULL_TREE); - tree v16qi_ftype_pchar - = build_function_type_list (V16QI_type_node, pchar_type_node, NULL_TREE); + tree v16qi_ftype_pcchar + = build_function_type_list (V16QI_type_node, pcchar_type_node, NULL_TREE); tree void_ftype_pchar_v16qi = build_function_type_list (void_type_node, pchar_type_node, V16QI_type_node, NULL_TREE); - tree v4si_ftype_pchar - = build_function_type_list (V4SI_type_node, pchar_type_node, NULL_TREE); - tree void_ftype_pchar_v4si + tree v4si_ftype_pcint + = build_function_type_list (V4SI_type_node, pcint_type_node, NULL_TREE); + tree void_ftype_pcint_v4si = build_function_type_list (void_type_node, - pchar_type_node, V4SI_type_node, NULL_TREE); + pcint_type_node, V4SI_type_node, NULL_TREE); tree v2di_ftype_v2di = build_function_type_list (V2DI_type_node, V2DI_type_node, NULL_TREE); @@ -12971,9 +12979,9 @@ ix86_init_mmx_sse_builtins () def_builtin (MASK_SSE1 | MASK_3DNOW_A, "__builtin_ia32_maskmovq", void_ftype_v8qi_v8qi_pchar, IX86_BUILTIN_MASKMOVQ); - def_builtin (MASK_SSE1, "__builtin_ia32_loadaps", v4sf_ftype_pfloat, IX86_BUILTIN_LOADAPS); - def_builtin (MASK_SSE1, "__builtin_ia32_loadups", v4sf_ftype_pfloat, IX86_BUILTIN_LOADUPS); - def_builtin (MASK_SSE1, "__builtin_ia32_loadss", v4sf_ftype_pfloat, IX86_BUILTIN_LOADSS); + def_builtin (MASK_SSE1, "__builtin_ia32_loadaps", v4sf_ftype_pcfloat, IX86_BUILTIN_LOADAPS); + def_builtin (MASK_SSE1, "__builtin_ia32_loadups", v4sf_ftype_pcfloat, IX86_BUILTIN_LOADUPS); + def_builtin (MASK_SSE1, "__builtin_ia32_loadss", v4sf_ftype_pcfloat, IX86_BUILTIN_LOADSS); def_builtin (MASK_SSE1, "__builtin_ia32_storeaps", void_ftype_pfloat_v4sf, IX86_BUILTIN_STOREAPS); def_builtin (MASK_SSE1, "__builtin_ia32_storeups", void_ftype_pfloat_v4sf, IX86_BUILTIN_STOREUPS); def_builtin (MASK_SSE1, "__builtin_ia32_storess", void_ftype_pfloat_v4sf, IX86_BUILTIN_STORESS); @@ -13041,9 +13049,9 @@ ix86_init_mmx_sse_builtins () def_builtin (MASK_SSE2, "__builtin_ia32_movq2dq", v2di_ftype_di, IX86_BUILTIN_MOVQ2DQ); def_builtin (MASK_SSE2, "__builtin_ia32_movdq2q", di_ftype_v2di, IX86_BUILTIN_MOVDQ2Q); - def_builtin (MASK_SSE2, "__builtin_ia32_loadapd", v2df_ftype_pdouble, IX86_BUILTIN_LOADAPD); - def_builtin (MASK_SSE2, "__builtin_ia32_loadupd", v2df_ftype_pdouble, IX86_BUILTIN_LOADUPD); - def_builtin (MASK_SSE2, "__builtin_ia32_loadsd", v2df_ftype_pdouble, IX86_BUILTIN_LOADSD); + def_builtin (MASK_SSE2, "__builtin_ia32_loadapd", v2df_ftype_pcdouble, IX86_BUILTIN_LOADAPD); + def_builtin (MASK_SSE2, "__builtin_ia32_loadupd", v2df_ftype_pcdouble, IX86_BUILTIN_LOADUPD); + def_builtin (MASK_SSE2, "__builtin_ia32_loadsd", v2df_ftype_pcdouble, IX86_BUILTIN_LOADSD); def_builtin (MASK_SSE2, "__builtin_ia32_storeapd", void_ftype_pdouble_v2df, IX86_BUILTIN_STOREAPD); def_builtin (MASK_SSE2, "__builtin_ia32_storeupd", void_ftype_pdouble_v2df, IX86_BUILTIN_STOREUPD); def_builtin (MASK_SSE2, "__builtin_ia32_storesd", void_ftype_pdouble_v2df, IX86_BUILTIN_STORESD); @@ -13094,21 +13102,21 @@ ix86_init_mmx_sse_builtins () def_builtin (MASK_SSE2, "__builtin_ia32_setpd1", v2df_ftype_double, IX86_BUILTIN_SETPD1); def_builtin (MASK_SSE2, "__builtin_ia32_setpd", v2df_ftype_double_double, IX86_BUILTIN_SETPD); def_builtin (MASK_SSE2, "__builtin_ia32_setzeropd", ti_ftype_void, IX86_BUILTIN_CLRPD); - def_builtin (MASK_SSE2, "__builtin_ia32_loadpd1", v2df_ftype_pdouble, IX86_BUILTIN_LOADPD1); - def_builtin (MASK_SSE2, "__builtin_ia32_loadrpd", v2df_ftype_pdouble, IX86_BUILTIN_LOADRPD); + def_builtin (MASK_SSE2, "__builtin_ia32_loadpd1", v2df_ftype_pcdouble, IX86_BUILTIN_LOADPD1); + def_builtin (MASK_SSE2, "__builtin_ia32_loadrpd", v2df_ftype_pcdouble, IX86_BUILTIN_LOADRPD); def_builtin (MASK_SSE2, "__builtin_ia32_storepd1", void_ftype_pdouble_v2df, IX86_BUILTIN_STOREPD1); def_builtin (MASK_SSE2, "__builtin_ia32_storerpd", void_ftype_pdouble_v2df, IX86_BUILTIN_STORERPD); - def_builtin (MASK_SSE2, "__builtin_ia32_clflush", void_ftype_pvoid, IX86_BUILTIN_CLFLUSH); + def_builtin (MASK_SSE2, "__builtin_ia32_clflush", void_ftype_pcvoid, IX86_BUILTIN_CLFLUSH); def_builtin (MASK_SSE2, "__builtin_ia32_lfence", void_ftype_void, IX86_BUILTIN_LFENCE); def_builtin (MASK_SSE2, "__builtin_ia32_mfence", void_ftype_void, IX86_BUILTIN_MFENCE); - def_builtin (MASK_SSE2, "__builtin_ia32_loaddqa", v16qi_ftype_pchar, IX86_BUILTIN_LOADDQA); - def_builtin (MASK_SSE2, "__builtin_ia32_loaddqu", v16qi_ftype_pchar, IX86_BUILTIN_LOADDQU); - def_builtin (MASK_SSE2, "__builtin_ia32_loadd", v4si_ftype_pchar, IX86_BUILTIN_LOADD); + def_builtin (MASK_SSE2, "__builtin_ia32_loaddqa", v16qi_ftype_pcchar, IX86_BUILTIN_LOADDQA); + def_builtin (MASK_SSE2, "__builtin_ia32_loaddqu", v16qi_ftype_pcchar, IX86_BUILTIN_LOADDQU); + def_builtin (MASK_SSE2, "__builtin_ia32_loadd", v4si_ftype_pcint, IX86_BUILTIN_LOADD); def_builtin (MASK_SSE2, "__builtin_ia32_storedqa", void_ftype_pchar_v16qi, IX86_BUILTIN_STOREDQA); def_builtin (MASK_SSE2, "__builtin_ia32_storedqu", void_ftype_pchar_v16qi, IX86_BUILTIN_STOREDQU); - def_builtin (MASK_SSE2, "__builtin_ia32_stored", void_ftype_pchar_v4si, IX86_BUILTIN_STORED); + def_builtin (MASK_SSE2, "__builtin_ia32_stored", void_ftype_pcint_v4si, IX86_BUILTIN_STORED); def_builtin (MASK_SSE2, "__builtin_ia32_movq", v2di_ftype_v2di, IX86_BUILTIN_MOVQ); def_builtin (MASK_SSE1, "__builtin_ia32_setzero128", v2di_ftype_void, IX86_BUILTIN_CLRTI); diff --git a/gcc/config/i386/xmmintrin.h b/gcc/config/i386/xmmintrin.h index be378253cc1..1c6db97a86a 100644 --- a/gcc/config/i386/xmmintrin.h +++ b/gcc/config/i386/xmmintrin.h @@ -1586,13 +1586,13 @@ _mm_ucomineq_sd (__m128d __A, __m128d __B) static __inline __m128i _mm_load_si128 (__m128i const *__P) { - return (__m128i) __builtin_ia32_loaddqa (__P); + return (__m128i) __builtin_ia32_loaddqa ((char const *)__P); } static __inline __m128i _mm_loadu_si128 (__m128i const *__P) { - return (__m128i) __builtin_ia32_loaddqu (__P); + return (__m128i) __builtin_ia32_loaddqu ((char const *)__P); } static __inline __m128i @@ -1604,13 +1604,13 @@ _mm_loadl_epi64 (__m128i const *__P) static __inline void _mm_store_si128 (__m128i *__P, __m128i __B) { - __builtin_ia32_storedqa (__P, (__v16qi)__B); + __builtin_ia32_storedqa ((char *)__P, (__v16qi)__B); } static __inline void _mm_storeu_si128 (__m128i *__P, __m128i __B) { - __builtin_ia32_storedqu (__P, (__v16qi)__B); + __builtin_ia32_storedqu ((char *)__P, (__v16qi)__B); } static __inline void diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi index 14b911f82f6..2d90de4537d 100644 --- a/gcc/doc/md.texi +++ b/gcc/doc/md.texi @@ -2854,6 +2854,13 @@ codes and vice versa. If the machine does not have conditional move instructions, do not define these patterns. +@cindex @code{add@var{mode}cc} instruction pattern +@item @samp{mov@var{mode}cc} +Similar to @samp{mov@var{mode}cc} but for conditional addition. Conditionally +move operand 2 or (operands 2 + operand 3) into operand 0 according to the +comparison in operand 1. If the comparison is true, operand 2 is moved into +operand 0, otherwise operand 3 is moved. + @cindex @code{s@var{cond}} instruction pattern @item @samp{s@var{cond}} Store zero or nonzero in the operand according to the condition codes. diff --git a/gcc/genopinit.c b/gcc/genopinit.c index 01bfdd4e7b8..1a10f0342e3 100644 --- a/gcc/genopinit.c +++ b/gcc/genopinit.c @@ -130,6 +130,7 @@ static const char * const optabs[] = "movstrict_optab->handlers[$A].insn_code = CODE_FOR_$(movstrict$a$)", "cmp_optab->handlers[$A].insn_code = CODE_FOR_$(cmp$a$)", "tst_optab->handlers[$A].insn_code = CODE_FOR_$(tst$a$)", + "addcc_optab->handlers[$A].insn_code = CODE_FOR_$(add$acc$)", "bcc_gen_fctn[$C] = gen_$(b$c$)", "setcc_gen_code[$C] = CODE_FOR_$(s$c$)", "movcc_gen_code[$A] = CODE_FOR_$(mov$acc$)", diff --git a/gcc/ifcvt.c b/gcc/ifcvt.c index 0652afd99ee..3cf01942da7 100644 --- a/gcc/ifcvt.c +++ b/gcc/ifcvt.c @@ -582,7 +582,7 @@ struct noce_if_info static rtx noce_emit_store_flag PARAMS ((struct noce_if_info *, rtx, int, int)); static int noce_try_store_flag PARAMS ((struct noce_if_info *)); -static int noce_try_store_flag_inc PARAMS ((struct noce_if_info *)); +static int noce_try_addcc PARAMS ((struct noce_if_info *)); static int noce_try_store_flag_constants PARAMS ((struct noce_if_info *)); static int noce_try_store_flag_mask PARAMS ((struct noce_if_info *)); static rtx noce_emit_cmove PARAMS ((struct noce_if_info *, @@ -864,43 +864,32 @@ noce_try_store_flag_constants (if_info) similarly for "foo--". */ static int -noce_try_store_flag_inc (if_info) +noce_try_addcc (if_info) struct noce_if_info *if_info; { rtx target, seq; int subtract, normalize; if (! no_new_pseudos - && (BRANCH_COST >= 2 - || HAVE_incscc - || HAVE_decscc) /* Should be no `else' case to worry about. */ && if_info->b == if_info->x && GET_CODE (if_info->a) == PLUS - && (XEXP (if_info->a, 1) == const1_rtx - || XEXP (if_info->a, 1) == constm1_rtx) && rtx_equal_p (XEXP (if_info->a, 0), if_info->x) && (reversed_comparison_code (if_info->cond, if_info->jump) != UNKNOWN)) { - if (STORE_FLAG_VALUE == INTVAL (XEXP (if_info->a, 1))) - subtract = 0, normalize = 0; - else if (-STORE_FLAG_VALUE == INTVAL (XEXP (if_info->a, 1))) - subtract = 1, normalize = 0; - else - subtract = 0, normalize = INTVAL (XEXP (if_info->a, 1)); - - start_sequence (); + rtx cond = if_info->cond; + enum rtx_code code = reversed_comparison_code (cond, if_info->jump); - target = noce_emit_store_flag (if_info, - gen_reg_rtx (GET_MODE (if_info->x)), - 1, normalize); - - if (target) - target = expand_simple_binop (GET_MODE (if_info->x), - subtract ? MINUS : PLUS, - if_info->x, target, if_info->x, - 0, OPTAB_WIDEN); + /* First try to use addcc pattern. */ + start_sequence (); + target = emit_conditional_add (if_info->x, code, + XEXP (cond, 0), XEXP (cond, 1), + VOIDmode, + if_info->b, XEXP (if_info->a, 1), + GET_MODE (if_info->x), + (code == LTU || code == GEU + || code == LEU || code == GTU)); if (target) { if (target != if_info->x) @@ -908,17 +897,54 @@ noce_try_store_flag_inc (if_info) seq = get_insns (); end_sequence (); - - if (seq_contains_jump (seq)) - return FALSE; - emit_insn_before_scope (seq, if_info->jump, INSN_SCOPE (if_info->insn_a)); - return TRUE; } - end_sequence (); + + /* If that fails, construct conditional increment or decrement using + setcc. */ + if (BRANCH_COST >= 2 + && (XEXP (if_info->a, 1) == const1_rtx + || XEXP (if_info->a, 1) == constm1_rtx)) + { + start_sequence (); + if (STORE_FLAG_VALUE == INTVAL (XEXP (if_info->a, 1))) + subtract = 0, normalize = 0; + else if (-STORE_FLAG_VALUE == INTVAL (XEXP (if_info->a, 1))) + subtract = 1, normalize = 0; + else + subtract = 0, normalize = INTVAL (XEXP (if_info->a, 1)); + + + target = noce_emit_store_flag (if_info, + gen_reg_rtx (GET_MODE (if_info->x)), + 1, normalize); + + if (target) + target = expand_simple_binop (GET_MODE (if_info->x), + subtract ? MINUS : PLUS, + if_info->x, target, if_info->x, + 0, OPTAB_WIDEN); + if (target) + { + if (target != if_info->x) + noce_emit_move_insn (if_info->x, target); + + seq = get_insns (); + end_sequence (); + + if (seq_contains_jump (seq)) + return FALSE; + + emit_insn_before_scope (seq, if_info->jump, + INSN_SCOPE (if_info->insn_a)); + + return TRUE; + } + end_sequence (); + } } return FALSE; @@ -1860,7 +1886,7 @@ noce_process_if_block (ce_info) { if (noce_try_store_flag_constants (&if_info)) goto success; - if (noce_try_store_flag_inc (&if_info)) + if (noce_try_addcc (&if_info)) goto success; if (noce_try_store_flag_mask (&if_info)) goto success; diff --git a/gcc/optabs.c b/gcc/optabs.c index 9aa2e4ae3f8..3956299e4ea 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -4230,6 +4230,134 @@ can_conditionally_move_p (mode) } #endif /* HAVE_conditional_move */ + +/* Emit a conditional addition instruction if the machine supports one for that + condition and machine mode. + + OP0 and OP1 are the operands that should be compared using CODE. CMODE is + the mode to use should they be constants. If it is VOIDmode, they cannot + both be constants. + + OP2 should be stored in TARGET if the comparison is true, otherwise OP2+OP3 + should be stored there. MODE is the mode to use should they be constants. + If it is VOIDmode, they cannot both be constants. + + The result is either TARGET (perhaps modified) or NULL_RTX if the operation + is not supported. */ + +rtx +emit_conditional_add (target, code, op0, op1, cmode, op2, op3, mode, + unsignedp) + rtx target; + enum rtx_code code; + rtx op0, op1; + enum machine_mode cmode; + rtx op2, op3; + enum machine_mode mode; + int unsignedp; +{ + rtx tem, subtarget, comparison, insn; + enum insn_code icode; + enum rtx_code reversed; + + /* If one operand is constant, make it the second one. Only do this + if the other operand is not constant as well. */ + + if (swap_commutative_operands_p (op0, op1)) + { + tem = op0; + op0 = op1; + op1 = tem; + code = swap_condition (code); + } + + /* get_condition will prefer to generate LT and GT even if the old + comparison was against zero, so undo that canonicalization here since + comparisons against zero are cheaper. */ + if (code == LT && GET_CODE (op1) == CONST_INT && INTVAL (op1) == 1) + code = LE, op1 = const0_rtx; + else if (code == GT && GET_CODE (op1) == CONST_INT && INTVAL (op1) == -1) + code = GE, op1 = const0_rtx; + + if (cmode == VOIDmode) + cmode = GET_MODE (op0); + + if (swap_commutative_operands_p (op2, op3) + && ((reversed = reversed_comparison_code_parts (code, op0, op1, NULL)) + != UNKNOWN)) + { + tem = op2; + op2 = op3; + op3 = tem; + code = reversed; + } + + if (mode == VOIDmode) + mode = GET_MODE (op2); + + icode = addcc_optab->handlers[(int) mode].insn_code; + + if (icode == CODE_FOR_nothing) + return 0; + + if (flag_force_mem) + { + op2 = force_not_mem (op2); + op3 = force_not_mem (op3); + } + + if (target) + target = protect_from_queue (target, 1); + else + target = gen_reg_rtx (mode); + + subtarget = target; + + emit_queue (); + + op2 = protect_from_queue (op2, 0); + op3 = protect_from_queue (op3, 0); + + /* If the insn doesn't accept these operands, put them in pseudos. */ + + if (! (*insn_data[icode].operand[0].predicate) + (subtarget, insn_data[icode].operand[0].mode)) + subtarget = gen_reg_rtx (insn_data[icode].operand[0].mode); + + if (! (*insn_data[icode].operand[2].predicate) + (op2, insn_data[icode].operand[2].mode)) + op2 = copy_to_mode_reg (insn_data[icode].operand[2].mode, op2); + + if (! (*insn_data[icode].operand[3].predicate) + (op3, insn_data[icode].operand[3].mode)) + op3 = copy_to_mode_reg (insn_data[icode].operand[3].mode, op3); + + /* Everything should now be in the suitable form, so emit the compare insn + and then the conditional move. */ + + comparison + = compare_from_rtx (op0, op1, code, unsignedp, cmode, NULL_RTX); + + /* ??? Watch for const0_rtx (nop) and const_true_rtx (unconditional)? */ + /* We can get const0_rtx or const_true_rtx in some circumstances. Just + return NULL and let the caller figure out how best to deal with this + situation. */ + if (GET_CODE (comparison) != code) + return NULL_RTX; + + insn = GEN_FCN (icode) (subtarget, comparison, op2, op3); + + /* If that failed, then give up. */ + if (insn == 0) + return 0; + + emit_insn (insn); + + if (subtarget != target) + convert_move (target, subtarget, 0); + + return target; +} /* These functions generate an insn body and return it rather than emitting the insn. @@ -5229,6 +5357,7 @@ init_optabs () negv_optab = init_optabv (NEG); abs_optab = init_optab (ABS); absv_optab = init_optabv (ABS); + addcc_optab = init_optab (UNKNOWN); one_cmpl_optab = init_optab (NOT); ffs_optab = init_optab (FFS); sqrt_optab = init_optab (SQRT); diff --git a/gcc/optabs.h b/gcc/optabs.h index b9d528ee387..e3890fe9a90 100644 --- a/gcc/optabs.h +++ b/gcc/optabs.h @@ -160,6 +160,9 @@ enum optab_index /* Push instruction. */ OTI_push, + /* Conditional add instruction. */ + OTI_addcc, + OTI_MAX }; @@ -226,6 +229,7 @@ extern GTY(()) optab optab_table[OTI_MAX]; #define cmov_optab (optab_table[OTI_cmov]) #define cstore_optab (optab_table[OTI_cstore]) #define push_optab (optab_table[OTI_push]) +#define addcc_optab (optab_table[OTI_addcc]) /* Tables of patterns for extending one integer mode to another. */ extern enum insn_code extendtab[MAX_MACHINE_MODE][MAX_MACHINE_MODE][2]; diff --git a/gcc/reload1.c b/gcc/reload1.c index aeb740ef91f..40204074af7 100644 --- a/gcc/reload1.c +++ b/gcc/reload1.c @@ -7608,6 +7608,11 @@ delete_output_reload (insn, j, last_reload_reg) rtx i1; rtx substed; + /* It is possible that this reload has been only used to set another reload + we eliminated earlier and thus deleted this instruction too. */ + if (INSN_DELETED_P (output_reload_insn)) + return; + /* Get the raw pseudo-register referred to. */ while (GET_CODE (reg) == SUBREG) |