OSDN Git Service

* ifcvt.c (noce_get_alt_condition): Use reg_overlap_mentioned_p.
[pf3gnuchains/gcc-fork.git] / gcc / recog.c
index 3b9d961..c56069a 100644 (file)
@@ -161,7 +161,7 @@ check_asm_operands (x)
        c = constraints[c[0] - '0'];
 
       if (! asm_operand_ok (operands[i], c))
-        return 0;
+       return 0;
     }
 
   return 1;
@@ -227,11 +227,11 @@ validate_change (object, loc, new, in_group)
       else
        changes_allocated *= 2;
 
-      changes = 
-       (change_t*) xrealloc (changes, 
-                             sizeof (change_t) * changes_allocated); 
+      changes =
+       (change_t*) xrealloc (changes,
+                             sizeof (change_t) * changes_allocated);
     }
-  
+
   changes[num_changes].object = object;
   changes[num_changes].loc = loc;
   changes[num_changes].old = old;
@@ -272,7 +272,7 @@ insn_invalid_p (insn)
                     ? &num_clobbers : 0);
   int is_asm = icode < 0 && asm_noperands (PATTERN (insn)) >= 0;
 
-  
+
   /* If this is an asm and the operand aren't legal, then fail.  Likewise if
      this is not an asm and the insn wasn't recognized.  */
   if ((is_asm && ! check_asm_operands (PATTERN (insn)))
@@ -308,6 +308,13 @@ insn_invalid_p (insn)
   return 0;
 }
 
+/* Return number of changes made and not validated yet.  */
+int
+num_changes_pending ()
+{
+  return num_changes;
+}
+
 /* Apply a group of changes previously issued with `validate_change'.
    Return 1 if all changes are valid, zero otherwise.  */
 
@@ -362,7 +369,7 @@ apply_change_group ()
                  int j;
 
                  newpat
-                   = gen_rtx_PARALLEL (VOIDmode, 
+                   = gen_rtx_PARALLEL (VOIDmode,
                                        rtvec_alloc (XVECLEN (pat, 0) - 1));
                  for (j = 0; j < XVECLEN (newpat, 0); j++)
                    XVECEXP (newpat, 0, j) = XVECEXP (pat, 0, j);
@@ -397,11 +404,8 @@ apply_change_group ()
       for (i = 0; i < num_changes; i++)
        if (changes[i].object
            && INSN_P (changes[i].object)
-           && basic_block_for_insn
-           && ((unsigned int)INSN_UID (changes[i].object)
-               < basic_block_for_insn->num_elements)
            && (bb = BLOCK_FOR_INSN (changes[i].object)))
-        bb->flags |= BB_DIRTY;
+         bb->flags |= BB_DIRTY;
 
       num_changes = 0;
       return 1;
@@ -674,11 +678,10 @@ validate_replace_src_1 (x, data)
 }
 
 /* Try replacing every occurrence of FROM in INSN with TO, avoiding
-   SET_DESTs.  After all changes have been made, validate by seeing if
-   INSN is still valid.  */
+   SET_DESTs.  */
 
-int
-validate_replace_src (from, to, insn)
+void
+validate_replace_src_group (from, to, insn)
      rtx from, to, insn;
 {
   struct validate_replace_src_data d;
@@ -687,6 +690,15 @@ validate_replace_src (from, to, insn)
   d.to = to;
   d.insn = insn;
   note_uses (&PATTERN (insn), validate_replace_src_1, &d);
+}
+
+/* Same as validate_repalace_src_group, but validate by seeing if
+   INSN is still valid.  */
+int
+validate_replace_src (from, to, insn)
+     rtx from, to, insn;
+{
+  validate_replace_src_group (from, to, insn);
   return apply_change_group ();
 }
 \f
@@ -789,7 +801,7 @@ find_single_use_1 (dest, loc)
     case MEM:
     case SUBREG:
       return find_single_use_1 (dest, &XEXP (x, 0));
-      
+
     default:
       break;
     }
@@ -961,24 +973,32 @@ general_operand (op, mode)
 
   if (code == SUBREG)
     {
+      rtx sub = SUBREG_REG (op);
+
 #ifdef INSN_SCHEDULING
       /* On machines that have insn scheduling, we want all memory
         reference to be explicit, so outlaw paradoxical SUBREGs.  */
-      if (GET_CODE (SUBREG_REG (op)) == MEM
-         && GET_MODE_SIZE (mode) > GET_MODE_SIZE (GET_MODE (SUBREG_REG (op))))
+      if (GET_CODE (sub) == MEM
+         && GET_MODE_SIZE (mode) > GET_MODE_SIZE (GET_MODE (sub)))
        return 0;
 #endif
       /* Avoid memories with nonzero SUBREG_BYTE, as offsetting the memory
          may result in incorrect reference.  We should simplify all valid
          subregs of MEM anyway.  But allow this after reload because we
-        might be called from cleanup_subreg_operands. 
+        might be called from cleanup_subreg_operands.
 
         ??? This is a kludge.  */
       if (!reload_completed && SUBREG_BYTE (op) != 0
-         && GET_CODE (SUBREG_REG (op)) == MEM)
-        return 0;
+         && GET_CODE (sub) == MEM)
+       return 0;
 
-      op = SUBREG_REG (op);
+      /* FLOAT_MODE subregs can't be paradoxical.  Combine will occasionally
+        create such rtl, and we must reject it.  */
+      if (GET_MODE_CLASS (GET_MODE (op)) == MODE_FLOAT
+         && GET_MODE_SIZE (GET_MODE (op)) > GET_MODE_SIZE (GET_MODE (sub)))
+       return 0;
+
+      op = sub;
       code = GET_CODE (op);
     }
 
@@ -1051,28 +1071,36 @@ register_operand (op, mode)
 
   if (GET_CODE (op) == SUBREG)
     {
+      rtx sub = SUBREG_REG (op);
+
       /* Before reload, we can allow (SUBREG (MEM...)) as a register operand
         because it is guaranteed to be reloaded into one.
         Just make sure the MEM is valid in itself.
         (Ideally, (SUBREG (MEM)...) should not exist after reload,
         but currently it does result from (SUBREG (REG)...) where the
         reg went on the stack.)  */
-      if (! reload_completed && GET_CODE (SUBREG_REG (op)) == MEM)
+      if (! reload_completed && GET_CODE (sub) == MEM)
        return general_operand (op, mode);
 
 #ifdef CLASS_CANNOT_CHANGE_MODE
-      if (GET_CODE (SUBREG_REG (op)) == REG
-         && REGNO (SUBREG_REG (op)) < FIRST_PSEUDO_REGISTER
+      if (GET_CODE (sub) == REG
+         && REGNO (sub) < FIRST_PSEUDO_REGISTER
          && (TEST_HARD_REG_BIT
              (reg_class_contents[(int) CLASS_CANNOT_CHANGE_MODE],
-              REGNO (SUBREG_REG (op))))
-         && CLASS_CANNOT_CHANGE_MODE_P (mode, GET_MODE (SUBREG_REG (op)))
-         && GET_MODE_CLASS (GET_MODE (SUBREG_REG (op))) != MODE_COMPLEX_INT
-         && GET_MODE_CLASS (GET_MODE (SUBREG_REG (op))) != MODE_COMPLEX_FLOAT)
+              REGNO (sub)))
+         && CLASS_CANNOT_CHANGE_MODE_P (mode, GET_MODE (sub))
+         && GET_MODE_CLASS (GET_MODE (sub)) != MODE_COMPLEX_INT
+         && GET_MODE_CLASS (GET_MODE (sub)) != MODE_COMPLEX_FLOAT)
        return 0;
 #endif
 
-      op = SUBREG_REG (op);
+      /* FLOAT_MODE subregs can't be paradoxical.  Combine will occasionally
+        create such rtl, and we must reject it.  */
+      if (GET_MODE_CLASS (GET_MODE (op)) == MODE_FLOAT
+         && GET_MODE_SIZE (GET_MODE (op)) > GET_MODE_SIZE (GET_MODE (sub)))
+       return 0;
+
+      op = sub;
     }
 
   /* If we have an ADDRESSOF, consider it valid since it will be
@@ -1329,7 +1357,7 @@ memory_address_p (mode, addr)
 {
   if (GET_CODE (addr) == ADDRESSOF)
     return 1;
-  
+
   GO_IF_LEGITIMATE_ADDRESS (mode, addr, win);
   return 0;
 
@@ -1583,7 +1611,7 @@ decode_asm_operands (body, operands, operand_locs, constraints, modes)
        {
          if (GET_CODE (XVECEXP (body, 0, i)) == CLOBBER)
            break;              /* Past last SET */
-         
+
          if (operands)
            operands[i] = SET_DEST (XVECEXP (body, 0, i));
          if (operand_locs)
@@ -1635,7 +1663,7 @@ decode_asm_operands (body, operands, operand_locs, constraints, modes)
   return template;
 }
 
-/* Check if an asm_operand matches it's constraints. 
+/* Check if an asm_operand matches it's constraints.
    Return > 0 if ok, = 0 if bad, < 0 if inconclusive.  */
 
 int
@@ -1703,7 +1731,7 @@ asm_operand_ok (op, constraint)
          if (GET_CODE (op) == MEM
              && (1
                  || GET_CODE (XEXP (op, 0)) == PRE_DEC
-                  || GET_CODE (XEXP (op, 0)) == POST_DEC))
+                 || GET_CODE (XEXP (op, 0)) == POST_DEC))
            return 1;
          break;
 
@@ -1711,13 +1739,15 @@ asm_operand_ok (op, constraint)
          if (GET_CODE (op) == MEM
              && (1
                  || GET_CODE (XEXP (op, 0)) == PRE_INC
-                  || GET_CODE (XEXP (op, 0)) == POST_INC))
+                 || GET_CODE (XEXP (op, 0)) == POST_INC))
            return 1;
          break;
 
        case 'E':
        case 'F':
-         if (GET_CODE (op) == CONST_DOUBLE)
+         if (GET_CODE (op) == CONST_DOUBLE
+             || (GET_CODE (op) == CONST_VECTOR
+                 && GET_MODE_CLASS (GET_MODE (op)) == MODE_VECTOR_FLOAT))
            return 1;
          break;
 
@@ -2215,7 +2245,7 @@ preprocess_constraints ()
                  break;
                case '&':
                  op_alt[j].earlyclobber = 1;
-                 break;                  
+                 break;
 
                case '0': case '1': case '2': case '3': case '4':
                case '5': case '6': case '7': case '8': case '9':
@@ -2264,7 +2294,7 @@ preprocess_constraints ()
        }
     }
 }
+
 /* Check the operands of an insn against the insn's operand constraints
    and return 1 if they are valid.
    The information about the insn's operands, constraints, operand modes
@@ -2485,7 +2515,9 @@ constrain_operands (strict)
 
              case 'E':
              case 'F':
-               if (GET_CODE (op) == CONST_DOUBLE)
+               if (GET_CODE (op) == CONST_DOUBLE
+                   || (GET_CODE (op) == CONST_VECTOR
+                       && GET_MODE_CLASS (GET_MODE (op)) == MODE_VECTOR_FLOAT))
                  win = 1;
                break;
 
@@ -2700,7 +2732,7 @@ split_insn (insn)
          NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
 
          /* ??? Coddle to md files that generate subregs in post-
-            reload splitters instead of computing the proper 
+            reload splitters instead of computing the proper
             hard register.  */
          if (reload_completed && first != last)
            {
@@ -2727,15 +2759,14 @@ split_all_insns (upd_life)
 {
   sbitmap blocks;
   int changed;
-  int i;
+  basic_block bb;
 
-  blocks = sbitmap_alloc (n_basic_blocks);
+  blocks = sbitmap_alloc (last_basic_block);
   sbitmap_zero (blocks);
   changed = 0;
 
-  for (i = n_basic_blocks - 1; i >= 0; --i)
+  FOR_EACH_BB_REVERSE (bb)
     {
-      basic_block bb = BASIC_BLOCK (i);
       rtx insn, next;
       bool finish = false;
 
@@ -2756,7 +2787,7 @@ split_all_insns (upd_life)
 
              while (GET_CODE (last) == BARRIER)
                last = PREV_INSN (last);
-             SET_BIT (blocks, i);
+             SET_BIT (blocks, bb->index);
              changed = 1;
              insn = last;
            }
@@ -2780,7 +2811,7 @@ split_all_insns (upd_life)
   sbitmap_free (blocks);
 }
 
-/* Same as split_all_insns, but do not expect CFG to be available. 
+/* Same as split_all_insns, but do not expect CFG to be available.
    Used by machine depedent reorg passes.  */
 
 void
@@ -2999,7 +3030,8 @@ peephole2_optimize (dump_file)
   regset_head rs_heads[MAX_INSNS_PER_PEEP2 + 2];
   rtx insn, prev;
   regset live;
-  int i, b;
+  int i;
+  basic_block bb;
 #ifdef HAVE_conditional_execution
   sbitmap blocks;
   bool changed;
@@ -3013,16 +3045,15 @@ peephole2_optimize (dump_file)
   live = INITIALIZE_REG_SET (rs_heads[i]);
 
 #ifdef HAVE_conditional_execution
-  blocks = sbitmap_alloc (n_basic_blocks);
+  blocks = sbitmap_alloc (last_basic_block);
   sbitmap_zero (blocks);
   changed = false;
 #else
   count_or_remove_death_notes (NULL, 1);
 #endif
 
-  for (b = n_basic_blocks - 1; b >= 0; --b)
+  FOR_EACH_BB_REVERSE (bb)
     {
-      basic_block bb = BASIC_BLOCK (b);
       struct propagate_block_info *pbi;
 
       /* Indicate that all slots except the last holds invalid data.  */
@@ -3051,6 +3082,7 @@ peephole2_optimize (dump_file)
              rtx try, before_try, x;
              int match_len;
              rtx note;
+             bool was_call = false;
 
              /* Record this insn.  */
              if (--peep2_current < 0)
@@ -3068,7 +3100,7 @@ peephole2_optimize (dump_file)
                     cfg-related call notes.  */
                  for (i = 0; i <= match_len; ++i)
                    {
-                     int j, k;
+                     int j;
                      rtx old_insn, new_insn, note;
 
                      j = i + peep2_current;
@@ -3077,21 +3109,17 @@ peephole2_optimize (dump_file)
                      old_insn = peep2_insn_data[j].insn;
                      if (GET_CODE (old_insn) != CALL_INSN)
                        continue;
+                     was_call = true;
 
-                     new_insn = NULL_RTX;
-                     if (GET_CODE (try) == SEQUENCE)
-                       for (k = XVECLEN (try, 0) - 1; k >= 0; k--)
-                         {
-                           rtx x = XVECEXP (try, 0, k);
-                           if (GET_CODE (x) == CALL_INSN)
-                             {
-                               new_insn = x;
-                               break;
-                             }
-                         }
-                     else if (GET_CODE (try) == CALL_INSN)
-                       new_insn = try;
-                     if (! new_insn)
+                     new_insn = try;
+                     while (new_insn != NULL_RTX)
+                       {
+                         if (GET_CODE (new_insn) == CALL_INSN)
+                           break;
+                         new_insn = NEXT_INSN (new_insn);
+                       }
+
+                     if (new_insn == NULL_RTX)
                        abort ();
 
                      CALL_INSN_FUNCTION_USAGE (new_insn)
@@ -3131,22 +3159,23 @@ peephole2_optimize (dump_file)
                  if (i >= MAX_INSNS_PER_PEEP2 + 1)
                    i -= MAX_INSNS_PER_PEEP2 + 1;
 
-                 note = find_reg_note (peep2_insn_data[i].insn, 
+                 note = find_reg_note (peep2_insn_data[i].insn,
                                        REG_EH_REGION, NULL_RTX);
 
                  /* Replace the old sequence with the new.  */
-                 try = emit_insn_after (try, peep2_insn_data[i].insn);
+                 try = emit_insn_after_scope (try, peep2_insn_data[i].insn,
+                                              INSN_SCOPE (peep2_insn_data[i].insn));
                  before_try = PREV_INSN (insn);
                  delete_insn_chain (insn, peep2_insn_data[i].insn);
 
                  /* Re-insert the EH_REGION notes.  */
-                 if (note)
+                 if (note || (was_call && nonlocal_goto_handler_labels))
                    {
                      edge eh_edge;
 
                      for (eh_edge = bb->succ; eh_edge
                           ; eh_edge = eh_edge->succ_next)
-                       if (eh_edge->flags & EDGE_EH)
+                       if (eh_edge->flags & (EDGE_EH | EDGE_ABNORMAL_CALL))
                          break;
 
                      for (x = try ; x != before_try ; x = PREV_INSN (x))
@@ -3155,10 +3184,11 @@ peephole2_optimize (dump_file)
                                && may_trap_p (PATTERN (x))
                                && !find_reg_note (x, REG_EH_REGION, NULL)))
                          {
-                           REG_NOTES (x)
-                             = gen_rtx_EXPR_LIST (REG_EH_REGION,
-                                                  XEXP (note, 0),
-                                                  REG_NOTES (x));
+                           if (note)
+                             REG_NOTES (x)
+                               = gen_rtx_EXPR_LIST (REG_EH_REGION,
+                                                    XEXP (note, 0),
+                                                    REG_NOTES (x));
 
                            if (x != bb->end && eh_edge)
                              {
@@ -3166,7 +3196,8 @@ peephole2_optimize (dump_file)
                                int flags;
 
                                nfte = split_block (bb, x);
-                               flags = EDGE_EH | EDGE_ABNORMAL;
+                               flags = (eh_edge->flags
+                                        & (EDGE_EH | EDGE_ABNORMAL));
                                if (GET_CODE (x) == CALL_INSN)
                                  flags |= EDGE_ABNORMAL_CALL;
                                nehe = make_edge (nfte->src, eh_edge->dest,
@@ -3197,7 +3228,7 @@ peephole2_optimize (dump_file)
                     death data structures are not so self-contained.
                     So record that we've made a modification to this
                     block and update life information at the end.  */
-                 SET_BIT (blocks, b);
+                 SET_BIT (blocks, bb->index);
                  changed = true;
 
                  for (i = 0; i < MAX_INSNS_PER_PEEP2 + 1; ++i)
@@ -3357,7 +3388,7 @@ if_test_bypass_p (out_insn, in_insn)
     {
       if (reg_mentioned_p (SET_DEST (out_set), XEXP (in_set, 1))
          || reg_mentioned_p (SET_DEST (out_set), XEXP (in_set, 2)))
-        return false;
+       return false;
     }
   else
     {