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#include "Delta.h"
17#include "llvm/ADT/STLExtras.h"
18#include "llvm/IR/Instructions.h"
19#include <iterator>
20#include <vector>
21
22using namespace llvm;
23
24/// Removes all the Defined Functions
25/// that aren't inside any of the desired Chunks.
26static void extractFunctionsFromModule(const std::vector<Chunk> &ChunksToKeep,
27                                       Module *Program) {
28  Oracle O(ChunksToKeep);
29
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](Function &F) {
34            // Intrinsics don't have function bodies that are useful to
35            // reduce. Additionally, intrinsics may have additional operand
36            // constraints. But, do drop intrinsics that are not referenced.
37            return (!F.isIntrinsic() || F.use_empty()) && !O.shouldKeep();
38          });
39
40  // Then, drop body of each of them. We want to batch this and do nothing else
41  // here so that minimal number of remaining exteranal uses will remain.
42  for (Function &F : FuncsToRemove)
43    F.dropAllReferences();
44
45  // And finally, we can actually delete them.
46  for (Function &F : FuncsToRemove) {
47    // Replace all *still* remaining uses with undef.
48    F.replaceAllUsesWith(UndefValue::get(F.getType()));
49    // And finally, fully drop it.
50    F.eraseFromParent();
51  }
52}
53
54/// Counts the amount of functions and prints their
55/// respective name & index
56static int countFunctions(Module *Program) {
57  // TODO: Silence index with --quiet flag
58  errs() << "----------------------------\n";
59  errs() << "Function Index Reference:\n";
60  int FunctionCount = 0;
61  for (auto &F : *Program) {
62    if (F.isIntrinsic() && !F.use_empty())
63      continue;
64
65    errs() << '\t' << ++FunctionCount << ": " << F.getName() << '\n';
66  }
67
68  errs() << "----------------------------\n";
69  return FunctionCount;
70}
71
72void llvm::reduceFunctionsDeltaPass(TestRunner &Test) {
73  errs() << "*** Reducing Functions...\n";
74  int Functions = countFunctions(Test.getProgram());
75  runDeltaPass(Test, Functions, extractFunctionsFromModule);
76  errs() << "----------------------------\n";
77}
78