<html><head><meta http-equiv="Content-Type" content="text/html charset=windows-1252"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;">On Jun 10, 2014, at 10:53 AM, Tom Stellard <<a href="mailto:tom@stellard.net">tom@stellard.net</a>> wrote:<br><div><br class="Apple-interchange-newline"><blockquote type="cite"><div style="font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;">On Tue, Jun 10, 2014 at 04:56:25PM +0000, Quentin Colombet wrote:<br><blockquote type="cite">Hi,<br><br>The proposed patch extends the peephole optimization introduced in r190713 to allow even more cross register banks copies rewriting.<br>As it is, the extension may not be that useful, but I thought it may be easier to reviewer than the complete solution (see Motivating Examples and What Is Next?).<br><br>Thanks for your feedback.<br><br>** Context  **<br><br>In r190713 we introduced a peephole optimization that produces register-coalescer friendly copies when possible.<br>This optimization basically looks through a chain of copies to find a more suitable source for a cross register banks copy.<br>E.g.,<br>b = copy A <-- cross-bank copy<br>…<br>C = copy b <-- cross-bank copy<br><br>Is rewritten into:<br>b = copy A  <-- cross-bank copy<br>…<br>C = copy A <-- same-bank copy<span class="Apple-converted-space"> </span><br><br>However, there are several instructions that are lowered via cross-bank copies that this optimization fails to optimize.<br>E.g.<br>b = insert_subreg e, A, sub0 <-- cross-bank copy<br>…<br>C = copy b.sub0 <-- cross-bank copy<br><br>Ideally, we would like to produce the following code:<br>b = insert_subreg e, A, sub0 <-- cross-bank copy<br>…<br>C = copy A <-- same-bank copy<br><br><br>** Proposed Patch **<br><br>The proposed patch taught the existing cross-bank copy optimization how to deal with the instructions that generate cross-bank copies, i.e., insert_subreg, extract_subreg, reg_sequence, and subreg_to_reg.<br>We introduce a new helper class for that: ValueTracker.<br>This class implements the logic to look through the copy related instructions and get the related source.<br><br>For now, the advanced copy rewriting is disabled by default as it is not sufficient to solve the motivating examples and I had a hard time to come up with a test case because of that (see motivating example section). However, you can give it a try on your favorite platform with -disable-adv-copy-opt=false and if it helps, I would be happy to add a test case!<br><br>I have also checked that the introduced refactoring does not change the current code gen through the entire llvm-testsuite + SPECs, when the extension is disable, for both x86_64 and arm64 with both O3 and Os.<br><br><br>** Motivating Examples **<br><br>Let us consider a couple of examples.<br><br>* armv7s *<br><br>define <2 x i32> @testuvec(<2 x i32> %A, <2 x i32> %B) nounwind {<br>entry:<br> %div = udiv <2 x i32> %A, %B<br> ret <2 x i32> %div<br>}<br><br>We would like the following code to be generated on swift (which has a udiv instruction):<br>// %A is in r0, r1<br>// %B is in r2, r3<br><span class="Apple-tab-span" style="white-space: pre;">       </span>udiv<span class="Apple-tab-span" style="white-space: pre;">      </span>r0, r2, r0<br><span class="Apple-tab-span" style="white-space: pre;">      </span>udiv<span class="Apple-tab-span" style="white-space: pre;">      </span>r1, r3, r1<br><span class="Apple-tab-span" style="white-space: pre;">      </span>bx lr<br><br>However, we generate a far more complicated sequence of instructions because we do not recognize that we are moving r0, r1, etc, through d registers:<br><span class="Apple-tab-span" style="white-space: pre;">  </span>vmov<span class="Apple-tab-span" style="white-space: pre;">      </span>d1, r0, r1<br><span class="Apple-tab-span" style="white-space: pre;">      </span>vmov<span class="Apple-tab-span" style="white-space: pre;">      </span>d0, r2, r3<br><span class="Apple-tab-span" style="white-space: pre;">      </span>vmov<span class="Apple-tab-span" style="white-space: pre;">      </span>r1, s2<br><span class="Apple-tab-span" style="white-space: pre;">  </span>vmov<span class="Apple-tab-span" style="white-space: pre;">      </span>r0, s0<br><span class="Apple-tab-span" style="white-space: pre;">  </span>vmov<span class="Apple-tab-span" style="white-space: pre;">      </span>r2, s3<br><span class="Apple-tab-span" style="white-space: pre;">  </span>udiv<span class="Apple-tab-span" style="white-space: pre;">      </span>r0, r1, r0<br><span class="Apple-tab-span" style="white-space: pre;">      </span>vmov<span class="Apple-tab-span" style="white-space: pre;">      </span>r1, s1<br><span class="Apple-tab-span" style="white-space: pre;">  </span>udiv<span class="Apple-tab-span" style="white-space: pre;">      </span>r1, r2, r1<br><span class="Apple-tab-span" style="white-space: pre;">      </span>vmov.32<span class="Apple-tab-span" style="white-space: pre;">   </span>d16[0], r0<br><span class="Apple-tab-span" style="white-space: pre;">      </span>vmov.32<span class="Apple-tab-span" style="white-space: pre;">   </span>d16[1], r1<br><span class="Apple-tab-span" style="white-space: pre;">      </span>vmov<span class="Apple-tab-span" style="white-space: pre;">      </span>r0, r1, d16<br><span class="Apple-tab-span" style="white-space: pre;">     </span>bx<span class="Apple-tab-span" style="white-space: pre;">        </span>lr<br><br>* AArch64 *<br><br>define i64 @test2(i128 %arg) {<br> %vec = bitcast i128 %arg to <2 x i64><br> %scalar = extractelement <2 x i64> %vec, i32 0<br> ret i64 %scalar<br>}<br><br>One would expect that this code :<br>// %arg is in x0, x1<br>// we simply return x0<br><span class="Apple-tab-span" style="white-space: pre;"> </span>ret<br><br>However, we generate a less straight forward sequence:<br><span class="Apple-tab-span" style="white-space: pre;">   </span>fmov<span class="Apple-tab-span" style="white-space: pre;">      </span>d0, x0<br><span class="Apple-tab-span" style="white-space: pre;">  </span>ins.d<span class="Apple-tab-span" style="white-space: pre;">     </span>v0[1], x1<br><span class="Apple-tab-span" style="white-space: pre;">       </span>fmov<span class="Apple-tab-span" style="white-space: pre;">      </span>x0, d0<br><span class="Apple-tab-span" style="white-space: pre;">  </span>ret<br><br>The proposed patch is not sufficient to catch those cases yet, as they use target specific instructions to implement the insert_subreg, extract_subreg logic. However, if the lowering was using the generic instructions, this optimization would have helped. See "What Is Next?” for how I plan to tackle that.<br><br><br>** Testcase ?! **<br><br>Since the current patch does not yet support the motivating examples, I do not have something reasonably small that exercises the new path. Thus, I have disabled it by default until we have the full support.<br>Again, if you think that this optimization can help some of the cases you are seeing, give it a try, and propose your test case!<br><br></blockquote><br>The SI and newer subtargets in the R600 backend will probably benefit a<br>lot from this optimization.  You might try force enabling it and running<br>all the test cases in test/CodeGen/R600 to see if any tests fail.<br></div></blockquote><div><br></div><div>Thanks for the suggestion.</div><div>I have given it a try but none of the test fails. I haven’t checked if it is just the test checks that are not sensible enough.</div><div><br></div><div>That said, I guess that to express the full potential of value tracking, in particular for R600, we should use this technic to rewrite the arguments of REG_SEQUENCE, INSERT_SUBREG, and so on, not just copies.</div><div><br></div><div>By the way, thanks to this test, I realized I uploaded the wrong patch (I was missing one fix a typo) :).</div><div><br></div><div>Thanks,</div><div>-Quentin</div><br><blockquote type="cite"><div style="font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><br>If I get some time, I will try to take a look at how it impacts R600.<br><br>-Tom<br><br><blockquote type="cite"><br>** What Is Next? **<br><br>* Teach the optimization about target specific nodes, so that we can handle the motivating examples.<br>The idea would be to add new tablegen properties so that we would be able to specify that an instruction is similar to a insert_subreg instruction, etc., the same way we did with bitcast (though a little bit more complicated).<br>* Enable the optimization by default or provide a target hook to control it.<br><br>Thanks,<br>-Quentin<br><br><a href="http://reviews.llvm.org/D4086">http://reviews.llvm.org/D4086</a><br><br>Files:<br> lib/CodeGen/PeepholeOptimizer.cpp<br></blockquote><br><blockquote type="cite">Index: lib/CodeGen/PeepholeOptimizer.cpp<br>===================================================================<br>--- lib/CodeGen/PeepholeOptimizer.cpp<br>+++ lib/CodeGen/PeepholeOptimizer.cpp<br>@@ -91,6 +91,10 @@<br>DisablePeephole("disable-peephole", cl::Hidden, cl::init(false),<br>                cl::desc("Disable the peephole optimizer"));<br><br>+static cl::opt<bool><br>+DisableAdvCopyOpt("disable-adv-copy-opt", cl::Hidden, cl::init(true),<br>+                  cl::desc("Disable advanced copy optimization"));<br>+<br>STATISTIC(NumReuse,      "Number of extension results reused");<br>STATISTIC(NumCmps,       "Number of compares eliminated");<br>STATISTIC(NumImmFold,    "Number of move immediate folded");<br>@@ -137,6 +141,105 @@<br>    bool isLoadFoldable(MachineInstr *MI,<br>                        SmallSet<unsigned, 16> &FoldAsLoadDefCandidates);<br>  };<br>+<br>+  /// \brief Helper class to track the possible sources of a value defined by<br>+  /// a (chain of) copy related instructions.<br>+  /// Given a definition (instruction and definition index), this class<br>+  /// follow the use-def chain to find successive suitable sources.<br>+  /// The given source can be used to rewrite the definition into<br>+  /// def = COPY src.<br>+  ///<br>+  /// For instance, let us consider the following snippet:<br>+  /// v0 =<br>+  /// v2 = INSERT_SUBREG v1, v0, sub0<br>+  /// def = COPY v2.sub0<br>+  ///<br>+  /// Using a ValueTracker for def = COPY v2.sub0 will give the following<br>+  /// suitable sources:<br>+  /// v2.sub0 and v0.<br>+  /// Then, def can be rewritten into def = COPY v0.<br>+  class ValueTracker {<br>+  private:<br>+    /// The current point into the use-def chain.<br>+    const MachineInstr *Def;<br>+    /// The index of the definition in Def.<br>+    unsigned DefIdx;<br>+    /// The sub register index of the definition.<br>+    unsigned DefSubReg;<br>+    /// The register where the value can be found.<br>+    unsigned Reg;<br>+    /// Specifiy whether or not the value tracking looks through<br>+    /// complex instructions. When this is false, the value tracker<br>+    /// bails on everything that is not a copy or a bitcast.<br>+    ///<br>+    /// Note: This could have been implemented as a specialized version of<br>+    /// the ValueTracker class but that would have complicated the code of<br>+    /// the users of this class.<br>+    bool UseAdvancedTracking;<br>+    /// Optional MachineRegisterInfo used to perform some complex<br>+    /// tracking.<br>+    const MachineRegisterInfo *MRI;<br>+<br>+    /// \brief Dispatcher to the right underlying implementation of<br>+    /// getNextSource.<br>+    bool getNextSourceImpl(unsigned &SrcIdx, unsigned &SrcSubReg);<br>+    /// \brief Specialized version of getNextSource for Copy instructions.<br>+    bool getNextSourceFromCopy(unsigned &SrcIdx, unsigned &SrcSubReg);<br>+    /// \brief Specialized version of getNextSource for Bitcast instructions.<br>+    bool getNextSourceFromBitcast(unsigned &SrcIdx, unsigned &SrcSubReg);<br>+    /// \brief Specialized version of getNextSource for RegSequence<br>+    /// instructions.<br>+    bool getNextSourceFromRegSequence(unsigned &SrcIdx, unsigned &SrcSubReg);<br>+    /// \brief Specialized version of getNextSource for InsertSubreg<br>+    /// instructions.<br>+    bool getNextSourceFromInsertSubreg(unsigned &SrcIdx, unsigned &SrcSubReg);<br>+    /// \brief Specialized version of getNextSource for ExtractSubreg<br>+    /// instructions.<br>+    bool getNextSourceFromExtractSubreg(unsigned &SrcIdx, unsigned &SrcSubReg);<br>+    /// \brief Specialized version of getNextSource for SubregToReg<br>+    /// instructions.<br>+    bool getNextSourceFromSubregToReg(unsigned &SrcIdx, unsigned &SrcSubReg);<br>+<br>+  public:<br>+    /// \brief Create a ValueTracker instance for the value defines by \p MI<br>+    /// at the operand index \p DefIdx.<br>+    /// \p DefSubReg represents the sub register index the value tracker will<br>+    /// track. It does not need to match the sub register index used in \p MI.<br>+    /// \p UseAdvancedTracking specifies whether or not the value tracker looks<br>+    /// through complex instructions. By default (false), it handles only copy<br>+    /// and bitcast instructions.<br>+    /// \p MRI useful to perform some complex checks.<br>+    ValueTracker(const MachineInstr &MI, unsigned DefIdx, unsigned DefSubReg,<br>+                 bool UseAdvancedTracking = false,<br>+                 const MachineRegisterInfo *MRI = nullptr)<br>+        : Def(&MI), DefIdx(DefIdx), DefSubReg(DefSubReg),<br>+          UseAdvancedTracking(UseAdvancedTracking), MRI(MRI) {<br>+      assert(Def->getOperand(DefIdx).isDef() &&<br>+             Def->getOperand(DefIdx).isReg() &&<br>+             "Definition does not match machine instruction");<br>+      // Initially the value is in the defined register.<br>+      Reg = Def->getOperand(DefIdx).getReg();<br>+    }<br>+<br>+    /// \brief Following the use-def chain, get the next available source<br>+    /// for the tracked value.<br>+    /// When the returned value is not nullptr, getReg() gives the register<br>+    /// that contain the tracked value.<br>+    /// \note The sub register index returned in \p SrcSubReg must be used<br>+    /// on that getReg() to access the actual value.<br>+    /// \return Unless the returned value is nullptr (i.e., no source found),<br>+    /// \p SrcIdx gives the index of the next source in the returned<br>+    /// instruction and \p SrcSubReg the index to be used on that source to<br>+    /// get the tracked value. When nullptr is returned, no alternative source<br>+    /// has been found.<br>+    const MachineInstr *getNextSource(unsigned &SrcIdx, unsigned &SrcSubReg);<br>+<br>+    /// \brief Get the last register where the initial value can be found.<br>+    /// Initially this is the register of the definition.<br>+    /// Then, after each successful call to getNextSource, this is the<br>+    /// register of the last source.<br>+    unsigned getReg() const { return Reg; }<br>+  };<br>}<br><br>char PeepholeOptimizer::ID = 0;<br>@@ -443,31 +546,27 @@<br>  unsigned Src;<br>  unsigned SrcSubReg;<br>  bool ShouldRewrite = false;<br>-  MachineInstr *Copy = MI;<br>  const TargetRegisterInfo &TRI = *TM->getRegisterInfo();<br><br>-  // Follow the chain of copies until we reach the top or find a<br>-  // more suitable source.<br>+  // Follow the chain of copies until we reach the top of the use-def chain<br>+  // or find a more suitable source.<br>+  ValueTracker ValTracker(*MI, DefIdx, DefSubReg, !DisableAdvCopyOpt, MRI);<br>  do {<br>-    unsigned CopyDefIdx, CopySrcIdx;<br>-    if (!getCopyOrBitcastDefUseIdx(*Copy, CopyDefIdx, CopySrcIdx))<br>+    unsigned CopySrcIdx, CopySrcSubReg;<br>+    if (!ValTracker.getNextSource(CopySrcIdx, CopySrcSubReg))<br>      break;<br>-    const MachineOperand &MO = Copy->getOperand(CopySrcIdx);<br>-    assert(MO.isReg() && "Copies must be between registers.");<br>-    Src = MO.getReg();<br>+    Src = ValTracker.getReg();<br>+    SrcSubReg = CopySrcSubReg;<br><br>    if (TargetRegisterInfo::isPhysicalRegister(Src))<br>      break;<br><br>    const TargetRegisterClass *SrcRC = MRI->getRegClass(Src);<br>-    SrcSubReg = MO.getSubReg();<br><br>    // If this source does not incur a cross register bank copy, use it.<br>    ShouldRewrite = shareSameRegisterFile(TRI, DefRC, DefSubReg, SrcRC,<br>                                          SrcSubReg);<br>-    // Follow the chain of copies: get the definition of Src.<br>-    Copy = MRI->getVRegDef(Src);<br>-  } while (!ShouldRewrite && Copy && (Copy->isCopy() || Copy->isBitcast()));<br>+  } while (!ShouldRewrite);<br><br>  // If we did not find a more suitable source, there is nothing to optimize.<br>  if (!ShouldRewrite || Src == MI->getOperand(SrcIdx).getReg())<br>@@ -483,6 +582,9 @@<br><br>  MRI->replaceRegWith(Def, NewVR);<br>  MRI->clearKillFlags(NewVR);<br>+  // We extended the lifetime of Src.<br>+  // Clear the kill flags to account for that.<br>+  MRI->clearKillFlags(Src);<br>  MI->eraseFromParent();<br>  ++NumCopiesBitcasts;<br>  return true;<br>@@ -673,3 +775,247 @@<br><br>  return Changed;<br>}<br>+<br>+bool ValueTracker::getNextSourceFromCopy(unsigned &SrcIdx,<br>+                                         unsigned &SrcSubReg) {<br>+  assert(Def->isCopy() && "Invalid definition");<br>+  // Copy instruction are supposed to be: Def = Src.<br>+  if (Def->getDesc().getNumOperands() != 2)<br>+    return false;<br>+  if (Def->getOperand(DefIdx).getSubReg() != DefSubReg)<br>+    // If we look for a different subreg, it means we want a subreg of src.<br>+    // Bails as we do not support composing subreg yet.<br>+    return false;<br>+  // Otherwise, we want the whole source.<br>+  SrcIdx = 1;<br>+  SrcSubReg = Def->getOperand(SrcIdx).getSubReg();<br>+  return true;<br>+}<br>+<br>+bool ValueTracker::getNextSourceFromBitcast(unsigned &SrcIdx,<br>+                                            unsigned &SrcSubReg) {<br>+  assert(Def->isBitcast() && "Invalid definition");<br>+<br>+  // Bitcasts with more than one def are not supported.<br>+  if (Def->getDesc().getNumDefs() != 1)<br>+    return false;<br>+  if (Def->getOperand(DefIdx).getSubReg() != DefSubReg)<br>+    // If we look for a different subreg, it means we want a subreg of the src.<br>+    // Bails as we do not support composing subreg yet.<br>+    return false;<br>+<br>+  SrcIdx = Def->getDesc().getNumOperands();<br>+  for (unsigned OpIdx = DefIdx + 1, EndOpIdx = SrcIdx; OpIdx != EndOpIdx;<br>+       ++OpIdx) {<br>+    const MachineOperand &MO = Def->getOperand(OpIdx);<br>+    if (!MO.isReg() || !MO.getReg())<br>+      continue;<br>+    assert(!MO.isDef() && "We should have skipped all the definitions by now");<br>+    if (SrcIdx != EndOpIdx)<br>+      // Multiple sources?<br>+      return false;<br>+    SrcIdx = OpIdx;<br>+  }<br>+  SrcSubReg = Def->getOperand(SrcIdx).getSubReg();<br>+  return true;<br>+}<br>+<br>+bool ValueTracker::getNextSourceFromRegSequence(unsigned &SrcIdx,<br>+                                                unsigned &SrcSubReg) {<br>+  assert(Def->isRegSequence() && "Invalid definition");<br>+<br>+  if (Def->getOperand(DefIdx).getSubReg())<br>+    // If we are composing subreg, bails out.<br>+    // The case we are checking is Def.<subreg> = REG_SEQUENCE.<br>+    // This should almost never happen as the SSA property is tracked at<br>+    // the register level (as opposed to the subreg level).<br>+    // I.e.,<br>+    // Def.sub0 =<br>+    // Def.sub1 =<br>+    // is a valid SSA representation for Def.sub0 and Def.sub1, but not for<br>+    // Def. Thus, it must not be generated.<br>+    // However, some code could theoritically generates a single<br>+    // Def.sub0 (i.e, not defining the other subregs) and we would<br>+    // have this case.<br>+    // If we can ascertain (or force) that this never happens, we could<br>+    // turn that into an assertion.<br>+    return false;<br>+<br>+  // We are looking at:<br>+  // Def = REG_SEQUENCE v0, sub0, v1, sub1, ...<br>+  // Check if one of the operand defines the subreg we are interested in.<br>+  for (unsigned OpIdx = DefIdx + 1, EndOpIdx = Def->getDesc().getNumOperands();<br>+       OpIdx != EndOpIdx; OpIdx += 2) {<br>+    const MachineOperand &MOSubIdx = Def->getOperand(OpIdx + 1);<br>+    assert(MOSubIdx.isImm() &&<br>+           "One of the subindex of the reg_sequence is not an immediate");<br>+    if (MOSubIdx.getImm() == DefSubReg) {<br>+      assert(Def->getOperand(OpIdx).isReg() &&<br>+             "One of the source of the reg_sequence is not a register");<br>+      SrcIdx = OpIdx;<br>+      SrcSubReg = Def->getOperand(SrcIdx).getSubReg();<br>+      return true;<br>+    }<br>+  }<br>+<br>+  // If the subreg we are tracking is super-defined by another subreg,<br>+  // we could follow this value. However, this would require to compose<br>+  // the subreg and we do not do that for now.<br>+  return false;<br>+}<br>+<br>+bool ValueTracker::getNextSourceFromInsertSubreg(unsigned &SrcIdx,<br>+                                                 unsigned &SrcSubReg) {<br>+  assert(Def->isInsertSubreg() && "Invalid definition");<br>+  if (Def->getOperand(DefIdx).getSubReg())<br>+    // If we are composing subreg, bails out.<br>+    // Same remark as getNextSourceFromRegSequence.<br>+    // I.e., this may be turned into an assert.<br>+    return false;<br>+<br>+  // We are looking at:<br>+  // Def = INSERT_SUBREG v0, v1, sub1<br>+  // There are two cases:<br>+  // 1. DefSubReg == sub1, get v1.<br>+  // 2. DefSubReg != sub1, the value may be available through v0.<br>+<br>+  // #1 Check if the inserted register matches the require sub index.<br>+  unsigned InsertedSubReg = Def->getOperand(3).getImm();<br>+  if (InsertedSubReg == DefSubReg) {<br>+    SrcIdx = 2;<br>+    SrcSubReg = Def->getOperand(SrcIdx).getSubReg();<br>+    return true;<br>+  }<br>+  // #2 Otherwise, if the sub register we are looking for is not partial<br>+  // defined by the inserted element, we can look through the main<br>+  // register (v0).<br>+  // To check the overlapping we need a MRI and a TRI.<br>+  if (!MRI)<br>+    return false;<br>+<br>+  const MachineOperand &MODef = Def->getOperand(DefIdx);<br>+  const MachineOperand &MOBase = Def->getOperand(1);<br>+  // If the result register (Def) and the base register (v0) do not<br>+  // have the same register class or if we have to compose<br>+  // subregisters, bails out.<br>+  if (MRI->getRegClass(MODef.getReg()) != MRI->getRegClass(MOBase.getReg()) ||<br>+      MOBase.getSubReg())<br>+    return false;<br>+<br>+  // Get the TRI and check if inserted sub register overlaps with the<br>+  // sub register we are tracking.<br>+  const TargetRegisterInfo *TRI = MRI->getTargetRegisterInfo();<br>+  if (!TRI ||<br>+      (TRI->getSubRegIndexLaneMask(DefSubReg) &<br>+       TRI->getSubRegIndexLaneMask(InsertedSubReg)) != 0)<br>+    return false;<br>+  // At this point, the value is available in v0 via the same subreg<br>+  // we used for Def.<br>+  SrcIdx = 1;<br>+  SrcSubReg = DefSubReg;<br>+  return true;<br>+}<br>+<br>+bool ValueTracker::getNextSourceFromExtractSubreg(unsigned &SrcIdx,<br>+                                                  unsigned &SrcSubReg) {<br>+  assert(Def->getOpcode() == TargetOpcode::EXTRACT_SUBREG &&<br>+         "Invalid definition");<br>+  // We are looking at:<br>+  // Def = EXTRACT_SUBREG v0, sub0<br>+<br>+  // Bails if we have to compose sub registers.<br>+  // Indeed, if DefSubReg != 0, we would have to compose it with sub0.<br>+  if (DefSubReg)<br>+    return false;<br>+<br>+  // Bails if we have to compose sub registers.<br>+  // Likewise, if v0.subreg != 0, we would have to compose v0.subreg with sub0.<br>+  if (Def->getOperand(1).getSubReg())<br>+    return false;<br>+  // Otherwise, the value is available in the v0.sub0.<br>+  SrcIdx = 1;<br>+  SrcSubReg = Def->getOperand(2).getImm();<br>+  return true;<br>+}<br>+<br>+bool ValueTracker::getNextSourceFromSubregToReg(unsigned &SrcIdx,<br>+                                                unsigned &SrcSubReg) {<br>+  assert(Def->isSubregToReg() && "Invalid definition");<br>+  // We are looking at:<br>+  // Def = SUBREG_TO_REG Imm, v0, sub0<br>+<br>+  // Bails if we have to compose sub registers.<br>+  // If DefSubReg != sub0, we would have to check that all the bits<br>+  // we track are included in sub0 and if yes, we would have to<br>+  // determine the right subreg in v0.<br>+  if (DefSubReg != Def->getOperand(3).getSubReg())<br>+    return false;<br>+  // Bails if we have to compose sub registers.<br>+  // Likewise, if v0.subreg != 0, we would have to compose it with sub0.<br>+  if (Def->getOperand(2).getSubReg())<br>+    return false;<br>+<br>+  SrcIdx = 2;<br>+  SrcSubReg = Def->getOperand(3).getSubReg();<br>+  return true;<br>+}<br>+<br>+bool ValueTracker::getNextSourceImpl(unsigned &SrcIdx, unsigned &SrcSubReg) {<br>+  assert(Def && "This method needs a valid definition");<br>+<br>+  assert(<br>+      (DefIdx < Def->getDesc().getNumDefs() || Def->getDesc().isVariadic()) &&<br>+      Def->getOperand(DefIdx).isDef() && "Invalid DefIdx");<br>+  if (Def->isCopy())<br>+    return getNextSourceFromCopy(SrcIdx, SrcSubReg);<br>+  if (Def->isBitcast())<br>+    return getNextSourceFromBitcast(SrcIdx, SrcSubReg);<br>+  // All the remaining cases involve "complex" instructions.<br>+  // Bails if we did not ask for the advanced tracking.<br>+  if (!UseAdvancedTracking)<br>+    return false;<br>+  if (Def->isRegSequence())<br>+    return getNextSourceFromRegSequence(SrcIdx, SrcSubReg);<br>+  if (Def->isInsertSubreg())<br>+    return getNextSourceFromInsertSubreg(SrcIdx, SrcSubReg);<br>+  if (Def->getOpcode() == TargetOpcode::EXTRACT_SUBREG)<br>+    return getNextSourceFromExtractSubreg(SrcIdx, SrcSubReg);<br>+  if (Def->isSubregToReg())<br>+    return getNextSourceFromSubregToReg(SrcIdx, SrcSubReg);<br>+  return false;<br>+}<br>+<br>+const MachineInstr *ValueTracker::getNextSource(unsigned &SrcIdx,<br>+                                                unsigned &SrcSubReg) {<br>+  // If we reach a point where we cannot move up in the use-def chain,<br>+  // there is nothing we can get.<br>+  if (!Def)<br>+    return nullptr;<br>+<br>+  const MachineInstr *PrevDef = nullptr;<br>+  // Try to find the next source.<br>+  if (getNextSourceImpl(SrcIdx, SrcSubReg)) {<br>+    // Update definition, definition index, and subregister for the<br>+    // next call of getNextSource.<br>+    const MachineOperand &MO = Def->getOperand(SrcIdx);<br>+    assert(MO.isReg() && !MO.isDef() && "Source is invalid");<br>+    // Update the current register.<br>+    Reg = MO.getReg();<br>+    // Update the return value before moving up in the use-def chain.<br>+    PrevDef = Def;<br>+    // If we can still move up in the use-def chain, move to the next<br>+    // defintion.<br>+    if (!TargetRegisterInfo::isPhysicalRegister(Reg)) {<br>+      Def = MRI->getVRegDef(Reg);<br>+      DefIdx = MRI->def_begin(Reg).getOperandNo();<br>+      DefSubReg = SrcSubReg;<br>+      return PrevDef;<br>+    }<br>+  }<br>+  // If we end up here, this means we will not be able to find another source<br>+  // for the next iteration.<br>+  // Make sure any new call to getNextSource bails out early by cutting the<br>+  // use-def chain.<br>+  Def = nullptr;<br>+  return PrevDef;<br>+}<br></blockquote><br><blockquote type="cite">_______________________________________________<br>llvm-commits mailing list<br><a href="mailto:llvm-commits@cs.uiuc.edu">llvm-commits@cs.uiuc.edu</a><br><a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a></blockquote></div></blockquote></div><br></body></html>