[llvm] 26bc8b0 - llvm-reduce: Reduce with early return of arguments (#133627)

via llvm-commits llvm-commits at lists.llvm.org
Fri May 2 07:17:17 PDT 2025


Author: Matt Arsenault
Date: 2025-05-02T16:17:14+02:00
New Revision: 26bc8b0ffa4335fa18359de7c224f1460a8c102c

URL: https://github.com/llvm/llvm-project/commit/26bc8b0ffa4335fa18359de7c224f1460a8c102c
DIFF: https://github.com/llvm/llvm-project/commit/26bc8b0ffa4335fa18359de7c224f1460a8c102c.diff

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

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.

Added: 
    llvm/test/tools/llvm-reduce/reduce-values-to-return-args.ll

Modified: 
    llvm/tools/llvm-reduce/DeltaPasses.def
    llvm/tools/llvm-reduce/deltas/ReduceValuesToReturn.cpp
    llvm/tools/llvm-reduce/deltas/ReduceValuesToReturn.h

Removed: 
    


################################################################################
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..e75eb9382e584
--- /dev/null
+++ b/llvm/test/tools/llvm-reduce/reduce-values-to-return-args.ll
@@ -0,0 +1,89 @@
+; 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
+
+ at gv = global i32 0
+
+; INTERESTING-LABEL: @move_entry_block_use_argument_to_return(i32 %arg) {
+; INTERESTING: i32 %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) {
+  store i32 %arg, ptr @gv
+  ret void
+}
+
+; INTERESTING-LABEL: @move_entry_block_use_argument_to_return_existing_ret(i32 %arg) {
+; 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) {
+  store i32 %arg, ptr @gv
+  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_first_arg(i32 %arg0, ptr %arg1) {
+; INTERESTING: %arg0
+
+; RESULT-LABEL: define i32 @keep_first_arg(
+; RESULT-NEXT: ret i32 %arg0
+; RESULT-NEXT: }
+define void @keep_first_arg(i32 %arg0, ptr %arg1) {
+  store i32 %arg0, ptr %arg1
+  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/tools/llvm-reduce/DeltaPasses.def b/llvm/tools/llvm-reduce/DeltaPasses.def
index 421e4472006b6..3aed0ccd74b84 100644
--- a/llvm/tools/llvm-reduce/DeltaPasses.def
+++ b/llvm/tools/llvm-reduce/DeltaPasses.def
@@ -49,7 +49,11 @@ DELTA_PASS_IR("attributes", reduceAttributesDeltaPass, "Reducing Attributes")
 DELTA_PASS_IR("target-features-attr", reduceTargetFeaturesAttrDeltaPass, "Reducing target-features")
 DELTA_PASS_IR("module-data", reduceModuleDataDeltaPass, "Reducing Module Data")
 DELTA_PASS_IR("opcodes", reduceOpcodesDeltaPass, "Reducing Opcodes")
-DELTA_PASS_IR("instructions-to-return", reduceInstructionsToReturnDeltaPass, "Early return of instructions")
+
+DELTA_PASS_IR("arguments-to-return", reduceArgumentsToReturnDeltaPass,
+              "Converting arguments to function return value")
+DELTA_PASS_IR("instructions-to-return", reduceInstructionsToReturnDeltaPass,
+              "Early return of instructions")
 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 91d7f5faea61f..6a0bca6f7f3a8 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()) {
@@ -223,6 +225,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 58279421d9aae..f6dcb9b02df5d 100644
--- a/llvm/tools/llvm-reduce/deltas/ReduceValuesToReturn.h
+++ b/llvm/tools/llvm-reduce/deltas/ReduceValuesToReturn.h
@@ -12,6 +12,7 @@
 #include "Delta.h"
 
 namespace llvm {
+void reduceArgumentsToReturnDeltaPass(Oracle &O, ReducerWorkItem &WorkItem);
 void reduceInstructionsToReturnDeltaPass(Oracle &O, ReducerWorkItem &WorkItem);
 } // namespace llvm
 


        


More information about the llvm-commits mailing list