Currently, scratch_operand allows all hard registers, also those that cannot be allocated and are only generated explicitly by the backend.
This causes problems. Consider the case where combine combines instructions A and B, where B clobbers such a non-allocatable hard reg X, into an instruction C that has a clobber of a match_scratch. Concretely for example: A is (set (reg:SI 98) (eq:SI ...)) B is (parallel [(set (reg:SI 99) (minus (const_int 1) (reg:SI 98))) (clobber (reg:SI CA_REGNO))]) so that combine tries an insn C (parallel [(set (reg:SI 99) (ne:SI ...)) (clobber (reg:SI CA_REGNO))]) which matches the pattern (parallel [(set (match_operand:SI 0 "..." "=r") (ne:SI ...)) (clobber (match_scratch:SI 3 "=r"))]) which is not going to work; it is not a valid insn. (In my testcase, reload eventually replaces CA_REGNO with a GPR that is not dead. Oops.) Combine shouldn't keep the original clobbers. But also, scratch_operand should not allow non-allocatable registers, since that can never work. This patch does the latter. Bootstrapped and regression checked on powerpc64-linux, with options -m32,-m32/-mpowerpc64,-m64,-m64/-mlra. No regressions, and testcase fixed (the testcase is forall_4.f90, it requires some backend patches to fail). Is this okay for mainline? Segher 2014-09-15 Segher Boessenkool <seg...@kernel.crashing.org> * recog.c (scratch_operand): Do not simply allow all hard registers: only allow those that are allocatable. --- gcc/recog.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/gcc/recog.c b/gcc/recog.c index 2150b7a..6987afb 100644 --- a/gcc/recog.c +++ b/gcc/recog.c @@ -1143,7 +1143,9 @@ scratch_operand (rtx op, enum machine_mode mode) return (GET_CODE (op) == SCRATCH || (REG_P (op) - && (lra_in_progress || REGNO (op) < FIRST_PSEUDO_REGISTER))); + && (lra_in_progress + || (REGNO (op) < FIRST_PSEUDO_REGISTER + && REGNO_REG_CLASS (REGNO (op)) != NO_REGS)))); } /* Return 1 if OP is a valid immediate operand for mode MODE. -- 1.8.1.4