Message ID | 74729933448c3ec81b326073757add5ddb1165a7.1410826448.git.segher@kernel.crashing.org |
---|---|
State | New |
Headers | show |
On 09/15/14 18:58, Segher Boessenkool wrote: > 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 <segher@kernel.crashing.org> > > * recog.c (scratch_operand): Do not simply allow all hard registers: > only allow those that are allocatable. Shouldn't you be testing if the register is fixed rather than its class? Or maybe both? jeff
On Thu, Sep 18, 2014 at 11:54:46PM -0600, Jeff Law wrote: > Shouldn't you be testing if the register is fixed rather than its class? > Or maybe both? register_operand (via general_operand) uses operand_reg_set for this; it is initialised via the regclass NO_REGS too (and other things). This would work for us (rs6000) too, or indeed fixed_regs[], or even wider classes. I have no idea if it would hurt other targets though, and I have no desire to test all weirdo targets ;-) If another regclass reg is assigned to a match_scratch (and then via a splitter to a match_operand register), reload can fix it up. It cannot fix up things properly for regs of NO_REGS class. This is what this patch is for: a class NO_REGS reg cannot ever work as a match_scratch. I could test for a wider class if you want, but I'll need some guidance what to test for exactly then; existing code isn't exactly consistent. Segher
On 09/19/14 06:21, Segher Boessenkool wrote: > On Thu, Sep 18, 2014 at 11:54:46PM -0600, Jeff Law wrote: >> Shouldn't you be testing if the register is fixed rather than its class? >> Or maybe both? > > register_operand (via general_operand) uses operand_reg_set for this; it is > initialised via the regclass NO_REGS too (and other things). > > This would work for us (rs6000) too, or indeed fixed_regs[], or even wider > classes. I have no idea if it would hurt other targets though, and I have > no desire to test all weirdo targets ;-) Can't blame you for that :-) Thanks for the pointer to operand_reg_set. Having walked through some of that code, I think we're OK just looking at the class like your original patch did. Concerns withdrawn. Patch approved. Jeff
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.