xref: /llvm-project/llvm/tools/llvm-reduce/deltas/ReduceFunctions.cpp (revision bda73ae0bbb0d8a11c5e4b58dd1461748f8f54dd)
1 //===- ReduceFunctions.cpp - Specialized Delta Pass -----------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements a function which calls the Generic Delta pass in order
10 // to reduce functions (and any instruction that calls it) in the provided
11 // Module.
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #include "ReduceFunctions.h"
16 
17 /// Removes all the Defined Functions (as well as their calls)
18 /// that aren't inside any of the desired Chunks.
19 static void extractFunctionsFromModule(const std::vector<Chunk> &ChunksToKeep,
20                                        Module *Program) {
21   // Get functions inside desired chunks
22   std::set<Function *> FuncsToKeep;
23   unsigned I = 0, FunctionCount = 0;
24   for (auto &F : *Program)
25     if (!F.isDeclaration() && I < ChunksToKeep.size()) {
26       if (ChunksToKeep[I].contains(++FunctionCount))
27         FuncsToKeep.insert(&F);
28       if (FunctionCount == ChunksToKeep[I].end)
29         ++I;
30     }
31 
32   // Delete out-of-chunk functions, and replace their calls with undef
33   std::vector<Function *> FuncsToRemove;
34   for (auto &F : *Program)
35     if (!F.isDeclaration() && !FuncsToKeep.count(&F)) {
36       F.replaceAllUsesWith(UndefValue::get(F.getType()));
37       FuncsToRemove.push_back(&F);
38     }
39 
40   for (auto *F : FuncsToRemove)
41     F->eraseFromParent();
42 
43   // Delete instructions with undef calls
44   std::vector<Instruction *> InstToRemove;
45   for (auto &F : *Program)
46     for (auto &BB : F)
47       for (auto &I : BB)
48         if (auto *Call = dyn_cast<CallInst>(&I))
49           if (!Call->getCalledFunction()) {
50             // Instruction might be stored / used somewhere else
51             I.replaceAllUsesWith(UndefValue::get(I.getType()));
52             InstToRemove.push_back(&I);
53           }
54 
55   for (auto *I : InstToRemove)
56     I->eraseFromParent();
57 }
58 
59 /// Counts the amount of non-declaration functions and prints their
60 /// respective name & index
61 static unsigned countDefinedFunctions(Module *Program) {
62   // TODO: Silence index with --quiet flag
63   outs() << "----------------------------\n";
64   outs() << "Function Index Reference:\n";
65   unsigned FunctionCount = 0;
66   for (auto &F : *Program)
67     if (!F.isDeclaration())
68       outs() << "\t" << ++FunctionCount << ": " << F.getName() << "\n";
69 
70   outs() << "----------------------------\n";
71   return FunctionCount;
72 }
73 
74 void llvm::reduceFunctionsDeltaPass(TestRunner &Test) {
75   outs() << "*** Reducing Functions...\n";
76   unsigned Functions = countDefinedFunctions(Test.getProgram());
77   runDeltaPass(Test, Functions, extractFunctionsFromModule);
78   outs() << "----------------------------\n";
79 }
80