-
Notifications
You must be signed in to change notification settings - Fork 14.3k
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
llvm-reduce: Reduce with early return of arguments #133627
Conversation
This stack of pull requests is managed by Graphite. Learn more about stacking. |
@llvm/pr-subscribers-llvm-ir Author: Matt Arsenault (arsenm) ChangesExtend the instruction -> return reduction with one that inserts Full diff: https://github.com/llvm/llvm-project/pull/133627.diff 6 Files Affected:
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
|
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. |
349a15d
to
449b087
Compare
d1a9a08
to
f66732b
Compare
f66732b
to
976e948
Compare
449b087
to
3e646d9
Compare
976e948
to
655b6d8
Compare
3e646d9
to
57ba2fd
Compare
57ba2fd
to
51fde94
Compare
256d7cd
to
dba33af
Compare
19664d8
to
562a680
Compare
c1d5c08
to
754dc68
Compare
562a680
to
53a063e
Compare
Merge activity
|
754dc68
to
f2584ca
Compare
53a063e
to
c48d5d5
Compare
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.
c48d5d5
to
bc20481
Compare
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.
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.
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.
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.
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.