[llvm] [LoopUnroll] Ignore inlinable calls if unrolling is forced (PR #88149)
George Burgess IV via llvm-commits
llvm-commits at lists.llvm.org
Mon May 20 10:29:27 PDT 2024
https://github.com/gburgessiv updated https://github.com/llvm/llvm-project/pull/88149
>From 18de7144d7f8a111218d2506915accab3165c9aa Mon Sep 17 00:00:00 2001
From: George Burgess IV <george.burgess.iv at gmail.com>
Date: Mon, 15 Apr 2024 23:28:35 +0000
Subject: [PATCH] [LoopUnroll] Ignore inlinable calls if unrolling is forced
`NumInlineCandidates` counts candidates that are _very likely_ to be
inlined. This is a useful metric, but causes linker warnings if:
- the loop to be unrolled has had unrolling forced by the user, and
- the inliner fails to inline the call (e.g., because it's considered a
very cold callsite)
Fixes #88141
---
llvm/lib/Transforms/Scalar/LoopUnrollPass.cpp | 15 ++++++--
.../LoopUnroll/unroll-calls-if-forced.ll | 35 +++++++++++++++++++
2 files changed, 47 insertions(+), 3 deletions(-)
create mode 100644 llvm/test/Transforms/LoopUnroll/unroll-calls-if-forced.ll
diff --git a/llvm/lib/Transforms/Scalar/LoopUnrollPass.cpp b/llvm/lib/Transforms/Scalar/LoopUnrollPass.cpp
index 10fc9e9303e89..66990e356eb35 100644
--- a/llvm/lib/Transforms/Scalar/LoopUnrollPass.cpp
+++ b/llvm/lib/Transforms/Scalar/LoopUnrollPass.cpp
@@ -1157,9 +1157,11 @@ tryToUnrollLoop(Loop *L, DominatorTree &DT, LoopInfo *LI, ScalarEvolution &SE,
// automatic unrolling from interfering with the user requested
// transformation.
Loop *ParentL = L->getParentLoop();
+ const bool UnrollIsForcedByUser =
+ hasUnrollTransformation(L) == TM_ForcedByUser;
if (ParentL != nullptr &&
hasUnrollAndJamTransformation(ParentL) == TM_ForcedByUser &&
- hasUnrollTransformation(L) != TM_ForcedByUser) {
+ !UnrollIsForcedByUser) {
LLVM_DEBUG(dbgs() << "Not unrolling loop since parent loop has"
<< " llvm.loop.unroll_and_jam.\n");
return LoopUnrollResult::Unmodified;
@@ -1169,7 +1171,7 @@ tryToUnrollLoop(Loop *L, DominatorTree &DT, LoopInfo *LI, ScalarEvolution &SE,
// loop has an explicit unroll-and-jam pragma. This is to prevent automatic
// unrolling from interfering with the user requested transformation.
if (hasUnrollAndJamTransformation(L) == TM_ForcedByUser &&
- hasUnrollTransformation(L) != TM_ForcedByUser) {
+ !UnrollIsForcedByUser) {
LLVM_DEBUG(
dbgs()
<< " Not unrolling loop since it has llvm.loop.unroll_and_jam.\n");
@@ -1219,7 +1221,14 @@ tryToUnrollLoop(Loop *L, DominatorTree &DT, LoopInfo *LI, ScalarEvolution &SE,
if (OptForSize)
UP.Threshold = std::max(UP.Threshold, LoopSize + 1);
- if (UCE.NumInlineCandidates != 0) {
+ // Ignore the potential for inlining if unrolling is forced by the user. It's
+ // only _very likely_ that `NumInlineCandidates` functions will be inlined;
+ // things like profile data can make this significantly less likely.
+ //
+ // TODO: It could be beneficial to allow this check in pre-link LTO, since
+ // that pipeline prefers to minimize IR size, but that requires a decent
+ // amount of extra plumbing.
+ if (!UnrollIsForcedByUser && UCE.NumInlineCandidates != 0) {
LLVM_DEBUG(dbgs() << " Not unrolling loop with inlinable calls.\n");
return LoopUnrollResult::Unmodified;
}
diff --git a/llvm/test/Transforms/LoopUnroll/unroll-calls-if-forced.ll b/llvm/test/Transforms/LoopUnroll/unroll-calls-if-forced.ll
new file mode 100644
index 0000000000000..00b774ea898d5
--- /dev/null
+++ b/llvm/test/Transforms/LoopUnroll/unroll-calls-if-forced.ll
@@ -0,0 +1,35 @@
+; RUN: opt -passes=loop-unroll -S < %s | FileCheck %s
+;
+; Ensure that loop unrolling occurs if the user forces it, even if there are
+; calls that may be inlined.
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define internal void @foo() {
+ ret void
+}
+
+; CHECK-LABEL: @forced(
+; CHECK: call {{.*}}void @foo
+; CHECK: call {{.*}}void @foo
+define void @forced(ptr nocapture %a) {
+entry:
+ br label %for.body
+
+for.body:
+ %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
+ %arrayidx = getelementptr inbounds i32, ptr %a, i64 %indvars.iv
+ call void @foo()
+ %0 = load i32, ptr %arrayidx, align 4
+ %inc = add nsw i32 %0, 1
+ store i32 %inc, ptr %arrayidx, align 4
+ %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
+ %exitcond = icmp eq i64 %indvars.iv.next, 64
+ br i1 %exitcond, label %for.end, label %for.body, !llvm.loop !0
+
+for.end:
+ ret void
+}
+
+!0 = distinct !{!0, !{!"llvm.loop.unroll.enable"},
+ !{!"llvm.loop.unroll.count", i32 2}}
More information about the llvm-commits
mailing list