xref: /llvm-project/llvm/tools/llvm-reduce/deltas/ReduceFunctions.cpp (revision ddc64eb948c7e71039325f21bc4e1cc763494da5)
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 /// @returns the Module stripped of out-of-chunk functions
20 static void extractFunctionsFromModule(const std::vector<Chunk> &ChunksToKeep,
21                                        Module *Program) {
22   // Get functions inside desired chunks
23   std::set<Function *> FuncsToKeep;
24   unsigned I = 0, FunctionCount = 0;
25   for (auto &F : *Program)
26     if (!F.isDeclaration() && I < ChunksToKeep.size()) {
27       if (ChunksToKeep[I].contains(++FunctionCount))
28         FuncsToKeep.insert(&F);
29       if (FunctionCount == ChunksToKeep[I].end)
30         ++I;
31     }
32 
33   // Delete out-of-chunk functions, and replace their calls with undef
34   std::vector<Function *> FuncsToRemove;
35   for (auto &F : *Program)
36     if (!F.isDeclaration() && !FuncsToKeep.count(&F)) {
37       F.replaceAllUsesWith(UndefValue::get(F.getType()));
38       FuncsToRemove.push_back(&F);
39     }
40 
41   for (auto *F : FuncsToRemove)
42     F->eraseFromParent();
43 
44   // Delete instructions with undef calls
45   std::vector<Instruction *> InstToRemove;
46   for (auto &F : *Program)
47     for (auto &BB : F)
48       for (auto &I : BB)
49         if (auto *Call = dyn_cast<CallInst>(&I))
50           if (!Call->getCalledFunction()) {
51             // Instruction might be stored / used somewhere else
52             I.replaceAllUsesWith(UndefValue::get(I.getType()));
53             InstToRemove.push_back(&I);
54           }
55 
56   for (auto *I : InstToRemove)
57     I->eraseFromParent();
58 }
59 
60 /// Counts the amount of non-declaration functions and prints their
61 /// respective name & index
62 static unsigned countDefinedFunctions(Module *Program) {
63   // TODO: Silence index with --quiet flag
64   outs() << "----------------------------\n";
65   outs() << "Function Index Reference:\n";
66   unsigned FunctionCount = 0;
67   for (auto &F : *Program)
68     if (!F.isDeclaration())
69       outs() << "\t" << ++FunctionCount << ": " << F.getName() << "\n";
70 
71   outs() << "----------------------------\n";
72   return FunctionCount;
73 }
74 
75 void llvm::reduceFunctionsDeltaPass(TestRunner &Test) {
76   outs() << "*** Reducing Functions...\n";
77   unsigned Functions = countDefinedFunctions(Test.getProgram());
78   runDeltaPass(Test, Functions, extractFunctionsFromModule);
79   outs() << "----------------------------\n";
80 }