Recent changes to the ira code exposed problems in handling secondary reloads for copies between the shift amount register and floating point registers. This requires an intermediate general register.
I also saw a case where reload tried to stuff a SFmode value into the shift amount register compiling libjava. This won't work since the shift amount register is only 5/6 bits long... The following change has been tested on hppa2.0w-hp-hpux11.11, hppa64-hp-hpux11.11 and hppa-unknown-linux-gnu. Committed to trunk. Dave -- J. David Anglin dave.ang...@nrc-cnrc.gc.ca National Research Council of Canada (613) 990-0752 (FAX: 952-6602) 2011-04-08 John David Anglin <dave.ang...@nrc-cnrc.gc.ca> PR target/48366 * config/pa/pa.c (hppa_register_move_cost): Increase to 18 cost of move from floating point to shift amount register . (emit_move_sequence): Remove secondary reload support for floating point to shift amount amount register copies. (pa_secondary_reload): Return GENERAL_REGS for floating point/shift amount register copies. * config/pa/pa32-regs.h (HARD_REGNO_MODE_OK): For shift amount register, return false if mode isn't a scalar integer mode. * config/pa/pa64-regs.h (HARD_REGNO_MODE_OK): Likewise. Index: config/pa/pa.c =================================================================== --- config/pa/pa.c (revision 172005) +++ config/pa/pa.c (working copy) @@ -1447,6 +1447,8 @@ { if (from == SHIFT_REGS) return 0x100; + else if (to == SHIFT_REGS && FP_REG_CLASS_P (from)) + return 18; else if ((FP_REG_CLASS_P (from) && ! FP_REG_CLASS_P (to)) || (FP_REG_CLASS_P (to) && ! FP_REG_CLASS_P (from))) return 16; @@ -1790,15 +1792,12 @@ return 1; } /* Handle secondary reloads for SAR. These occur when trying to load - the SAR from memory, FP register, or with a constant. */ + the SAR from memory or a constant. */ else if (scratch_reg && GET_CODE (operand0) == REG && REGNO (operand0) < FIRST_PSEUDO_REGISTER && REGNO_REG_CLASS (REGNO (operand0)) == SHIFT_REGS - && (GET_CODE (operand1) == MEM - || GET_CODE (operand1) == CONST_INT - || (GET_CODE (operand1) == REG - && FP_REG_CLASS_P (REGNO_REG_CLASS (REGNO (operand1)))))) + && (GET_CODE (operand1) == MEM || GET_CODE (operand1) == CONST_INT)) { /* D might not fit in 14 bits either; for such cases load D into scratch reg. */ @@ -5863,6 +5862,10 @@ fputc ('\n', asm_out_file); } +/* Inform reload about cases where moving X with a mode MODE to a register in + RCLASS requires an extra scratch or immediate register. Return the class + needed for the immediate register. */ + static reg_class_t pa_secondary_reload (bool in_p, rtx x, reg_class_t rclass_i, enum machine_mode mode, secondary_reload_info *sri) @@ -5965,24 +5968,29 @@ return NO_REGS; } - /* We need a secondary register (GPR) for copies between the SAR - and anything other than a general register. */ - if (rclass == SHIFT_REGS && (regno <= 0 || regno >= 32)) + /* A SAR<->FP register copy requires an intermediate general register + and secondary memory. We need a secondary reload with a general + scratch register for spills. */ + if (rclass == SHIFT_REGS) { - sri->icode = (in_p - ? direct_optab_handler (reload_in_optab, mode) - : direct_optab_handler (reload_out_optab, mode)); - return NO_REGS; + /* Handle spill. */ + if (regno >= FIRST_PSEUDO_REGISTER || regno < 0) + { + sri->icode = (in_p + ? direct_optab_handler (reload_in_optab, mode) + : direct_optab_handler (reload_out_optab, mode)); + return NO_REGS; + } + + /* Handle FP copy. */ + if (FP_REG_CLASS_P (REGNO_REG_CLASS (regno))) + return GENERAL_REGS; } - /* A SAR<->FP register copy requires a secondary register (GPR) as - well as secondary memory. */ if (regno >= 0 && regno < FIRST_PSEUDO_REGISTER - && (REGNO_REG_CLASS (regno) == SHIFT_REGS - && FP_REG_CLASS_P (rclass))) - sri->icode = (in_p - ? direct_optab_handler (reload_in_optab, mode) - : direct_optab_handler (reload_out_optab, mode)); + && REGNO_REG_CLASS (regno) == SHIFT_REGS + && FP_REG_CLASS_P (rclass)) + return GENERAL_REGS; return NO_REGS; } Index: config/pa/pa32-regs.h =================================================================== --- config/pa/pa32-regs.h (revision 172005) +++ config/pa/pa32-regs.h (working copy) @@ -209,6 +209,7 @@ registers. */ #define HARD_REGNO_MODE_OK(REGNO, MODE) \ ((REGNO) == 0 ? (MODE) == CCmode || (MODE) == CCFPmode \ + : (REGNO) == 88 ? SCALAR_INT_MODE_P (MODE) \ : !TARGET_PA_11 && FP_REGNO_P (REGNO) \ ? (VALID_FP_MODE_P (MODE) \ && (GET_MODE_SIZE (MODE) <= 8 \ Index: config/pa/pa64-regs.h =================================================================== --- config/pa/pa64-regs.h (revision 172005) +++ config/pa/pa64-regs.h (working copy) @@ -149,10 +149,11 @@ /* Value is 1 if hard register REGNO can hold a value of machine-mode MODE. On the HP-PA, the cpu registers can hold any mode. We - force this to be an even register is it cannot hold the full mode. */ + force this to be an even register if it cannot hold the full mode. */ #define HARD_REGNO_MODE_OK(REGNO, MODE) \ ((REGNO) == 0 \ ? (MODE) == CCmode || (MODE) == CCFPmode \ + : (REGNO) == 60 ? SCALAR_INT_MODE_P (MODE) \ /* Make wide modes be in aligned registers. */ \ : FP_REGNO_P (REGNO) \ ? (VALID_FP_MODE_P (MODE) \