Conversation
This was referenced Apr 2, 2025
Contributor
Author
This stack of pull requests is managed by Graphite. Learn more about stacking. |
Member
|
@llvm/pr-subscribers-llvm-ir Author: Matt Arsenault (arsenm) ChangesExtend the early return on value reduction to mutate the function return This is enough to cleanup the common case where we end up with one Full diff: https://github.com/llvm/llvm-project/pull/134035.diff 2 Files Affected:
diff --git a/llvm/test/tools/llvm-reduce/reduce-values-to-return-new-return-type.ll b/llvm/test/tools/llvm-reduce/reduce-values-to-return-new-return-type.ll
new file mode 100644
index 0000000000000..9ddbbe3def44f
--- /dev/null
+++ b/llvm/test/tools/llvm-reduce/reduce-values-to-return-new-return-type.ll
@@ -0,0 +1,95 @@
+; Test that llvm-reduce can move intermediate values by inserting
+; early returns when the function already has a different return type
+;
+; RUN: llvm-reduce --abort-on-invalid-reduction --delta-passes=instructions-to-return --test FileCheck --test-arg --check-prefix=INTERESTING --test-arg %s --test-arg --input-file %s -o %t
+; RUN: FileCheck --check-prefix=RESULT %s < %t
+
+
+@gv = global i32 0, align 4
+@ptr_array = global [2 x ptr] [ptr @inst_to_return_has_different_type_but_no_func_call_use,
+ ptr @multiple_callsites_wrong_return_type]
+
+; Should rewrite this return from i64 to i32 since the function has no
+; uses.
+; INTERESTING-LABEL: @inst_to_return_has_different_type_but_no_func_call_use(
+; RESULT-LABEL: define i32 @inst_to_return_has_different_type_but_no_func_call_use(ptr %arg) {
+; RESULT-NEXT: %load = load i32, ptr %arg, align 4
+; RESULT-NEXT: ret i32 %load
+define i64 @inst_to_return_has_different_type_but_no_func_call_use(ptr %arg) {
+ %load = load i32, ptr %arg
+ store i32 %load, ptr @gv
+ ret i64 0
+}
+
+; INTERESTING-LABEL: @callsite_different_type_unused_0(
+; RESULT-LABEL: define i64 @inst_to_return_has_different_type_but_call_result_unused(
+; RESULT-NEXT: %load = load i32, ptr %arg
+; RESULT-NEXT: store i32 %load, ptr @gv
+; RESULT-NEXT: ret i64 0
+define void @callsite_different_type_unused_0(ptr %arg) {
+ %unused0 = call i64 @inst_to_return_has_different_type_but_call_result_unused(ptr %arg)
+ %unused1 = call i64 @inst_to_return_has_different_type_but_call_result_unused(ptr null)
+ ret void
+}
+
+; TODO: Could rewrite this return from i64 to i32 since the callsite is unused.
+; INTERESTING-LABEL: @inst_to_return_has_different_type_but_call_result_unused(
+; RESULT-LABEL: define i64 @inst_to_return_has_different_type_but_call_result_unused(
+; RESULT: ret i64 0
+define i64 @inst_to_return_has_different_type_but_call_result_unused(ptr %arg) {
+ %load = load i32, ptr %arg
+ store i32 %load, ptr @gv
+ ret i64 0
+}
+
+; INTERESTING-LABEL: @multiple_callsites_wrong_return_type(
+; RESULT-LABEL: define i64 @multiple_callsites_wrong_return_type(
+; RESULT: ret i64 0
+define i64 @multiple_callsites_wrong_return_type(ptr %arg) {
+ %load = load i32, ptr %arg
+ store i32 %load, ptr @gv
+ ret i64 0
+}
+
+; INTERESTING-LABEL: @unused_with_wrong_return_types(
+; RESULT-LABEL: define i64 @unused_with_wrong_return_types(
+; RESULT-NEXT: %unused0 = call i64 @multiple_callsites_wrong_return_type(ptr %arg)
+; RESULT-NEXT: ret i64 %unused0
+define void @unused_with_wrong_return_types(ptr %arg) {
+ %unused0 = call i64 @multiple_callsites_wrong_return_type(ptr %arg)
+ %unused1 = call i32 @multiple_callsites_wrong_return_type(ptr %arg)
+ %unused2 = call ptr @multiple_callsites_wrong_return_type(ptr %arg)
+ ret void
+}
+
+; INTERESTING-LABEL: @multiple_returns_wrong_return_type(
+; INTERESTING: %load0 = load i32,
+
+; RESULT-LABEL: define i32 @multiple_returns_wrong_return_type(
+; RESULT: ret i32
+; RESULT: ret i32
+; RESULT: ret i32
+define i32 @multiple_returns_wrong_return_type(ptr %arg, i1 %cond, i32 %arg2) {
+entry:
+ br i1 %cond, label %bb0, label %bb1
+
+bb0:
+ %load0 = load i32, ptr %arg
+ store i32 %load0, ptr @gv
+ ret i32 234
+
+bb1:
+ ret i32 %arg2
+
+bb2:
+ ret i32 34
+}
+
+; INTERESTING-LABEL: @call_multiple_returns_wrong_return_type(
+; RESULT-LABEL: define <2 x i32> @call_multiple_returns_wrong_return_type(
+; RESULT-NEXT: %unused = call <2 x i32> @multiple_returns_wrong_return_type(
+; RESULT-NEXT: ret <2 x i32> %unused
+define void @call_multiple_returns_wrong_return_type(ptr %arg, i1 %cond, i32 %arg2) {
+ %unused = call <2 x i32> @multiple_returns_wrong_return_type(ptr %arg, i1 %cond, i32 %arg2)
+ ret void
+}
diff --git a/llvm/tools/llvm-reduce/deltas/ReduceValuesToReturn.cpp b/llvm/tools/llvm-reduce/deltas/ReduceValuesToReturn.cpp
index 3e400ffc89482..0a02298acc73e 100644
--- a/llvm/tools/llvm-reduce/deltas/ReduceValuesToReturn.cpp
+++ b/llvm/tools/llvm-reduce/deltas/ReduceValuesToReturn.cpp
@@ -164,7 +164,9 @@ static bool canReplaceFuncUsers(const Function &F, Type *NewRetTy) {
if (CB->getType() == NewRetTy)
continue;
- LLVM_DEBUG(dbgs() << "Cannot replace callsite with wrong type: " << *CB
+ // TODO: If all callsites have no uses, we could mutate the type of all the
+ // callsites. This will complicate the visit and rewrite ordering though.
+ LLVM_DEBUG(dbgs() << "Cannot replace used callsite with wrong type: " << *CB
<< '\n');
return false;
}
@@ -200,8 +202,7 @@ static bool shouldForwardValueToReturn(const BasicBlock &BB, const Value *V,
if (!isReallyValidReturnType(V->getType()))
return false;
- return (RetTy->isVoidTy() ||
- (RetTy == V->getType() && shouldReplaceNonVoidReturnValue(BB, V))) &&
+ return (RetTy->isVoidTy() || shouldReplaceNonVoidReturnValue(BB, V)) &&
canReplaceFuncUsers(*BB.getParent(), V->getType());
}
|
Contributor
Author
|
Forgot the part to fix the multiple return case |
a413a52 to
4baf45b
Compare
You can test this locally with the following command:git-clang-format --diff HEAD~1 HEAD --extensions cpp -- llvm/tools/llvm-reduce/deltas/ReduceValuesToReturn.cppView the diff from clang-format here.diff --git a/llvm/tools/llvm-reduce/deltas/ReduceValuesToReturn.cpp b/llvm/tools/llvm-reduce/deltas/ReduceValuesToReturn.cpp
index 4ef2f50a6..8a5ccb998 100644
--- a/llvm/tools/llvm-reduce/deltas/ReduceValuesToReturn.cpp
+++ b/llvm/tools/llvm-reduce/deltas/ReduceValuesToReturn.cpp
@@ -59,7 +59,8 @@ static void rewriteFuncWithReturnType(Function &OldF, Value *NewRetValue) {
Type *OldRetTy = OldFuncTy->getReturnType();
- // Hack up any return values in other blocks, we can't leave them as returning OldRetTy.
+ // Hack up any return values in other blocks, we can't leave them as returning
+ // OldRetTy.
if (OldRetTy != NewRetTy) {
for (BasicBlock &OtherRetBB : OldF) {
if (&OtherRetBB != NewRetBlock) {
|
449b087 to
3e646d9
Compare
4baf45b to
5490073
Compare
Contributor
|
LGTM! |
5490073 to
f86430f
Compare
3e646d9 to
57ba2fd
Compare
fhahn
approved these changes
Apr 8, 2025
f86430f to
59926c0
Compare
57ba2fd to
51fde94
Compare
59926c0 to
254c039
Compare
51fde94 to
19664d8
Compare
254c039 to
579ac18
Compare
19664d8 to
562a680
Compare
579ac18 to
d5457f8
Compare
562a680 to
53a063e
Compare
Contributor
Author
c48d5d5 to
bc20481
Compare
Base automatically changed from
users/arsenm/llvm-reduce/add-reduce-values-to-return-argument-case
to
main
May 2, 2025 14:17
Extend the early return on value reduction to mutate the function return type if the function has no call uses. This could be generalized to rewrite cases where all callsites are used, but it turns out that complicates the visitation order given we try to compute all opportunities up front. This is enough to cleanup the common case where we end up with one function with a return of an uninteresting constant.
19ec5ce to
07008f3
Compare
IanWood1
pushed a commit
to IanWood1/llvm-project
that referenced
this pull request
May 6, 2025
…lvm#134035) Extend the early return on value reduction to mutate the function return type if the function has no call uses. This could be generalized to rewrite cases where all callsites are used, but it turns out that complicates the visitation order given we try to compute all opportunities up front. This is enough to cleanup the common case where we end up with one function with a return of an uninteresting constant.
GeorgeARM
pushed a commit
to GeorgeARM/llvm-project
that referenced
this pull request
May 7, 2025
…lvm#134035) Extend the early return on value reduction to mutate the function return type if the function has no call uses. This could be generalized to rewrite cases where all callsites are used, but it turns out that complicates the visitation order given we try to compute all opportunities up front. This is enough to cleanup the common case where we end up with one function with a return of an uninteresting constant.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Extend the early return on value reduction to mutate the function return
type if the function has no call uses. This could be generalized to rewrite
cases where all callsites are used, but it turns out that complicates the
visitation order given we try to compute all opportunities up front.
This is enough to cleanup the common case where we end up with one
function with a return of an uninteresting constant.