<div dir="ltr"><div class="gmail_default" style="font-size:small">Submitted a patch <a href="http://reviews.llvm.org/D20731">http://reviews.llvm.org/D20731</a> to turn off the enhanced stack coloring until I can incorporate a real fix.</div><div class="gmail_default" style="font-size:small"><br></div><div class="gmail_default" style="font-size:small">Thanks, Than</div><div class="gmail_default" style="font-size:small"><br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Fri, May 27, 2016 at 8:47 AM, Teresa Johnson <span dir="ltr"><<a href="mailto:tejohnson@google.com" target="_blank">tejohnson@google.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">Forgot to update on llvm-commits yesterday: I filed <a href="https://llvm.org/bugs/show_bug.cgi?id=27903" target="_blank">https://llvm.org/bugs/show_bug.cgi?id=27903</a>, and Than has already made good progress on narrowing this down.<span class="HOEnZb"><font color="#888888"><div>Teresa</div></font></span></div><div class="HOEnZb"><div class="h5"><div class="gmail_extra"><br><div class="gmail_quote">On Thu, May 26, 2016 at 7:46 AM, Teresa Johnson <span dir="ltr"><<a href="mailto:tejohnson@google.com" target="_blank">tejohnson@google.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">I have a way to repro this now using llc on a bitcode file I got via save-temps and linked with a bunch of native objects. The seg fault disappears when passing -no-stack-coloring to llc. Than, I will package up something and get it to you off-list.<div><br></div><div>Thanks,</div><div>Teresa</div></div><div><div><div class="gmail_extra"><br><div class="gmail_quote">On Wed, May 25, 2016 at 6:55 PM, Teresa Johnson <span dir="ltr"><<a href="mailto:tejohnson@google.com" target="_blank">tejohnson@google.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><br><div class="gmail_quote"><span>On Wed, May 25, 2016 at 6:29 PM, Than McIntosh <span dir="ltr"><<a href="mailto:thanm@google.com" target="_blank">thanm@google.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div style="font-size:small">Hello Teresa,</div><div style="font-size:small"><br></div><div style="font-size:small">Thanks for the heads-up.  So far I have not seen any other issues.</div><div style="font-size:small"><br></div><div style="font-size:small">What is a "ThinLTO bootstrap using gold"?</div></div></blockquote><div><br></div></span><div>Sorry, clang/llvm bootstrap using ThinLTO and the gold linker (since this was linux).</div><div><br></div><div>The patch I referenced below just went in, but I will see if I can come up with something smaller to reproduce.</div><span><font color="#888888"><div><br></div><div>Teresa</div></font></span><div><div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div style="font-size:small"><br></div><div style="font-size:small">Thanks, Than</div><div style="font-size:small"><br></div></div><div><div><div class="gmail_extra"><br><div class="gmail_quote">On Wed, May 25, 2016 at 7:32 PM, Teresa Johnson <span dir="ltr"><<a href="mailto:tejohnson@google.com" target="_blank">tejohnson@google.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">Hi Than,<div><br></div><div>I started getting failures running llvm-tblgen yesterday in a ThinLTO bootstrap of clang. I just bisected it to this commit. </div><div><br></div><div>I'll work on packaging up a reproducer (a ThinLTO bootstrap using gold requires D20559 to fix an issue handling archives, which I should be submitting soon since it just got approved). I had earlier today tracked this down to happening when we import a particular function, presumably exposed with the expanded optimization scope after the importing.</div><div><br></div><div>I wanted to give you a heads up though in case any other issues have been reported.</div><div><br></div><div>Thanks</div><div>Teresa</div><div class="gmail_extra"><div><div><br><div class="gmail_quote">On Tue, May 24, 2016 at 6:23 AM, Than McIntosh via llvm-commits <span dir="ltr"><<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: thanm<br>
Date: Tue May 24 08:23:44 2016<br>
New Revision: 270559<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=270559&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=270559&view=rev</a><br>
Log:<br>
Rework/enhance stack coloring data flow analysis.<br>
<br>
Replace bidirectional flow analysis to compute liveness with forward<br>
analysis pass. Treat lifetimes as starting when there is a first<br>
reference to the stack slot, as opposed to starting at the point of the<br>
lifetime.start intrinsic, so as to increase the number of stack<br>
variables we can overlap.<br>
<br>
Reviewers: gbiv, qcolumbet, wmi<br>
Differential Revision: <a href="http://reviews.llvm.org/D18827" rel="noreferrer" target="_blank">http://reviews.llvm.org/D18827</a><br>
<br>
Bug: 25776<br>
<br>
Modified:<br>
  Â  llvm/trunk/lib/CodeGen/StackColoring.cpp<br>
  Â  llvm/trunk/test/CodeGen/X86/StackColoring.ll<br>
  Â  llvm/trunk/test/CodeGen/X86/misched-aa-colored.ll<br>
<br>
Modified: llvm/trunk/lib/CodeGen/StackColoring.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/StackColoring.cpp?rev=270559&r1=270558&r2=270559&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/StackColoring.cpp?rev=270559&r1=270558&r2=270559&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/CodeGen/StackColoring.cpp (original)<br>
+++ llvm/trunk/lib/CodeGen/StackColoring.cpp Tue May 24 08:23:44 2016<br>
@@ -64,18 +64,180 @@ DisableColoring("no-stack-coloring",<br>
 /// The user may write code that uses allocas outside of the declared lifetime<br>
 /// zone. This can happen when the user returns a reference to a local<br>
 /// data-structure. We can detect these cases and decide not to optimize the<br>
-/// code. If this flag is enabled, we try to save the user.<br>
+/// code. If this flag is enabled, we try to save the user. This option<br>
+/// is treated as overriding LifetimeStartOnFirstUse below.<br>
 static cl::opt<bool><br>
 ProtectFromEscapedAllocas("protect-from-escaped-allocas",<br>
  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â cl::init(false), cl::Hidden,<br>
  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â cl::desc("Do not optimize lifetime zones that "<br>
  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  "are broken"));<br>
<br>
+/// Enable enhanced dataflow scheme for lifetime analysis (treat first<br>
+/// use of stack slot as start of slot lifetime, as opposed to looking<br>
+/// for LIFETIME_START marker). See "Implementation notes" below for<br>
+/// more info.<br>
+static cl::opt<bool><br>
+LifetimeStartOnFirstUse("stackcoloring-lifetime-start-on-first-use",<br>
+  Â  Â  Â  cl::init(true), cl::Hidden,<br>
+  Â  Â  Â  cl::desc("Treat stack lifetimes as starting on first use, not on START marker."));<br>
+<br>
+<br>
 STATISTIC(NumMarkerSeen,  "Number of lifetime markers found.");<br>
 STATISTIC(StackSpaceSaved, "Number of bytes saved due to merging slots.");<br>
 STATISTIC(StackSlotMerged, "Number of stack slot merged.");<br>
 STATISTIC(EscapedAllocas, "Number of allocas that escaped the lifetime region");<br>
<br>
+//<br>
+// Implementation Notes:<br>
+// ---------------------<br>
+//<br>
+// Consider the following motivating example:<br>
+//<br>
+//  Â  Â int foo() {<br>
+//  Â  Â  Â char b1[1024], b2[1024];<br>
+//  Â  Â  Â if (...) {<br>
+//  Â  Â  Â  Â char b3[1024];<br>
+//  Â  Â  Â  Â <uses of b1, b3>;<br>
+//  Â  Â  Â  Â return x;<br>
+//  Â  Â  Â } else {<br>
+//  Â  Â  Â  Â char b4[1024], b5[1024];<br>
+//  Â  Â  Â  Â <uses of b2, b4, b5>;<br>
+//  Â  Â  Â  Â return y;<br>
+//  Â  Â  Â }<br>
+//  Â  Â }<br>
+//<br>
+// In the code above, "b3" and "b4" are declared in distinct lexical<br>
+// scopes, meaning that it is easy to prove that they can share the<br>
+// same stack slot. Variables "b1" and "b2" are declared in the same<br>
+// scope, meaning that from a lexical point of view, their lifetimes<br>
+// overlap. From a control flow pointer of view, however, the two<br>
+// variables are accessed in disjoint regions of the CFG, thus it<br>
+// should be possible for them to share the same stack slot. An ideal<br>
+// stack allocation for the function above would look like:<br>
+//<br>
+//  Â  Â slot 0: b1, b2<br>
+//  Â  Â slot 1: b3, b4<br>
+//  Â  Â slot 2: b5<br>
+//<br>
+// Achieving this allocation is tricky, however, due to the way<br>
+// lifetime markers are inserted. Here is a simplified view of the<br>
+// control flow graph for the code above:<br>
+//<br>
+//  Â  Â  Â  Â  Â  Â  Â  +------  block 0 -------+<br>
+//  Â  Â  Â  Â  Â  Â  Â 0| LIFETIME_START b1, b2 |<br>
+//  Â  Â  Â  Â  Â  Â  Â 1| <test 'if' condition> |<br>
+//  Â  Â  Â  Â  Â  Â  Â  +-----------------------+<br>
+//  Â  Â  Â  Â  Â  Â  Â  Â  Â ./  Â  Â  Â  Â  Â  Â  \.<br>
+//  Â +------  block 1 -------+  Â +------  block 2 -------+<br>
+//  2| LIFETIME_START b3  Â  Â |  5| LIFETIME_START b4, b5 |<br>
+//  3| <uses of b1, b3>  Â  Â  |  6| <uses of b2, b4, b5>  |<br>
+//  4| LIFETIME_END b3  Â  Â  Â |  7| LIFETIME_END b4, b5  Â |<br>
+//  Â +-----------------------+  Â +-----------------------+<br>
+//  Â  Â  Â  Â  Â  Â  Â  Â  Â \.  Â  Â  Â  Â  Â  Â  /.<br>
+//  Â  Â  Â  Â  Â  Â  Â  +------  block 3 -------+<br>
+//  Â  Â  Â  Â  Â  Â  Â 8| <cleanupcode>  Â  Â  Â  Â |<br>
+//  Â  Â  Â  Â  Â  Â  Â 9| LIFETIME_END b1, b2  Â |<br>
+//  Â  Â  Â  Â  Â  Â  10| return  Â  Â  Â  Â  Â  Â  Â  |<br>
+//  Â  Â  Â  Â  Â  Â  Â  +-----------------------+<br>
+//<br>
+// If we create live intervals for the variables above strictly based<br>
+// on the lifetime markers, we'll get the set of intervals on the<br>
+// left. If we ignore the lifetime start markers and instead treat a<br>
+// variable's lifetime as beginning with the first reference to the<br>
+// var, then we get the intervals on the right.<br>
+//<br>
+//  Â  Â  Â  Â  Â  LIFETIME_START  Â  Â  First Use<br>
+//  Â  Â b1:  Â  [0,9]  Â  Â  Â  Â  Â  Â  Â [3,4] [8,9]<br>
+//  Â  Â b2:  Â  [0,9]  Â  Â  Â  Â  Â  Â  Â [6,9]<br>
+//  Â  Â b3:  Â  [2,4]  Â  Â  Â  Â  Â  Â  Â [3,4]<br>
+//  Â  Â b4:  Â  [5,7]  Â  Â  Â  Â  Â  Â  Â [6,7]<br>
+//  Â  Â b5:  Â  [5,7]  Â  Â  Â  Â  Â  Â  Â [6,7]<br>
+//<br>
+// For the intervals on the left, the best we can do is overlap two<br>
+// variables (b3 and b4, for example); this gives us a stack size of<br>
+// 4*1024 bytes, not ideal. When treating first-use as the start of a<br>
+// lifetime, we can additionally overlap b1 and b5, giving us a 3*1024<br>
+// byte stack (better).<br>
+//<br>
+// Relying entirely on first-use of stack slots is problematic,<br>
+// however, due to the fact that optimizations can sometimes migrate<br>
+// uses of a variable outside of its lifetime start/end region. Here<br>
+// is an example:<br>
+//<br>
+//  Â  Â int bar() {<br>
+//  Â  Â  Â char b1[1024], b2[1024];<br>
+//  Â  Â  Â if (...) {<br>
+//  Â  Â  Â  Â <uses of b2><br>
+//  Â  Â  Â  Â return y;<br>
+//  Â  Â  Â } else {<br>
+//  Â  Â  Â  Â <uses of b1><br>
+//  Â  Â  Â  Â while (...) {<br>
+//  Â  Â  Â  Â  Â char b3[1024];<br>
+//  Â  Â  Â  Â  Â <uses of b3><br>
+//  Â  Â  Â  Â }<br>
+//  Â  Â  Â }<br>
+//  Â  Â }<br>
+//<br>
+// Before optimization, the control flow graph for the code above<br>
+// might look like the following:<br>
+//<br>
+//  Â  Â  Â  Â  Â  Â  Â  +------  block 0 -------+<br>
+//  Â  Â  Â  Â  Â  Â  Â 0| LIFETIME_START b1, b2 |<br>
+//  Â  Â  Â  Â  Â  Â  Â 1| <test 'if' condition> |<br>
+//  Â  Â  Â  Â  Â  Â  Â  +-----------------------+<br>
+//  Â  Â  Â  Â  Â  Â  Â  Â  Â ./  Â  Â  Â  Â  Â  Â  \.<br>
+//  Â +------  block 1 -------+  Â  +------- block 2 -------+<br>
+//  2| <uses of b2>  Â  Â  Â  Â  |  Â 3| <uses of b1>  Â  Â  Â  Â  |<br>
+//  Â +-----------------------+  Â  +-----------------------+<br>
+//  Â  Â  Â  Â  Â  Â  |  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  |<br>
+//  Â  Â  Â  Â  Â  Â  |  Â  Â  Â  Â  Â  Â  Â  Â +------- block 3 -------+ <-\.<br>
+//  Â  Â  Â  Â  Â  Â  |  Â  Â  Â  Â  Â  Â  Â  4| <while condition>  Â  Â |  Â  |<br>
+//  Â  Â  Â  Â  Â  Â  |  Â  Â  Â  Â  Â  Â  Â  Â +-----------------------+  Â  |<br>
+//  Â  Â  Â  Â  Â  Â  |  Â  Â  Â  Â  Â  Â  Â /  Â  Â  Â  Â  |  Â  Â  Â  Â  Â  Â  Â  Â  Â |<br>
+//  Â  Â  Â  Â  Â  Â  |  Â  Â  Â  Â  Â  Â  /  +------- block 4 -------+<br>
+//  Â  Â  Â  Â  Â  Â  \  Â  Â  Â  Â  Â  Â /  5| LIFETIME_START b3  Â  Â |  Â  |<br>
+//  Â  Â  Â  Â  Â  Â  Â \  Â  Â  Â  Â  Â /  Â 6| <uses of b3>  Â  Â  Â  Â  |  Â  |<br>
+//  Â  Â  Â  Â  Â  Â  Â  \  Â  Â  Â  Â /  Â  7| LIFETIME_END b3  Â  Â  Â |  Â  |<br>
+//  Â  Â  Â  Â  Â  Â  Â  Â \  Â  Â  Â  |  Â  +------------------------+  Â  |<br>
+//  Â  Â  Â  Â  Â  Â  Â  Â  \  Â  Â  Â |  Â  Â  Â  Â  Â  Â  Â  Â \  Â  Â  Â  Â  Â  Â  Â  /<br>
+//  Â  Â  Â  Â  Â  Â  Â  +------  block 5 -----+  Â  Â  \---------------<br>
+//  Â  Â  Â  Â  Â  Â  Â 8| <cleanupcode>  Â  Â  Â |<br>
+//  Â  Â  Â  Â  Â  Â  Â 9| LIFETIME_END b1, b2 |<br>
+//  Â  Â  Â  Â  Â  Â  10| return  Â  Â  Â  Â  Â  Â  |<br>
+//  Â  Â  Â  Â  Â  Â  Â  +---------------------+<br>
+//<br>
+// During optimization, however, it can happen that an instruction<br>
+// computing an address in "b3" (for example, a loop-invariant GEP) is<br>
+// hoisted up out of the loop from block 4 to block 2.  [Note that<br>
+// this is not an actual load from the stack, only an instruction that<br>
+// computes the address to be loaded]. If this happens, there is now a<br>
+// path leading from the first use of b3 to the return instruction<br>
+// that does not encounter the b3 LIFETIME_END, hence b3's lifetime is<br>
+// now larger than if we were computing live intervals strictly based<br>
+// on lifetime markers. In the example above, this lengthened lifetime<br>
+// would mean that it would appear illegal to overlap b3 with b2.<br>
+//<br>
+// To deal with this such cases, the code in ::collectMarkers() below<br>
+// tries to identify "degenerate" slots -- those slots where on a single<br>
+// forward pass through the CFG we encounter a first reference to slot<br>
+// K before we hit the slot K lifetime start marker. For such slots,<br>
+// we fall back on using the lifetime start marker as the beginning of<br>
+// the variable's lifetime.  NB: with this implementation, slots can<br>
+// appear degenerate in cases where there is unstructured control flow:<br>
+//<br>
+//  Â  if (q) goto mid;<br>
+//  Â  if (x > 9) {<br>
+//  Â  Â  Â  Â int b[100];<br>
+//  Â  Â  Â  Â memcpy(&b[0], ...);<br>
+//  Â  mid: b[k] = ...;<br>
+//  Â  Â  Â  Â abc(&b);<br>
+//  Â  }<br>
+//<br>
+// If in RPO ordering chosen to walk the CFG  we happen to visit the b[k]<br>
+// before visiting the memcpy block (which will contain the lifetime start<br>
+// for "b" then it will appear that 'b' has a degenerate lifetime.<br>
+//<br>
+<br>
 //===----------------------------------------------------------------------===//<br>
 //  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â StackColoring Pass<br>
 //===----------------------------------------------------------------------===//<br>
@@ -123,6 +285,17 @@ class StackColoring : public MachineFunc<br>
  Â /// once the coloring is done.<br>
  Â SmallVector<MachineInstr*, 8> Markers;<br>
<br>
+  /// Record the FI slots for which we have seen some sort of<br>
+  /// lifetime marker (either start or end).<br>
+  BitVector InterestingSlots;<br>
+<br>
+  /// Degenerate slots -- first use appears outside of start/end<br>
+  /// lifetime markers.<br>
+  BitVector DegenerateSlots;<br>
+<br>
+  /// Number of iterations taken during data flow analysis.<br>
+  unsigned NumIterations;<br>
+<br>
 public:<br>
  Â static char ID;<br>
  Â StackColoring() : MachineFunctionPass(ID) {<br>
@@ -153,6 +326,25 @@ private:<br>
  Â /// in and out blocks.<br>
  Â void calculateLocalLiveness();<br>
<br>
+  /// Returns TRUE if we're using the first-use-begins-lifetime method for<br>
+  /// this slot (if FALSE, then the start marker is treated as start of lifetime).<br>
+  bool applyFirstUse(int Slot) {<br>
+  Â  if (!LifetimeStartOnFirstUse || ProtectFromEscapedAllocas)<br>
+  Â  Â  return false;<br>
+  Â  if (DegenerateSlots.test(Slot))<br>
+  Â  Â  return false;<br>
+  Â  return true;<br>
+  }<br>
+<br>
+  /// Examines the specified instruction and returns TRUE if the instruction<br>
+  /// represents the start or end of an interesting lifetime. The slot or slots<br>
+  /// starting or ending are added to the vector "slots" and "isStart" is set<br>
+  /// accordingly.<br>
+  /// \returns True if inst contains a lifetime start or end<br>
+  bool isLifetimeStartOrEnd(const MachineInstr &MI,<br>
+  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  SmallVector<int, 4> &slots,<br>
+  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  bool &isStart);<br>
+<br>
  Â /// Construct the LiveIntervals for the slots.<br>
  Â void calculateLiveIntervals(unsigned NumSlots);<br>
<br>
@@ -170,7 +362,10 @@ private:<br>
<br>
  Â /// Map entries which point to other entries to their destination.<br>
  Â ///  Â A->B->C becomes A->C.<br>
-  Â void expungeSlotMap(DenseMap<int, int> &SlotRemap, unsigned NumSlots);<br>
+  void expungeSlotMap(DenseMap<int, int> &SlotRemap, unsigned NumSlots);<br>
+<br>
+  /// Used in collectMarkers<br>
+  typedef DenseMap<const MachineBasicBlock*, BitVector> BlockBitVecMap;<br>
 };<br>
 } // end anonymous namespace<br>
<br>
@@ -228,9 +423,140 @@ LLVM_DUMP_METHOD void StackColoring::dum<br>
<br>
 #endif // not NDEBUG<br>
<br>
-unsigned StackColoring::collectMarkers(unsigned NumSlot) {<br>
+static inline int getStartOrEndSlot(const MachineInstr &MI)<br>
+{<br>
+  assert((MI.getOpcode() == TargetOpcode::LIFETIME_START ||<br>
+  Â  Â  Â  Â  MI.getOpcode() == TargetOpcode::LIFETIME_END) &&<br>
+  Â  Â  Â  Â "Expected LIFETIME_START or LIFETIME_END op");<br>
+  const MachineOperand &MO = MI.getOperand(0);<br>
+  int Slot = MO.getIndex();<br>
+  if (Slot >= 0)<br>
+  Â  return Slot;<br>
+  return -1;<br>
+}<br>
+<br>
+//<br>
+// At the moment the only way to end a variable lifetime is with<br>
+// a VARIABLE_LIFETIME op (which can't contain a start). If things<br>
+// change and the IR allows for a single inst that both begins<br>
+// and ends lifetime(s), this interface will need to be reworked.<br>
+//<br>
+bool StackColoring::isLifetimeStartOrEnd(const MachineInstr &MI,<br>
+  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â SmallVector<int, 4> &slots,<br>
+  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â bool &isStart)<br>
+{<br>
+  if (MI.getOpcode() == TargetOpcode::LIFETIME_START ||<br>
+  Â  Â  MI.getOpcode() == TargetOpcode::LIFETIME_END) {<br>
+  Â  int Slot = getStartOrEndSlot(MI);<br>
+  Â  if (Slot < 0)<br>
+  Â  Â  return false;<br>
+  Â  if (!InterestingSlots.test(Slot))<br>
+  Â  Â  return false;<br>
+  Â  slots.push_back(Slot);<br>
+  Â  if (MI.getOpcode() == TargetOpcode::LIFETIME_END) {<br>
+  Â  Â  isStart = false;<br>
+  Â  Â  return true;<br>
+  Â  }<br>
+  Â  if (! applyFirstUse(Slot)) {<br>
+  Â  Â  isStart = true;<br>
+  Â  Â  return true;<br>
+  Â  }<br>
+  } else if (LifetimeStartOnFirstUse && !ProtectFromEscapedAllocas) {<br>
+  Â  if (! MI.isDebugValue()) {<br>
+  Â  Â  bool found = false;<br>
+  Â  Â  for (const MachineOperand &MO : MI.operands()) {<br>
+  Â  Â  Â  if (!MO.isFI())<br>
+  Â  Â  Â  Â  continue;<br>
+  Â  Â  Â  int Slot = MO.getIndex();<br>
+  Â  Â  Â  if (Slot<0)<br>
+  Â  Â  Â  Â  continue;<br>
+  Â  Â  Â  if (InterestingSlots.test(Slot) && applyFirstUse(Slot)) {<br>
+  Â  Â  Â  Â  slots.push_back(Slot);<br>
+  Â  Â  Â  Â  found = true;<br>
+  Â  Â  Â  }<br>
+  Â  Â  }<br>
+  Â  Â  if (found) {<br>
+  Â  Â  Â  isStart = true;<br>
+  Â  Â  Â  return true;<br>
+  Â  Â  }<br>
+  Â  }<br>
+  }<br>
+  return false;<br>
+}<br>
+<br>
+unsigned StackColoring::collectMarkers(unsigned NumSlot)<br>
+{<br>
  Â unsigned MarkersFound = 0;<br>
-  // Scan the function to find all lifetime markers.<br>
+  BlockBitVecMap SeenStartMap;<br>
+  InterestingSlots.clear();<br>
+  InterestingSlots.resize(NumSlot);<br>
+  DegenerateSlots.clear();<br>
+  DegenerateSlots.resize(NumSlot);<br>
+<br>
+  // Step 1: collect markers and populate the "InterestingSlots"<br>
+  // and "DegenerateSlots" sets.<br>
+  for (MachineBasicBlock *MBB : depth_first(MF)) {<br>
+<br>
+  Â  // Compute the set of slots for which we've seen a START marker but have<br>
+  Â  // not yet seen an END marker at this point in the walk (e.g. on entry<br>
+  Â  // to this bb).<br>
+  Â  BitVector BetweenStartEnd;<br>
+  Â  BetweenStartEnd.resize(NumSlot);<br>
+  Â  for (MachineBasicBlock::const_pred_iterator PI = MBB->pred_begin(),<br>
+  Â  Â  Â  Â  Â  Â PE = MBB->pred_end(); PI != PE; ++PI) {<br>
+  Â  Â  BlockBitVecMap::const_iterator I = SeenStartMap.find(*PI);<br>
+  Â  Â  if (I != SeenStartMap.end()) {<br>
+  Â  Â  Â  BetweenStartEnd |= I->second;<br>
+  Â  Â  }<br>
+  Â  }<br>
+<br>
+  Â  // Walk the instructions in the block to look for start/end ops.<br>
+  Â  for (MachineInstr &MI : *MBB) {<br>
+  Â  Â  if (MI.getOpcode() == TargetOpcode::LIFETIME_START ||<br>
+  Â  Â  Â  Â  MI.getOpcode() == TargetOpcode::LIFETIME_END) {<br>
+  Â  Â  Â  int Slot = getStartOrEndSlot(MI);<br>
+  Â  Â  Â  if (Slot < 0)<br>
+  Â  Â  Â  Â  continue;<br>
+  Â  Â  Â  InterestingSlots.set(Slot);<br>
+  Â  Â  Â  if (MI.getOpcode() == TargetOpcode::LIFETIME_START)<br>
+  Â  Â  Â  Â  BetweenStartEnd.set(Slot);<br>
+  Â  Â  Â  else<br>
+  Â  Â  Â  Â  BetweenStartEnd.reset(Slot);<br>
+  Â  Â  Â  const AllocaInst *Allocation = MFI->getObjectAllocation(Slot);<br>
+  Â  Â  Â  if (Allocation) {<br>
+  Â  Â  Â  Â  DEBUG(dbgs() << "Found a lifetime ");<br>
+  Â  Â  Â  Â  DEBUG(dbgs() << (MI.getOpcode() == TargetOpcode::LIFETIME_START<br>
+  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â ? "start"<br>
+  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â : "end"));<br>
+  Â  Â  Â  Â  DEBUG(dbgs() << " marker for slot #" << Slot);<br>
+  Â  Â  Â  Â  DEBUG(dbgs() << " with allocation: " << Allocation->getName()<br>
+  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â << "\n");<br>
+  Â  Â  Â  }<br>
+  Â  Â  Â  Markers.push_back(&MI);<br>
+  Â  Â  Â  MarkersFound += 1;<br>
+  Â  Â  } else {<br>
+  Â  Â  Â  for (const MachineOperand &MO : MI.operands()) {<br>
+  Â  Â  Â  Â  if (!MO.isFI())<br>
+  Â  Â  Â  Â  Â  continue;<br>
+  Â  Â  Â  Â  int Slot = MO.getIndex();<br>
+  Â  Â  Â  Â  if (Slot < 0)<br>
+  Â  Â  Â  Â  Â  continue;<br>
+  Â  Â  Â  Â  if (! BetweenStartEnd.test(Slot)) {<br>
+  Â  Â  Â  Â  Â  DegenerateSlots.set(Slot);<br>
+  Â  Â  Â  Â  }<br>
+  Â  Â  Â  }<br>
+  Â  Â  }<br>
+  Â  }<br>
+  Â  BitVector &SeenStart = SeenStartMap[MBB];<br>
+  Â  SeenStart |= BetweenStartEnd;<br>
+  }<br>
+  if (!MarkersFound) {<br>
+  Â  return 0;<br>
+  }<br>
+  DEBUG(dumpBV("Degenerate slots", DegenerateSlots));<br>
+<br>
+  // Step 2: compute begin/end sets for each block<br>
+<br>
  Â // NOTE: We use a reverse-post-order iteration to ensure that we obtain a<br>
  Â // deterministic numbering, and because we'll need a post-order iteration<br>
  Â // later for solving the liveness dataflow problem.<br>
@@ -246,37 +572,33 @@ unsigned StackColoring::collectMarkers(u<br>
  Â  Â BlockInfo.Begin.resize(NumSlot);<br>
  Â  Â BlockInfo.End.resize(NumSlot);<br>
<br>
+  Â  SmallVector<int, 4> slots;<br>
  Â  Â for (MachineInstr &MI : *MBB) {<br>
-  Â  Â  if (MI.getOpcode() != TargetOpcode::LIFETIME_START &&<br>
-  Â  Â  Â  Â  MI.getOpcode() != TargetOpcode::LIFETIME_END)<br>
-  Â  Â  Â  continue;<br>
-<br>
-  Â  Â  bool IsStart = MI.getOpcode() == TargetOpcode::LIFETIME_START;<br>
-  Â  Â  const MachineOperand &MO = MI.getOperand(0);<br>
-  Â  Â  int Slot = MO.getIndex();<br>
-  Â  Â  if (Slot < 0)<br>
-  Â  Â  Â  continue;<br>
-<br>
-  Â  Â  Markers.push_back(&MI);<br>
-<br>
-  Â  Â  MarkersFound++;<br>
-<br>
-  Â  Â  const AllocaInst *Allocation = MFI->getObjectAllocation(Slot);<br>
-  Â  Â  if (Allocation) {<br>
-  Â  Â  Â  DEBUG(dbgs()<<"Found a lifetime marker for slot #"<<Slot<<<br>
-  Â  Â  Â  Â  Â  Â  " with allocation: "<< Allocation->getName()<<"\n");<br>
-  Â  Â  }<br>
-<br>
-  Â  Â  if (IsStart) {<br>
-  Â  Â  Â  BlockInfo.Begin.set(Slot);<br>
-  Â  Â  } else {<br>
-  Â  Â  Â  if (BlockInfo.Begin.test(Slot)) {<br>
-  Â  Â  Â  Â  // Allocas that start and end within a single block are handled<br>
-  Â  Â  Â  Â  // specially when computing the LiveIntervals to avoid pessimizing<br>
-  Â  Â  Â  Â  // the liveness propagation.<br>
-  Â  Â  Â  Â  BlockInfo.Begin.reset(Slot);<br>
-  Â  Â  Â  } else {<br>
+  Â  Â  bool isStart = false;<br>
+  Â  Â  slots.clear();<br>
+  Â  Â  if (isLifetimeStartOrEnd(MI, slots, isStart)) {<br>
+  Â  Â  Â  if (!isStart) {<br>
+  Â  Â  Â  Â  assert(slots.size() == 1 && "unexpected: MI ends multiple slots");<br>
+  Â  Â  Â  Â  int Slot = slots[0];<br>
+  Â  Â  Â  Â  if (BlockInfo.Begin.test(Slot)) {<br>
+  Â  Â  Â  Â  Â  BlockInfo.Begin.reset(Slot);<br>
+  Â  Â  Â  Â  }<br>
  Â  Â  Â  Â  Â BlockInfo.End.set(Slot);<br>
+  Â  Â  Â  } else {<br>
+  Â  Â  Â  Â  for (auto Slot : slots) {<br>
+  Â  Â  Â  Â  Â  DEBUG(dbgs() << "Found a use of slot #" << Slot);<br>
+  Â  Â  Â  Â  Â  DEBUG(dbgs() << " at BB#" << MBB->getNumber() << " index ");<br>
+  Â  Â  Â  Â  Â  DEBUG(Indexes->getInstructionIndex(MI).print(dbgs()));<br>
+  Â  Â  Â  Â  Â  const AllocaInst *Allocation = MFI->getObjectAllocation(Slot);<br>
+  Â  Â  Â  Â  Â  if (Allocation) {<br>
+  Â  Â  Â  Â  Â  Â  DEBUG(dbgs() << " with allocation: "<< Allocation->getName());<br>
+  Â  Â  Â  Â  Â  }<br>
+  Â  Â  Â  Â  Â  DEBUG(dbgs() << "\n");<br>
+  Â  Â  Â  Â  Â  if (BlockInfo.End.test(Slot)) {<br>
+  Â  Â  Â  Â  Â  Â  BlockInfo.End.reset(Slot);<br>
+  Â  Â  Â  Â  Â  }<br>
+  Â  Â  Â  Â  Â  BlockInfo.Begin.set(Slot);<br>
+  Â  Â  Â  Â  }<br>
  Â  Â  Â  Â }<br>
  Â  Â  Â }<br>
  Â  Â }<br>
@@ -287,90 +609,56 @@ unsigned StackColoring::collectMarkers(u<br>
  Â return MarkersFound;<br>
 }<br>
<br>
-void StackColoring::calculateLocalLiveness() {<br>
-  // Perform a standard reverse dataflow computation to solve for<br>
-  // global liveness.  The BEGIN set here is equivalent to KILL in the standard<br>
-  // formulation, and END is equivalent to GEN.  The result of this computation<br>
-  // is a map from blocks to bitvectors where the bitvectors represent which<br>
-  // allocas are live in/out of that block.<br>
-  SmallPtrSet<const MachineBasicBlock*, 8> BBSet(BasicBlockNumbering.begin(),<br>
-  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â BasicBlockNumbering.end());<br>
-  unsigned NumSSMIters = 0;<br>
+void StackColoring::calculateLocalLiveness()<br>
+{<br>
+  unsigned NumIters = 0;<br>
  Â bool changed = true;<br>
  Â while (changed) {<br>
  Â  Â changed = false;<br>
-  Â  ++NumSSMIters;<br>
-<br>
-  Â  SmallPtrSet<const MachineBasicBlock*, 8> NextBBSet;<br>
+  Â  ++NumIters;<br>
<br>
  Â  Â for (const MachineBasicBlock *BB : BasicBlockNumbering) {<br>
-  Â  Â  if (!BBSet.count(BB)) continue;<br>
<br>
  Â  Â  Â // Use an iterator to avoid repeated lookups.<br>
  Â  Â  Â LivenessMap::iterator BI = BlockLiveness.find(BB);<br>
  Â  Â  Â assert(BI != BlockLiveness.end() && "Block not found");<br>
  Â  Â  Â BlockLifetimeInfo &BlockInfo = BI->second;<br>
<br>
+  Â  Â  // Compute LiveIn by unioning together the LiveOut sets of all preds.<br>
  Â  Â  Â BitVector LocalLiveIn;<br>
-  Â  Â  BitVector LocalLiveOut;<br>
-<br>
-  Â  Â  // Forward propagation from begins to ends.<br>
  Â  Â  Â for (MachineBasicBlock::const_pred_iterator PI = BB->pred_begin(),<br>
  Â  Â  Â  Â  Â  PE = BB->pred_end(); PI != PE; ++PI) {<br>
  Â  Â  Â  Â LivenessMap::const_iterator I = BlockLiveness.find(*PI);<br>
  Â  Â  Â  Â assert(I != BlockLiveness.end() && "Predecessor not found");<br>
  Â  Â  Â  Â LocalLiveIn |= I->second.LiveOut;<br>
  Â  Â  Â }<br>
-  Â  Â  LocalLiveIn |= BlockInfo.End;<br>
-  Â  Â  LocalLiveIn.reset(BlockInfo.Begin);<br>
-<br>
-  Â  Â  // Reverse propagation from ends to begins.<br>
-  Â  Â  for (MachineBasicBlock::const_succ_iterator SI = BB->succ_begin(),<br>
-  Â  Â  Â  Â  Â SE = BB->succ_end(); SI != SE; ++SI) {<br>
-  Â  Â  Â  LivenessMap::const_iterator I = BlockLiveness.find(*SI);<br>
-  Â  Â  Â  assert(I != BlockLiveness.end() && "Successor not found");<br>
-  Â  Â  Â  LocalLiveOut |= I->second.LiveIn;<br>
-  Â  Â  }<br>
-  Â  Â  LocalLiveOut |= BlockInfo.Begin;<br>
-  Â  Â  LocalLiveOut.reset(BlockInfo.End);<br>
-<br>
-  Â  Â  LocalLiveIn |= LocalLiveOut;<br>
-  Â  Â  LocalLiveOut |= LocalLiveIn;<br>
<br>
-  Â  Â  // After adopting the live bits, we need to turn-off the bits which<br>
-  Â  Â  // are de-activated in this block.<br>
+  Â  Â  // Compute LiveOut by subtracting out lifetimes that end in this<br>
+  Â  Â  // block, then adding in lifetimes that begin in this block.  If<br>
+  Â  Â  // we have both BEGIN and END markers in the same basic block<br>
+  Â  Â  // then we know that the BEGIN marker comes after the END,<br>
+  Â  Â  // because we already handle the case where the BEGIN comes<br>
+  Â  Â  // before the END when collecting the markers (and building the<br>
+  Â  Â  // BEGIN/END vectors).<br>
+  Â  Â  BitVector LocalLiveOut = LocalLiveIn;<br>
  Â  Â  Â LocalLiveOut.reset(BlockInfo.End);<br>
-  Â  Â  LocalLiveIn.reset(BlockInfo.Begin);<br>
-<br>
-  Â  Â  // If we have both BEGIN and END markers in the same basic block then<br>
-  Â  Â  // we know that the BEGIN marker comes after the END, because we already<br>
-  Â  Â  // handle the case where the BEGIN comes before the END when collecting<br>
-  Â  Â  // the markers (and building the BEGIN/END vectore).<br>
-  Â  Â  // Want to enable the LIVE_IN and LIVE_OUT of slots that have both<br>
-  Â  Â  // BEGIN and END because it means that the value lives before and after<br>
-  Â  Â  // this basic block.<br>
-  Â  Â  BitVector LocalEndBegin = BlockInfo.End;<br>
-  Â  Â  LocalEndBegin &= BlockInfo.Begin;<br>
-  Â  Â  LocalLiveIn |= LocalEndBegin;<br>
-  Â  Â  LocalLiveOut |= LocalEndBegin;<br>
+  Â  Â  LocalLiveOut |= BlockInfo.Begin;<br>
<br>
+  Â  Â  // Update block LiveIn set, noting whether it has changed.<br>
  Â  Â  Â if (LocalLiveIn.test(BlockInfo.LiveIn)) {<br>
  Â  Â  Â  Â changed = true;<br>
  Â  Â  Â  Â BlockInfo.LiveIn |= LocalLiveIn;<br>
-<br>
-  Â  Â  Â  NextBBSet.insert(BB->pred_begin(), BB->pred_end());<br>
  Â  Â  Â }<br>
<br>
+  Â  Â  // Update block LiveOut set, noting whether it has changed.<br>
  Â  Â  Â if (LocalLiveOut.test(BlockInfo.LiveOut)) {<br>
  Â  Â  Â  Â changed = true;<br>
  Â  Â  Â  Â BlockInfo.LiveOut |= LocalLiveOut;<br>
-<br>
-  Â  Â  Â  NextBBSet.insert(BB->succ_begin(), BB->succ_end());<br>
  Â  Â  Â }<br>
  Â  Â }<br>
-<br>
-  Â  BBSet = std::move(NextBBSet);<br>
  Â }// while changed.<br>
+<br>
+  NumIterations = NumIters;<br>
 }<br>
<br>
 void StackColoring::calculateLiveIntervals(unsigned NumSlots) {<br>
@@ -385,29 +673,22 @@ void StackColoring::calculateLiveInterva<br>
  Â  Â Finishes.clear();<br>
  Â  Â Finishes.resize(NumSlots);<br>
<br>
-  Â  // Create the interval for the basic blocks with lifetime markers in them.<br>
-  Â  for (const MachineInstr *MI : Markers) {<br>
-  Â  Â  if (MI->getParent() != &MBB)<br>
-  Â  Â  Â  continue;<br>
+  Â  // Create the interval for the basic blocks containing lifetime begin/end.<br>
+  Â  for (const MachineInstr &MI : MBB) {<br>
<br>
-  Â  Â  assert((MI->getOpcode() == TargetOpcode::LIFETIME_START ||<br>
-  Â  Â  Â  Â  Â  Â  MI->getOpcode() == TargetOpcode::LIFETIME_END) &&<br>
-  Â  Â  Â  Â  Â  Â "Invalid Lifetime marker");<br>
-<br>
-  Â  Â  bool IsStart = MI->getOpcode() == TargetOpcode::LIFETIME_START;<br>
-  Â  Â  const MachineOperand &Mo = MI->getOperand(0);<br>
-  Â  Â  int Slot = Mo.getIndex();<br>
-  Â  Â  if (Slot < 0)<br>
+  Â  Â  SmallVector<int, 4> slots;<br>
+  Â  Â  bool IsStart = false;<br>
+  Â  Â  if (!isLifetimeStartOrEnd(MI, slots, IsStart))<br>
  Â  Â  Â  Â continue;<br>
-<br>
-  Â  Â  SlotIndex ThisIndex = Indexes->getInstructionIndex(*MI);<br>
-<br>
-  Â  Â  if (IsStart) {<br>
-  Â  Â  Â  if (!Starts[Slot].isValid() || Starts[Slot] > ThisIndex)<br>
-  Â  Â  Â  Â  Starts[Slot] = ThisIndex;<br>
-  Â  Â  } else {<br>
-  Â  Â  Â  if (!Finishes[Slot].isValid() || Finishes[Slot] < ThisIndex)<br>
-  Â  Â  Â  Â  Finishes[Slot] = ThisIndex;<br>
+  Â  Â  SlotIndex ThisIndex = Indexes->getInstructionIndex(MI);<br>
+  Â  Â  for (auto Slot : slots) {<br>
+  Â  Â  Â  if (IsStart) {<br>
+  Â  Â  Â  Â  if (!Starts[Slot].isValid() || Starts[Slot] > ThisIndex)<br>
+  Â  Â  Â  Â  Â  Starts[Slot] = ThisIndex;<br>
+  Â  Â  Â  } else {<br>
+  Â  Â  Â  Â  if (!Finishes[Slot].isValid() || Finishes[Slot] < ThisIndex)<br>
+  Â  Â  Â  Â  Â  Finishes[Slot] = ThisIndex;<br>
+  Â  Â  Â  }<br>
  Â  Â  Â }<br>
  Â  Â }<br>
<br>
@@ -423,7 +704,29 @@ void StackColoring::calculateLiveInterva<br>
  Â  Â }<br>
<br>
  Â  Â for (unsigned i = 0; i < NumSlots; ++i) {<br>
-  Â  Â  assert(Starts[i].isValid() == Finishes[i].isValid() && "Unmatched range");<br>
+  Â  Â  //<br>
+  Â  Â  // When LifetimeStartOnFirstUse is turned on, data flow analysis<br>
+  Â  Â  // is forward (from starts to ends), not bidirectional. A<br>
+  Â  Â  // consequence of this is that we can wind up in situations<br>
+  Â  Â  // where Starts[i] is invalid but Finishes[i] is valid and vice<br>
+  Â  Â  // versa. Example:<br>
+  Â  Â  //<br>
+  Â  Â  //  Â  Â LIFETIME_START x<br>
+  Â  Â  //  Â  Â if (...) {<br>
+  Â  Â  //  Â  Â  Â <use of x><br>
+  Â  Â  //  Â  Â  Â throw ...;<br>
+  Â  Â  //  Â  Â }<br>
+  Â  Â  //  Â  Â LIFETIME_END x<br>
+  Â  Â  //  Â  Â return 2;<br>
+  Â  Â  //<br>
+  Â  Â  //<br>
+  Â  Â  // Here the slot for "x" will not be live into the block<br>
+  Â  Â  // containing the "return 2" (since lifetimes start with first<br>
+  Â  Â  // use, not at the dominating LIFETIME_START marker).<br>
+  Â  Â  //<br>
+  Â  Â  if (Starts[i].isValid() && !Finishes[i].isValid()) {<br>
+  Â  Â  Â  Finishes[i] = Indexes->getMBBEndIdx(&MBB);<br>
+  Â  Â  }<br>
  Â  Â  Â if (!Starts[i].isValid())<br>
  Â  Â  Â  Â continue;<br>
<br>
@@ -684,7 +987,6 @@ bool StackColoring::runOnMachineFunction<br>
  Â  Â return false;<br>
<br>
  Â SmallVector<int, 8> SortedSlots;<br>
-<br>
  Â SortedSlots.reserve(NumSlots);<br>
  Â Intervals.reserve(NumSlots);<br>
<br>
@@ -717,9 +1019,12 @@ bool StackColoring::runOnMachineFunction<br>
<br>
  Â // Calculate the liveness of each block.<br>
  Â calculateLocalLiveness();<br>
+  DEBUG(dbgs() << "Dataflow iterations: " << NumIterations << "\n");<br>
+  DEBUG(dump());<br>
<br>
  Â // Propagate the liveness information.<br>
  Â calculateLiveIntervals(NumSlots);<br>
+  DEBUG(dumpIntervals());<br>
<br>
  Â // Search for allocas which are used outside of the declared lifetime<br>
  Â // markers.<br>
<br>
Modified: llvm/trunk/test/CodeGen/X86/StackColoring.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/StackColoring.ll?rev=270559&r1=270558&r2=270559&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/StackColoring.ll?rev=270559&r1=270558&r2=270559&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/CodeGen/X86/StackColoring.ll (original)<br>
+++ llvm/trunk/test/CodeGen/X86/StackColoring.ll Tue May 24 08:23:44 2016<br>
@@ -87,7 +87,7 @@ bb3:<br>
 }<br>
<br>
 ;CHECK-LABEL: myCall_w4:<br>
-;YESCOLOR: subq  $200, %rsp<br>
+;YESCOLOR: subq  $120, %rsp<br>
 ;NOCOLOR: subq  $408, %rsp<br>
<br>
 define i32 @myCall_w4(i32 %in) {<br>
@@ -217,7 +217,7 @@ bb3:<br>
<br>
<br>
 ;CHECK-LABEL: myCall2_nostart:<br>
-;YESCOLOR: subq  $144, %rsp<br>
+;YESCOLOR: subq  $272, %rsp<br>
 ;NOCOLOR: subq  $272, %rsp<br>
 define i32 @myCall2_nostart(i32 %in, i1 %d) {<br>
 entry:<br>
@@ -425,6 +425,120 @@ define i32 @shady_range(i32 %argc, i8**<br>
  Â ret i32 9<br>
 }<br>
<br>
+; In this case 'itar1' and 'itar2' can't be overlapped if we treat<br>
+; lifetime.start as the beginning of the lifetime, but we can<br>
+; overlap if we consider first use of the slot as lifetime<br>
+; start. See llvm bug 25776.<br>
+<br>
+;CHECK-LABEL: ifthen_twoslots:<br>
+;YESCOLOR: subq  $536, %rsp<br>
+;NOCOLOR: subq  $1048, %rsp<br>
+<br>
+define i32 @ifthen_twoslots(i32 %x) #0 {<br>
+entry:<br>
+  %retval = alloca i32, align 4<br>
+  %x.addr = alloca i32, align 4<br>
+  %itar1 = alloca [128 x i32], align 16<br>
+  %itar2 = alloca [128 x i32], align 16<br>
+  %cleanup.dest.slot = alloca i32<br>
+  store i32 %x, i32* %x.addr, align 4<br>
+  %itar1_start_8 = bitcast [128 x i32]* %itar1 to i8*<br>
+  call void @llvm.lifetime.start(i64 512, i8* %itar1_start_8) #3<br>
+  %itar2_start_8 = bitcast [128 x i32]* %itar2 to i8*<br>
+  call void @llvm.lifetime.start(i64 512, i8* %itar2_start_8) #3<br>
+  %xval = load i32, i32* %x.addr, align 4<br>
+  %and = and i32 %xval, 1<br>
+  %tobool = icmp ne i32 %and, 0<br>
+  br i1 %tobool, label %if.then, label %if.else<br>
+<br>
+if.then:  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  ; preds = %entry<br>
+  %arraydecay = getelementptr inbounds [128 x i32], [128 x i32]* %itar1, i32 0, i32 0<br>
+  call void @inita(i32* %arraydecay)<br>
+  store i32 1, i32* %retval, align 4<br>
+  store i32 1, i32* %cleanup.dest.slot, align 4<br>
+  %itar2_end_8 = bitcast [128 x i32]* %itar2 to i8*<br>
+  call void @llvm.lifetime.end(i64 512, i8* %itar2_end_8) #3<br>
+  %itar1_end_8 = bitcast [128 x i32]* %itar1 to i8*<br>
+  call void @llvm.lifetime.end(i64 512, i8* %itar1_end_8) #3<br>
+  br label %cleanup<br>
+<br>
+if.else:  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  ; preds = %entry<br>
+  %arraydecay1 = getelementptr inbounds [128 x i32], [128 x i32]* %itar2, i32 0, i32 0<br>
+  call void @inita(i32* %arraydecay1)<br>
+  store i32 0, i32* %retval, align 4<br>
+  store i32 1, i32* %cleanup.dest.slot, align 4<br>
+  %itar2_end2_8 = bitcast [128 x i32]* %itar2 to i8*<br>
+  call void @llvm.lifetime.end(i64 512, i8* %itar2_end2_8) #3<br>
+  %itar1_end2_8 = bitcast [128 x i32]* %itar1 to i8*<br>
+  call void @llvm.lifetime.end(i64 512, i8* %itar1_end2_8) #3<br>
+  br label %cleanup<br>
+<br>
+cleanup:  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  ; preds = %if.else, %if.then<br>
+  %final_retval = load i32,<br>
+ i32* %retval, align 4<br>
+  ret i32 %final_retval<br>
+}<br>
+<br>
+; This function is intended to test the case where you<br>
+; have a reference to a stack slot that lies outside of<br>
+; the START/END lifetime markers-- the flow analysis<br>
+; should catch this and build the lifetime based on the<br>
+; markers only.<br>
+<br>
+;CHECK-LABEL: while_loop:<br>
+;YESCOLOR: subq  $1032, %rsp<br>
+;NOCOLOR: subq  $1544, %rsp<br>
+<br>
+define i32 @while_loop(i32 %x) #0 {<br>
+entry:<br>
+  %b1 = alloca [128 x i32], align 16<br>
+  %b2 = alloca [128 x i32], align 16<br>
+  %b3 = alloca [128 x i32], align 16<br>
+  %tmp = bitcast [128 x i32]* %b1 to i8*<br>
+  call void @llvm.lifetime.start(i64 512, i8* %tmp) #3<br>
+  %tmp1 = bitcast [128 x i32]* %b2 to i8*<br>
+  call void @llvm.lifetime.start(i64 512, i8* %tmp1) #3<br>
+  %and = and i32 %x, 1<br>
+  %tobool = icmp eq i32 %and, 0<br>
+  br i1 %tobool, label %if.else, label %if.then<br>
+<br>
+if.then:  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  ; preds = %entry<br>
+  %arraydecay = getelementptr inbounds [128 x i32], [128 x i32]* %b2, i64 0, i64 0<br>
+  call void @inita(i32* %arraydecay) #3<br>
+  br label %if.end<br>
+<br>
+if.else:  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  ; preds = %entry<br>
+  %arraydecay1 = getelementptr inbounds [128 x i32], [128 x i32]* %b1, i64 0, i64 0<br>
+  call void @inita(i32* %arraydecay1) #3<br>
+  %arraydecay3 = getelementptr inbounds [128 x i32], [128 x i32]* %b3, i64 0, i64 0<br>
+  call void @inita(i32* %arraydecay3) #3<br>
+  %tobool25 = icmp eq i32 %x, 0<br>
+  br i1 %tobool25, label %if.end, label %<a href="http://while.body.lr.ph" rel="noreferrer" target="_blank">while.body.lr.ph</a><br>
+<br>
+<a href="http://while.body.lr.ph" rel="noreferrer" target="_blank">while.body.lr.ph</a>:  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â ; preds = %if.else<br>
+  %tmp2 = bitcast [128 x i32]* %b3 to i8*<br>
+  br label %while.body<br>
+<br>
+while.body:  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â ; preds = %<a href="http://while.body.lr.ph" rel="noreferrer" target="_blank">while.body.lr.ph</a>, %while.body<br>
+  %x.addr.06 = phi i32 [ %x, %<a href="http://while.body.lr.ph" rel="noreferrer" target="_blank">while.body.lr.ph</a> ], [ %dec, %while.body ]<br>
+  %dec = add nsw i32 %x.addr.06, -1<br>
+  call void @llvm.lifetime.start(i64 512, i8* %tmp2) #3<br>
+  call void @inita(i32* %arraydecay3) #3<br>
+  call void @llvm.lifetime.end(i64 512, i8* %tmp2) #3<br>
+  %tobool2 = icmp eq i32 %dec, 0<br>
+  br i1 %tobool2, label %if.end.loopexit, label %while.body<br>
+<br>
+if.end.loopexit:  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  ; preds = %while.body<br>
+  br label %if.end<br>
+<br>
+if.end:  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â ; preds = %if.end.loopexit, %if.else, %if.then<br>
+  call void @llvm.lifetime.end(i64 512, i8* %tmp1) #3<br>
+  call void @llvm.lifetime.end(i64 512, i8* %tmp) #3<br>
+  ret i32 0<br>
+}<br>
+<br>
+declare void @inita(i32*) #2<br>
+<br>
 declare void @bar([100 x i32]* , [100 x i32]*) nounwind<br>
<br>
 declare void @llvm.lifetime.start(i64, i8* nocapture) nounwind<br>
<br>
Modified: llvm/trunk/test/CodeGen/X86/misched-aa-colored.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/misched-aa-colored.ll?rev=270559&r1=270558&r2=270559&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/misched-aa-colored.ll?rev=270559&r1=270558&r2=270559&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/CodeGen/X86/misched-aa-colored.ll (original)<br>
+++ llvm/trunk/test/CodeGen/X86/misched-aa-colored.ll Tue May 24 08:23:44 2016<br>
@@ -155,6 +155,7 @@ entry:<br>
  Â %ref.tmp.i = alloca %"struct.std::pair.112.119.719.1079.2039.2159.2399.4199", align 8<br>
  Â %Op.i = alloca %"class.llvm::SDValue.3.603.963.1923.2043.2283.4083", align 8<br>
  Â %0 = bitcast %"struct.std::pair.112.119.719.1079.2039.2159.2399.4199"* %ref.tmp.i to i8*<br>
+  call void @llvm.lifetime.start(i64 24, i8* %0) #1<br>
  Â %retval.sroa.0.0.idx.i36 = getelementptr inbounds %"struct.std::pair.112.119.719.1079.2039.2159.2399.4199", %"struct.std::pair.112.119.719.1079.2039.2159.2399.4199"* %ref.tmp.i, i64 0, i32 1, i32 0, i32 0<br>
  Â %retval.sroa.0.0.copyload.i37 = load i32, i32* %retval.sroa.0.0.idx.i36, align 8<br>
  Â call void @llvm.lifetime.end(i64 24, i8* %0) #1<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br>
</blockquote></div><br><br clear="all"><div><br></div></div></div><span><font color="#888888">-- <br><div><span style="font-family:Times;font-size:medium"><table cellspacing="0" cellpadding="0"><tbody><tr style="color:rgb(85,85,85);font-family:sans-serif;font-size:small"><td nowrap style="border-top-style:solid;border-top-color:rgb(213,15,37);border-top-width:2px">Teresa Johnson |</td><td nowrap style="border-top-style:solid;border-top-color:rgb(51,105,232);border-top-width:2px"> Software Engineer |</td><td nowrap style="border-top-style:solid;border-top-color:rgb(0,153,57);border-top-width:2px"> <a href="mailto:tejohnson@google.com" target="_blank">tejohnson@google.com</a> |</td><td nowrap style="border-top-style:solid;border-top-color:rgb(238,178,17);border-top-width:2px"> <a href="tel:408-460-2413" value="+14084602413" target="_blank">408-460-2413</a></td></tr></tbody></table></span></div>
</font></span></div></div>
</blockquote></div><br></div>
</div></div></blockquote></div></div></div><div><div><br><br clear="all"><div><br></div>-- <br><div><span style="font-family:Times;font-size:medium"><table cellspacing="0" cellpadding="0"><tbody><tr style="color:rgb(85,85,85);font-family:sans-serif;font-size:small"><td nowrap style="border-top-style:solid;border-top-color:rgb(213,15,37);border-top-width:2px">Teresa Johnson |</td><td nowrap style="border-top-style:solid;border-top-color:rgb(51,105,232);border-top-width:2px"> Software Engineer |</td><td nowrap style="border-top-style:solid;border-top-color:rgb(0,153,57);border-top-width:2px"> <a href="mailto:tejohnson@google.com" target="_blank">tejohnson@google.com</a> |</td><td nowrap style="border-top-style:solid;border-top-color:rgb(238,178,17);border-top-width:2px"> <a href="tel:408-460-2413" value="+14084602413" target="_blank">408-460-2413</a></td></tr></tbody></table></span></div>
</div></div></div></div>
</blockquote></div><br><br clear="all"><div><br></div>-- <br><div><span style="font-family:Times;font-size:medium"><table cellspacing="0" cellpadding="0"><tbody><tr style="color:rgb(85,85,85);font-family:sans-serif;font-size:small"><td nowrap style="border-top-style:solid;border-top-color:rgb(213,15,37);border-top-width:2px">Teresa Johnson |</td><td nowrap style="border-top-style:solid;border-top-color:rgb(51,105,232);border-top-width:2px"> Software Engineer |</td><td nowrap style="border-top-style:solid;border-top-color:rgb(0,153,57);border-top-width:2px"> <a href="mailto:tejohnson@google.com" target="_blank">tejohnson@google.com</a> |</td><td nowrap style="border-top-style:solid;border-top-color:rgb(238,178,17);border-top-width:2px"> <a href="tel:408-460-2413" value="+14084602413" target="_blank">408-460-2413</a></td></tr></tbody></table></span></div>
</div>
</div></div></blockquote></div><br><br clear="all"><div><br></div>-- <br><div><span style="font-family:Times;font-size:medium"><table cellspacing="0" cellpadding="0"><tbody><tr style="color:rgb(85,85,85);font-family:sans-serif;font-size:small"><td nowrap style="border-top-style:solid;border-top-color:rgb(213,15,37);border-top-width:2px">Teresa Johnson |</td><td nowrap style="border-top-style:solid;border-top-color:rgb(51,105,232);border-top-width:2px"> Software Engineer |</td><td nowrap style="border-top-style:solid;border-top-color:rgb(0,153,57);border-top-width:2px"> <a href="mailto:tejohnson@google.com" target="_blank">tejohnson@google.com</a> |</td><td nowrap style="border-top-style:solid;border-top-color:rgb(238,178,17);border-top-width:2px"> <a href="tel:408-460-2413" value="+14084602413" target="_blank">408-460-2413</a></td></tr></tbody></table></span></div>
</div>
</div></div></blockquote></div><br></div>