<div dir="ltr">I guess my area of confusion is how do I know that the br_cc instruction is for a loop and not just an if statement. I am still getting familiar with the backend process, so sorry for any dumb questions.<div><br><div>-Dilan</div></div></div><br><div class="gmail_quote"><div dir="ltr">On Wed, Jun 1, 2016 at 8:43 PM Tim Northover <<a href="mailto:t.p.northover@gmail.com">t.p.northover@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">On 1 June 2016 at 20:18, Dilan Manatunga via llvm-dev<br>
<<a href="mailto:llvm-dev@lists.llvm.org" target="_blank">llvm-dev@lists.llvm.org</a>> wrote:<br>
> I'm working on project which involves writing a backend for a hypothetical<br>
> architecture. I am currently trying to figure out the best way to translate<br>
> for loops to use a specialized "loop" instruction the architecture supports.<br>
> The instruction is similar X86's loop instruction, where a register is<br>
> automatically decremented and the condition is automatically checked to see<br>
> if loop execution should continue.<br>
<br>
This sounds like it's not something the TableGen patterns could<br>
handle, but ought to be fairly easy during ISelDAGToDAG. You'd be<br>
looking for a something like "(br_cc SETGT, (sub $iter, 1), 0,<br>
$GoAgain)". The C++ code is needed because your final LOOP instruction<br>
also has an output (induction variable for the next iteration) that<br>
needs to be propagated from the "(sub $iter, 1)".<br>
<br>
Some very vague and untested pseudo-code would be:<br>
<br>
    // To produce a (LOOP Chain, InductionVariable, Dest)<br>
    SDNode *SelectLOOPFromBR_CC(SDNode *N) {<br>
      // TODO: check whatever conditions (sub 1, SETGT, ..).<br>
      SDValue IV = N->getOperand(1);<br>
      SDNode *LOOP = CurDAG->getMachineNode(XYZ::LOOP, DL,<br>
              CurDAG->getVTList(MVT::Other, IV.getType()),<br>
IV.getOperand(0), N->getOperand(3));<br>
      CurDAG->ReplaceAllUsesWith(IV, SDValue(Loop, 1));<br>
      return LOOP;<br>
    }<br>
<br>
where the key point is that you have to manually call<br>
ReplaceAllUsesWith to move your induction variable onto the LOOP<br>
instruction. The rest is just bog-standard "match a BR_CC" code.<br>
<br>
The LOOP instruction would output a GPR (new induction variable) and<br>
take the old one as an input (tied via "let Constraints = ..." if<br>
they're really the same register), as well as a destination basic<br>
block.<br>
<br>
Hope this is a little helpful.<br>
<br>
Tim.<br>
<br>
P.S. Beware the position of the Chain changes between<br>
pre-isel/post-isel and I can never remember which way round it should<br>
be. There's at least a 50% chance I've got it wrong here. Probably<br>
closer to 75%.<br>
</blockquote></div>