Skip to content

Commit d4c3f20

Browse files
committed
[Reduce] Rewrite function body delta pass again
It is not enough to replace all uses of users of the function with undef, the users, we only drop instruction users, so they may stick around. Let's try different approach - first drop bodies for all the functions we will drop, which should take care of blockaddress issue the previous rewrite was dealing with; then, after dropping *all* such bodies, replace remaining uses with undef (thus all the uses are either outside of functions, or are in kept functions) and then finally drop functions. This seems to work, and passes the *existing* test coverage, but it is possible that a new issue will be discovered later :) A new (previously crashing) test added.
1 parent 48887c4 commit d4c3f20

File tree

2 files changed

+33
-25
lines changed

2 files changed

+33
-25
lines changed
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
; RUN: llvm-reduce --test FileCheck --test-arg --check-prefixes=CHECK-ALL,CHECK-INTERESTINGNESS --test-arg %s --test-arg --input-file %s -o %t
2+
; RUN: cat %t | FileCheck --check-prefixes=CHECK-ALL,CHECK-FINAL %s
3+
4+
; CHECK-INTERESTINGNESS: @alias =
5+
; CHECK-FINAL: @alias = alias void (i32), void (i32)* undef
6+
7+
@alias = alias void (i32), void (i32)* @func
8+
9+
; CHECK-FINAL-NOT: @func()
10+
11+
define void @func(i32 %arg) {
12+
entry:
13+
ret void
14+
}

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

Lines changed: 19 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -14,42 +14,36 @@
1414

1515
#include "ReduceFunctions.h"
1616
#include "Delta.h"
17-
#include "llvm/ADT/SetVector.h"
17+
#include "llvm/ADT/STLExtras.h"
1818
#include "llvm/IR/Instructions.h"
19-
#include <set>
19+
#include <iterator>
20+
#include <vector>
2021

2122
using namespace llvm;
2223

23-
/// Removes all the Defined Functions (as well as their calls)
24+
/// Removes all the Defined Functions
2425
/// that aren't inside any of the desired Chunks.
2526
static void extractFunctionsFromModule(const std::vector<Chunk> &ChunksToKeep,
2627
Module *Program) {
2728
Oracle O(ChunksToKeep);
2829

29-
// Get functions inside desired chunks
30-
std::set<Function *> FuncsToKeep;
31-
for (auto &F : *Program)
32-
if (O.shouldKeep())
33-
FuncsToKeep.insert(&F);
34-
35-
// Delete out-of-chunk functions, and replace their users with undef
36-
std::vector<Function *> FuncsToRemove;
37-
SetVector<Instruction *> InstrsToRemove;
38-
for (auto &F : *Program)
39-
if (!FuncsToKeep.count(&F)) {
40-
for (auto U : F.users()) {
41-
U->replaceAllUsesWith(UndefValue::get(U->getType()));
42-
if (auto *I = dyn_cast<Instruction>(U))
43-
InstrsToRemove.insert(I);
44-
}
45-
FuncsToRemove.push_back(&F);
46-
}
30+
// Record all out-of-chunk functions.
31+
std::vector<std::reference_wrapper<Function>> FuncsToRemove;
32+
copy_if(Program->functions(), std::back_inserter(FuncsToRemove),
33+
[&O](auto &unused) { return !O.shouldKeep(); });
4734

48-
for (auto *I : InstrsToRemove)
49-
I->eraseFromParent();
35+
// Then, drop body of each of them. We want to batch this and do nothing else
36+
// here so that minimal number of remaining exteranal uses will remain.
37+
for (Function &F : FuncsToRemove)
38+
F.dropAllReferences();
5039

51-
for (auto *F : FuncsToRemove)
52-
F->eraseFromParent();
40+
// And finally, we can actually delete them.
41+
for (Function &F : FuncsToRemove) {
42+
// Replace all *still* remaining uses with undef.
43+
F.replaceAllUsesWith(UndefValue::get(F.getType()));
44+
// And finally, fully drop it.
45+
F.eraseFromParent();
46+
}
5347
}
5448

5549
/// Counts the amount of non-declaration functions and prints their

0 commit comments

Comments
 (0)