diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 009dcb13041..769983ae93a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,32 @@ +Sat Feb 1 00:28:30 CET 2003 Jan Hubicka + + * loop.c (emit_prefetch_instructions): Do conversion at right place in + RTL chain. + + * combine.c (simplify_set): Reverse order of ragumetns to + REG_CANNOT_CHANGE_MODE_P + * df.c (df_def_record_1): Likewise. + * recog.c (register_operand): Likewise. + * simplify-rtx.c (simplify_subreg): Likewise. + * hard-reg-set.h (REG_CANNOT_CHANGE_MODE_P): Update use of + CANNOT_CHANGE_MODE_CLASS. + * regclass.c (cannot_change_mode_set_regs, invalid_mode_change_p): + Likewise. + * reload.c (push_reload): Likewise. + * alpha.h (CANNOT_CHANGE_MODE_CLASS): Update definition. + * ia64.h (CANNOT_CHANGE_MODE_CLASS): Update definition. + * mips.h (CANNOT_CHANGE_MODE_CLASS): Update definition. + * mips-protos.h (mips_cannot_change_mode_class): Update prototype. + * mips.c (mips_cannot_change_mode_class): Update. + * pa64-regs.h (CANNOT_CHANGE_MODE_CLASS): Update definition. + * rs6000.h (CANNOT_CHANGE_MODE_CLASS): Update definition. + * s390.h (CANNOT_CHANGE_MODE_CLASS): Update definition. + * sh.h (CANNOT_CHANGE_MODE_CLASS): Update definition. + * sh-protos.h (sh_cannot_change_mode_class): Update prototype. + * sh.c (sh_cannot_change_mode_class): Update. + * i386.h (CANNOT_CHANGE_MODE_CLASS): New. + * tm.texi (CANNOT_CHANGE_MODE_CLASS): Update documentation. + 2003-01-31 Geoffrey Keating * config/darwin.h (LINK_COMMAND_SPEC): Update for Nathan's recent diff --git a/gcc/combine.c b/gcc/combine.c index 90c4482e33a..d3203fe5a49 100644 --- a/gcc/combine.c +++ b/gcc/combine.c @@ -5238,8 +5238,8 @@ simplify_set (x) #ifdef CANNOT_CHANGE_MODE_CLASS && ! (GET_CODE (dest) == REG && REGNO (dest) < FIRST_PSEUDO_REGISTER && REG_CANNOT_CHANGE_MODE_P (REGNO (dest), - GET_MODE (src), - GET_MODE (SUBREG_REG (src)))) + GET_MODE (SUBREG_REG (src)), + GET_MODE (src))) #endif && (GET_CODE (dest) == REG || (GET_CODE (dest) == SUBREG diff --git a/gcc/config/alpha/alpha.h b/gcc/config/alpha/alpha.h index 0522ba6c080..8824f12f0f7 100644 --- a/gcc/config/alpha/alpha.h +++ b/gcc/config/alpha/alpha.h @@ -869,8 +869,9 @@ enum reg_class { /* Return the class of registers that cannot change mode from FROM to TO. */ -#define CANNOT_CHANGE_MODE_CLASS(FROM, TO) \ - (GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO) ? FLOAT_REGS : NO_REGS) +#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \ + (GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO) \ + ? reg_classes_intersect_p (FLOAT_REGS, CLASS) : 0) /* Define the cost of moving between registers of various classes. Moving between FLOAT_REGS and anything else except float regs is expensive. diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index d70054b069c..edf6d44747e 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -10153,7 +10153,6 @@ ix86_expand_int_addcc (operands) rtx compare_op; rtx val = const0_rtx; bool fpcmp = false; - rtx pat, clob; enum machine_mode mode = GET_MODE (operands[0]); if (operands[3] != const1_rtx diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index 1e38d10d36e..e46a19f6b30 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -1558,6 +1558,20 @@ enum reg_class || ((CLASS) == SIREG) \ || ((CLASS) == DIREG)) +/* Return a class of registers that cannot change FROM mode to TO mode. + + x87 registers can't do subreg as all values are reformated to extended + precision. XMM registers does not support with nonzero offsets equal + to 4, 8 and 12 otherwise valid for integer registers. Since we can't + determine these, prohibit all nonparadoxical subregs changing size. */ + +#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \ + (GET_MODE_SIZE (TO) < GET_MODE_SIZE (FROM) \ + ? reg_classes_intersect_p (FLOAT_SSE_REGS, (CLASS)) \ + || MAYBE_MMX_CLASS_P (CLASS) \ + : GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO) \ + ? reg_classes_intersect_p (FLOAT_REGS, (CLASS)) : 0) + /* A C statement that adds to CLOBBERS any hard regs the port wishes to automatically clobber for all asms. diff --git a/gcc/config/ia64/ia64.h b/gcc/config/ia64/ia64.h index 3e1f295d73e..835c93faeab 100644 --- a/gcc/config/ia64/ia64.h +++ b/gcc/config/ia64/ia64.h @@ -1036,8 +1036,9 @@ enum reg_class /* In FP regs, we can't change FP values to integer values and vice versa, but we can change e.g. DImode to SImode. */ -#define CANNOT_CHANGE_MODE_CLASS(FROM, TO) \ - (GET_MODE_CLASS (FROM) != GET_MODE_CLASS (TO) ? FR_REGS : NO_REGS) +#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \ + (GET_MODE_CLASS (FROM) != GET_MODE_CLASS (TO) \ + ? reg_classes_intersect_p (CLASS, FR_REGS) : 0) /* A C expression that defines the machine-dependent operand constraint letters (`I', `J', `K', .. 'P') that specify particular ranges of diff --git a/gcc/config/mips/mips-protos.h b/gcc/config/mips/mips-protos.h index 902f1bef48b..75489de623b 100644 --- a/gcc/config/mips/mips-protos.h +++ b/gcc/config/mips/mips-protos.h @@ -121,8 +121,9 @@ extern int mips_adjust_insn_length PARAMS ((rtx, int)); extern enum reg_class mips_secondary_reload_class PARAMS ((enum reg_class, enum machine_mode, rtx, int)); -extern enum reg_class mips_cannot_change_mode_class - PARAMS ((enum machine_mode, enum machine_mode)); +extern bool mips_cannot_change_mode_class + PARAMS ((enum machine_mode, enum machine_mode, + enum reg_class)); extern int mips_class_max_nregs PARAMS ((enum reg_class, enum machine_mode)); extern int mips_register_move_cost PARAMS ((enum machine_mode, diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index a6ad4c0f7ab..bcfc0f65f1b 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -8779,19 +8779,20 @@ function_arg_pass_by_reference (cum, mode, type, named) We can't allow 64-bit float registers to change from a 32-bit mode to a 64-bit mode. */ -enum reg_class -mips_cannot_change_mode_class (from, to) +bool +mips_cannot_change_mode_class (from, to, class) enum machine_mode from, to; + enum reg_class class; { if (GET_MODE_SIZE (from) != GET_MODE_SIZE (to)) { if (TARGET_BIG_ENDIAN) - return FP_REGS; + return reg_classes_intersect_p (FP_REGS, class); if (TARGET_FLOAT64) - return HI_AND_FP_REGS; - return HI_REG; + return reg_classes_intersect_p (HI_AND_FP_REGS, class); + return reg_classes_intersect_p (HI_REG, class); } - return NO_REGS; + return false; } /* This function returns the register class required for a secondary diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h index 24b668b70fe..e76a7395259 100644 --- a/gcc/config/mips/mips.h +++ b/gcc/config/mips/mips.h @@ -2376,8 +2376,8 @@ extern enum reg_class mips_char_to_class[256]; #define CLASS_MAX_NREGS(CLASS, MODE) mips_class_max_nregs (CLASS, MODE) -#define CANNOT_CHANGE_MODE_CLASS(FROM, TO) \ - mips_cannot_change_mode_class (FROM, TO) +#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \ + mips_cannot_change_mode_class (FROM, TO, CLASS) /* Stack layout; function entry, exit and calling. */ diff --git a/gcc/config/pa/pa64-regs.h b/gcc/config/pa/pa64-regs.h index 2d0ebe3d172..ced7df737e7 100644 --- a/gcc/config/pa/pa64-regs.h +++ b/gcc/config/pa/pa64-regs.h @@ -240,9 +240,9 @@ enum reg_class { NO_REGS, R1_REGS, GENERAL_REGS, FPUPPER_REGS, FP_REGS, we inhibit changes from SImode unless they are to a mode that is identical in size. */ -#define CANNOT_CHANGE_MODE_CLASS(FROM, TO) \ +#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \ ((FROM) == SImode && GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO) \ - ? FP_REGS : NO_REGS) + ? reg_classes_intersect_p (CLASS, FP_REGS) : 0) /* Return the class number of the smallest class containing reg number REGNO. This could be a conditional expression diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h index a96984d17ba..7cfb3ccfdc4 100644 --- a/gcc/config/rs6000/rs6000.h +++ b/gcc/config/rs6000/rs6000.h @@ -1329,10 +1329,12 @@ enum reg_class /* Return a class of registers that cannot change FROM mode to TO mode. */ -#define CANNOT_CHANGE_MODE_CLASS(FROM, TO) \ - (GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO) ? FLOAT_REGS \ - : (SPE_VECTOR_MODE (FROM) + SPE_VECTOR_MODE (TO)) == 1 ? GENERAL_REGS \ - : NO_REGS) +#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \ + (GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO) \ + ? reg_classes_intersect_p (FLOAT_REGS, CLASS) \ + : (SPE_VECTOR_MODE (FROM) + SPE_VECTOR_MODE (TO)) == 1 \ + ? reg_classes_intersect_p (GENERAL_REGS, CLASS) \ + : 0) /* Stack layout; function entry, exit and calling. */ diff --git a/gcc/config/s390/s390.h b/gcc/config/s390/s390.h index 1623666cb65..3cc731c84f2 100644 --- a/gcc/config/s390/s390.h +++ b/gcc/config/s390/s390.h @@ -374,8 +374,9 @@ do \ /* If a 4-byte value is loaded into a FPR, it is placed into the *upper* half of the register, not the lower. Therefore, we cannot use SUBREGs to switch between modes in FP registers. */ -#define CANNOT_CHANGE_MODE_CLASS(FROM, TO) \ - (GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO) ? FP_REGS : NO_REGS) +#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \ + (GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO) \ + ? reg_classes_intersect_p (FP_REGS, CLASS) : 0) /* Register classes. */ diff --git a/gcc/config/sh/sh-protos.h b/gcc/config/sh/sh-protos.h index 535fb30687a..f04ab016709 100644 --- a/gcc/config/sh/sh-protos.h +++ b/gcc/config/sh/sh-protos.h @@ -123,8 +123,8 @@ extern int sh_pr_n_sets PARAMS ((void)); extern int sh_hard_regno_rename_ok PARAMS ((unsigned int, unsigned int)); extern int sh_cfun_interrupt_handler_p PARAMS ((void)); extern void sh_initialize_trampoline PARAMS ((rtx, rtx, rtx)); -extern enum reg_class sh_cannot_change_mode_class - PARAMS ((enum machine_mode, enum machine_mode)); +extern bool sh_cannot_change_mode_class + PARAMS ((enum machine_mode, enum machine_mode, enum reg_class)); extern void sh_mark_label PARAMS ((rtx, int)); extern int sh_register_move_cost PARAMS ((enum machine_mode mode, enum reg_class, enum reg_class)); diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c index 0d839109747..b1df940dd9d 100644 --- a/gcc/config/sh/sh.c +++ b/gcc/config/sh/sh.c @@ -8030,24 +8030,25 @@ sh_expand_binop_v2sf (code, op0, op1, op2) /* Return the class of registers for which a mode change from FROM to TO is invalid. */ -enum reg_class -sh_cannot_change_mode_class (from, to) +bool +sh_cannot_change_mode_class (from, to, class) enum machine_mode from, to; + enum reg_class class; { if (GET_MODE_SIZE (from) != GET_MODE_SIZE (to)) { if (TARGET_LITTLE_ENDIAN) { if (GET_MODE_SIZE (to) < 8 || GET_MODE_SIZE (from) < 8) - return DF_REGS; + return reg_classes_intersect_p (DF_REGS, class); } else { if (GET_MODE_SIZE (from) < 8) - return DF_HI_REGS; + return reg_classes_intersect_p (DF_HI_REGS, class); } } - return NO_REGS; + return 0; } diff --git a/gcc/config/sh/sh.h b/gcc/config/sh/sh.h index cf8ac7fd910..25406a17839 100644 --- a/gcc/config/sh/sh.h +++ b/gcc/config/sh/sh.h @@ -1395,8 +1395,8 @@ extern enum reg_class reg_class_from_letter[]; /* ??? We need to renumber the internal numbers for the frnn registers when in little endian in order to allow mode size changes. */ -#define CANNOT_CHANGE_MODE_CLASS(FROM, TO) \ - sh_cannot_change_mode_class (FROM, TO) +#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \ + sh_cannot_change_mode_class (FROM, TO, CLASS) /* Stack layout; function entry, exit and calling. */ diff --git a/gcc/df.c b/gcc/df.c index cce6a3c03ec..c151249a197 100644 --- a/gcc/df.c +++ b/gcc/df.c @@ -928,8 +928,8 @@ df_def_record_1 (df, x, bb, insn) #ifdef CLASS_CANNOT_CHANGE_MODE if (GET_CODE (dst) == SUBREG - && CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (dst), - GET_MODE (SUBREG_REG (dst)))) + && CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (SUBREG_REG (dst)), + GET_MODE (dst))) flags |= DF_REF_MODE_CHANGE; #endif @@ -949,8 +949,8 @@ df_def_record_1 (df, x, bb, insn) } #ifdef CLASS_CANNOT_CHANGE_MODE if (GET_CODE (dst) == SUBREG - && CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (dst), - GET_MODE (SUBREG_REG (dst)))) + && CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (SUBREG_REG (dst)), + GET_MODE (dst))) flags |= DF_REF_MODE_CHANGE; #endif loc = &XEXP (dst, 0); diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index 382df86688c..b5cb2404429 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -2599,10 +2599,9 @@ should be the maximum value of @code{HARD_REGNO_NREGS (@var{regno}, This macro helps control the handling of multiple-word values in the reload pass. -@item CANNOT_CHANGE_MODE_CLASS(@var{from}, @var{to}) -If defined, a C expression that returns a register class for which -a change from mode @var{from} to mode @var{to} is invalid, otherwise the -macro returns @code{NO_REGS}. +@item CANNOT_CHANGE_MODE_CLASS(@var{from}, @var{to}, @var{class}) +If defined, a C expression that returns nonzero for a @var{class} for which +a change from mode @var{from} to mode @var{to} is invalid. For the example, loading 32-bit integer or floating-point objects into floating-point registers on the Alpha extends them to 64 bits. @@ -2612,8 +2611,9 @@ register. Therefore, @file{alpha.h} defines @code{CANNOT_CHANGE_MODE_CLASS} as below: @example -#define CANNOT_CHANGE_MODE_CLASS \ - (GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO) ? FLOAT_REGS : NO_REGS) +#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \ + (GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO) \ + ? reg_classes_intersect_p (FLOAT_REGS, (CLASS)) : 0) @end example @end table diff --git a/gcc/hard-reg-set.h b/gcc/hard-reg-set.h index 0574738fbe5..53330cf28b7 100644 --- a/gcc/hard-reg-set.h +++ b/gcc/hard-reg-set.h @@ -491,8 +491,6 @@ extern const char * reg_names[FIRST_PSEUDO_REGISTER]; /* Given a hard REGN a FROM mode and a TO mode, return nonzero if REGN cannot change modes between the specified modes. */ #define REG_CANNOT_CHANGE_MODE_P(REGN, FROM, TO) \ - (TEST_HARD_REG_BIT \ - (reg_class_contents[(int) CANNOT_CHANGE_MODE_CLASS (FROM, TO)], \ - REGN)) + CANNOT_CHANGE_MODE_CLASS (FROM, TO, REGNO_REG_CLASS (REGN)) #endif /* ! GCC_HARD_REG_SET_H */ diff --git a/gcc/loop.c b/gcc/loop.c index b366b542445..4bdef2d0af7 100644 --- a/gcc/loop.c +++ b/gcc/loop.c @@ -4199,7 +4199,15 @@ emit_prefetch_instructions (loop) non-constant INIT_VAL to have the same mode as REG, which in this case we know to be Pmode. */ if (GET_MODE (init_val) != Pmode && !CONSTANT_P (init_val)) - init_val = convert_to_mode (Pmode, init_val, 0); + { + rtx seq; + + start_sequence (); + init_val = convert_to_mode (Pmode, init_val, 0); + seq = get_insns (); + end_sequence (); + loop_insn_emit_before (loop, 0, loop_start, seq); + } loop_iv_add_mult_emit_before (loop, init_val, info[i].giv->mult_val, add_val, reg, 0, loop_start); diff --git a/gcc/recog.c b/gcc/recog.c index d7618b90305..34eaeb32732 100644 --- a/gcc/recog.c +++ b/gcc/recog.c @@ -1088,7 +1088,7 @@ register_operand (op, mode) #ifdef CANNOT_CHANGE_MODE_CLASS if (GET_CODE (sub) == REG && REGNO (sub) < FIRST_PSEUDO_REGISTER - && REG_CANNOT_CHANGE_MODE_P (REGNO (sub), mode, GET_MODE (sub)) + && REG_CANNOT_CHANGE_MODE_P (REGNO (sub), GET_MODE (sub), mode) && GET_MODE_CLASS (GET_MODE (sub)) != MODE_COMPLEX_INT && GET_MODE_CLASS (GET_MODE (sub)) != MODE_COMPLEX_FLOAT) return 0; diff --git a/gcc/regclass.c b/gcc/regclass.c index ea6c86b6c57..5481ea2a26f 100644 --- a/gcc/regclass.c +++ b/gcc/regclass.c @@ -2633,14 +2633,15 @@ cannot_change_mode_set_regs (used, from, regno) unsigned int regno; { enum machine_mode to; - enum reg_class class; for (to = VOIDmode; to < MAX_MACHINE_MODE; ++to) if (REGNO_REG_SET_P (&subregs_of_mode[to], regno)) { - class = CANNOT_CHANGE_MODE_CLASS (from, to); - if (class != NO_REGS) - IOR_HARD_REG_SET (*used, reg_class_contents [(int) class]); + int i; + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) + if (! TEST_HARD_REG_BIT (*used, i) + && REG_CANNOT_CHANGE_MODE_P (from, to, i)) + SET_HARD_REG_BIT (*used, i); } } @@ -2657,8 +2658,7 @@ invalid_mode_change_p (regno, class, from_mode) for (to_mode = 0; to_mode < NUM_MACHINE_MODES; ++to_mode) if (REGNO_REG_SET_P (&subregs_of_mode[(int) to_mode], regno) - && reg_classes_intersect_p - (class, CANNOT_CHANGE_MODE_CLASS (from_mode, to_mode))) + && CANNOT_CHANGE_MODE_CLASS (from_mode, to_mode, class)) return 1; return 0; } diff --git a/gcc/reload.c b/gcc/reload.c index a16012c651f..46d0d6417df 100644 --- a/gcc/reload.c +++ b/gcc/reload.c @@ -976,9 +976,7 @@ push_reload (in, out, inloc, outloc, class, if (in != 0 && GET_CODE (in) == SUBREG && (subreg_lowpart_p (in) || strict_low) #ifdef CANNOT_CHANGE_MODE_CLASS - && !reg_classes_intersect_p - (class, CANNOT_CHANGE_MODE_CLASS (GET_MODE (SUBREG_REG (in)), - inmode)) + && !CANNOT_CHANGE_MODE_CLASS (GET_MODE (SUBREG_REG (in)), inmode, class) #endif && (CONSTANT_P (SUBREG_REG (in)) || GET_CODE (SUBREG_REG (in)) == PLUS @@ -1088,9 +1086,7 @@ push_reload (in, out, inloc, outloc, class, if (out != 0 && GET_CODE (out) == SUBREG && (subreg_lowpart_p (out) || strict_low) #ifdef CANNOT_CHANGE_MODE_CLASS - && !reg_classes_intersect_p - (class, CANNOT_CHANGE_MODE_CLASS (GET_MODE (SUBREG_REG (out)), - outmode)) + && !CANNOT_CHANGE_MODE_CLASS (GET_MODE (SUBREG_REG (out)), outmode, class) #endif && (CONSTANT_P (SUBREG_REG (out)) || strict_low diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c index 1cef92a211f..d563caeae2f 100644 --- a/gcc/simplify-rtx.c +++ b/gcc/simplify-rtx.c @@ -2544,7 +2544,7 @@ simplify_subreg (outermode, op, innermode, byte) || ! rtx_equal_function_value_matters) && REGNO (op) < FIRST_PSEUDO_REGISTER #ifdef CANNOT_CHANGE_MODE_CLASS - && ! (REG_CANNOT_CHANGE_MODE_P (REGNO (op), outermode, innermode) + && ! (REG_CANNOT_CHANGE_MODE_P (REGNO (op), innermode, outermode) && GET_MODE_CLASS (innermode) != MODE_COMPLEX_INT && GET_MODE_CLASS (innermode) != MODE_COMPLEX_FLOAT) #endif