OSDN Git Service

* config/h8300/h8300.md (movqi_h8sx, movhi_h8sx, movsi_h8sx,
[pf3gnuchains/gcc-fork.git] / gcc / recog.c
index 6874d6c..1847c23 100644 (file)
@@ -1,6 +1,6 @@
 /* Subroutines used by or related to instruction recognition.
    Copyright (C) 1987, 1988, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998
-   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
    Free Software Foundation, Inc.
 
 This file is part of GCC.
@@ -35,7 +35,6 @@ along with GCC; see the file COPYING3.  If not see
 #include "expr.h"
 #include "function.h"
 #include "flags.h"
-#include "real.h"
 #include "toplev.h"
 #include "basic-block.h"
 #include "output.h"
@@ -286,7 +285,7 @@ canonicalize_change_group (rtx insn, rtx x)
   else
     return false;
 }
-  
+
 
 /* This subroutine of apply_change_group verifies whether the changes to INSN
    were valid; i.e. whether INSN can still be recognized.  */
@@ -376,7 +375,9 @@ verify_changes (int num)
 
       if (MEM_P (object))
        {
-         if (! memory_address_p (GET_MODE (object), XEXP (object, 0)))
+         if (! memory_address_addr_space_p (GET_MODE (object),
+                                            XEXP (object, 0),
+                                            MEM_ADDR_SPACE (object)))
            break;
        }
       else if (REG_P (changes[i].old)
@@ -527,7 +528,7 @@ cancel_changes (int num)
    rtx.  */
 
 static void
-simplify_while_replacing (rtx *loc, rtx to, rtx object, 
+simplify_while_replacing (rtx *loc, rtx to, rtx object,
                           enum machine_mode op0_mode)
 {
   rtx x = *loc;
@@ -658,7 +659,7 @@ simplify_while_replacing (rtx *loc, rtx to, rtx object,
    validate_change passing OBJECT.  */
 
 static void
-validate_replace_rtx_1 (rtx *loc, rtx from, rtx to, rtx object, 
+validate_replace_rtx_1 (rtx *loc, rtx from, rtx to, rtx object,
                         bool simplify)
 {
   int i, j;
@@ -711,7 +712,7 @@ validate_replace_rtx_1 (rtx *loc, rtx from, rtx to, rtx object,
                                      from, to, object, simplify);
            }
          else
-           validate_replace_rtx_1 (&XVECEXP (x, 0, j), from, to, object, 
+           validate_replace_rtx_1 (&XVECEXP (x, 0, j), from, to, object,
                                     simplify);
        }
     }
@@ -722,7 +723,7 @@ validate_replace_rtx_1 (rtx *loc, rtx from, rtx to, rtx object,
          validate_replace_rtx_1 (&XEXP (x, i), from, to, object, simplify);
        else if (fmt[i] == 'E')
          for (j = XVECLEN (x, i) - 1; j >= 0; j--)
-           validate_replace_rtx_1 (&XVECEXP (x, i, j), from, to, object, 
+           validate_replace_rtx_1 (&XVECEXP (x, i, j), from, to, object,
                                     simplify);
       }
 
@@ -763,9 +764,9 @@ validate_replace_rtx (rtx from, rtx to, rtx insn)
 }
 
 /* Try replacing every occurrence of FROM in WHERE with TO.  Assume that WHERE
-   is a part of INSN.  After all changes have been made, validate by seeing if 
-   INSN is still valid.  
-   validate_replace_rtx (from, to, insn) is equivalent to 
+   is a part of INSN.  After all changes have been made, validate by seeing if
+   INSN is still valid.
+   validate_replace_rtx (from, to, insn) is equivalent to
    validate_replace_rtx_part (from, to, &PATTERN (insn), insn).  */
 
 int
@@ -776,8 +777,8 @@ validate_replace_rtx_part (rtx from, rtx to, rtx *where, rtx insn)
 }
 
 /* Same as above, but do not simplify rtx afterwards.  */
-int 
-validate_replace_rtx_part_nosimplify (rtx from, rtx to, rtx *where, 
+int
+validate_replace_rtx_part_nosimplify (rtx from, rtx to, rtx *where,
                                       rtx insn)
 {
   validate_replace_rtx_1 (where, from, to, insn, false);
@@ -785,12 +786,18 @@ validate_replace_rtx_part_nosimplify (rtx from, rtx to, rtx *where,
 
 }
 
-/* Try replacing every occurrence of FROM in INSN with TO.  */
+/* Try replacing every occurrence of FROM in INSN with TO.  This also
+   will replace in REG_EQUAL and REG_EQUIV notes.  */
 
 void
 validate_replace_rtx_group (rtx from, rtx to, rtx insn)
 {
+  rtx note;
   validate_replace_rtx_1 (&PATTERN (insn), from, to, insn, true);
+  for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
+    if (REG_NOTE_KIND (note) == REG_EQUAL
+       || REG_NOTE_KIND (note) == REG_EQUIV)
+      validate_replace_rtx_1 (&XEXP (note, 0), from, to, insn, true);
 }
 
 /* Function called by note_uses to replace used subexpressions.  */
@@ -978,7 +985,7 @@ general_operand (rtx op, enum machine_mode mode)
        return 0;
 
       /* Use the mem's mode, since it will be reloaded thus.  */
-      if (memory_address_p (GET_MODE (op), y))
+      if (memory_address_addr_space_p (GET_MODE (op), y, MEM_ADDR_SPACE (op)))
        return 1;
     }
 
@@ -1262,19 +1269,22 @@ pop_operand (rtx op, enum machine_mode mode)
   return XEXP (op, 0) == stack_pointer_rtx;
 }
 
-/* Return 1 if ADDR is a valid memory address for mode MODE.  */
+/* Return 1 if ADDR is a valid memory address
+   for mode MODE in address space AS.  */
 
 int
-memory_address_p (enum machine_mode mode ATTRIBUTE_UNUSED, rtx addr)
+memory_address_addr_space_p (enum machine_mode mode ATTRIBUTE_UNUSED,
+                            rtx addr, addr_space_t as)
 {
 #ifdef GO_IF_LEGITIMATE_ADDRESS
+  gcc_assert (ADDR_SPACE_GENERIC_P (as));
   GO_IF_LEGITIMATE_ADDRESS (mode, addr, win);
   return 0;
 
  win:
   return 1;
 #else
-  return targetm.legitimate_address_p (mode, addr, 0);
+  return targetm.addr_space.legitimate_address_p (mode, addr, 0, as);
 #endif
 }
 
@@ -1430,7 +1440,7 @@ asm_noperands (const_rtx body)
       if (GET_CODE (XVECEXP (body, 0, 0)) == SET)
        {
          /* Multiple output operands, or 1 output plus some clobbers:
-            body is 
+            body is
             [(set OUTPUT (asm_operands ...))... (clobber (reg ...))...].  */
          /* Count backwards through CLOBBERs to determine number of SETs.  */
          for (i = XVECLEN (body, 0); i > 0; i--)
@@ -1491,7 +1501,7 @@ decode_asm_operands (rtx body, rtx *operands, rtx **operand_locs,
                     const char **constraints, enum machine_mode *modes,
                     location_t *loc)
 {
-  int noperands, nbase = 0, n, i;
+  int nbase = 0, n, i;
   rtx asmop;
 
   switch (GET_CODE (body))
@@ -1551,9 +1561,6 @@ decode_asm_operands (rtx body, rtx *operands, rtx **operand_locs,
       gcc_unreachable ();
     }
 
-  noperands = (ASM_OPERANDS_INPUT_LENGTH (asmop)
-              + ASM_OPERANDS_LABEL_LENGTH (asmop) + nbase);
-
   n = ASM_OPERANDS_INPUT_LENGTH (asmop);
   for (i = 0; i < n; i++)
     {
@@ -1871,7 +1878,8 @@ int
 offsettable_memref_p (rtx op)
 {
   return ((MEM_P (op))
-         && offsettable_address_p (1, GET_MODE (op), XEXP (op, 0)));
+         && offsettable_address_addr_space_p (1, GET_MODE (op), XEXP (op, 0),
+                                              MEM_ADDR_SPACE (op)));
 }
 
 /* Similar, but don't require a strictly valid mem ref:
@@ -1881,12 +1889,13 @@ int
 offsettable_nonstrict_memref_p (rtx op)
 {
   return ((MEM_P (op))
-         && offsettable_address_p (0, GET_MODE (op), XEXP (op, 0)));
+         && offsettable_address_addr_space_p (0, GET_MODE (op), XEXP (op, 0),
+                                              MEM_ADDR_SPACE (op)));
 }
 
 /* Return 1 if Y is a memory address which contains no side effects
-   and would remain valid after the addition of a positive integer
-   less than the size of that mode.
+   and would remain valid for address space AS after the addition of
+   a positive integer less than the size of that mode.
 
    We assume that the original address is valid and do not check it.
    We do check that it is valid for narrower modes.
@@ -1895,14 +1904,16 @@ offsettable_nonstrict_memref_p (rtx op)
    for the sake of use in reload.c.  */
 
 int
-offsettable_address_p (int strictp, enum machine_mode mode, rtx y)
+offsettable_address_addr_space_p (int strictp, enum machine_mode mode, rtx y,
+                                 addr_space_t as)
 {
   enum rtx_code ycode = GET_CODE (y);
   rtx z;
   rtx y1 = y;
   rtx *y2;
-  int (*addressp) (enum machine_mode, rtx) =
-    (strictp ? strict_memory_address_p : memory_address_p);
+  int (*addressp) (enum machine_mode, rtx, addr_space_t) =
+    (strictp ? strict_memory_address_addr_space_p
+            : memory_address_addr_space_p);
   unsigned int mode_sz = GET_MODE_SIZE (mode);
 
   if (CONSTANT_ADDRESS_P (y))
@@ -1932,7 +1943,7 @@ offsettable_address_p (int strictp, enum machine_mode mode, rtx y)
       *y2 = plus_constant (*y2, mode_sz - 1);
       /* Use QImode because an odd displacement may be automatically invalid
         for any wider mode.  But it should be valid for a single byte.  */
-      good = (*addressp) (QImode, y);
+      good = (*addressp) (QImode, y, as);
 
       /* In any case, restore old contents of memory.  */
       *y2 = y1;
@@ -1957,7 +1968,7 @@ offsettable_address_p (int strictp, enum machine_mode mode, rtx y)
 
   /* Use QImode because an odd displacement may be automatically invalid
      for any wider mode.  But it should be valid for a single byte.  */
-  return (*addressp) (QImode, z);
+  return (*addressp) (QImode, z, as);
 }
 
 /* Return 1 if ADDR is an address-expression whose effect depends
@@ -1966,7 +1977,7 @@ offsettable_address_p (int strictp, enum machine_mode mode, rtx y)
    Autoincrement addressing is a typical example of mode-dependence
    because the amount of the increment depends on the mode.  */
 
-int
+bool
 mode_dependent_address_p (rtx addr)
 {
   /* Auto-increment addressing with anything other than post_modify
@@ -1976,13 +1987,9 @@ mode_dependent_address_p (rtx addr)
       || GET_CODE (addr) == POST_INC
       || GET_CODE (addr) == PRE_DEC
       || GET_CODE (addr) == POST_DEC)
-    return 1;
+    return true;
 
-  GO_IF_MODE_DEPENDENT_ADDRESS (addr, win);
-  return 0;
-  /* Label `win' might (not) be used via GO_IF_MODE_DEPENDENT_ADDRESS.  */
- win: ATTRIBUTE_UNUSED_LABEL
-  return 1;
+  return targetm.mode_dependent_address_p (addr);
 }
 \f
 /* Like extract_insn, but save insn extracted and don't extract again, when
@@ -2070,6 +2077,7 @@ extract_insn (rtx insn)
                               recog_data.operand_loc,
                               recog_data.constraints,
                               recog_data.operand_mode, NULL);
+         memset (recog_data.is_operator, 0, sizeof recog_data.is_operator);
          if (noperands > 0)
            {
              const char *p =  recog_data.constraints[0];
@@ -2099,6 +2107,7 @@ extract_insn (rtx insn)
       for (i = 0; i < noperands; i++)
        {
          recog_data.constraints[i] = insn_data[icode].operand[i].constraint;
+         recog_data.is_operator[i] = insn_data[icode].operand[i].is_operator;
          recog_data.operand_mode[i] = insn_data[icode].operand[i].mode;
          /* VOIDmode match_operands gets mode from their real operand.  */
          if (recog_data.operand_mode[i] == VOIDmode)
@@ -2502,11 +2511,14 @@ constrain_operands (int strict)
                if (MEM_P (op))
                  {
                    if (strict > 0
-                       && !strict_memory_address_p (GET_MODE (op),
-                                                    XEXP (op, 0)))
+                       && !strict_memory_address_addr_space_p
+                            (GET_MODE (op), XEXP (op, 0),
+                             MEM_ADDR_SPACE (op)))
                      break;
                    if (strict == 0
-                       && !memory_address_p (GET_MODE (op), XEXP (op, 0)))
+                       && !memory_address_addr_space_p
+                            (GET_MODE (op), XEXP (op, 0),
+                             MEM_ADDR_SPACE (op)))
                      break;
                    win = 1;
                  }
@@ -3267,40 +3279,44 @@ peephole2_optimize (void)
                      do_cleanup_cfg |= purge_dead_edges (bb);
                    }
 
-#ifdef HAVE_conditional_execution
-                 for (i = 0; i < MAX_INSNS_PER_PEEP2 + 1; ++i)
-                   peep2_insn_data[i].insn = NULL_RTX;
-                 peep2_insn_data[peep2_current].insn = PEEP2_EOB;
-                 peep2_current_count = 0;
-#else
-                 /* Back up lifetime information past the end of the
-                    newly created sequence.  */
-                 if (++i >= MAX_INSNS_PER_PEEP2 + 1)
-                   i = 0;
-                 bitmap_copy (live, peep2_insn_data[i].live_before);
-
-                 /* Update life information for the new sequence.  */
-                 x = attempt;
-                 do
+                 if (targetm.have_conditional_execution ())
                    {
-                     if (INSN_P (x))
+                     for (i = 0; i < MAX_INSNS_PER_PEEP2 + 1; ++i)
+                       peep2_insn_data[i].insn = NULL_RTX;
+                     peep2_insn_data[peep2_current].insn = PEEP2_EOB;
+                     peep2_current_count = 0;
+                   }
+                 else
+                   {
+                     /* Back up lifetime information past the end of the
+                        newly created sequence.  */
+                     if (++i >= MAX_INSNS_PER_PEEP2 + 1)
+                       i = 0;
+                     bitmap_copy (live, peep2_insn_data[i].live_before);
+
+                     /* Update life information for the new sequence.  */
+                     x = attempt;
+                     do
                        {
-                         if (--i < 0)
-                           i = MAX_INSNS_PER_PEEP2;
-                         if (peep2_current_count < MAX_INSNS_PER_PEEP2
-                             && peep2_insn_data[i].insn == NULL_RTX)
-                           peep2_current_count++;
-                         peep2_insn_data[i].insn = x;
-                         df_insn_rescan (x);
-                         df_simulate_one_insn_backwards (bb, x, live);
-                         bitmap_copy (peep2_insn_data[i].live_before, live);
+                         if (INSN_P (x))
+                           {
+                             if (--i < 0)
+                               i = MAX_INSNS_PER_PEEP2;
+                             if (peep2_current_count < MAX_INSNS_PER_PEEP2
+                                 && peep2_insn_data[i].insn == NULL_RTX)
+                               peep2_current_count++;
+                             peep2_insn_data[i].insn = x;
+                             df_insn_rescan (x);
+                             df_simulate_one_insn_backwards (bb, x, live);
+                             bitmap_copy (peep2_insn_data[i].live_before,
+                                          live);
+                           }
+                         x = PREV_INSN (x);
                        }
-                     x = PREV_INSN (x);
-                   }
-                 while (x != prev);
+                     while (x != prev);
 
-                 peep2_current = i;
-#endif
+                     peep2_current = i;
+                   }
 
                  /* If we generated a jump instruction, it won't have
                     JUMP_LABEL set.  Recompute after we're done.  */
@@ -3658,7 +3674,7 @@ gate_do_final_split (void)
   return 1;
 #else
   return 0;
-#endif 
+#endif
 }
 
 struct rtl_opt_pass pass_split_for_shorten_branches =