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

Reply via email to