OSDN Git Service

PR c/39779
[pf3gnuchains/gcc-fork.git] / gcc / expmed.c
index c540537..98a99a2 100644 (file)
@@ -5128,10 +5128,10 @@ expand_and (enum machine_mode mode, rtx op0, rtx op1, rtx target)
 static rtx
 emit_cstore (rtx target, enum insn_code icode, enum rtx_code code,
             enum machine_mode mode, enum machine_mode compare_mode,
-            int unsignedp, rtx x, rtx y, int normalizep)
+            int unsignedp, rtx x, rtx y, int normalizep,
+            enum machine_mode target_mode)
 {
   rtx op0, last, comparison, subtarget, pattern;
-  enum machine_mode target_mode;
   enum machine_mode result_mode = insn_data[(int) icode].operand[0].mode;
 
   last = get_last_insn ();
@@ -5149,8 +5149,12 @@ emit_cstore (rtx target, enum insn_code icode, enum rtx_code code,
       return NULL_RTX;
     }
 
-  if (!target
-      || optimize
+  if (target_mode == VOIDmode)
+    target_mode = result_mode;
+  if (!target)
+    target = gen_reg_rtx (target_mode);
+  
+  if (optimize
       || !(insn_data[(int) icode].operand[0].predicate (target, result_mode)))
     subtarget = gen_reg_rtx (result_mode);
   else
@@ -5161,10 +5165,6 @@ emit_cstore (rtx target, enum insn_code icode, enum rtx_code code,
     return NULL_RTX;
   emit_insn (pattern);
 
-  if (!target)
-    target = gen_reg_rtx (GET_MODE (subtarget));
-  target_mode = GET_MODE (target);
-  
   /* If we are converting to a wider mode, first convert to
      TARGET_MODE, then normalize.  This produces better combining
      opportunities on machines that have a SIGN_EXTRACT when we are
@@ -5235,12 +5235,12 @@ emit_cstore (rtx target, enum insn_code icode, enum rtx_code code,
 
 static rtx
 emit_store_flag_1 (rtx target, enum rtx_code code, rtx op0, rtx op1,
-                  enum machine_mode mode, int unsignedp, int normalizep)
+                  enum machine_mode mode, int unsignedp, int normalizep,
+                  enum machine_mode target_mode)
 {
   rtx subtarget;
   enum insn_code icode;
   enum machine_mode compare_mode;
-  enum machine_mode target_mode = target ? GET_MODE (target) : VOIDmode;
   enum mode_class mclass;
   enum rtx_code scode;
   rtx tem;
@@ -5319,7 +5319,7 @@ emit_store_flag_1 (rtx target, enum rtx_code code, rtx op0, rtx op1,
 
          if (tem != 0)
            tem = emit_store_flag (NULL_RTX, code, tem, op1, word_mode,
-                                   unsignedp, normalizep);
+                                  unsignedp, normalizep);
        }
       else if ((code == LT || code == GE) && op1 == const0_rtx)
        {
@@ -5337,11 +5337,13 @@ emit_store_flag_1 (rtx target, enum rtx_code code, rtx op0, rtx op1,
 
       if (tem)
        {
-         if (target_mode == VOIDmode)
+         if (target_mode == VOIDmode || GET_MODE (tem) == target_mode)
            return tem;
+         if (!target)
+           target = gen_reg_rtx (target_mode);
 
          convert_move (target, tem,
-                       0 == (STORE_FLAG_VALUE
+                       0 == ((normalizep ? normalizep : STORE_FLAG_VALUE)
                              & ((HOST_WIDE_INT) 1
                                 << (GET_MODE_BITSIZE (word_mode) -1))));
          return target;
@@ -5404,14 +5406,14 @@ emit_store_flag_1 (rtx target, enum rtx_code code, rtx op0, rtx op1,
        {
          do_pending_stack_adjust ();
          tem = emit_cstore (target, icode, code, mode, compare_mode,
-                            unsignedp, op0, op1, normalizep);
+                            unsignedp, op0, op1, normalizep, target_mode);
          if (tem)
            return tem;
 
          if (GET_MODE_CLASS (mode) == MODE_FLOAT)
            {
              tem = emit_cstore (target, icode, scode, mode, compare_mode,
-                                unsignedp, op1, op0, normalizep);
+                                unsignedp, op1, op0, normalizep, target_mode);
              if (tem)
                return tem;
            }
@@ -5446,7 +5448,8 @@ emit_store_flag (rtx target, enum rtx_code code, rtx op0, rtx op1,
   rtx subtarget;
   rtx tem, last, trueval;
 
-  tem = emit_store_flag_1 (target, code, op0, op1, mode, unsignedp, normalizep);
+  tem = emit_store_flag_1 (target, code, op0, op1, mode, unsignedp, normalizep,
+                          target_mode);
   if (tem)
     return tem;
 
@@ -5499,7 +5502,7 @@ emit_store_flag (rtx target, enum rtx_code code, rtx op0, rtx op1,
              || (STORE_FLAG_VALUE == -1 && normalizep == 1))
            {
              tem = emit_store_flag_1 (subtarget, rcode, op0, op1, mode, 0,
-                                      STORE_FLAG_VALUE);
+                                      STORE_FLAG_VALUE, target_mode);
              if (tem)
                 return expand_binop (target_mode, add_optab, tem,
                                     GEN_INT (normalizep),
@@ -5508,7 +5511,7 @@ emit_store_flag (rtx target, enum rtx_code code, rtx op0, rtx op1,
          else
            {
              tem = emit_store_flag_1 (subtarget, rcode, op0, op1, mode, 0,
-                                      normalizep);
+                                      normalizep, target_mode);
              if (tem)
                 return expand_binop (target_mode, xor_optab, tem, trueval,
                                     target, INTVAL (trueval) >= 0, OPTAB_WIDEN);
@@ -5528,13 +5531,15 @@ emit_store_flag (rtx target, enum rtx_code code, rtx op0, rtx op1,
       if (!HONOR_NANS (mode))
        {
           gcc_assert (first_code == (and_them ? ORDERED : UNORDERED));
-         return emit_store_flag_1 (target, code, op0, op1, mode, 0, normalizep);
+         return emit_store_flag_1 (target, code, op0, op1, mode, 0, normalizep,
+                                   target_mode);
        }
 
 #ifdef HAVE_conditional_move
       /* Try using a setcc instruction for ORDERED/UNORDERED, followed by a
         conditional move.  */
-      tem = emit_store_flag_1 (subtarget, first_code, op0, op1, mode, 0, normalizep);
+      tem = emit_store_flag_1 (subtarget, first_code, op0, op1, mode, 0,
+                              normalizep, target_mode);
       if (tem == 0)
        return 0;
 
@@ -5572,8 +5577,8 @@ emit_store_flag (rtx target, enum rtx_code code, rtx op0, rtx op1,
        tem = expand_binop (mode, sub_optab, op0, op1, subtarget, 1,
                            OPTAB_WIDEN);
       if (tem != 0)
-       tem = emit_store_flag_1 (target, code, tem, const0_rtx,
-                                mode, unsignedp, normalizep);
+       tem = emit_store_flag (target, code, tem, const0_rtx,
+                              mode, unsignedp, normalizep);
       if (tem != 0)
        return tem;
 
@@ -5595,7 +5600,7 @@ emit_store_flag (rtx target, enum rtx_code code, rtx op0, rtx op1,
          || (STORE_FLAG_VALUE == -1 && normalizep == 1))
        {
          tem = emit_store_flag_1 (subtarget, rcode, op0, op1, mode, 0,
-                                  STORE_FLAG_VALUE);
+                                  STORE_FLAG_VALUE, target_mode);
          if (tem != 0)
             tem = expand_binop (target_mode, add_optab, tem,
                                GEN_INT (normalizep), target, 0, OPTAB_WIDEN);
@@ -5603,7 +5608,7 @@ emit_store_flag (rtx target, enum rtx_code code, rtx op0, rtx op1,
       else
        {
          tem = emit_store_flag_1 (subtarget, rcode, op0, op1, mode, 0,
-                                  normalizep);
+                                  normalizep, target_mode);
          if (tem != 0)
             tem = expand_binop (target_mode, xor_optab, tem, trueval, target,
                                INTVAL (trueval) >= 0, OPTAB_WIDEN);