<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  </head>
  <body text="#000000" bgcolor="#FFFFFF">
    <div class="moz-cite-prefix">On 2020-02-22 16:14, Craig Topper
      wrote:<br>
    </div>
    <blockquote type="cite"
cite="mid:CAF7ks-Nh=VV3jbiJfoS5m2mEYt_H9tFYiQhc8BmJX5ev6CEcHQ@mail.gmail.com">
      <meta http-equiv="content-type" content="text/html; charset=UTF-8">
      <div dir="ltr">
        <div>Could you emit a target specific ISD opcode where the
          CopyToReg is created? Then you could isel that ISD opcode
          however you want.</div>
        <br clear="all">
      </div>
    </blockquote>
    <p>That doesn't seem quite satisfactory to me, since a copy could
      potentially be created in many different places. Since reg copies
      are kept as a general COPY instruction all the way until after
      regalloc until the target is supposed to implement them, it seems
      reasonable to let the target provide a constrained regclass at
      some point if needed. <br>
    </p>
    <p>Adding a new TRI hook for this is one way, another one might be
      to view this as an isel finalization step and let the target also
      handle COPY instructions in FinalizeISel. It would simply be a
      matter then of constraining the register class.</p>
    <p>It seems possible (but ugly) though to handle this with a backend
      hack, by using a target pseudo opcode that needs the constrained
      regclass and insert that as a user of the copyFromReg during
      instruction selection. That might be fine if there really is only
      this one single case of this problem, but that would surprise me.<br>
    </p>
    <p>To give some more context, here is one test case I am looking at:</p>
    <p><br>
      <tt>define i32 @fun() {</tt><tt><br>
      </tt><tt>  %val = call i32 asm "blah", "={a0}, {a1}" (i32 0)</tt><tt><br>
      </tt><tt>  ret i32 %val</tt><tt><br>
      </tt><tt>}</tt></p>
    <p>(llc -mtriple=s390x-linux-gnu -mcpu=z196 -O0)<br>
    </p>
    <p><tt></tt><tt># *** IR Dump After Finalize ISel and expand
        pseudo-instructions ***:</tt><tt><br>
      </tt><tt># Machine code for function fun: IsSSA, TracksLiveness</tt><tt><br>
      </tt><tt><br>
      </tt><tt>bb.0 (%ir-block.0):</tt><tt><br>
      </tt><tt>  %0:grx32bit = LHIMux 0</tt><tt><br>
      </tt><tt>  $a1 = COPY %0:grx32bit</tt><tt><br>
      </tt><tt>  INLINEASM &blah [attdialect], $0:[regdef],
        implicit-def $a0, $1:[reguse], $a1</tt><tt><br>
      </tt><tt>  %1:grx32bit = COPY $a0</tt><tt><br>
      </tt><tt>  $r2l = COPY %1:grx32bit</tt><tt><br>
      </tt><tt>  Return implicit $r2l</tt><br>
    </p>
    <p>ISel here produces COPYs to/from the GRX32 registers (both low
      and high parts) where access registers a1/a0 are involved. This is
      then the problem since these COPYs can only be made with low-parts
      by the processor. This was the SelectionDAG:<br>
      <br>
      <tt>SelectionDAG has 15 nodes:</tt><tt><br>
      </tt><tt>  t0: ch = EntryToken</tt><tt><br>
      </tt><tt>  t8: ch,glue = CopyToReg t0, Register:i32 $a1,
        Constant:i32<0></tt><tt><br>
      </tt><tt>    t11: i32,ch,glue = CopyFromReg t15, Register:i32 $a0,
        t15:1</tt><tt><br>
      </tt><tt>  t13: ch,glue = CopyToReg t0, Register:i32 $r2l, t11</tt><tt><br>
      </tt><tt>  t15: ch,glue = inlineasm t8,
        TargetExternalSymbol:i64'blah', MDNode:ch<null>,
        TargetConstant:i64<0>, TargetConstant:i32<10>,
        Register:i32 $a0, TargetConstant:i32<9>,\</tt><tt><br>
      </tt><tt> Register:i32 $a1, t8:1</tt><tt><br>
      </tt><tt>  t14: ch = Return Register:i32 $r2l, t13, t13:1</tt><tt><br>
      </tt><br>
      I can't simply select t8 here into a SAR (Set Access Register),
      because that would not provide the specific destination reg ($a1).
      So I tried replacing t8 with a target pseudo machine instruction
      opcode (CopyToAR) that looks identical on the DAG:<br>
      <br>
      => patched =><br>
      <br>
      <tt>SelectionDAG has 15 nodes:</tt><tt><br>
      </tt><tt>  t0: ch = EntryToken</tt><tt><br>
      </tt><tt>  t8: ch,glue = CopyToAR Register:i32 $a1,
        Constant:i32<0>, t0</tt><tt><br>
      </tt><tt>    t11: i32,ch,glue = CopyFromReg t15, Register:i32 $a0,
        t15:1</tt><tt><br>
      </tt><tt>  t13: ch,glue = CopyToReg t0, Register:i32 $r2l, t11</tt><tt><br>
      </tt><tt>  t15: ch,glue = inlineasm t8,
        TargetExternalSymbol:i64'blah', MDNode:ch<null>,
        TargetConstant:i64<0>, TargetConstant:i32<10>,
        Register:i32 $a0, TargetConstant:i32<9>,\</tt><tt><br>
      </tt><tt> Register:i32 $a1, t8:1</tt><tt><br>
      </tt><tt>  t14: ch = Return Register:i32 $r2l, t13, t13:1</tt><tt><br>
      </tt></p>
    <p>When instruction selection ends, the only difference between the
      DAGs is that the CopyToReg has changed opcode to the target pseudo
      instruction opcode CopyToAR. The idea was to then insert CopyToAR
      with a custom inserter. However, before that can happen
      InstrEmitter triggers an assert in EmitMachineNode in the "Scan
      the glue chain for any used physregs" clause. Here, the glue users
      are looped over and while a ISD::CopyToReg would simply be
      skipped, the target CopyToAR opcode is not. In this example,
      CopyToAR is glued to an inlineasm and therefore the call to
      F->getMachineOpcode() triggers the assert "Not a MachineInstr
      opcode!".<br>
      <br>
      I did not yet try to do the same opcode replacement for
      ISD::CopyFromReg since at this point it was clear to me that these
      nodes have special handlings in InstrEmitter and it probably would
      be worrisome to have a target opcode that did *not* get the same
      treatment even if that would succeed.</p>
    <p>My patch at <a class="moz-txt-link-freetext" href="https://reviews.llvm.org/D75014">https://reviews.llvm.org/D75014</a> now has two separate
      versions ("Diff 1" and "Diff 2") where the first one handles this
      in common code and the other one in the backend. Any comments and
      suggestions welcome!<br>
    </p>
    <p>/Jonas</p>
    <p><br>
    </p>
    <blockquote type="cite"
cite="mid:CAF7ks-Nh=VV3jbiJfoS5m2mEYt_H9tFYiQhc8BmJX5ev6CEcHQ@mail.gmail.com">
      <div dir="ltr">
        <div>
          <div dir="ltr" class="gmail_signature"
            data-smartmail="gmail_signature">~Craig</div>
        </div>
        <br>
      </div>
      <br>
      <div class="gmail_quote">
        <div dir="ltr" class="gmail_attr">On Sat, Feb 22, 2020 at 3:45
          PM Jonas Paulsson via llvm-dev <<a
            href="mailto:llvm-dev@lists.llvm.org" moz-do-not-send="true">llvm-dev@lists.llvm.org</a>>
          wrote:<br>
        </div>
        <blockquote class="gmail_quote" style="margin:0px 0px 0px
          0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Hi,<br>
          <br>
          On SystemZ there are a set of "access registers" that can be
          copied in <br>
          and out of 32-bit GPRs with special instructions. These
          instructions can <br>
          only perform the copy using low 32-bit parts of the 64-bit
          GPRs. As <br>
          reported and discussed at <a
            href="https://bugs.llvm.org/show_bug.cgi?id=44254"
            rel="noreferrer" target="_blank" moz-do-not-send="true">https://bugs.llvm.org/show_bug.cgi?id=44254</a>,
          <br>
          this is currently broken due to the fact that the default
          register class <br>
          for 32-bit integers is GRX32, which also contains the high
          32-bit part <br>
          registers.<br>
          <br>
          I have tried to find a simple way to constrain the register
          class of <br>
          such copies (also at -O0), but this turned out to not be quite
          simple. <br>
          Just selecting a pseudo instruction with a custom inserter
          does not seem <br>
          to work since CopyToReg/CopyFromReg have special handlings in
          InstrEmitter.<br>
          <br>
          I then tried in SystemZDAGToDAG.cpp to select a CopyToReg to
          (CopyToReg <br>
          COPY_TO_REGCLASS), which worked fine. But I could not get the
          same <br>
          results with CopyFromReg. (COPY_TO_REGCLASS CopyFromReg) only
          resulted <br>
          in a later COPY into GR32, but the COPY from the Access
          register was <br>
          still first made to GRX32.<br>
          <br>
          One alternative might be to let InstrEmitter deduce the needed
          register <br>
          class for a CopyFromReg if there is only one user which is a <br>
          COPY_TO_REGCLASS. I thought this seemed a bit messy, so I
          instead tried <br>
          adding a new TargetRegisterInfo hook that is used in
          InstrEmitter when <br>
          emitting CopyToReg/CopyFromReg nodes (<a
            href="https://reviews.llvm.org/D75014" rel="noreferrer"
            target="_blank" moz-do-not-send="true">https://reviews.llvm.org/D75014</a>).<br>
          <br>
          Does this make sense, or is there a better way?<br>
          <br>
          A related question is if the target is required to be able to
          implement <br>
          *any* move between register classes?<br>
          <br>
          Thanks,<br>
          <br>
          Jonas<br>
          <br>
          <br>
          _______________________________________________<br>
          LLVM Developers mailing list<br>
          <a href="mailto:llvm-dev@lists.llvm.org" target="_blank"
            moz-do-not-send="true">llvm-dev@lists.llvm.org</a><br>
          <a
            href="https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev"
            rel="noreferrer" target="_blank" moz-do-not-send="true">https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev</a><br>
        </blockquote>
      </div>
    </blockquote>
  </body>
</html>