From: Richard Henderson Date: Sat, 30 Oct 1999 21:46:57 +0000 (-0700) Subject: alpha.h (SECONDARY_INPUT_RELOAD_CLASS): Call secondary_reload_class. X-Git-Tag: prereleases/libstdc++-2.92~9797 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3611aef055f106ae733306dd66419a239d92aaa6;p=thirdparty%2Fgcc.git 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 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 330d5abdf668..1a41457dcbf1 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,17 @@ +Sat Oct 30 14:41:40 1999 Richard Henderson + + * 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 * 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 d9a2d7415fc2..9a47854b1d1e 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 078244076a5e..07e70612b5fa 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 c39a2a4f51f7..2266f50009d2 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 505a58339904..c5a0db1264da 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))"