Skip to content

Commit 26bc8b0

Browse files
authored
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.
1 parent aa4b44e commit 26bc8b0

File tree

4 files changed

+134
-4
lines changed

4 files changed

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

llvm/tools/llvm-reduce/DeltaPasses.def

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,11 @@ DELTA_PASS_IR("attributes", reduceAttributesDeltaPass, "Reducing Attributes")
4949
DELTA_PASS_IR("target-features-attr", reduceTargetFeaturesAttrDeltaPass, "Reducing target-features")
5050
DELTA_PASS_IR("module-data", reduceModuleDataDeltaPass, "Reducing Module Data")
5151
DELTA_PASS_IR("opcodes", reduceOpcodesDeltaPass, "Reducing Opcodes")
52-
DELTA_PASS_IR("instructions-to-return", reduceInstructionsToReturnDeltaPass, "Early return of instructions")
52+
53+
DELTA_PASS_IR("arguments-to-return", reduceArgumentsToReturnDeltaPass,
54+
"Converting arguments to function return value")
55+
DELTA_PASS_IR("instructions-to-return", reduceInstructionsToReturnDeltaPass,
56+
"Early return of instructions")
5357
DELTA_PASS_IR("volatile", reduceVolatileInstructionsDeltaPass, "Reducing Volatile Instructions")
5458
DELTA_PASS_IR("atomic-ordering", reduceAtomicOrderingDeltaPass, "Reducing Atomic Ordering")
5559
DELTA_PASS_IR("syncscopes", reduceAtomicSyncScopesDeltaPass, "Reducing Atomic Sync Scopes")

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

Lines changed: 39 additions & 3 deletions
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()) {
@@ -223,6 +225,40 @@ static bool tryForwardingInstructionsToReturn(
223225
return false;
224226
}
225227

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

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "Delta.h"
1313

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

0 commit comments

Comments
 (0)