-
Notifications
You must be signed in to change notification settings - Fork 14.8k
[licm] don't drop MD_prof
when dropping other metadata
#152420
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
[licm] don't drop MD_prof
when dropping other metadata
#152420
Conversation
This stack of pull requests is managed by Graphite. Learn more about stacking. |
31a3f5c
to
f0cf2e9
Compare
82b2df1
to
9bea77f
Compare
7186d3e
to
15e7ab7
Compare
9bea77f
to
ac134fb
Compare
15e7ab7
to
df2474e
Compare
ac134fb
to
cac2eba
Compare
df2474e
to
d35d9df
Compare
cac2eba
to
b8aa221
Compare
d35d9df
to
336185b
Compare
@llvm/pr-subscribers-llvm-transforms Author: Mircea Trofin (mtrofin) ChangesFull diff: https://github.com/llvm/llvm-project/pull/152420.diff 4 Files Affected:
diff --git a/llvm/include/llvm/IR/Instruction.h b/llvm/include/llvm/IR/Instruction.h
index 5d25804a684ac..2eb4fd36c5b7d 100644
--- a/llvm/include/llvm/IR/Instruction.h
+++ b/llvm/include/llvm/IR/Instruction.h
@@ -584,9 +584,10 @@ class Instruction : public User,
dropUBImplyingAttrsAndUnknownMetadata(ArrayRef<unsigned> KnownIDs = {});
/// Drop any attributes or metadata that can cause immediate undefined
- /// behavior. Retain other attributes/metadata on a best-effort basis.
- /// This should be used when speculating instructions.
- LLVM_ABI void dropUBImplyingAttrsAndMetadata();
+ /// behavior. Retain other attributes/metadata on a best-effort basis, as well
+ /// as those passed in `Keep`. This should be used when speculating
+ /// instructions.
+ LLVM_ABI void dropUBImplyingAttrsAndMetadata(ArrayRef<unsigned> Keep = {});
/// Return true if this instruction has UB-implying attributes
/// that can cause immediate undefined behavior.
diff --git a/llvm/lib/IR/Instruction.cpp b/llvm/lib/IR/Instruction.cpp
index cf19b97333514..2815ea8498b4a 100644
--- a/llvm/lib/IR/Instruction.cpp
+++ b/llvm/lib/IR/Instruction.cpp
@@ -554,13 +554,15 @@ void Instruction::dropUBImplyingAttrsAndUnknownMetadata(
CB->removeRetAttrs(UBImplyingAttributes);
}
-void Instruction::dropUBImplyingAttrsAndMetadata() {
+void Instruction::dropUBImplyingAttrsAndMetadata(ArrayRef<unsigned> Keep) {
// !annotation metadata does not impact semantics.
// !range, !nonnull and !align produce poison, so they are safe to speculate.
// !noundef and various AA metadata must be dropped, as it generally produces
// immediate undefined behavior.
- unsigned KnownIDs[] = {LLVMContext::MD_annotation, LLVMContext::MD_range,
- LLVMContext::MD_nonnull, LLVMContext::MD_align};
+ SmallVector<unsigned> KnownIDs(Keep.size() + 4);
+ KnownIDs.append({LLVMContext::MD_annotation, LLVMContext::MD_range,
+ LLVMContext::MD_nonnull, LLVMContext::MD_align});
+ append_range(KnownIDs, Keep);
dropUBImplyingAttrsAndUnknownMetadata(KnownIDs);
}
diff --git a/llvm/lib/Transforms/Scalar/LICM.cpp b/llvm/lib/Transforms/Scalar/LICM.cpp
index 34adc7745f67c..7a203638a1d78 100644
--- a/llvm/lib/Transforms/Scalar/LICM.cpp
+++ b/llvm/lib/Transforms/Scalar/LICM.cpp
@@ -1698,8 +1698,12 @@ static void hoist(Instruction &I, const DominatorTree *DT, const Loop *CurLoop,
// The check on hasMetadataOtherThanDebugLoc is to prevent us from burning
// time in isGuaranteedToExecute if we don't actually have anything to
// drop. It is a compile time optimization, not required for correctness.
- !SafetyInfo->isGuaranteedToExecute(I, DT, CurLoop))
- I.dropUBImplyingAttrsAndMetadata();
+ !SafetyInfo->isGuaranteedToExecute(I, DT, CurLoop)) {
+ if (ProfcheckDisableMetadataFixes)
+ I.dropUBImplyingAttrsAndMetadata();
+ else
+ I.dropUBImplyingAttrsAndMetadata({LLVMContext::MD_prof});
+ }
if (isa<PHINode>(I))
// Move the new node to the end of the phi list in the destination block.
diff --git a/llvm/test/Transforms/LICM/hoist-profdata.ll b/llvm/test/Transforms/LICM/hoist-profdata.ll
new file mode 100644
index 0000000000000..18fa1b9f92e8a
--- /dev/null
+++ b/llvm/test/Transforms/LICM/hoist-profdata.ll
@@ -0,0 +1,45 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals --version 2
+; Test that hoisting conditional branches copies the debug and profiling info
+; metadata from the branch being hoisted.
+; RUN: opt -S -passes=licm %s -o - | FileCheck %s
+
+declare i32 @foo()
+
+; to_hoist should get hoisted, and that should not result
+; in a loss of profiling info
+define i32 @hoist_select(i1 %cond, i32 %a, i32 %b) nounwind {
+; CHECK-LABEL: define i32 @hoist_select
+; CHECK-SAME: (i1 [[COND:%.*]], i32 [[A:%.*]], i32 [[B:%.*]]) #[[ATTR0:[0-9]+]] {
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[TO_HOIST:%.*]] = select i1 [[COND]], i32 [[A]], i32 [[B]], !prof [[PROF0:![0-9]+]]
+; CHECK-NEXT: br label [[L0:%.*]]
+; CHECK: L0:
+; CHECK-NEXT: [[G:%.*]] = call i32 @foo()
+; CHECK-NEXT: [[SUM:%.*]] = add i32 [[G]], [[TO_HOIST]]
+; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[SUM]], 0
+; CHECK-NEXT: br i1 [[C]], label [[L0]], label [[EXIT:%.*]], !prof [[PROF1:![0-9]+]]
+; CHECK: exit:
+; CHECK-NEXT: [[SUM_LCSSA:%.*]] = phi i32 [ [[SUM]], [[L0]] ]
+; CHECK-NEXT: ret i32 [[SUM_LCSSA]]
+;
+entry:
+ br label %L0
+L0:
+ %g = call i32 @foo()
+ %to_hoist = select i1 %cond, i32 %a, i32 %b, !prof !0
+ %sum = add i32 %g, %to_hoist
+ %c = icmp eq i32 %sum, 0
+ br i1 %c, label %L0, label %exit, !prof !1
+
+exit:
+ ret i32 %sum
+}
+
+!0 = !{!"branch_weights", i32 2, i32 5}
+!1 = !{!"branch_weights", i32 101, i32 189}
+;.
+; CHECK: attributes #[[ATTR0]] = { nounwind }
+;.
+; CHECK: [[PROF0]] = !{!"branch_weights", i32 2, i32 5}
+; CHECK: [[PROF1]] = !{!"branch_weights", i32 101, i32 189}
+;.
|
@llvm/pr-subscribers-llvm-ir Author: Mircea Trofin (mtrofin) ChangesFull diff: https://github.com/llvm/llvm-project/pull/152420.diff 4 Files Affected:
diff --git a/llvm/include/llvm/IR/Instruction.h b/llvm/include/llvm/IR/Instruction.h
index 5d25804a684ac..2eb4fd36c5b7d 100644
--- a/llvm/include/llvm/IR/Instruction.h
+++ b/llvm/include/llvm/IR/Instruction.h
@@ -584,9 +584,10 @@ class Instruction : public User,
dropUBImplyingAttrsAndUnknownMetadata(ArrayRef<unsigned> KnownIDs = {});
/// Drop any attributes or metadata that can cause immediate undefined
- /// behavior. Retain other attributes/metadata on a best-effort basis.
- /// This should be used when speculating instructions.
- LLVM_ABI void dropUBImplyingAttrsAndMetadata();
+ /// behavior. Retain other attributes/metadata on a best-effort basis, as well
+ /// as those passed in `Keep`. This should be used when speculating
+ /// instructions.
+ LLVM_ABI void dropUBImplyingAttrsAndMetadata(ArrayRef<unsigned> Keep = {});
/// Return true if this instruction has UB-implying attributes
/// that can cause immediate undefined behavior.
diff --git a/llvm/lib/IR/Instruction.cpp b/llvm/lib/IR/Instruction.cpp
index cf19b97333514..2815ea8498b4a 100644
--- a/llvm/lib/IR/Instruction.cpp
+++ b/llvm/lib/IR/Instruction.cpp
@@ -554,13 +554,15 @@ void Instruction::dropUBImplyingAttrsAndUnknownMetadata(
CB->removeRetAttrs(UBImplyingAttributes);
}
-void Instruction::dropUBImplyingAttrsAndMetadata() {
+void Instruction::dropUBImplyingAttrsAndMetadata(ArrayRef<unsigned> Keep) {
// !annotation metadata does not impact semantics.
// !range, !nonnull and !align produce poison, so they are safe to speculate.
// !noundef and various AA metadata must be dropped, as it generally produces
// immediate undefined behavior.
- unsigned KnownIDs[] = {LLVMContext::MD_annotation, LLVMContext::MD_range,
- LLVMContext::MD_nonnull, LLVMContext::MD_align};
+ SmallVector<unsigned> KnownIDs(Keep.size() + 4);
+ KnownIDs.append({LLVMContext::MD_annotation, LLVMContext::MD_range,
+ LLVMContext::MD_nonnull, LLVMContext::MD_align});
+ append_range(KnownIDs, Keep);
dropUBImplyingAttrsAndUnknownMetadata(KnownIDs);
}
diff --git a/llvm/lib/Transforms/Scalar/LICM.cpp b/llvm/lib/Transforms/Scalar/LICM.cpp
index 34adc7745f67c..7a203638a1d78 100644
--- a/llvm/lib/Transforms/Scalar/LICM.cpp
+++ b/llvm/lib/Transforms/Scalar/LICM.cpp
@@ -1698,8 +1698,12 @@ static void hoist(Instruction &I, const DominatorTree *DT, const Loop *CurLoop,
// The check on hasMetadataOtherThanDebugLoc is to prevent us from burning
// time in isGuaranteedToExecute if we don't actually have anything to
// drop. It is a compile time optimization, not required for correctness.
- !SafetyInfo->isGuaranteedToExecute(I, DT, CurLoop))
- I.dropUBImplyingAttrsAndMetadata();
+ !SafetyInfo->isGuaranteedToExecute(I, DT, CurLoop)) {
+ if (ProfcheckDisableMetadataFixes)
+ I.dropUBImplyingAttrsAndMetadata();
+ else
+ I.dropUBImplyingAttrsAndMetadata({LLVMContext::MD_prof});
+ }
if (isa<PHINode>(I))
// Move the new node to the end of the phi list in the destination block.
diff --git a/llvm/test/Transforms/LICM/hoist-profdata.ll b/llvm/test/Transforms/LICM/hoist-profdata.ll
new file mode 100644
index 0000000000000..18fa1b9f92e8a
--- /dev/null
+++ b/llvm/test/Transforms/LICM/hoist-profdata.ll
@@ -0,0 +1,45 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals --version 2
+; Test that hoisting conditional branches copies the debug and profiling info
+; metadata from the branch being hoisted.
+; RUN: opt -S -passes=licm %s -o - | FileCheck %s
+
+declare i32 @foo()
+
+; to_hoist should get hoisted, and that should not result
+; in a loss of profiling info
+define i32 @hoist_select(i1 %cond, i32 %a, i32 %b) nounwind {
+; CHECK-LABEL: define i32 @hoist_select
+; CHECK-SAME: (i1 [[COND:%.*]], i32 [[A:%.*]], i32 [[B:%.*]]) #[[ATTR0:[0-9]+]] {
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[TO_HOIST:%.*]] = select i1 [[COND]], i32 [[A]], i32 [[B]], !prof [[PROF0:![0-9]+]]
+; CHECK-NEXT: br label [[L0:%.*]]
+; CHECK: L0:
+; CHECK-NEXT: [[G:%.*]] = call i32 @foo()
+; CHECK-NEXT: [[SUM:%.*]] = add i32 [[G]], [[TO_HOIST]]
+; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[SUM]], 0
+; CHECK-NEXT: br i1 [[C]], label [[L0]], label [[EXIT:%.*]], !prof [[PROF1:![0-9]+]]
+; CHECK: exit:
+; CHECK-NEXT: [[SUM_LCSSA:%.*]] = phi i32 [ [[SUM]], [[L0]] ]
+; CHECK-NEXT: ret i32 [[SUM_LCSSA]]
+;
+entry:
+ br label %L0
+L0:
+ %g = call i32 @foo()
+ %to_hoist = select i1 %cond, i32 %a, i32 %b, !prof !0
+ %sum = add i32 %g, %to_hoist
+ %c = icmp eq i32 %sum, 0
+ br i1 %c, label %L0, label %exit, !prof !1
+
+exit:
+ ret i32 %sum
+}
+
+!0 = !{!"branch_weights", i32 2, i32 5}
+!1 = !{!"branch_weights", i32 101, i32 189}
+;.
+; CHECK: attributes #[[ATTR0]] = { nounwind }
+;.
+; CHECK: [[PROF0]] = !{!"branch_weights", i32 2, i32 5}
+; CHECK: [[PROF1]] = !{!"branch_weights", i32 101, i32 189}
+;.
|
336ba46
to
6b1a568
Compare
b8aa221
to
223404b
Compare
MD_prof
when dropping
223404b
to
871de1e
Compare
6b1a568
to
9487727
Compare
9487727
to
76de28d
Compare
871de1e
to
8ed35ac
Compare
3144e61
to
91c0ca5
Compare
MD_prof
when dropping MD_prof
when dropping other metadata
llvm/lib/IR/Instruction.cpp
Outdated
static const unsigned KnownIDs[] = { | ||
LLVMContext::MD_annotation, LLVMContext::MD_range, | ||
LLVMContext::MD_nonnull, LLVMContext::MD_align}; | ||
SmallVector<unsigned> KeepIDs(Keep.size() + std::size(KnownIDs)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do you need to pass Keep.size() + std::size(KnownIDs)
? The append_range calls below insert at the end so I think this means you'll end up with a bunch of zeros in the beginning.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because I meant reserve
if (ProfcheckDisableMetadataFixes) | ||
I.dropUBImplyingAttrsAndMetadata(); | ||
else | ||
I.dropUBImplyingAttrsAndMetadata({LLVMContext::MD_prof}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we directly call dropUBImplyingAttrsAndUnknownMetadata
here with the md_prof arg instead of changing the other function with a keep argument?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
but we'd still want to pass the other bunch of OK metadata, which would mean exposing it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah. Didn't realize it wasn't exposed already.
91c0ca5
to
9f7c772
Compare
9f7c772
to
cb8c897
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lgtm
LLVMContext::MD_annotation, LLVMContext::MD_range, | ||
LLVMContext::MD_nonnull, LLVMContext::MD_align}; | ||
SmallVector<unsigned> KeepIDs; | ||
KeepIDs.reserve(Keep.size() + std::size(KnownIDs)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this useful in practice? SmallVector might already allocate enough inline storage to not require an allocation for the small number of metadata types we have.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe. it's harmless though and at best a tiny efficiency.
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/190/builds/25508 Here is the relevant piece of the build log for the reference
|
Part of Issue #147390