On Tue, Jul 23, 2024 at 11:40:00AM -0600, Jeff Law wrote:
> 
> 
> On 7/23/24 9:45 AM, Stefan Schulze Frielinghaus wrote:
> 
> > 
> > > They come from:
> > > ```
> > > (define_insn "*tf_to_fprx2_0"
> > >    [(set (subreg:DF (match_operand:FPRX2 0 "nonimmediate_operand" "+f") 0)
> > >          (subreg:DF (match_operand:TF    1 "general_operand"       "v") 
> > > 0))]
> > > ...
> > > (define_insn "*tf_to_fprx2_1"
> > >    [(set (subreg:DF (match_operand:FPRX2 0 "nonimmediate_operand" "+f") 8)
> > >          (subreg:DF (match_operand:TF    1 "general_operand"       "v") 
> > > 8))]
> > > 
> > > ```
> > > 
> > > I am not sure if that is a valid thing to do. s390 backend is the only
> > > one that has insn patterns like this. all that uses "+" use either
> > > strict_lowpart of zero_extract for the lhs or just a pure set.
> > > Maybe there is a better way of representing this. Maybe using unspec here?
> > 
> > I gave unspec a try and came up with
> > 
> > (define_insn "*tf_to_fprx2_0"
> >    [(set (subreg:DF (match_operand:FPRX2 0 "nonimmediate_operand" "+f") 0)
> >          (unspec:DF [(match_operand:TF    1 "general_operand"       "v")] 
> > UNSPEC_TF_TO_FPRX2_0))]
> >    "TARGET_VXE"
> >    ; M4 == 1 corresponds to %v0[0] = %v1[0]; %v0[1] = %v0[1];
> >    "vpdi\t%v0,%v1,%v0,1"
> >    [(set_attr "op_type" "VRR")])
> > 
> > (define_insn "*tf_to_fprx2_1"
> >    [(set (subreg:DF (match_operand:FPRX2 0 "nonimmediate_operand" "+f") 8)
> >          (unspec:DF [(match_operand:TF    1 "general_operand"       "v")] 
> > UNSPEC_TF_TO_FPRX2_1))]
> >    "TARGET_VXE"
> >    ; M4 == 5 corresponds to %V0[0] = %v1[1]; %V0[1] = %V0[1];
> >    "vpdi\t%V0,%v1,%V0,5"
> >    [(set_attr "op_type" "VRR")])
> > 
> > which seems to work.  However, I'm still getting subregs at final:
> > 
> > (insn 3 18 7 (set (reg/v:TF 18 %f4 [orig:62 x ] [62])
> >          (mem/c:TF (reg:DI 2 %r2 [65]) [1 x+0 S16 A64])) "t.c":3:1 421 
> > {movtf_vr}
> >       (expr_list:REG_DEAD (reg:DI 2 %r2 [65])
> >          (nil)))
> > (insn 7 3 8 (set (subreg:DF (reg:FPRX2 16 %f0 [64]) 0)
> >          (unspec:DF [
> >                  (reg/v:TF 18 %f4 [orig:62 x ] [62])
> >              ] UNSPEC_TF_TO_FPRX2_0)) "t.c":4:10 569 {*tf_to_fprx2_0}
> >       (nil))
> > (insn 8 7 14 (set (subreg:DF (reg:FPRX2 16 %f0 [64]) 8)
> >          (unspec:DF [
> >                  (reg/v:TF 18 %f4 [orig:62 x ] [62])
> >              ] UNSPEC_TF_TO_FPRX2_1)) "t.c":4:10 570 {*tf_to_fprx2_1}
> >       (expr_list:REG_DEAD (reg/v:TF 18 %f4 [orig:62 x ] [62])
> >          (nil)))
> > 
> > Thus, I'm not sure whether this really solves the problem or rather
> > shifts around it.  I'm still a bit puzzled why the initial RTL is
> > invalid.  If I understood you correctly Jeff, then we are missing a
> > pattern which would match once the subregs are eliminated.  Since none
> > exists the subregs survive and regrename gets confused.  This basically
> > means that subregs of register pairs must not survive RA and the unspec
> > solution from above is no real solution.
> I'd tend to agree.  The routine in question is cleanup_subreg_operands and
> from a quick looksie it's not going to work for the insn in question because
> cleanup_subreg_operands actually looks down into the recog data structures
> for each operand.  In the case above the subreg is explicit in the RTL
> rather than matched by the operand predicate.

Right, I did some further tests over night where I also added patterns
in order to match variants where the subregs are eliminated and that
seems to work.  I still haven't made up my mind which route would be
best.  Anyhow, it is clear that this patch should be dropped and I will
come up with a solution for the target.

Thank you Andrew and Jeff for pointing this out.  Some myths about
subregs have been revealed for me :)

Cheers,
Stefan

Reply via email to