On Mon, Jul 06, 2015 at 04:58:36PM -0500, Segher Boessenkool wrote: > On Mon, Jul 06, 2015 at 04:45:35PM -0400, DJ Delorie wrote: > > Combine gets as far as this: > > > > Trying 5 -> 9: > > Failed to match this instruction: > > (parallel [ > > (set (mem/v/j:QI (const_int 240 [0xf0]) [0 MEM[(volatile union > > un_per0 *)240B].BIT.no4+0 S1 A16]) > > (ior:QI (mem/v/j:QI (const_int 240 [0xf0]) [0 MEM[(volatile > > union un_per0 *)240B].BIT.no4+0 S1 A16]) > > (const_int 16 [0x10]))) > > (set (reg/f:HI 43) > > (const_int 240 [0xf0])) > > ]) > > > > (the set is left behind because it's used for the second assignment) > > > > Both of those insns in the parallel are valid rl78 insns. I tried > > adding that parallel as a define-and-split but combine doesn't split > > it at the point where it inserts it, so it doesn't work right. If it > > reduced those four instructions to the two in the parallel, but > > without the parallel, it would probably work too. > > Did you try just a define_split instead? Ugly, but it should work I think.
So I built a rl78-elf cross and tried the example (s/union __BITS9/__BITS8/). I couldn't get your exact code, I guess I need some special options? But before combine it looks the same. There is no combination of four instructions, the only combinations combine makes here are 2->1 combinations, and they all succeed, except that last one. Since combine won't do 2->2 no split will work. And, as far as combine is concerned, a define_insn_and_split is a define_insn, so that indeed won't help you either. What you need is some form of uncse, like the attached hack (which doesn't work in this case because the rtx costs prohibit it). Segher diff --git a/gcc/combine.c b/gcc/combine.c index b97aa10..20d526f 100644 --- a/gcc/combine.c +++ b/gcc/combine.c @@ -3928,8 +3938,10 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0, && XVECLEN (newpat, 0) == 2 && GET_CODE (XVECEXP (newpat, 0, 0)) == SET && GET_CODE (XVECEXP (newpat, 0, 1)) == SET - && (i1 || set_noop_p (XVECEXP (newpat, 0, 0)) - || set_noop_p (XVECEXP (newpat, 0, 1))) + && (1 + || i1 + || set_noop_p (XVECEXP (newpat, 0, 0)) + || set_noop_p (XVECEXP (newpat, 0, 1))) && GET_CODE (SET_DEST (XVECEXP (newpat, 0, 0))) != ZERO_EXTRACT && GET_CODE (SET_DEST (XVECEXP (newpat, 0, 0))) != STRICT_LOW_PART && GET_CODE (SET_DEST (XVECEXP (newpat, 0, 1))) != ZERO_EXTRACT