[llvm] [IROutliner] do not outline non-uniform constants (PR #195450)
Arda Serdar Pektezol via llvm-commits
llvm-commits at lists.llvm.org
Thu Jun 11 09:49:03 PDT 2026
https://github.com/pektezol updated https://github.com/llvm/llvm-project/pull/195450
>From 1178b3a7b107b1dffbf7a00cede44c8ceb4ba43e Mon Sep 17 00:00:00 2001
From: Arda Serdar Pektezol <arda at pektezol.dev>
Date: Sat, 2 May 2026 16:24:58 +0300
Subject: [PATCH 1/2] [IROutliner] do not outline non-uniform immarg constants
---
llvm/lib/Transforms/IPO/IROutliner.cpp | 43 +++++++++++++++++++
.../IROutliner/illegal-different-immarg.ll | 28 ++++++++++++
2 files changed, 71 insertions(+)
create mode 100644 llvm/test/Transforms/IROutliner/illegal-different-immarg.ll
diff --git a/llvm/lib/Transforms/IPO/IROutliner.cpp b/llvm/lib/Transforms/IPO/IROutliner.cpp
index c1640f3d0e2a7..157fc51a9ab2d 100644
--- a/llvm/lib/Transforms/IPO/IROutliner.cpp
+++ b/llvm/lib/Transforms/IPO/IROutliner.cpp
@@ -579,11 +579,54 @@ collectRegionsConstants(OutlinableRegion &Region,
return ConstantsTheSame;
}
+/// Check whether \p Region contains a non-uniform constant operand that must
+/// remain an immediate argument.
+///
+/// \param Region - The region to check for non-uniform immarg constants.
+/// \param NotSame - The set of global value numbers that do not have the same
+/// constant in each region.
+/// \returns true if \p Region contains a non-uniform immarg constant, and false
+/// otherwise.
+static bool containsNonUniformImmArgConstant(OutlinableRegion &Region,
+ DenseSet<unsigned> &NotSame) {
+ IRSimilarityCandidate &C = *Region.Candidate;
+
+ for (IRInstructionData &ID : C) {
+ auto *CB = dyn_cast<CallBase>(ID.Inst);
+ if (!CB)
+ continue;
+
+ for (unsigned ArgIdx = 0, ArgEnd = CB->arg_size(); ArgIdx != ArgEnd;
+ ++ArgIdx) {
+ if (!CB->paramHasAttr(ArgIdx, Attribute::ImmArg))
+ continue;
+
+ Value *Arg = CB->getArgOperand(ArgIdx);
+ if (!isa<Constant>(Arg))
+ continue;
+
+ std::optional<unsigned> GVN = C.getGVN(Arg);
+ assert(GVN && "Expected a GVN for immarg operand?");
+ if (NotSame.contains(*GVN))
+ return true;
+ }
+ }
+
+ return false;
+}
+
void OutlinableGroup::findSameConstants(DenseSet<unsigned> &NotSame) {
DenseMap<unsigned, Constant *> GVNToConstant;
for (OutlinableRegion *Region : Regions)
collectRegionsConstants(*Region, GVNToConstant, NotSame);
+
+ for (OutlinableRegion *Region : Regions) {
+ if (!containsNonUniformImmArgConstant(*Region, NotSame))
+ continue;
+ IgnoreGroup = true;
+ return;
+ }
}
void OutlinableGroup::collectGVNStoreSets(Module &M) {
diff --git a/llvm/test/Transforms/IROutliner/illegal-different-immarg.ll b/llvm/test/Transforms/IROutliner/illegal-different-immarg.ll
new file mode 100644
index 0000000000000..04f1ef7165869
--- /dev/null
+++ b/llvm/test/Transforms/IROutliner/illegal-different-immarg.ll
@@ -0,0 +1,28 @@
+; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost < %s | FileCheck %s
+
+; Do not outline structurally similar regions when doing so would replace a
+; non-uniform immarg constant with an outlined-function argument.
+
+declare void @llvm.memcpy.p0.p0.i64(ptr noalias writeonly captures(none), ptr noalias readonly captures(none), i64, i1 immarg)
+
+define ptr @PR194733() {
+entry:
+ br i1 false, label %then, label %else
+
+then:
+ %0 = load ptr, ptr null, align 8
+ call void @llvm.memcpy.p0.p0.i64(ptr null, ptr null, i64 0, i1 false)
+ ret ptr null
+
+else:
+ %1 = load ptr, ptr null, align 8
+ call void @llvm.memcpy.p0.p0.i64(ptr null, ptr null, i64 0, i1 true)
+ %2 = load ptr, ptr null, align 8
+ call void @llvm.memcpy.p0.p0.i64(ptr null, ptr null, i64 0, i1 false)
+ ret ptr null
+}
+; CHECK-LABEL: define ptr @PR194733(
+; CHECK-NOT: outlined_ir_func
+; CHECK: call void @llvm.memcpy.p0.p0.i64(ptr null, ptr null, i64 0, i1 false)
+; CHECK: call void @llvm.memcpy.p0.p0.i64(ptr null, ptr null, i64 0, i1 true)
+; CHECK: call void @llvm.memcpy.p0.p0.i64(ptr null, ptr null, i64 0, i1 false)
>From 24fa032ec93238e85452e6e8c31ce00b3ffd5fac Mon Sep 17 00:00:00 2001
From: Arda Serdar Pektezol <arda at pektezol.dev>
Date: Thu, 28 May 2026 21:03:47 +0300
Subject: [PATCH 2/2] [IROutliner] update test case
---
.../IROutliner/illegal-different-immarg.ll | 35 +++++++++++++------
1 file changed, 24 insertions(+), 11 deletions(-)
diff --git a/llvm/test/Transforms/IROutliner/illegal-different-immarg.ll b/llvm/test/Transforms/IROutliner/illegal-different-immarg.ll
index 04f1ef7165869..29f2d123534fa 100644
--- a/llvm/test/Transforms/IROutliner/illegal-different-immarg.ll
+++ b/llvm/test/Transforms/IROutliner/illegal-different-immarg.ll
@@ -1,3 +1,4 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost < %s | FileCheck %s
; Do not outline structurally similar regions when doing so would replace a
@@ -5,24 +6,36 @@
declare void @llvm.memcpy.p0.p0.i64(ptr noalias writeonly captures(none), ptr noalias readonly captures(none), i64, i1 immarg)
+ at slot = global ptr null, align 8
+ at buf = global [1 x i8] zeroinitializer, align 1
+
define ptr @PR194733() {
+; CHECK-LABEL: define ptr @PR194733() {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: br i1 false, label %[[THEN:.*]], label %[[ELSE:.*]]
+; CHECK: [[THEN]]:
+; CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr @slot, align 8
+; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr @buf, ptr @buf, i64 0, i1 false)
+; CHECK-NEXT: ret ptr null
+; CHECK: [[ELSE]]:
+; CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr @slot, align 8
+; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr @buf, ptr @buf, i64 0, i1 true)
+; CHECK-NEXT: [[TMP2:%.*]] = load ptr, ptr @slot, align 8
+; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr @buf, ptr @buf, i64 0, i1 false)
+; CHECK-NEXT: ret ptr null
+;
entry:
br i1 false, label %then, label %else
then:
- %0 = load ptr, ptr null, align 8
- call void @llvm.memcpy.p0.p0.i64(ptr null, ptr null, i64 0, i1 false)
+ %0 = load ptr, ptr @slot, align 8
+ call void @llvm.memcpy.p0.p0.i64(ptr @buf, ptr @buf, i64 0, i1 false)
ret ptr null
else:
- %1 = load ptr, ptr null, align 8
- call void @llvm.memcpy.p0.p0.i64(ptr null, ptr null, i64 0, i1 true)
- %2 = load ptr, ptr null, align 8
- call void @llvm.memcpy.p0.p0.i64(ptr null, ptr null, i64 0, i1 false)
+ %1 = load ptr, ptr @slot, align 8
+ call void @llvm.memcpy.p0.p0.i64(ptr @buf, ptr @buf, i64 0, i1 true)
+ %2 = load ptr, ptr @slot, align 8
+ call void @llvm.memcpy.p0.p0.i64(ptr @buf, ptr @buf, i64 0, i1 false)
ret ptr null
}
-; CHECK-LABEL: define ptr @PR194733(
-; CHECK-NOT: outlined_ir_func
-; CHECK: call void @llvm.memcpy.p0.p0.i64(ptr null, ptr null, i64 0, i1 false)
-; CHECK: call void @llvm.memcpy.p0.p0.i64(ptr null, ptr null, i64 0, i1 true)
-; CHECK: call void @llvm.memcpy.p0.p0.i64(ptr null, ptr null, i64 0, i1 false)
More information about the llvm-commits
mailing list