diff --git a/gcc/config/pa/pa.c b/gcc/config/pa/pa.c index 3b201cdf6665..c6fb1ed43418 100644 --- a/gcc/config/pa/pa.c +++ b/gcc/config/pa/pa.c @@ -1373,28 +1373,36 @@ output_move_double (operands) /* If the first move would clobber the source of the second one, do them in the other order. - RMS says "This happens only for registers; - such overlap can't happen in memory unless the user explicitly - sets it up, and that is an undefined circumstance." + This can happen in two cases: - but it happens on the HP-PA when loading parameter registers, - so I am going to define that circumstance, and make it work - as expected. */ + mem -> register where the first half of the destination register + is the same register used in the memory's address. Reload + can create such insns. - if (optype0 == REGOP && (optype1 == MEMOP || optype1 == OFFSOP) - && reg_overlap_mentioned_p (operands[0], XEXP (operands[1], 0))) + mem in this case will be either register indirect or register + indirect plus a valid offset. + + register -> register move where REGNO(dst) == REGNO(src + 1) + someone (Tim/Tege?) claimed this can happen for parameter loads. + + Handle mem -> register case first. */ + if (optype0 == REGOP + && (optype1 == MEMOP || optype1 == OFFSOP) + && refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1, + operands[1], 0)) { - /* XXX THIS PROBABLY DOESN'T WORK. */ /* Do the late half first. */ if (addreg1) output_asm_insn ("ldo 4(%0),%0", &addreg1); output_asm_insn (singlemove_string (latehalf), latehalf); + + /* Then clobber. */ if (addreg1) output_asm_insn ("ldo -4(%0),%0", &addreg1); - /* Then clobber. */ return singlemove_string (operands); } + /* Now handle register -> register case. */ if (optype0 == REGOP && optype1 == REGOP && REGNO (operands[0]) == REGNO (operands[1]) + 1) { diff --git a/gcc/config/pa/pa.md b/gcc/config/pa/pa.md index 80f5db3e201b..8b23ea4d9f9a 100644 --- a/gcc/config/pa/pa.md +++ b/gcc/config/pa/pa.md @@ -2146,7 +2146,7 @@ (define_insn "" [(set (match_operand:DF 0 "reg_or_nonsymb_mem_operand" - "=f,*r,Q,?o,?Q,f,*&r,*&r") + "=f,*r,Q,?o,?Q,f,*r,*r") (match_operand:DF 1 "reg_or_0_or_nonsymb_mem_operand" "fG,*rG,f,*r,*r,Q,o,Q"))] "(register_operand (operands[0], DFmode) @@ -2164,7 +2164,7 @@ (define_insn "" [(set (match_operand:DF 0 "reg_or_nonsymb_mem_operand" - "=r,?o,?Q,&r,&r") + "=r,?o,?Q,r,r") (match_operand:DF 1 "reg_or_0_or_nonsymb_mem_operand" "rG,r,r,o,Q"))] "(register_operand (operands[0], DFmode) @@ -2375,7 +2375,7 @@ (define_insn "" [(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand" - "=r,o,Q,&r,&r,&r,f,f,*T") + "=r,o,Q,r,r,r,f,f,*T") (match_operand:DI 1 "general_operand" "rM,r,r,o,Q,i,fM,*T,f"))] "(register_operand (operands[0], DImode) @@ -2393,7 +2393,7 @@ (define_insn "" [(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand" - "=r,o,Q,&r,&r,&r") + "=r,o,Q,r,r,r") (match_operand:DI 1 "general_operand" "rM,r,r,o,Q,i"))] "(register_operand (operands[0], DImode)