aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Henderson <rth@cygnus.com>1999-10-30 14:46:57 -0700
committerRichard Henderson <rth@gcc.gnu.org>1999-10-30 14:46:57 -0700
commit3611aef055f106ae733306dd66419a239d92aaa6 (patch)
tree55102708bebcf895b99da75dfa5a7703462b2ddd
parent1e1933372608930414255b4f5124713d227f2f9c (diff)
downloadgcc-3611aef055f106ae733306dd66419a239d92aaa6.zip
gcc-3611aef055f106ae733306dd66419a239d92aaa6.tar.gz
gcc-3611aef055f106ae733306dd66419a239d92aaa6.tar.bz2
alpha.h (SECONDARY_INPUT_RELOAD_CLASS): Call secondary_reload_class.
* 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. From-SVN: r30277
-rw-r--r--gcc/ChangeLog14
-rw-r--r--gcc/config/alpha/alpha-protos.h5
-rw-r--r--gcc/config/alpha/alpha.c70
-rw-r--r--gcc/config/alpha/alpha.h44
-rw-r--r--gcc/config/alpha/alpha.md108
5 files changed, 151 insertions, 90 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 330d5ab..1a41457 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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.
diff --git a/gcc/config/alpha/alpha-protos.h b/gcc/config/alpha/alpha-protos.h
index d9a2d741..9a47854 100644
--- a/gcc/config/alpha/alpha-protos.h
+++ b/gcc/config/alpha/alpha-protos.h
@@ -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));
diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c
index 0782440..07e7061 100644
--- a/gcc/config/alpha/alpha.c
+++ b/gcc/config/alpha/alpha.c
@@ -939,7 +939,26 @@ reg_no_subreg_operand (op, mode)
return 0;
return register_operand (op, mode);
}
-
+
+/* 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);
}
-
+
/* 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;
+}
/* Subfunction of the following function. Update the flags of any MEM
found in part of X. */
diff --git a/gcc/config/alpha/alpha.h b/gcc/config/alpha/alpha.h
index c39a2a4..2266f50 100644
--- a/gcc/config/alpha/alpha.h
+++ b/gcc/config/alpha/alpha.h
@@ -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}},
/* Define the `__builtin_va_list' type for the ABI. */
#define BUILD_VA_LIST_TYPE(VALIST) \
diff --git a/gcc/config/alpha/alpha.md b/gcc/config/alpha/alpha.md
index 505a583..c5a0db1 100644
--- a/gcc/config/alpha/alpha.md
+++ b/gcc/config/alpha/alpha.md
@@ -542,39 +542,47 @@
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
@@ -4004,8 +4012,8 @@
;; 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))"
@@ -4019,8 +4027,8 @@
[(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))"
@@ -4036,8 +4044,8 @@
[(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))"
@@ -4051,8 +4059,8 @@
[(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))"
@@ -4090,8 +4098,8 @@
}")
(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))"
@@ -4107,8 +4115,8 @@
[(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))"
@@ -4126,8 +4134,8 @@
[(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))"
@@ -4235,8 +4243,8 @@
}")
(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))"
@@ -4253,8 +4261,8 @@
[(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))"