-
Notifications
You must be signed in to change notification settings - Fork 15.3k
[IPO] Prevent removal of some convergent attr #134863
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
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1864,6 +1864,19 @@ static bool InstrBreaksNonConvergent(Instruction &I, | |
| !SCCNodes.contains(CB->getCalledFunction()); | ||
| } | ||
|
|
||
| static bool FunctionRequiresConvergence(const Function &F) { | ||
| for (auto &Use : F.uses()) { | ||
| CallBase *CB = dyn_cast<CallBase>(Use.getUser()); | ||
| if (!CB) | ||
| return true; | ||
|
|
||
| if (CB->getConvergenceControlToken()) | ||
| return true; | ||
| } | ||
|
|
||
| return false; | ||
| } | ||
|
|
||
| /// Helper for NoUnwind inference predicate InstrBreaksAttribute. | ||
| static bool InstrBreaksNonThrowing(Instruction &I, const SCCNodeSet &SCCNodes) { | ||
| if (!I.mayThrow(/* IncludePhaseOneUnwind */ true)) | ||
|
|
@@ -1967,7 +1980,9 @@ static void inferConvergent(const SCCNodeSet &SCCNodes, | |
| AI.registerAttrInference(AttributeInferer::InferenceDescriptor{ | ||
| Attribute::Convergent, | ||
| // Skip non-convergent functions. | ||
| [](const Function &F) { return !F.isConvergent(); }, | ||
| [](const Function &F) { | ||
| return !F.isConvergent() || FunctionRequiresConvergence(F); | ||
| }, | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does FunctionAttrs run in a bottom up and top down phase? Ideally we wouldn't need to inspect the users of the function, and strip convergent from call sites when possible
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looks like the pass is running bottom-up, so if we drop convergence intrinsics in the callee, then we should technically be able to strip the control tokens in the caller. But this would go beyond the scope of this pass no? |
||
| // Instructions that break non-convergent assumption. | ||
| [SCCNodes](Instruction &I) { | ||
| return InstrBreaksNonConvergent(I, SCCNodes); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| ; RUN: opt %s -passes=adce -S | FileCheck %s | ||
|
|
||
| ; CHECK: Function Attrs: convergent | ||
| ; CHECK-NEXT: define i32 @foo(i32 %a) #0 { | ||
| define i32 @foo(i32 %a) #0 { | ||
| entry: | ||
| ; CHECK-NOT: %0 = call token @llvm.experimental.convergence.entry() | ||
| %0 = call token @llvm.experimental.convergence.entry() | ||
| ret i32 %a | ||
| } | ||
|
|
||
| ; CHECK: Function Attrs: convergent | ||
| ; CHECK-NEXT: define void @bar() #0 { | ||
| define void @bar() #0 { | ||
| entry: | ||
| ; CHECK-NOT: %0 = call token @llvm.experimental.convergence.entry() | ||
| %0 = call token @llvm.experimental.convergence.anchor() | ||
| ret void | ||
| } | ||
|
|
||
| ; CHECK: Function Attrs: convergent | ||
| ; CHECK-NEXT: define void @baz() #0 { | ||
| define void @baz() #0 { | ||
| entry: | ||
| ; CHECK-NOT: %0 = call token @llvm.experimental.convergence.entry() | ||
| %0 = call token @llvm.experimental.convergence.entry() | ||
Keenuts marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| br label %header | ||
|
|
||
| header: | ||
| ; CHECK-NOT: %1 = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token %0) ] | ||
Keenuts marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| %1 = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token %0) ] | ||
| br i1 true, label %body, label %exit | ||
|
|
||
| body: | ||
| br label %header | ||
|
|
||
| exit: | ||
| ret void | ||
| } | ||
|
|
||
Keenuts marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| declare token @llvm.experimental.convergence.entry() #1 | ||
| declare token @llvm.experimental.convergence.anchor() #1 | ||
| declare token @llvm.experimental.convergence.loop() #1 | ||
|
|
||
| attributes #0 = { convergent } | ||
| attributes #1 = { convergent nocallback nofree nosync nounwind willreturn memory(none) } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| ; RUN: opt %s -passes=bdce -S | FileCheck %s | ||
|
|
||
| ; CHECK: Function Attrs: convergent | ||
| ; CHECK-NEXT: define i32 @foo(i32 %a) #0 { | ||
| define i32 @foo(i32 %a) #0 { | ||
| entry: | ||
| ; CHECK-NOT: %0 = call token @llvm.experimental.convergence.entry() | ||
| %0 = call token @llvm.experimental.convergence.entry() | ||
| ret i32 %a | ||
| } | ||
|
|
||
| ; CHECK: Function Attrs: convergent | ||
| ; CHECK-NEXT: define void @bar() #0 { | ||
| define void @bar() #0 { | ||
| entry: | ||
| ; CHECK-NOT: %0 = call token @llvm.experimental.convergence.entry() | ||
| %0 = call token @llvm.experimental.convergence.anchor() | ||
| ret void | ||
| } | ||
|
|
||
| ; CHECK: Function Attrs: convergent | ||
| ; CHECK-NEXT: define void @baz() #0 { | ||
| define void @baz() #0 { | ||
| entry: | ||
| ; CHECK-NOT: %0 = call token @llvm.experimental.convergence.entry() | ||
| %0 = call token @llvm.experimental.convergence.entry() | ||
| br label %header | ||
|
|
||
| header: | ||
| ; CHECK-NOT: %1 = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token %0) ] | ||
| %1 = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token %0) ] | ||
| br i1 true, label %body, label %exit | ||
|
|
||
| body: | ||
| br label %header | ||
|
|
||
| exit: | ||
| ret void | ||
| } | ||
|
|
||
| declare token @llvm.experimental.convergence.entry() #1 | ||
| declare token @llvm.experimental.convergence.anchor() #1 | ||
| declare token @llvm.experimental.convergence.loop() #1 | ||
|
|
||
| attributes #0 = { convergent } | ||
| attributes #1 = { convergent nocallback nofree nosync nounwind willreturn memory(none) } | ||
|
|
Uh oh!
There was an error while loading. Please reload this page.