1//===- ReduceGlobalVars.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 Global Variables in the provided Module.
11//
12//===----------------------------------------------------------------------===//
13
14#include "ReduceGlobalVars.h"
15#include "Utils.h"
16#include "llvm/IR/Value.h"
17#include "llvm/Transforms/Utils/Cloning.h"
18#include "llvm/Transforms/Utils/ModuleUtils.h"
19
20using namespace llvm;
21
22static bool shouldAlwaysKeep(const GlobalVariable &GV) {
23 return GV.getName() == "llvm.used" || GV.getName() == "llvm.compiler.used";
24}
25
26/// Removes all the GVs that aren't inside the desired Chunks.
27void llvm::reduceGlobalsDeltaPass(Oracle &O, ReducerWorkItem &WorkItem) {
28 Module &Program = WorkItem.getModule();
29
30 // Get GVs inside desired chunks
31 std::vector<Constant *> InitGVsToKeep;
32 for (auto &GV : Program.globals()) {
33 if (shouldAlwaysKeep(GV) || O.shouldKeep())
34 InitGVsToKeep.push_back(x: &GV);
35 }
36
37 // We create a vector first, then convert it to a set, so that we don't have
38 // to pay the cost of rebalancing the set frequently if the order we insert
39 // the elements doesn't match the order they should appear inside the set.
40 DenseSet<Constant *> GVsToKeep(InitGVsToKeep.begin(), InitGVsToKeep.end());
41
42 // Delete out-of-chunk GVs and their uses
43 DenseSet<Constant *> ToRemove;
44 for (auto &GV : Program.globals()) {
45 if (!GVsToKeep.count(V: &GV))
46 ToRemove.insert(V: &GV);
47 }
48
49 removeFromUsedLists(M&: Program,
50 ShouldRemove: [&ToRemove](Constant *C) { return ToRemove.count(V: C); });
51
52 for (auto *GV : ToRemove) {
53 GV->replaceAllUsesWith(V: getDefaultValue(T: GV->getType()));
54 cast<GlobalVariable>(Val: GV)->eraseFromParent();
55 }
56}
57