OSDN Git Service

* alpha.h (SECONDARY_INPUT_RELOAD_CLASS): Call secondary_reload_class.
authorrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 30 Oct 1999 21:46:57 +0000 (21:46 +0000)
committerrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 30 Oct 1999 21:46:57 +0000 (21:46 +0000)
        (SECONDARY_OUTPUT_RELOAD_CLASS): Likewise.
        (PREDICATE_CODES): Add addition_operation.
        * alpha-protos.h (addition_operation): Declare.
        (secondary_reload_class): Likewise.
        * alpha.c (addition_operation): New.
        (secondary_reload_class): New, from old SECONDARY_INPUT_RELOAD_CLASS.
        * alpha.md (adddi3): Turn into expander.
        (*lda, *adddi_2): New.
        (movsf, movdf patterns): Don't preference integer regs.
        (movsi, movdi patterns): Don't preference fp regs.

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

gcc/ChangeLog
gcc/config/alpha/alpha-protos.h
gcc/config/alpha/alpha.c
gcc/config/alpha/alpha.h
gcc/config/alpha/alpha.md

index 330d5ab..1a41457 100644 (file)
@@ -1,3 +1,17 @@
+Sat Oct 30 14:41:40 1999  Richard Henderson  <rth@cygnus.com>
+
+       * alpha.h (SECONDARY_INPUT_RELOAD_CLASS): Call secondary_reload_class.
+       (SECONDARY_OUTPUT_RELOAD_CLASS): Likewise.
+       (PREDICATE_CODES): Add addition_operation.
+       * alpha-protos.h (addition_operation): Declare.
+       (secondary_reload_class): Likewise.
+       * alpha.c (addition_operation): New.
+       (secondary_reload_class): New, from old SECONDARY_INPUT_RELOAD_CLASS.
+       * alpha.md (adddi3): Turn into expander.
+       (*lda, *adddi_2): New.
+       (movsf, movdf patterns): Don't preference integer regs.
+       (movsi, movdi patterns): Don't preference fp regs.
+
 Sat Oct 30 14:38:22 1999  Richard Henderson  <rth@cygnus.com>
 
        * genrecog.c (write_switch): Check for duplicate CODE cases.
index d9a2d74..9a47854 100644 (file)
@@ -66,10 +66,13 @@ extern int any_memory_operand PROTO ((rtx, enum machine_mode));
 extern int reg_not_elim_operand PROTO ((rtx, enum machine_mode));
 extern int normal_memory_operand PROTO ((rtx, enum machine_mode));
 extern int reg_no_subreg_operand PROTO ((rtx, enum machine_mode));
+extern int addition_operation PROTO ((rtx, enum machine_mode));
 
 extern void get_aligned_mem PROTO ((rtx, rtx *, rtx *));
 extern rtx get_unaligned_address PROTO ((rtx, int));
-
+extern enum reg_class secondary_reload_class PROTO ((enum reg_class,
+                                                    enum machine_mode, 
+                                                    rtx, int));
 extern void alpha_set_memflags PROTO ((rtx, rtx));
 extern rtx alpha_emit_set_const PROTO ((rtx, enum machine_mode,
                                        HOST_WIDE_INT, int));
index 0782440..07e7061 100644 (file)
@@ -939,7 +939,26 @@ reg_no_subreg_operand (op, mode)
     return 0;
   return register_operand (op, mode);
 }
-\f
+
+/* Recognize a addition operation that includes a constant.  Used to
+   convince reload to canonize (plus (plus reg c1) c2) during register
+   elimination.  */
+
+int
+addition_operation (op, mode)
+     register rtx op;
+     enum machine_mode mode;
+{
+  if (GET_MODE (op) != mode && mode != VOIDmode)
+    return 0;
+  if (GET_CODE (op) == PLUS
+      && register_operand (XEXP (op, 0), mode)
+      && GET_CODE (XEXP (op, 1)) == CONST_INT
+      && CONST_OK_FOR_LETTER_P (INTVAL (XEXP (op, 1)), 'K'))
+    return 1;
+  return 0;
+}
+
 /* Return 1 if this function can directly return via $26.  */
 
 int
@@ -950,7 +969,7 @@ direct_return ()
          && current_function_outgoing_args_size == 0
          && current_function_pretend_args_size == 0);
 }
-
+\f
 /* REF is an alignable memory location.  Place an aligned SImode
    reference into *PALIGNED_MEM and the number of bits to shift into
    *PBITNUM.  SCRATCH is a free register for use in reloading out
@@ -1026,6 +1045,53 @@ get_unaligned_address (ref, extra_offset)
 
   return plus_constant (base, offset + extra_offset);
 }
+
+/* Loading and storing HImode or QImode values to and from memory
+   usually requires a scratch register.  The exceptions are loading
+   QImode and HImode from an aligned address to a general register
+   unless byte instructions are permitted. 
+
+   We also cannot load an unaligned address or a paradoxical SUBREG
+   into an FP register. 
+
+   We also cannot do integral arithmetic into FP regs, as might result
+   from register elimination into a DImode fp register.  */
+
+enum reg_class
+secondary_reload_class (class, mode, x, in)
+     enum reg_class class;
+     enum machine_mode mode;
+     rtx x;
+     int in;
+{
+  if ((GET_CODE (x) == MEM
+       || (GET_CODE (x) == REG && REGNO (x) >= FIRST_PSEUDO_REGISTER)
+       || (GET_CODE (x) == SUBREG
+          && (GET_CODE (SUBREG_REG (x)) == MEM
+              || (GET_CODE (SUBREG_REG (x)) == REG
+                  && REGNO (SUBREG_REG (x)) >= FIRST_PSEUDO_REGISTER))))
+      && ((class == FLOAT_REGS
+          && (mode == SImode || mode == HImode || mode == QImode))
+         || ((mode == QImode || mode == HImode)
+             && ! TARGET_BWX && ! aligned_memory_operand (x, mode))))
+    return GENERAL_REGS;
+
+  if (class == FLOAT_REGS)
+    {
+      if (GET_CODE (x) == MEM && GET_CODE (XEXP (x, 0)) == AND)
+       return GENERAL_REGS;
+
+      if (GET_CODE (x) == SUBREG
+         && (GET_MODE_SIZE (GET_MODE (x))
+             > GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))))
+       return GENERAL_REGS;
+
+      if (in && INTEGRAL_MODE_P (mode) && ! general_operand (x, mode))
+       return GENERAL_REGS;
+    }
+
+  return NO_REGS;
+}
 \f
 /* Subfunction of the following function.  Update the flags of any MEM
    found in part of X.  */
index c39a2a4..2266f50 100644 (file)
@@ -815,42 +815,11 @@ enum reg_class { NO_REGS, GENERAL_REGS, FLOAT_REGS, ALL_REGS,
    We also cannot load an unaligned address or a paradoxical SUBREG into an
    FP register.   */
 
-#define SECONDARY_INPUT_RELOAD_CLASS(CLASS,MODE,IN)                    \
-(((GET_CODE (IN) == MEM                                                \
-   || (GET_CODE (IN) == REG && REGNO (IN) >= FIRST_PSEUDO_REGISTER)    \
-   || (GET_CODE (IN) == SUBREG                                         \
-       && (GET_CODE (SUBREG_REG (IN)) == MEM                           \
-          || (GET_CODE (SUBREG_REG (IN)) == REG                        \
-              && REGNO (SUBREG_REG (IN)) >= FIRST_PSEUDO_REGISTER))))  \
-  && (((CLASS) == FLOAT_REGS                                           \
-       && ((MODE) == SImode || (MODE) == HImode || (MODE) == QImode))  \
-      || (((MODE) == QImode || (MODE) == HImode)                       \
-         && ! TARGET_BWX && ! aligned_memory_operand (IN, MODE))))     \
- ? GENERAL_REGS                                                                \
- : ((CLASS) == FLOAT_REGS && GET_CODE (IN) == MEM                      \
-    && GET_CODE (XEXP (IN, 0)) == AND) ? GENERAL_REGS                  \
- : ((CLASS) == FLOAT_REGS && GET_CODE (IN) == SUBREG                   \
-    && (GET_MODE_SIZE (GET_MODE (IN))                                  \
-       > GET_MODE_SIZE (GET_MODE (SUBREG_REG (IN))))) ? GENERAL_REGS   \
- : NO_REGS)
-
-#define SECONDARY_OUTPUT_RELOAD_CLASS(CLASS,MODE,OUT)                  \
-(((GET_CODE (OUT) == MEM                                               \
-   || (GET_CODE (OUT) == REG && REGNO (OUT) >= FIRST_PSEUDO_REGISTER)  \
-   || (GET_CODE (OUT) == SUBREG                                                \
-       && (GET_CODE (SUBREG_REG (OUT)) == MEM                          \
-          || (GET_CODE (SUBREG_REG (OUT)) == REG                       \
-              && REGNO (SUBREG_REG (OUT)) >= FIRST_PSEUDO_REGISTER)))) \
-  && ((((MODE) == HImode || (MODE) == QImode)                          \
-       && (! TARGET_BWX || (CLASS) == FLOAT_REGS))                     \
-      || ((MODE) == SImode && (CLASS) == FLOAT_REGS)))                 \
- ? GENERAL_REGS                                                                \
- : ((CLASS) == FLOAT_REGS && GET_CODE (OUT) == MEM                     \
-    && GET_CODE (XEXP (OUT, 0)) == AND) ? GENERAL_REGS                 \
- : ((CLASS) == FLOAT_REGS && GET_CODE (OUT) == SUBREG                  \
-    && (GET_MODE_SIZE (GET_MODE (OUT))                                 \
-       > GET_MODE_SIZE (GET_MODE (SUBREG_REG (OUT))))) ? GENERAL_REGS  \
- : NO_REGS)
+#define SECONDARY_INPUT_RELOAD_CLASS(CLASS,MODE,IN) \
+  secondary_reload_class((CLASS), (MODE), (IN), 1)
+
+#define SECONDARY_OUTPUT_RELOAD_CLASS(CLASS,MODE,OUT) \
+  secondary_reload_class((CLASS), (MODE), (OUT), 0)
 
 /* If we are copying between general and FP registers, we need a memory
    location unless the FIX extension is available.  */
@@ -2340,7 +2309,8 @@ do {                                                                      \
   {"any_memory_operand", {MEM}},                                       \
   {"hard_fp_register_operand", {SUBREG, REG}},                         \
   {"reg_not_elim_operand", {SUBREG, REG}},                             \
-  {"reg_no_subreg_operand", {REG}},
+  {"reg_no_subreg_operand", {REG}},                                    \
+  {"addition_operation", {PLUS}},
 \f
 /* Define the `__builtin_va_list' type for the ABI.  */
 #define BUILD_VA_LIST_TYPE(VALIST) \
index 505a583..c5a0db1 100644 (file)
   operands[7] = gen_lowpart (SImode, operands[5]);
 }")
 
-(define_insn "adddi3"
-  [(set (match_operand:DI 0 "register_operand" "=r,r,r,r")
-       (plus:DI (match_operand:DI 1 "reg_or_0_operand" "%rJ,rJ,rJ,rJ")
-                (match_operand:DI 2 "add_operand" "rI,O,K,L")))]
+(define_expand "adddi3"
+  [(set (match_operand:DI 0 "register_operand" "")
+       (plus:DI (match_operand:DI 1 "register_operand" "")
+                (match_operand:DI 2 "add_operand" "")))]
   ""
-  "*
-{
-  static const char * const pattern[4] = {
-    \"addq %r1,%2,%0\",
-    \"subq %r1,%n2,%0\",
-    \"lda %0,%2(%r1)\",
-    \"ldah %0,%h2(%r1)\"
-  };
-
-  /* The NT stack unwind code can't handle a subq to adjust the stack
-     (that's a bug, but not one we can do anything about).  As of NT4.0 SP3,
-     the exception handling code will loop if a subq is used and an
-     exception occurs.
-
-     The 19980616 change to emit prologues as RTL also confused some
-     versions of GDB, which also interprets prologues.  This has been
-     fixed as of GDB 4.18, but it does not harm to unconditionally
-     use lda here.  */
-
-  int which = which_alternative;
-
-  if (operands[0] == stack_pointer_rtx
-      && GET_CODE (operands[2]) == CONST_INT
-      && CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'K'))
-    which = 2;
-
-  return pattern[which];
-}")
+  "")
+
+;; This pattern exists so that register elimination tries to canonize
+;; (plus (plus reg c1) c2).
+
+(define_insn "*lda"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+        (match_operand:DI 1 "addition_operation" "p"))]
+  ""
+  "lda %0,%a1")
+
+;; We used to expend quite a lot of effort choosing addq/subq/lda.
+;; With complications like
+;;
+;;   The NT stack unwind code can't handle a subq to adjust the stack
+;;   (that's a bug, but not one we can do anything about).  As of NT4.0 SP3,
+;;   the exception handling code will loop if a subq is used and an
+;;   exception occurs.
+;;  
+;;   The 19980616 change to emit prologues as RTL also confused some
+;;   versions of GDB, which also interprets prologues.  This has been
+;;   fixed as of GDB 4.18, but it does not harm to unconditionally
+;;   use lda here.
+;;
+;; and the fact that the three insns schedule exactly the same, it's
+;; just not worth the effort.
+
+(define_insn "*adddi_2"
+  [(set (match_operand:DI 0 "register_operand" "=r,r,r")
+       (plus:DI (match_operand:DI 1 "register_operand" "%r,r,r")
+                (match_operand:DI 2 "add_operand" "r,K,L")))]
+  ""
+  "@
+   addq %1,%2,%0
+   lda %0,%2(%1)
+   ldah %0,%h2(%1)")
 
 ;; ??? Allow large constants when basing off the frame pointer or some
 ;; virtual register that may eliminate to the frame pointer.  This is
 ;; they are simpler.
 
 (define_insn ""
-  [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,r,r,m,m")
-       (match_operand:SF 1 "input_operand" "fG,m,rG,m,fG,r"))]
+  [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,*r,*r,m,m")
+       (match_operand:SF 1 "input_operand" "fG,m,*rG,m,fG,*r"))]
   "! TARGET_FIX
    && (register_operand (operands[0], SFmode)
        || reg_or_fp0_operand (operands[1], SFmode))"
   [(set_attr "type" "fcpys,fld,ilog,ild,fst,ist")])
 
 (define_insn ""
-  [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,r,r,m,m,f,*r")
-       (match_operand:SF 1 "input_operand" "fG,m,rG,m,fG,r,r,*f"))]
+  [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,*r,*r,m,m,f,*r")
+       (match_operand:SF 1 "input_operand" "fG,m,*rG,m,fG,*r,*r,f"))]
   "TARGET_FIX
    && (register_operand (operands[0], SFmode)
        || reg_or_fp0_operand (operands[1], SFmode))"
   [(set_attr "type" "fcpys,fld,ilog,ild,fst,ist,itof,ftoi")])
 
 (define_insn ""
-  [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f,r,r,m,m")
-       (match_operand:DF 1 "input_operand" "fG,m,rG,m,fG,r"))]
+  [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f,*r,*r,m,m")
+       (match_operand:DF 1 "input_operand" "fG,m,*rG,m,fG,*r"))]
   "! TARGET_FIX
    && (register_operand (operands[0], DFmode)
        || reg_or_fp0_operand (operands[1], DFmode))"
   [(set_attr "type" "fcpys,fld,ilog,ild,fst,ist")])
 
 (define_insn ""
-  [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f,r,r,m,m,f,*r")
-       (match_operand:DF 1 "input_operand" "fG,m,rG,m,fG,r,r,*f"))]
+  [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f,*r,*r,m,m,f,*r")
+       (match_operand:DF 1 "input_operand" "fG,m,*rG,m,fG,*r,*r,f"))]
   "TARGET_FIX
    && (register_operand (operands[0], DFmode)
        || reg_or_fp0_operand (operands[1], DFmode))"
 }")
 
 (define_insn ""
-  [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,r,m,f,f,m")
-       (match_operand:SI 1 "input_operand" "rJ,K,L,m,rJ,fJ,m,f"))]
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,r,m,*f,*f,m")
+       (match_operand:SI 1 "input_operand" "rJ,K,L,m,rJ,*fJ,m,*f"))]
   "! TARGET_WINDOWS_NT && ! TARGET_OPEN_VMS && ! TARGET_FIX
    && (register_operand (operands[0], SImode)
        || reg_or_0_operand (operands[1], SImode))"
   [(set_attr "type" "ilog,iadd,iadd,ild,ist,fcpys,fld,fst")])
 
 (define_insn ""
-  [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,r,m,f,f,m,r,*f")
-       (match_operand:SI 1 "input_operand" "rJ,K,L,m,rJ,fJ,m,f,f,*r"))]
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,r,m,*f,*f,m,r,*f")
+       (match_operand:SI 1 "input_operand" "rJ,K,L,m,rJ,*fJ,m,*f,*f,r"))]
   "! TARGET_WINDOWS_NT && ! TARGET_OPEN_VMS && TARGET_FIX
    && (register_operand (operands[0], SImode)
        || reg_or_0_operand (operands[1], SImode))"
   [(set_attr "type" "ilog,iadd,iadd,ild,ist,fcpys,fld,fst,ftoi,itof")])
 
 (define_insn ""
-  [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,r,r,m,f,f,m")
-       (match_operand:SI 1 "input_operand" "rJ,K,L,s,m,rJ,fJ,m,f"))]
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,r,r,m,*f,*f,m")
+       (match_operand:SI 1 "input_operand" "rJ,K,L,s,m,rJ,*fJ,m,*f"))]
   "(TARGET_WINDOWS_NT || TARGET_OPEN_VMS)
     && (register_operand (operands[0], SImode)
         || reg_or_0_operand (operands[1], SImode))"
 }")
 
 (define_insn ""
-  [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,r,r,m,f,f,Q")
-       (match_operand:DI 1 "input_operand" "rJ,K,L,s,m,rJ,fJ,Q,f"))]
+  [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,r,r,m,*f,*f,Q")
+       (match_operand:DI 1 "input_operand" "rJ,K,L,s,m,rJ,*fJ,Q,*f"))]
   "! TARGET_FIX
    && (register_operand (operands[0], DImode)
        || reg_or_0_operand (operands[1], DImode))"
   [(set_attr "type" "ilog,iadd,iadd,ldsym,ild,ist,fcpys,fld,fst")])
 
 (define_insn ""
-  [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,r,r,m,f,f,Q,r,*f")
-       (match_operand:DI 1 "input_operand" "rJ,K,L,s,m,rJ,fJ,Q,f,f,*r"))]
+  [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,r,r,m,*f,*f,Q,r,*f")
+       (match_operand:DI 1 "input_operand" "rJ,K,L,s,m,rJ,*fJ,Q,*f,*f,r"))]
   "TARGET_FIX
    && (register_operand (operands[0], DImode)
        || reg_or_0_operand (operands[1], DImode))"