* genopinit.c (optabs): Add addc_optab.
authorhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 7 Jan 2003 21:09:21 +0000 (21:09 +0000)
committerhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 7 Jan 2003 21:09:21 +0000 (21:09 +0000)
* 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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@61019 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/i386/i386.c
gcc/config/i386/xmmintrin.h
gcc/doc/md.texi
gcc/genopinit.c
gcc/ifcvt.c
gcc/optabs.c
gcc/optabs.h
gcc/reload1.c

index 3a88736..7de2cb0 100644 (file)
@@ -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.
index 63d8a01..c1a760b 100644 (file)
@@ -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);
index be37825..1c6db97 100644 (file)
@@ -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
index 14b911f..2d90de4 100644 (file)
@@ -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.
index 01bfdd4..1a10f03 100644 (file)
@@ -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$)",
index 0652afd..3cf0194 100644 (file)
@@ -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;
index 9aa2e4a..3956299 100644 (file)
@@ -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;
+}
 \f
 /* 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);
index b9d528e..e3890fe 100644 (file)
@@ -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];
index aeb740e..4020407 100644 (file)
@@ -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)