re PR target/34571 (Segfault in alpha_expand_mov at -O3)
[gcc.git] / gcc / config / alpha / predicates.md
index 9ee22c299cc0971181f6c959e75300995d3d05d4..4aa06f4c33a032fd3ce573e22ba25a08914dadd5 100644 (file)
@@ -1,11 +1,11 @@
 ;; Predicate definitions for DEC Alpha.
-;; Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+;; Copyright (C) 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
 ;;
 ;; This file is part of GCC.
 ;;
 ;; GCC is free software; you can redistribute it and/or modify
 ;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
+;; the Free Software Foundation; either version 3, or (at your option)
 ;; any later version.
 ;;
 ;; GCC is distributed in the hope that it will be useful,
@@ -14,9 +14,8 @@
 ;; GNU General Public License for more details.
 ;;
 ;; You should have received a copy of the GNU General Public License
-;; along with GCC; see the file COPYING.  If not, write to
-;; the Free Software Foundation, 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
+;; along with GCC; see the file COPYING3.  If not see
+;; <http://www.gnu.org/licenses/>.
 
 ;; Return 1 if OP is the zero constant for MODE.
 (define_predicate "const0_operand"
 ;; Return 1 if the operand is a valid second operand to an add insn.
 (define_predicate "add_operand"
   (if_then_else (match_code "const_int")
-    (match_test "CONST_OK_FOR_LETTER_P (INTVAL (op), 'K')
-                || CONST_OK_FOR_LETTER_P (INTVAL (op), 'L')")
+    (match_test "satisfies_constraint_K (op) || satisfies_constraint_L (op)")
     (match_operand 0 "register_operand")))
 
 ;; Return 1 if the operand is a valid second operand to a
 ;; sign-extending add insn.
 (define_predicate "sext_add_operand"
   (if_then_else (match_code "const_int")
-    (match_test "CONST_OK_FOR_LETTER_P (INTVAL (op), 'I')
-                || CONST_OK_FOR_LETTER_P (INTVAL (op), 'O')")
+    (match_test "satisfies_constraint_I (op) || satisfies_constraint_O (op)")
     (match_operand 0 "register_operand")))
 
 ;; Return 1 if the operand is a non-symbolic constant operand that
@@ -72,7 +69,7 @@
   (and (match_code "const_int,const_double,const_vector")
        (not (match_operand 0 "add_operand"))))
 
-;; Return 1 if the operand is a non-symbolic, non-zero constant operand.
+;; Return 1 if the operand is a non-symbolic, nonzero constant operand.
 (define_predicate "non_zero_const_operand"
   (and (match_code "const_int,const_double,const_vector")
        (match_test "op != CONST0_RTX (mode)")))
@@ -89,7 +86,8 @@
                 || (unsigned HOST_WIDE_INT) ~ INTVAL (op) < 0x100
                 || zap_mask (INTVAL (op))")
     (if_then_else (match_code "const_double")
-      (match_test "zap_mask (CONST_DOUBLE_LOW (op))
+      (match_test "GET_MODE (op) == VOIDmode
+                  && zap_mask (CONST_DOUBLE_LOW (op))
                   && zap_mask (CONST_DOUBLE_HIGH (op))")
       (match_operand 0 "register_operand"))))
 
       return add_operand (op, mode);
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
   return 0;
 })
   tree op_decl, cfun_sec, op_sec;
 
   /* If profiling is implemented via linker tricks, we can't jump
-     to the nogp alternate entry point.  Note that current_function_profile
+     to the nogp alternate entry point.  Note that crtl->profile
      would not be correct, since that doesn't indicate if the target
      function uses profiling.  */
   /* ??? TARGET_PROFILING_NEEDS_GP isn't really the right test,
   if (GET_CODE (op) != SYMBOL_REF)
     return 0;
 
-  return SYMBOL_REF_LOCAL_P (op) && !SYMBOL_REF_TLS_MODEL (op);
+  return (SYMBOL_REF_LOCAL_P (op)
+         && !SYMBOL_REF_WEAK (op)
+         && !SYMBOL_REF_TLS_MODEL (op));
 })
 
 ;; Return true if OP is a SYMBOL_REF or CONST referencing a variable
 
   return (SYMBOL_REF_LOCAL_P (op)
          && SYMBOL_REF_SMALL_P (op)
-         && SYMBOL_REF_TLS_MODEL (op) == 0);
+         && !SYMBOL_REF_WEAK (op)
+         && !SYMBOL_REF_TLS_MODEL (op));
 })
 
 ;; Return true if OP is a SYMBOL_REF or CONST referencing a variable
   if (GET_CODE (op) != SYMBOL_REF)
     return 0;
 
-  return !SYMBOL_REF_LOCAL_P (op) && !SYMBOL_REF_TLS_MODEL (op);
+  return ((!SYMBOL_REF_LOCAL_P (op) || SYMBOL_REF_WEAK (op))
+         && !SYMBOL_REF_TLS_MODEL (op));
 })
 
 ;; Returns 1 if OP is a symbolic operand, i.e. a symbol_ref or a label_ref,
   (ior (match_code "symbol_ref,label_ref")
        (and (match_code "const")
            (match_test "GET_CODE (XEXP (op,0)) == PLUS
-                        && GET_CODE (XEXP (XEXP (op,0), 0)) == SYMBOL_REF
+                        && (GET_CODE (XEXP (XEXP (op,0), 0)) == SYMBOL_REF
+                            || GET_CODE (XEXP (XEXP (op,0), 0)) == LABEL_REF)
                         && GET_CODE (XEXP (XEXP (op,0), 1)) == CONST_INT"))))
 
 ;; Return true if OP is valid for 16-bit DTP relative relocations.
 ;; use recog during reload, so pretending these codes are accepted 
 ;; pessimizes things a tad.
 
-(define_predicate "aligned_memory_operand"
+(define_special_predicate "aligned_memory_operand"
   (ior (match_test "op = resolve_reload_operand (op), 0")
        (match_code "mem"))
 {
 
 ;; Similar, but return 1 if OP is a MEM which is not alignable.
 
-(define_predicate "unaligned_memory_operand"
+(define_special_predicate "unaligned_memory_operand"
   (ior (match_test "op = resolve_reload_operand (op), 0")
        (match_code "mem"))
 {
 })
 
 ;; Return 1 if OP is any memory location.  During reload a pseudo matches.
-(define_predicate "any_memory_operand"
-  (ior (match_code "mem,reg")
-       (and (match_code "subreg")
-           (match_test "GET_CODE (SUBREG_REG (op)) == REG"))))
+(define_special_predicate "any_memory_operand"
+  (match_code "mem,reg,subreg")
+{
+  if (GET_CODE (op) == SUBREG)
+    op = SUBREG_REG (op);
 
-;; Return 1 if OP is either a register or an unaligned memory location.
-(define_predicate "reg_or_unaligned_mem_operand"
-  (ior (match_operand 0 "register_operand")
-       (match_operand 0 "unaligned_memory_operand")))
+  if (MEM_P (op))
+    return true;
+  if (reload_in_progress && REG_P (op))
+    {
+      unsigned regno = REGNO (op);
+      if (HARD_REGISTER_NUM_P (regno))
+       return false;
+      else
+       return reg_renumber[regno] < 0;
+    }
+
+  return false;
+})
 
 ;; Return 1 is OP is a memory location that is not a reference
 ;; (using an AND) to an unaligned location.  Take into account
 ;; what reload will do.
-(define_predicate "normal_memory_operand"
+(define_special_predicate "normal_memory_operand"
   (ior (match_test "op = resolve_reload_operand (op), 0")
        (and (match_code "mem")
            (match_test "GET_CODE (XEXP (op, 0)) != AND"))))
 
 ;; Returns 1 if OP is not an eliminable register.
 ;;
-;; This exists to cure a pathological abort in the s8addq (et al) patterns,
+;; This exists to cure a pathological failure in the s8addq (et al) patterns,
 ;;
 ;;     long foo () { long t; bar(); return (long) &t * 26107; }
 ;;
 
 ;; Similarly, but with swapped operands.
 (define_predicate "alpha_swapped_comparison_operator"
-  (match_code "eq,ge,gt,gtu,gtu"))
+  (match_code "eq,ge,gt,gtu"))
 
 ;; Return 1 if OP is a valid Alpha comparison operator against zero
 ;; for "bcc" style instructions.
 (define_predicate "addition_operation"
   (and (match_code "plus")
        (match_test "register_operand (XEXP (op, 0), mode)
-                   && GET_CODE (XEXP (op, 1)) == CONST_INT
-                   && CONST_OK_FOR_LETTER_P (INTVAL (XEXP (op, 1)), 'K')")))
+                   && satisfies_constraint_K (XEXP (op, 1))")))
 
 ;; For TARGET_EXPLICIT_RELOCS, we don't obfuscate a SYMBOL_REF to a
 ;; small symbolic operand until after reload.  At which point we need