Skip to content

llvm-reduce: Reduce with early return of arguments #133627

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

Conversation

arsenm
Copy link
Contributor

@arsenm arsenm commented Mar 30, 2025

Extend the instruction -> return reduction with one that inserts
return of function arguments. Not sure how useful this really is. This
has more freedom since we could insert the return anywhere in the function,
but this just inserts the return in the entry block.

Copy link
Contributor Author

arsenm commented Mar 30, 2025

@arsenm arsenm marked this pull request as ready for review March 30, 2025 07:44
@llvmbot
Copy link
Member

llvmbot commented Mar 30, 2025

@llvm/pr-subscribers-llvm-ir

Author: Matt Arsenault (arsenm)

Changes

Extend the instruction -> return reduction with one that inserts
return of function arguments. Not sure how useful this really is. This
has more freedom since we could insert the return anywhere in the function,
but this just inserts the return in the entry block.


Full diff: https://github.com/llvm/llvm-project/pull/133627.diff

6 Files Affected:

  • (added) llvm/test/tools/llvm-reduce/reduce-values-to-return-args.ll (+77)
  • (modified) llvm/test/tools/llvm-reduce/reduce-values-to-return-nonvoid-noncallee-use.ll (+1-1)
  • (modified) llvm/test/tools/llvm-reduce/reduce-values-to-return.ll (+1-1)
  • (modified) llvm/tools/llvm-reduce/DeltaPasses.def (+4-1)
  • (modified) llvm/tools/llvm-reduce/deltas/ReduceValuesToReturn.cpp (+39-3)
  • (modified) llvm/tools/llvm-reduce/deltas/ReduceValuesToReturn.h (+2-1)
diff --git a/llvm/test/tools/llvm-reduce/reduce-values-to-return-args.ll b/llvm/test/tools/llvm-reduce/reduce-values-to-return-args.ll
new file mode 100644
index 0000000000000..abbc643822033
--- /dev/null
+++ b/llvm/test/tools/llvm-reduce/reduce-values-to-return-args.ll
@@ -0,0 +1,77 @@
+; RUN: llvm-reduce --abort-on-invalid-reduction --delta-passes=arguments-to-return --test FileCheck --test-arg --check-prefixes=INTERESTING --test-arg %s --test-arg --input-file %s -o %t
+; RUN: FileCheck --check-prefixes=RESULT %s < %t
+
+
+; INTERESTING-LABEL: @move_entry_block_use_argument_to_return(i32 %arg, ptr %ptr) {
+; INTERESTING: %arg
+
+; RESULT-LABEL: define i32 @move_entry_block_use_argument_to_return(
+; RESULT-NEXT: ret i32 %arg
+; RESULT-NEXT: }
+define void @move_entry_block_use_argument_to_return(i32 %arg, ptr %ptr) {
+  store i32 %arg, ptr %ptr
+  ret void
+}
+
+; INTERESTING-LABEL: @move_entry_block_use_argument_to_return_existing_ret(i32 %arg, ptr %ptr) {
+; INTERESTING: %arg
+
+; RESULT-LABEL: define i32 @move_entry_block_use_argument_to_return_existing_ret(
+; RESULT-NEXT: ret i32 %arg
+; RESULT-NEXT: }
+define i32 @move_entry_block_use_argument_to_return_existing_ret(i32 %arg, ptr %ptr) {
+  store i32 %arg, ptr %ptr
+  ret i32 0
+}
+
+; INTERESTING-LABEL: @move_phi_block_use_argument_to_return(i32 %arg, ptr %ptr0, ptr %ptr1, i1 %cond0, i1 %cond1) {
+; INTERESTING: %arg
+
+; RESULT-LABEL: define i32 @move_phi_block_use_argument_to_return(
+; RESULT-NEXT: entry:
+; RESULT-NEXT: ret i32 %arg
+define void @move_phi_block_use_argument_to_return(i32 %arg, ptr %ptr0, ptr %ptr1, i1 %cond0, i1 %cond1) {
+entry:
+  br i1 %cond0, label %bb0, label %bb1
+
+bb0:
+  %phi = phi i32 [ %arg, %entry ], [ 123, %bb1 ]
+  store i32 %arg, ptr %ptr0
+  store i32 %phi, ptr %ptr1
+  br label %bb1
+
+bb1:
+  br i1 %cond1, label %bb0, label %bb2
+
+bb2:
+  ret void
+}
+
+; INTERESTING-LABEL: define {{.*}} @keep_second_arg(i32 %arg0, ptr %arg1) {
+; INTERESTING: %arg1
+
+; RESULT-LABEL: define ptr @keep_second_arg(
+; RESULT-NEXT: ret ptr %arg1
+; RESULT-NEXT: }
+define void @keep_second_arg(i32 %arg0, ptr %arg1) {
+  store i32 %arg0, ptr %arg1
+  ret void
+}
+
+; INTERESTING-LABEL: @multi_void_return_arg(i1 %arg0, ptr %arg1, i32 %arg2) {
+; INTERESTING: i32 %arg2
+
+; RESULT-LABEL: define i32 @multi_void_return_arg(i1 %arg0, ptr %arg1, i32 %arg2) {
+; RESULT-NEXT: entry:
+; RESULT-NEXT: ret i32 %arg2
+define void @multi_void_return_arg(i1 %arg0, ptr %arg1, i32 %arg2) {
+entry:
+  br i1 %arg0, label %bb0, label %bb1
+
+bb0:
+  store i32 %arg2, ptr %arg1
+  ret void
+
+bb1:
+  ret void
+}
diff --git a/llvm/test/tools/llvm-reduce/reduce-values-to-return-nonvoid-noncallee-use.ll b/llvm/test/tools/llvm-reduce/reduce-values-to-return-nonvoid-noncallee-use.ll
index 215ea97a8be91..11166479318c6 100644
--- a/llvm/test/tools/llvm-reduce/reduce-values-to-return-nonvoid-noncallee-use.ll
+++ b/llvm/test/tools/llvm-reduce/reduce-values-to-return-nonvoid-noncallee-use.ll
@@ -1,7 +1,7 @@
 ; Make sure we don't break on non-callee uses of funtions with a
 ; non-void return type.
 
-; RUN: llvm-reduce --abort-on-invalid-reduction --delta-passes=values-to-return --test FileCheck --test-arg --check-prefix=INTERESTING --test-arg %s --test-arg --input-file %s -o %t
+; 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
 
 ; INTERESTING-LABEL: @interesting(
diff --git a/llvm/test/tools/llvm-reduce/reduce-values-to-return.ll b/llvm/test/tools/llvm-reduce/reduce-values-to-return.ll
index 0c36db8ebc278..2af87aad05169 100644
--- a/llvm/test/tools/llvm-reduce/reduce-values-to-return.ll
+++ b/llvm/test/tools/llvm-reduce/reduce-values-to-return.ll
@@ -1,7 +1,7 @@
 ; Test that llvm-reduce can move intermediate values by inserting
 ; early returns
 ;
-; RUN: llvm-reduce --abort-on-invalid-reduction --delta-passes=values-to-return --test FileCheck --test-arg --check-prefixes=CHECK,INTERESTING --test-arg %s --test-arg --input-file %s -o %t
+; RUN: llvm-reduce --abort-on-invalid-reduction --delta-passes=instructions-to-return --test FileCheck --test-arg --check-prefixes=CHECK,INTERESTING --test-arg %s --test-arg --input-file %s -o %t
 ; RUN: FileCheck --check-prefixes=CHECK,RESULT %s < %t
 
 @gv = global i32 0, align 4
diff --git a/llvm/tools/llvm-reduce/DeltaPasses.def b/llvm/tools/llvm-reduce/DeltaPasses.def
index bf1e71de6f312..e9a265e6cc793 100644
--- a/llvm/tools/llvm-reduce/DeltaPasses.def
+++ b/llvm/tools/llvm-reduce/DeltaPasses.def
@@ -47,7 +47,10 @@ DELTA_PASS_IR("operand-bundles", reduceOperandBundesDeltaPass, "Reducing Operand
 DELTA_PASS_IR("attributes", reduceAttributesDeltaPass, "Reducing Attributes")
 DELTA_PASS_IR("module-data", reduceModuleDataDeltaPass, "Reducing Module Data")
 DELTA_PASS_IR("opcodes", reduceOpcodesDeltaPass, "Reducing Opcodes")
-DELTA_PASS_IR("values-to-return", reduceValuesToReturnDeltaPass, "Converting values to function return value")
+DELTA_PASS_IR("arguments-to-return", reduceArgumentsToReturnDeltaPass,
+              "Converting arguments to function return value")
+DELTA_PASS_IR("instructions-to-return", reduceInstructionsToReturnDeltaPass,
+              "Converting instructions to function return value")
 DELTA_PASS_IR("volatile", reduceVolatileInstructionsDeltaPass, "Reducing Volatile Instructions")
 DELTA_PASS_IR("atomic-ordering", reduceAtomicOrderingDeltaPass, "Reducing Atomic Ordering")
 DELTA_PASS_IR("syncscopes", reduceAtomicSyncScopesDeltaPass, "Reducing Atomic Sync Scopes")
diff --git a/llvm/tools/llvm-reduce/deltas/ReduceValuesToReturn.cpp b/llvm/tools/llvm-reduce/deltas/ReduceValuesToReturn.cpp
index 9ee0af3e1a69b..3e400ffc89482 100644
--- a/llvm/tools/llvm-reduce/deltas/ReduceValuesToReturn.cpp
+++ b/llvm/tools/llvm-reduce/deltas/ReduceValuesToReturn.cpp
@@ -48,10 +48,12 @@ static void rewriteFuncWithReturnType(Function &OldF, Value *NewRetValue) {
       FunctionType::get(NewRetTy, OldFuncTy->params(), OldFuncTy->isVarArg());
 
   LLVMContext &Ctx = OldF.getContext();
-  Instruction *NewRetI = cast<Instruction>(NewRetValue);
-  BasicBlock *NewRetBlock = NewRetI->getParent();
+  BasicBlock &EntryBB = OldF.getEntryBlock();
+  Instruction *NewRetI = dyn_cast<Instruction>(NewRetValue);
+  BasicBlock *NewRetBlock = NewRetI ? NewRetI->getParent() : &EntryBB;
 
-  BasicBlock::iterator NewValIt = NewRetI->getIterator();
+  BasicBlock::iterator NewValIt =
+      NewRetI ? NewRetI->getIterator() : EntryBB.end();
 
   // Hack up any return values in other blocks, we can't leave them as ret void.
   if (OldFuncTy->getReturnType()->isVoidTy()) {
@@ -226,6 +228,40 @@ static bool tryForwardingInstructionsToReturn(
   return false;
 }
 
+static bool tryForwardingArgumentsToReturn(
+    Function &F, Oracle &O,
+    std::vector<std::pair<Function *, Value *>> &FuncsToReplace) {
+
+  Type *RetTy = F.getReturnType();
+  BasicBlock &EntryBB = F.getEntryBlock();
+
+  for (Argument &A : F.args()) {
+    if (shouldForwardValueToReturn(EntryBB, &A, RetTy) && !O.shouldKeep()) {
+      FuncsToReplace.emplace_back(&F, &A);
+      return true;
+    }
+  }
+
+  return false;
+}
+
+void llvm::reduceArgumentsToReturnDeltaPass(Oracle &O,
+                                            ReducerWorkItem &WorkItem) {
+  Module &Program = WorkItem.getModule();
+
+  // We're going to chaotically hack on the other users of the function in other
+  // functions, so we need to collect a worklist of returns to replace.
+  std::vector<std::pair<Function *, Value *>> FuncsToReplace;
+
+  for (Function &F : Program.functions()) {
+    if (!F.isDeclaration() && canUseNonVoidReturnType(F))
+      tryForwardingArgumentsToReturn(F, O, FuncsToReplace);
+  }
+
+  for (auto [F, NewRetVal] : FuncsToReplace)
+    rewriteFuncWithReturnType(*F, NewRetVal);
+}
+
 void llvm::reduceInstructionsToReturnDeltaPass(Oracle &O,
                                                ReducerWorkItem &WorkItem) {
   Module &Program = WorkItem.getModule();
diff --git a/llvm/tools/llvm-reduce/deltas/ReduceValuesToReturn.h b/llvm/tools/llvm-reduce/deltas/ReduceValuesToReturn.h
index 7bfde832555bc..f6dcb9b02df5d 100644
--- a/llvm/tools/llvm-reduce/deltas/ReduceValuesToReturn.h
+++ b/llvm/tools/llvm-reduce/deltas/ReduceValuesToReturn.h
@@ -12,7 +12,8 @@
 #include "Delta.h"
 
 namespace llvm {
-void reduceValuesToReturnDeltaPass(Oracle &O, ReducerWorkItem &WorkItem);
+void reduceArgumentsToReturnDeltaPass(Oracle &O, ReducerWorkItem &WorkItem);
+void reduceInstructionsToReturnDeltaPass(Oracle &O, ReducerWorkItem &WorkItem);
 } // namespace llvm
 
 #endif

@regehr
Copy link
Contributor

regehr commented Mar 31, 2025

yeah I don't feel like we'll get interesting variants out of this one very often, but who knows. at some point it would be interesting to get a global view of which passes are providing interesting variants in practice and which ones aren't.

anyhow-- LGTM, this shouldn't slow reductions down noticeably.

@arsenm arsenm force-pushed the users/arsenm/llvm-reduce/add-reduce-values-to-return-argument-case branch from 349a15d to 449b087 Compare April 2, 2025 06:24
@arsenm arsenm force-pushed the users/arsenm/llvm-reduce/add-reduce-values-to-return-reduction branch from d1a9a08 to f66732b Compare April 2, 2025 06:24
@arsenm arsenm force-pushed the users/arsenm/llvm-reduce/add-reduce-values-to-return-reduction branch from f66732b to 976e948 Compare April 2, 2025 07:51
@arsenm arsenm force-pushed the users/arsenm/llvm-reduce/add-reduce-values-to-return-argument-case branch from 449b087 to 3e646d9 Compare April 2, 2025 07:51
@arsenm arsenm force-pushed the users/arsenm/llvm-reduce/add-reduce-values-to-return-reduction branch from 976e948 to 655b6d8 Compare April 8, 2025 06:47
@arsenm arsenm force-pushed the users/arsenm/llvm-reduce/add-reduce-values-to-return-argument-case branch from 3e646d9 to 57ba2fd Compare April 8, 2025 06:47
@arsenm arsenm force-pushed the users/arsenm/llvm-reduce/add-reduce-values-to-return-argument-case branch from 57ba2fd to 51fde94 Compare April 23, 2025 20:19
@arsenm arsenm force-pushed the users/arsenm/llvm-reduce/add-reduce-values-to-return-reduction branch 2 times, most recently from 256d7cd to dba33af Compare April 25, 2025 14:50
@arsenm arsenm force-pushed the users/arsenm/llvm-reduce/add-reduce-values-to-return-argument-case branch 2 times, most recently from 19664d8 to 562a680 Compare May 2, 2025 10:09
@arsenm arsenm force-pushed the users/arsenm/llvm-reduce/add-reduce-values-to-return-reduction branch 2 times, most recently from c1d5c08 to 754dc68 Compare May 2, 2025 11:52
@arsenm arsenm force-pushed the users/arsenm/llvm-reduce/add-reduce-values-to-return-argument-case branch from 562a680 to 53a063e Compare May 2, 2025 11:52
Copy link
Contributor Author

arsenm commented May 2, 2025

Merge activity

  • May 2, 10:06 AM EDT: A user started a stack merge that includes this pull request via Graphite.
  • May 2, 10:12 AM EDT: Graphite rebased this pull request as part of a merge.
  • May 2, 10:15 AM EDT: Graphite rebased this pull request as part of a merge.
  • May 2, 10:17 AM EDT: @arsenm merged this pull request with Graphite.

@arsenm arsenm force-pushed the users/arsenm/llvm-reduce/add-reduce-values-to-return-reduction branch from 754dc68 to f2584ca Compare May 2, 2025 14:08
Base automatically changed from users/arsenm/llvm-reduce/add-reduce-values-to-return-reduction to main May 2, 2025 14:11
@arsenm arsenm force-pushed the users/arsenm/llvm-reduce/add-reduce-values-to-return-argument-case branch from 53a063e to c48d5d5 Compare May 2, 2025 14:11
arsenm added 2 commits May 2, 2025 14:14
Extend the instruction -> return reduction with one that inserts
return of function arguments. Not sure how useful this really is. This
has more freedom since we could insert the return anywhere in the function,
but this just inserts the return in the entry block.
@arsenm arsenm force-pushed the users/arsenm/llvm-reduce/add-reduce-values-to-return-argument-case branch from c48d5d5 to bc20481 Compare May 2, 2025 14:14
@arsenm arsenm merged commit 26bc8b0 into main May 2, 2025
4 of 5 checks passed
@arsenm arsenm deleted the users/arsenm/llvm-reduce/add-reduce-values-to-return-argument-case branch May 2, 2025 14:17
IanWood1 pushed a commit to IanWood1/llvm-project that referenced this pull request May 6, 2025
Extend the instruction -> return reduction with one that inserts
return of function arguments. Not sure how useful this really is. This
has more freedom since we could insert the return anywhere in the function,
but this just inserts the return in the entry block.
IanWood1 pushed a commit to IanWood1/llvm-project that referenced this pull request May 6, 2025
Extend the instruction -> return reduction with one that inserts
return of function arguments. Not sure how useful this really is. This
has more freedom since we could insert the return anywhere in the function,
but this just inserts the return in the entry block.
IanWood1 pushed a commit to IanWood1/llvm-project that referenced this pull request May 6, 2025
Extend the instruction -> return reduction with one that inserts
return of function arguments. Not sure how useful this really is. This
has more freedom since we could insert the return anywhere in the function,
but this just inserts the return in the entry block.
GeorgeARM pushed a commit to GeorgeARM/llvm-project that referenced this pull request May 7, 2025
Extend the instruction -> return reduction with one that inserts
return of function arguments. Not sure how useful this really is. This
has more freedom since we could insert the return anywhere in the function,
but this just inserts the return in the entry block.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants