Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[StackColoring] Delete dead stack slots #72633

Merged
merged 6 commits into from
Dec 13, 2023
Merged

Conversation

mohammed-nurulhoque
Copy link
Contributor

deletes slots that have lifetime markers and the lifetime ranges are empty.

Copy link

github-actions bot commented Nov 17, 2023

✅ With the latest revision this PR passed the C/C++ code formatter.

@ShivaChen ShivaChen requested review from rnk and nikic November 17, 2023 10:19
deletes slots that have lifetime markers and the lifetime ranges are empty.
@nikic nikic changed the title delete dead stack slots (#104) [StackColoring] Delete dead stack slots Nov 17, 2023
Copy link
Contributor

@nikic nikic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks right to me, but I'm not very familiar with this pass.

llvm/test/CodeGen/RISCV/dead-stack-slot.ll Outdated Show resolved Hide resolved
@nikic
Copy link
Contributor

nikic commented Nov 17, 2023

There is an assertion failure in llvm/test/DebugInfo/COFF/lexicalblock.ll:

MachineFrameInfo.h:530: int64_t llvm::MachineFrameInfo::getObjectOffset(int) const: Assertion `!isDeadObjectIndex(ObjectIdx) && "Getting frame offset for a dead object?"' failed.

@llvmbot
Copy link
Collaborator

llvmbot commented Nov 27, 2023

@llvm/pr-subscribers-debuginfo

Author: None (mohammed-nurulhoque)

Changes

deletes slots that have lifetime markers and the lifetime ranges are empty.


Full diff: https://github.com/llvm/llvm-project/pull/72633.diff

5 Files Affected:

  • (modified) llvm/lib/CodeGen/StackColoring.cpp (+28-4)
  • (modified) llvm/test/CodeGen/PowerPC/aix32-cc-abi-vaarg.ll (-1)
  • (modified) llvm/test/CodeGen/PowerPC/aix64-cc-abi-vaarg.ll (+2-6)
  • (added) llvm/test/CodeGen/RISCV/dead-stack-slot.ll (+32)
  • (modified) llvm/test/DebugInfo/COFF/lexicalblock.ll (+2-22)
diff --git a/llvm/lib/CodeGen/StackColoring.cpp b/llvm/lib/CodeGen/StackColoring.cpp
index 3d261688fa8c817..9d23ddc342739e4 100644
--- a/llvm/lib/CodeGen/StackColoring.cpp
+++ b/llvm/lib/CodeGen/StackColoring.cpp
@@ -899,17 +899,34 @@ void StackColoring::remapInstructions(DenseMap<int, int> &SlotRemap) {
   unsigned FixedMemOp = 0;
   unsigned FixedDbg = 0;
 
-  // Remap debug information that refers to stack slots.
-  for (auto &VI : MF->getVariableDbgInfo()) {
-    if (!VI.Var || !VI.inStackSlot())
+  // Remap debug information that refers to stack slots and delete info for
+  // deleted slots.
+  auto &DbgInfo = MF->getVariableDbgInfo();
+  for (auto it = DbgInfo.begin(); it != DbgInfo.end();) {
+    auto &VI = *it;
+    if (!VI.Var || !VI.inStackSlot()) {
+      it++;
       continue;
+    }
     int Slot = VI.getStackSlot();
+
+    // slot was removed
+    if (Slot >= 0 && Intervals[Slot]->empty() &&
+        InterestingSlots.test(Slot) && !ConservativeSlots.test(Slot)) {
+      LLVM_DEBUG(dbgs() << "Removing debug info for ["
+                        << cast<DILocalVariable>(VI.Var)->getName() << "].\n");
+      it = DbgInfo.erase(it);
+      FixedDbg++;
+      continue;
+    }
+    // Slot was remapped
     if (SlotRemap.count(Slot)) {
       LLVM_DEBUG(dbgs() << "Remapping debug info for ["
                         << cast<DILocalVariable>(VI.Var)->getName() << "].\n");
       VI.updateStackSlot(SlotRemap[Slot]);
       FixedDbg++;
     }
+    it++;
   }
 
   // Keep a list of *allocas* which need to be remapped.
@@ -1249,8 +1266,15 @@ bool StackColoring::runOnMachineFunction(MachineFunction &Func) {
 
   // Do not bother looking at empty intervals.
   for (unsigned I = 0; I < NumSlots; ++I) {
-    if (Intervals[SortedSlots[I]]->empty())
+    int Slot = SortedSlots[I];
+    if (Intervals[Slot]->empty()) {
+      if (InterestingSlots.test(Slot) && !ConservativeSlots.test(Slot)) {
+        RemovedSlots += 1;
+        ReducedSize += MFI->getObjectSize(Slot);
+        MFI->RemoveStackObject(Slot);
+      }
       SortedSlots[I] = -1;
+    }
   }
 
   // This is a simple greedy algorithm for merging allocas. First, sort the
diff --git a/llvm/test/CodeGen/PowerPC/aix32-cc-abi-vaarg.ll b/llvm/test/CodeGen/PowerPC/aix32-cc-abi-vaarg.ll
index bf66a1ed042d228..1b0a803734ae9f3 100644
--- a/llvm/test/CodeGen/PowerPC/aix32-cc-abi-vaarg.ll
+++ b/llvm/test/CodeGen/PowerPC/aix32-cc-abi-vaarg.ll
@@ -347,7 +347,6 @@ entry:
 
 ; 32BIT-LABEL:   stack:
 ; 32BIT-DAG:     - { id: 0, name: arg1, type: default, offset: 0, size: 4, alignment: 4,
-; 32BIT-DAG:     - { id: 1, name: arg2, type: default, offset: 0, size: 4, alignment: 4,
 ; 32BIT-DAG:     - { id: 2, name: '', type: default, offset: 0, size: 8, alignment: 8,
 ; 32BIT-DAG:     - { id: 3, name: '', type: default, offset: 0, size: 8, alignment: 8,
 
diff --git a/llvm/test/CodeGen/PowerPC/aix64-cc-abi-vaarg.ll b/llvm/test/CodeGen/PowerPC/aix64-cc-abi-vaarg.ll
index ccf89aac2d5408e..a8684fdfe1c5682 100644
--- a/llvm/test/CodeGen/PowerPC/aix64-cc-abi-vaarg.ll
+++ b/llvm/test/CodeGen/PowerPC/aix64-cc-abi-vaarg.ll
@@ -138,9 +138,7 @@
 ; 64BIT-LABEL:   fixedStack:
 ; 64BIT-DAG:     - { id: 0, type: default, offset: 112, size: 8, alignment: 16, stack-id: default,
 
-; 64BIT-LABEL:   stack:
-; 64BIT-DAG:     - { id: 0, name: arg1, type: default, offset: 0, size: 8, alignment: 8,
-; 64BIT-DAG:     - { id: 1, name: arg2, type: default, offset: 0, size: 8, alignment: 8,
+; 64BIT-LABEL:   stack: []
 
 ; 64BIT-LABEL:   body:             |
 ; 64BIT-DAG:     liveins: $x3, $x4, $x5, $x6, $x7, $x8, $x9, $x10
@@ -305,9 +303,7 @@
 ; 64BIT-LABEL:   fixedStack:
 ; 64BIT-DAG:       - { id: 0, type: default, offset: 152, size: 8
 
-; 64BIT-LABEL:   stack:
-; 64BIT-DAG:       - { id: 0, name: arg1, type: default, offset: 0, size: 8
-; 64BIT-DAG:       - { id: 1, name: arg2, type: default, offset: 0, size: 8
+; 64BIT-LABEL:   stack:           []
 
 ; 64BIT-LABEL:     body:             |
 ; 64BIT-DAG:       liveins: $f1, $f2, $f3, $f4, $f5, $f6, $f7, $f8, $f9, $f10, $f11, $f12, $f13
diff --git a/llvm/test/CodeGen/RISCV/dead-stack-slot.ll b/llvm/test/CodeGen/RISCV/dead-stack-slot.ll
new file mode 100644
index 000000000000000..fdba359edddaf84
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/dead-stack-slot.ll
@@ -0,0 +1,32 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -mtriple=riscv32 -verify-machineinstrs < %s \
+; RUN:   | FileCheck %s -check-prefix=RV32I
+; RUN: llc -mtriple=riscv64 -verify-machineinstrs < %s \
+; RUN:   | FileCheck %s -check-prefix=RV64I
+
+; Remove the lifetime-marked alloca, but not the unmarked one.
+define dso_local signext i32 @f1() nounwind {
+; RV32I-LABEL: f1:
+; RV32I:       # %bb.0:
+; RV32I-NEXT:    addi sp, sp, -32
+; RV32I-NEXT:    li a0, 0
+; RV32I-NEXT:    addi sp, sp, 32
+; RV32I-NEXT:    ret
+;
+; RV64I-LABEL: f1:
+; RV64I:       # %bb.0:
+; RV64I-NEXT:    addi sp, sp, -32
+; RV64I-NEXT:    li a0, 0
+; RV64I-NEXT:    addi sp, sp, 32
+; RV64I-NEXT:    ret
+  %1 = alloca [32 x i8], align 4
+  %2 = alloca [32 x i8], align 4
+  %3 = getelementptr inbounds [32 x i8], [32 x i8]* %1, i64 0, i64 0
+  call void @llvm.lifetime.start.p0i8(i64 32, i8* nonnull %3)
+  call void @llvm.lifetime.end.p0i8(i64 32, i8* nonnull %3)
+  ret i32 0
+}
+
+declare void @llvm.lifetime.start.p0i8(i64 immarg, i8* nocapture)
+declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture)
+
diff --git a/llvm/test/DebugInfo/COFF/lexicalblock.ll b/llvm/test/DebugInfo/COFF/lexicalblock.ll
index 40dd8f894252c25..3bfae85f6c9bad9 100644
--- a/llvm/test/DebugInfo/COFF/lexicalblock.ll
+++ b/llvm/test/DebugInfo/COFF/lexicalblock.ll
@@ -63,32 +63,12 @@
 ; CHECK: LocalSym {
 ; CHECK:   VarName: localA
 ; CHECK: }
-; CHECK: LocalSym {
-; CHECK:   VarName: localB
-; CHECK: }
-; CHECK: BlockSym {
-; CHECK:   Kind: S_BLOCK32 {{.*}}
-; CHECK:   BlockName: 
-; CHECK: }
-; CHECK: ScopeEndSym {
-; CHECK:   Kind: S_END {{.*}}
-; CHECK: }
-; CHECK: BlockSym {
-; CHECK:   Kind: S_BLOCK32 {{.*}}
-; CHECK:   BlockName: 
-; CHECK: }
-; CHECK: ScopeEndSym {
-; CHECK:   Kind: S_END {{.*}}
-; CHECK: }
 ; CHECK: BlockSym {
 ; CHECK:   Kind: S_BLOCK32 {{.*}}
 ; CHECK:   BlockName: 
 ; CHECK: }
-; CHECK: ScopeEndSym {
-; CHECK: }
-; CHECK: BlockSym {
-; CHECK:   Kind: S_BLOCK32 {{.*}}
-; CHECK:   BlockName: 
+; CHECK: LocalSym {
+; CHECK:   VarName: localB
 ; CHECK: }
 ; CHECK: ScopeEndSym {
 ; CHECK:   Kind: S_END {{.*}}

@mohammed-nurulhoque
Copy link
Contributor Author

There is an assertion failure in llvm/test/DebugInfo/COFF/lexicalblock.ll:

MachineFrameInfo.h:530: int64_t llvm::MachineFrameInfo::getObjectOffset(int) const: Assertion `!isDeadObjectIndex(ObjectIdx) && "Getting frame offset for a dead object?"' failed.

The issue was VariableDbgInfos still had DebugInfo for the deleted stack slot. Fixed now.

Copy link
Contributor

@nikic nikic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks fine to me now, but I'd like someone more familiar with the backend to take a look at this.

if (Intervals[Slot]->empty()) {
if (InterestingSlots.test(Slot) && !ConservativeSlots.test(Slot)) {
RemovedSlots += 1;
ReducedSize += MFI->getObjectSize(Slot);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reduced size thing doesn't account for alignment but I guess this is only used for debug printing and was never accurate

Copy link
Contributor

@frasercrmck frasercrmck left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't speak to the StackColoring changes, sorry

llvm/test/CodeGen/RISCV/dead-stack-slot.ll Outdated Show resolved Hide resolved
@mohammed-nurulhoque
Copy link
Contributor Author

Could you please commit the code on my behalf?
Mohammed Nurul Hoque
mohammed.nurulhoque@imgtec.com

@arsenm
Copy link
Contributor

arsenm commented Dec 7, 2023

Could you please commit the code on my behalf? Mohammed Nurul Hoque mohammed.nurulhoque@imgtec.com

Can you fix the formatting error?

@mohammed-nurulhoque
Copy link
Contributor Author

ping

@nikic nikic merged commit a294578 into llvm:main Dec 13, 2023
4 checks passed
@piotrAMD
Copy link
Collaborator

The change is causing the assertion for me in "ninja check-llvm" on linux:
llc: /upstream/llvm/include/llvm/CodeGen/MachineFrameInfo.h:530: int64_t llvm::MachineFrameInfo::getObjectOffset(int) const: Assertion `!isDeadObjectIndex(ObjectIdx) && "Getting frame offset for a dead object?"' failed.

@nikic
Copy link
Contributor

nikic commented Dec 13, 2023

@piotrAMD What's the failing test?

@piotrAMD
Copy link
Collaborator

@piotrAMD What's the failing test?

LLVM :: DebugInfo/COFF/lexicalblock.ll

Also visible here: https://buildkite.com/llvm-project/github-pull-requests/builds/22410#018c633f-a0f4-4604-8c7d-17deb1708815

nikic added a commit that referenced this pull request Dec 13, 2023
This reverts commit a294578.

Causes an assertion failure in llvm/test/DebugInfo/COFF/lexicalblock.ll.
@nikic
Copy link
Contributor

nikic commented Dec 13, 2023

Thanks, I see it as well. I've reverted the patch. It's weird that this did not fail in the buildkite run on the PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants