Skip to content

Commit 449b087

Browse files
committed
llvm-reduce: Reduce with early return of arguments
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.
1 parent f66732b commit 449b087

6 files changed

+124
-7
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
; 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
2+
; RUN: FileCheck --check-prefixes=RESULT %s < %t
3+
4+
5+
; INTERESTING-LABEL: @move_entry_block_use_argument_to_return(i32 %arg, ptr %ptr) {
6+
; INTERESTING: %arg
7+
8+
; RESULT-LABEL: define i32 @move_entry_block_use_argument_to_return(
9+
; RESULT-NEXT: ret i32 %arg
10+
; RESULT-NEXT: }
11+
define void @move_entry_block_use_argument_to_return(i32 %arg, ptr %ptr) {
12+
store i32 %arg, ptr %ptr
13+
ret void
14+
}
15+
16+
; INTERESTING-LABEL: @move_entry_block_use_argument_to_return_existing_ret(i32 %arg, ptr %ptr) {
17+
; INTERESTING: %arg
18+
19+
; RESULT-LABEL: define i32 @move_entry_block_use_argument_to_return_existing_ret(
20+
; RESULT-NEXT: ret i32 %arg
21+
; RESULT-NEXT: }
22+
define i32 @move_entry_block_use_argument_to_return_existing_ret(i32 %arg, ptr %ptr) {
23+
store i32 %arg, ptr %ptr
24+
ret i32 0
25+
}
26+
27+
; INTERESTING-LABEL: @move_phi_block_use_argument_to_return(i32 %arg, ptr %ptr0, ptr %ptr1, i1 %cond0, i1 %cond1) {
28+
; INTERESTING: %arg
29+
30+
; RESULT-LABEL: define i32 @move_phi_block_use_argument_to_return(
31+
; RESULT-NEXT: entry:
32+
; RESULT-NEXT: ret i32 %arg
33+
define void @move_phi_block_use_argument_to_return(i32 %arg, ptr %ptr0, ptr %ptr1, i1 %cond0, i1 %cond1) {
34+
entry:
35+
br i1 %cond0, label %bb0, label %bb1
36+
37+
bb0:
38+
%phi = phi i32 [ %arg, %entry ], [ 123, %bb1 ]
39+
store i32 %arg, ptr %ptr0
40+
store i32 %phi, ptr %ptr1
41+
br label %bb1
42+
43+
bb1:
44+
br i1 %cond1, label %bb0, label %bb2
45+
46+
bb2:
47+
ret void
48+
}
49+
50+
; INTERESTING-LABEL: define {{.*}} @keep_second_arg(i32 %arg0, ptr %arg1) {
51+
; INTERESTING: %arg1
52+
53+
; RESULT-LABEL: define ptr @keep_second_arg(
54+
; RESULT-NEXT: ret ptr %arg1
55+
; RESULT-NEXT: }
56+
define void @keep_second_arg(i32 %arg0, ptr %arg1) {
57+
store i32 %arg0, ptr %arg1
58+
ret void
59+
}
60+
61+
; INTERESTING-LABEL: @multi_void_return_arg(i1 %arg0, ptr %arg1, i32 %arg2) {
62+
; INTERESTING: i32 %arg2
63+
64+
; RESULT-LABEL: define i32 @multi_void_return_arg(i1 %arg0, ptr %arg1, i32 %arg2) {
65+
; RESULT-NEXT: entry:
66+
; RESULT-NEXT: ret i32 %arg2
67+
define void @multi_void_return_arg(i1 %arg0, ptr %arg1, i32 %arg2) {
68+
entry:
69+
br i1 %arg0, label %bb0, label %bb1
70+
71+
bb0:
72+
store i32 %arg2, ptr %arg1
73+
ret void
74+
75+
bb1:
76+
ret void
77+
}

llvm/test/tools/llvm-reduce/reduce-values-to-return-nonvoid-noncallee-use.ll

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
; Make sure we don't break on non-callee uses of funtions with a
22
; non-void return type.
33

4-
; 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
4+
; 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
55
; RUN: FileCheck --check-prefix=RESULT %s < %t
66

77
; INTERESTING-LABEL: @interesting(

llvm/test/tools/llvm-reduce/reduce-values-to-return.ll

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
; Test that llvm-reduce can move intermediate values by inserting
22
; early returns
33
;
4-
; 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
4+
; 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
55
; RUN: FileCheck --check-prefixes=CHECK,RESULT %s < %t
66

77
@gv = global i32 0, align 4

llvm/tools/llvm-reduce/DeltaPasses.def

+4-1
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,10 @@ DELTA_PASS_IR("attributes", reduceAttributesDeltaPass, "Reducing Attributes")
4848
DELTA_PASS_IR("target-features-attr", reduceTargetFeaturesAttrDeltaPass, "Reducing target-features")
4949
DELTA_PASS_IR("module-data", reduceModuleDataDeltaPass, "Reducing Module Data")
5050
DELTA_PASS_IR("opcodes", reduceOpcodesDeltaPass, "Reducing Opcodes")
51-
DELTA_PASS_IR("values-to-return", reduceValuesToReturnDeltaPass, "Converting values to function return value")
51+
DELTA_PASS_IR("arguments-to-return", reduceArgumentsToReturnDeltaPass,
52+
"Converting arguments to function return value")
53+
DELTA_PASS_IR("instructions-to-return", reduceInstructionsToReturnDeltaPass,
54+
"Converting instructions to function return value")
5255
DELTA_PASS_IR("volatile", reduceVolatileInstructionsDeltaPass, "Reducing Volatile Instructions")
5356
DELTA_PASS_IR("atomic-ordering", reduceAtomicOrderingDeltaPass, "Reducing Atomic Ordering")
5457
DELTA_PASS_IR("syncscopes", reduceAtomicSyncScopesDeltaPass, "Reducing Atomic Sync Scopes")

llvm/tools/llvm-reduce/deltas/ReduceValuesToReturn.cpp

+39-3
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,12 @@ static void rewriteFuncWithReturnType(Function &OldF, Value *NewRetValue) {
4848
FunctionType::get(NewRetTy, OldFuncTy->params(), OldFuncTy->isVarArg());
4949

5050
LLVMContext &Ctx = OldF.getContext();
51-
Instruction *NewRetI = cast<Instruction>(NewRetValue);
52-
BasicBlock *NewRetBlock = NewRetI->getParent();
51+
BasicBlock &EntryBB = OldF.getEntryBlock();
52+
Instruction *NewRetI = dyn_cast<Instruction>(NewRetValue);
53+
BasicBlock *NewRetBlock = NewRetI ? NewRetI->getParent() : &EntryBB;
5354

54-
BasicBlock::iterator NewValIt = NewRetI->getIterator();
55+
BasicBlock::iterator NewValIt =
56+
NewRetI ? NewRetI->getIterator() : EntryBB.end();
5557

5658
// Hack up any return values in other blocks, we can't leave them as ret void.
5759
if (OldFuncTy->getReturnType()->isVoidTy()) {
@@ -226,6 +228,40 @@ static bool tryForwardingInstructionsToReturn(
226228
return false;
227229
}
228230

231+
static bool tryForwardingArgumentsToReturn(
232+
Function &F, Oracle &O,
233+
std::vector<std::pair<Function *, Value *>> &FuncsToReplace) {
234+
235+
Type *RetTy = F.getReturnType();
236+
BasicBlock &EntryBB = F.getEntryBlock();
237+
238+
for (Argument &A : F.args()) {
239+
if (shouldForwardValueToReturn(EntryBB, &A, RetTy) && !O.shouldKeep()) {
240+
FuncsToReplace.emplace_back(&F, &A);
241+
return true;
242+
}
243+
}
244+
245+
return false;
246+
}
247+
248+
void llvm::reduceArgumentsToReturnDeltaPass(Oracle &O,
249+
ReducerWorkItem &WorkItem) {
250+
Module &Program = WorkItem.getModule();
251+
252+
// We're going to chaotically hack on the other users of the function in other
253+
// functions, so we need to collect a worklist of returns to replace.
254+
std::vector<std::pair<Function *, Value *>> FuncsToReplace;
255+
256+
for (Function &F : Program.functions()) {
257+
if (!F.isDeclaration() && canUseNonVoidReturnType(F))
258+
tryForwardingArgumentsToReturn(F, O, FuncsToReplace);
259+
}
260+
261+
for (auto [F, NewRetVal] : FuncsToReplace)
262+
rewriteFuncWithReturnType(*F, NewRetVal);
263+
}
264+
229265
void llvm::reduceInstructionsToReturnDeltaPass(Oracle &O,
230266
ReducerWorkItem &WorkItem) {
231267
Module &Program = WorkItem.getModule();

llvm/tools/llvm-reduce/deltas/ReduceValuesToReturn.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@
1212
#include "Delta.h"
1313

1414
namespace llvm {
15-
void reduceValuesToReturnDeltaPass(Oracle &O, ReducerWorkItem &WorkItem);
15+
void reduceArgumentsToReturnDeltaPass(Oracle &O, ReducerWorkItem &WorkItem);
16+
void reduceInstructionsToReturnDeltaPass(Oracle &O, ReducerWorkItem &WorkItem);
1617
} // namespace llvm
1718

1819
#endif

0 commit comments

Comments
 (0)