https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88714
--- Comment #31 from Matthew Malcomson <matmal01 at gcc dot gnu.org> --- (In reply to Jakub Jelinek from comment #30) > (In reply to Matthew Malcomson from comment #29) > > I've been working on a patch that does very similar to the draft patch > > posted > > above, and I notice a few things I've tried to avoid in it. > > I doubt there are any actual bugs, since I don't know if the patterns that > > trigger actual faults can occur at the moment. > > > > -------- > > > > Using the `address_operand` predicate and 'p' constraint to ensure the > > address > > is a valid address would use the mode SImode of the operand rather than > > checking > > it's valid for the DImode of the emitted ldrd. > > Sure, but does it really matter? > This is a post reload pattern created by the peephole2s, so nothing that can > be matched out of the blue sky like combiner normally matches. > So, if it didn't pass the conditions in the peephole2s, the patterns > wouldn't be created. True -- as I mentioned I don't know if a problematic pattern could actually occur, so I doubt this is actually a problem. > Are there any addresses that pass arm_legitimate_address_p (DImode, x, true) > and fail address_operand (x, SImode)? From brief skimming I couldn't find > anything. > So, would you be happy if the && arm_legitimate_address_p (DImode, XEXP > (operands[n], 0), true) > condition is added to the insn conditions (after the rtx_equal_p check)? That sounds good to me. > > > There's a similar problem to the `address_operand` one above with using the > > `arm_count_output_move_double_insns` function. > > > > It's called on the original operands, which means it eventually calls > > `output_move_double` with the first two operands (which are in SImode). > > > > This function has some calls to `reg_overlap_mentioned_p`, which depends on > > the > > number of hard registers for a given registers mode. > > > > I've only found cases where the `arm_count_output_move_double_insns` > > function > > returns something other than what it should in cases that only match because > > of > > the `address_operand` problem above. > > > > This could be replaced by a wrapper that generates DImode registers > > specifically > > for checking this. > > For non-vfp or iwmmxt, the length is always 8, are there cases in the vfp > insn that the length is not 8? I believe the length *can* be 4 non-vfp, vfp, or iwmmxt (the case below produces a single ldrd when compiled with each of them). int __RTL (startwith ("peephole2")) foo_x4 (int *a) { (function "foo_x4" (insn-chain (cnote 1 NOTE_INSN_DELETED) (block 2 (edge-from entry (flags "FALLTHRU")) (cnote 3 [bb 2] NOTE_INSN_BASIC_BLOCK) (cinsn 101 (set (reg:SI r2) (mem/c:SI (plus:SI (reg:SI r0) (const_int 8)) [0 S4 A64])) "/home/matmal01/test.c":18) (cinsn 102 (set (reg:SI r3) (mem/c:SI (plus:SI (reg:SI r0) (const_int 12)) [0 S4 A32])) "/home/matmal01/test.c":18) (cinsn 103 (set (reg:SI r0) (plus:SI (reg:SI r2) (reg:SI r3))) "/home/matmal01/test.c":18) (edge-to exit (flags "FALLTHRU")) ) ;; block 2 ) ;; insn-chain (crtl (return_rtx (reg/i:SI r0) ) ;; return_rtx ) ;; crtl ) ;; function "main" } Something else I've just noticed: When compiling for vfp or iwmmxt, the ldm2_ define_insn matches the simpler case below as it comes first in the md order. That means we get a ldm instruction instead of the ldrd. int __RTL (startwith ("peephole2")) foo_x5 (int *a) { (function "foo_x5" (insn-chain (cnote 1 NOTE_INSN_DELETED) (block 2 (edge-from entry (flags "FALLTHRU")) (cnote 3 [bb 2] NOTE_INSN_BASIC_BLOCK) (cinsn 101 (set (reg:SI r2) (mem/c:SI (reg:SI r0) [0 S4 A64])) "/home/matmal01/test.c":18) (cinsn 102 (set (reg:SI r3) (mem/c:SI (plus:SI (reg:SI r0) (const_int 4)) [0 S4 A32])) "/home/matmal01/test.c":18) (cinsn 103 (set (reg:SI r0) (plus:SI (reg:SI r2) (reg:SI r3))) "/home/matmal01/test.c":18) (edge-to exit (flags "FALLTHRU")) ) ;; block 2 ) ;; insn-chain (crtl (return_rtx (reg/i:SI r0) ) ;; return_rtx ) ;; crtl ) ;; function "main" }