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