Skip to content

[CallSiteSplitting] Don't copy !llvm.loop metadata to split block #138974

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

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

wjschmidt
Copy link
Contributor

The call-site splitting pass uses the utility function DuplicateInstructionsInSplitBetween to split predecessor blocks. This utility copies branch metadata from the predecessor block's terminator to the split block terminator. When the predecessor is a loop latch, this results in !llvm.loop metadata being added to a non-latching branch. This patch detects the situation and erases the offending metadata.

The call-site splitting pass uses the utility function
DuplicateInstructionsInSplitBetween to split predecessor blocks.
This utility copies branch metadata from the predecessor block's
terminator to the split block terminator.  When the predecessor is
a loop latch, this results in !llvm.loop metadata being added to
a non-latching branch.  This patch detects the situation and
erases the offending metadata.
@llvmbot
Copy link
Member

llvmbot commented May 7, 2025

@llvm/pr-subscribers-llvm-transforms

Author: Bill Schmidt (wjschmidt)

Changes

The call-site splitting pass uses the utility function DuplicateInstructionsInSplitBetween to split predecessor blocks. This utility copies branch metadata from the predecessor block's terminator to the split block terminator. When the predecessor is a loop latch, this results in !llvm.loop metadata being added to a non-latching branch. This patch detects the situation and erases the offending metadata.


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

2 Files Affected:

  • (modified) llvm/lib/Transforms/Scalar/CallSiteSplitting.cpp (+6)
  • (added) llvm/test/Transforms/CallSiteSplitting/loop-metadata.ll (+44)
diff --git a/llvm/lib/Transforms/Scalar/CallSiteSplitting.cpp b/llvm/lib/Transforms/Scalar/CallSiteSplitting.cpp
index 2e955e061111f..4f11f3de469cf 100644
--- a/llvm/lib/Transforms/Scalar/CallSiteSplitting.cpp
+++ b/llvm/lib/Transforms/Scalar/CallSiteSplitting.cpp
@@ -328,6 +328,12 @@ static void splitCallSite(CallBase &CB,
         DTU);
     assert(SplitBlock && "Unexpected new basic block split.");
 
+    // The split block shouldn't inherit !llvm.loop metadata.
+    Instruction *SplitTerm = SplitBlock->getTerminator();
+    SplitTerm->eraseMetadataIf([](unsigned MDKind, MDNode *Node) {
+      return MDKind == LLVMContext::MD_loop;
+    });
+
     auto *NewCI =
         cast<CallBase>(&*std::prev(SplitBlock->getTerminator()->getIterator()));
     addConditions(*NewCI, Preds[i].second);
diff --git a/llvm/test/Transforms/CallSiteSplitting/loop-metadata.ll b/llvm/test/Transforms/CallSiteSplitting/loop-metadata.ll
new file mode 100644
index 0000000000000..ae680be669804
--- /dev/null
+++ b/llvm/test/Transforms/CallSiteSplitting/loop-metadata.ll
@@ -0,0 +1,44 @@
+; Verify that we don't add incorrect llvm.loop metadata to a
+; non-latching branch.
+
+; RUN: opt -passes=callsite-splitting -S < %s 2>&1 | FileCheck %s
+
+; CHECK-NOT: br label %x{{.*}}, !llvm.loop !0
+
+target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define internal void @foo(i1 %0, i1 %1, i1 %2) {
+  br i1 %0, label %x1, label %x2
+
+x1:
+  br label %x16
+
+x2:
+  br label %x16
+
+x16:
+  %x17 = phi i32 [ 0, %x1 ], [ 1, %x2 ]
+  br i1 %1, label %x55, label %x46
+
+x46:
+  %x47 = icmp eq i32 %x17, 0
+  br i1 %x47, label %x49, label %x48
+
+x48:
+  br i1 %2, label %x49, label %x48, !llvm.loop !0
+
+x49:
+  %x50 = tail call fastcc i32 @func1(i32 noundef %x17)
+  br label %x55
+
+x55:
+  ret void
+}
+
+define internal fastcc i32 @func1(i32 noundef %0) unnamed_addr {
+  ret i32 13
+}
+
+!0 = distinct !{!0, !1}
+!1 = !{!"llvm.loop.mustprogress"}

@wjschmidt
Copy link
Contributor Author

The buildkite failures are due to an unrelated bad Flang test case. Is there a way to re-trigger those checks?

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.

2 participants