[PATCH] D25243: [Statepoints] Reuse stack slots more than once within a basic block

Philip Reames via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Mon Dec 12 17:31:35 PST 2016


This revision was automatically updated to reflect the committed changes.
Closed by commit rL289509: [Statepoints] Reuse stack slots more than once within a basic block (authored by reames).

Changed prior to commit:
  https://reviews.llvm.org/D25243?vs=73498&id=81166#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D25243

Files:
  llvm/trunk/lib/CodeGen/SelectionDAG/StatepointLowering.cpp
  llvm/trunk/test/CodeGen/X86/statepoint-stack-usage.ll


Index: llvm/trunk/lib/CodeGen/SelectionDAG/StatepointLowering.cpp
===================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/StatepointLowering.cpp
+++ llvm/trunk/lib/CodeGen/SelectionDAG/StatepointLowering.cpp
@@ -55,7 +55,8 @@
   NextSlotToAllocate = 0;
   // Need to resize this on each safepoint - we need the two to stay in sync and
   // the clear patterns of a SelectionDAGBuilder have no relation to
-  // FunctionLoweringInfo.  SmallBitVector::reset initializes all bits to false.
+  // FunctionLoweringInfo.  Also need to ensure used bits get cleared.
+  AllocatedStackSlots.clear();
   AllocatedStackSlots.resize(Builder.FuncInfo.StatepointStackSlots.size());
 }
 
@@ -82,16 +83,16 @@
   const size_t NumSlots = AllocatedStackSlots.size();
   assert(NextSlotToAllocate <= NumSlots && "Broken invariant");
 
-  // The stack slots in StatepointStackSlots beyond the first NumSlots were
-  // added in this instance of StatepointLoweringState, and cannot be re-used.
-  assert(NumSlots <= Builder.FuncInfo.StatepointStackSlots.size() &&
+  assert(AllocatedStackSlots.size() ==
+         Builder.FuncInfo.StatepointStackSlots.size() &&
          "Broken invariant");
 
   for (; NextSlotToAllocate < NumSlots; NextSlotToAllocate++) {
     if (!AllocatedStackSlots.test(NextSlotToAllocate)) {
       const int FI = Builder.FuncInfo.StatepointStackSlots[NextSlotToAllocate];
       if (MFI.getObjectSize(FI) == SpillSize) {
         AllocatedStackSlots.set(NextSlotToAllocate);
+        // TODO: Is ValueType the right thing to use here?
         return Builder.DAG.getFrameIndex(FI, ValueType);
       }
     }
@@ -104,6 +105,10 @@
   MFI.markAsStatepointSpillSlotObjectIndex(FI);
 
   Builder.FuncInfo.StatepointStackSlots.push_back(FI);
+  AllocatedStackSlots.resize(AllocatedStackSlots.size()+1, true);
+  assert(AllocatedStackSlots.size() ==
+         Builder.FuncInfo.StatepointStackSlots.size() &&
+         "Broken invariant");
 
   StatepointMaxSlotsRequired = std::max<unsigned long>(
       StatepointMaxSlotsRequired, Builder.FuncInfo.StatepointStackSlots.size());
Index: llvm/trunk/test/CodeGen/X86/statepoint-stack-usage.ll
===================================================================
--- llvm/trunk/test/CodeGen/X86/statepoint-stack-usage.ll
+++ llvm/trunk/test/CodeGen/X86/statepoint-stack-usage.ll
@@ -54,6 +54,36 @@
   ret i32 1
 }
 
+; Check that we reuse the same stack slot across multiple calls.  The use of
+; more than two calls here is critical.  We've had a bug which allowed reuse
+; exactly once which went undetected for a long time.
+define i32 @back_to_back_deopt(i32 %a, i32 %b, i32 %c) #1 
+  gc "statepoint-example" {
+; CHECK-LABEL: back_to_back_deopt
+; The exact stores don't matter, but there need to be three stack slots created
+; CHECK: movl	%ebx, 12(%rsp)
+; CHECK: movl	%ebp, 8(%rsp)
+; CHECK: movl	%r14d, 4(%rsp)
+; CHECK: callq
+; CHECK: movl	%ebx, 12(%rsp)
+; CHECK: movl	%ebp, 8(%rsp)
+; CHECK: movl	%r14d, 4(%rsp)
+; CHECK: callq
+; CHECK: movl	%ebx, 12(%rsp)
+; CHECK: movl	%ebp, 8(%rsp)
+; CHECK: movl	%r14d, 4(%rsp)
+; CHECK: callq
+; CHECK: movl	%ebx, 12(%rsp)
+; CHECK: movl	%ebp, 8(%rsp)
+; CHECK: movl	%r14d, 4(%rsp)
+; CHECK: callq
+  call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* undef, i32 0, i32 0, i32 0, i32 3, i32 %a, i32 %b, i32 %c)
+call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* undef, i32 0, i32 0, i32 0, i32 3, i32 %a, i32 %b, i32 %c)
+call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* undef, i32 0, i32 0, i32 0, i32 3, i32 %a, i32 %b, i32 %c)
+call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* undef, i32 0, i32 0, i32 0, i32 3, i32 %a, i32 %b, i32 %c)
+  ret i32 1
+}
+
 ; Test that stack slots are reused for invokes
 define i32 @back_to_back_invokes(i32 addrspace(1)* %a, i32 addrspace(1)* %b, i32 addrspace(1)* %c) #1 gc "statepoint-example" personality i32 ()* @"personality_function" {
 ; CHECK-LABEL: back_to_back_invokes


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D25243.81166.patch
Type: text/x-patch
Size: 4227 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20161213/2f0b5278/attachment.bin>


More information about the llvm-commits mailing list