1 //===- ReduceArguments.cpp - Specialized Delta Pass -----------------------===//
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
7 //===----------------------------------------------------------------------===//
9 // This file implements a function which calls the Generic Delta pass in order
10 // to reduce uninteresting Arguments from defined functions.
12 //===----------------------------------------------------------------------===//
14 #include "ReduceArguments.h"
16 #include "llvm/ADT/SmallVector.h"
22 /// Goes over OldF calls and replaces them with a call to NewF
23 static void replaceFunctionCalls(Function
&OldF
, Function
&NewF
,
24 const std::set
<int> &ArgIndexesToKeep
) {
25 const auto &Users
= OldF
.users();
26 for (auto I
= Users
.begin(), E
= Users
.end(); I
!= E
; )
27 if (auto *CI
= dyn_cast
<CallInst
>(*I
++)) {
28 SmallVector
<Value
*, 8> Args
;
29 for (auto ArgI
= CI
->arg_begin(), E
= CI
->arg_end(); ArgI
!= E
; ++ArgI
)
30 if (ArgIndexesToKeep
.count(ArgI
- CI
->arg_begin()))
31 Args
.push_back(*ArgI
);
33 CallInst
*NewCI
= CallInst::Create(&NewF
, Args
);
34 NewCI
->setCallingConv(NewF
.getCallingConv());
36 CI
->replaceAllUsesWith(NewCI
);
37 ReplaceInstWithInst(CI
, NewCI
);
41 /// Removes out-of-chunk arguments from functions, and modifies their calls
42 /// accordingly. It also removes allocations of out-of-chunk arguments.
43 static void extractArgumentsFromModule(std::vector
<Chunk
> ChunksToKeep
,
45 int I
= 0, ArgCount
= 0;
46 std::set
<Argument
*> ArgsToKeep
;
47 std::vector
<Function
*> Funcs
;
48 // Get inside-chunk arguments, as well as their parent function
49 for (auto &F
: *Program
)
50 if (!F
.isDeclaration()) {
52 for (auto &A
: F
.args())
53 if (I
< (int)ChunksToKeep
.size()) {
54 if (ChunksToKeep
[I
].contains(++ArgCount
))
55 ArgsToKeep
.insert(&A
);
56 if (ChunksToKeep
[I
].end
== ArgCount
)
61 for (auto *F
: Funcs
) {
62 ValueToValueMapTy VMap
;
63 std::vector
<Instruction
*> InstToDelete
;
64 for (auto &A
: F
->args())
65 if (!ArgsToKeep
.count(&A
)) {
66 // By adding undesired arguments to the VMap, CloneFunction will remove
67 // them from the resulting Function
68 VMap
[&A
] = UndefValue::get(A
.getType());
69 for (auto *U
: A
.users())
70 if (auto *I
= dyn_cast
<Instruction
>(*&U
))
71 InstToDelete
.push_back(I
);
73 // Delete any instruction that uses the argument
74 for (auto *I
: InstToDelete
) {
75 I
->replaceAllUsesWith(UndefValue::get(I
->getType()));
79 // No arguments to reduce
83 std::set
<int> ArgIndexesToKeep
;
85 for (auto &Arg
: F
->args())
86 if (ArgsToKeep
.count(&Arg
))
87 ArgIndexesToKeep
.insert(++ArgI
);
89 auto *ClonedFunc
= CloneFunction(F
, VMap
);
90 // In order to preserve function order, we move Clone after old Function
91 ClonedFunc
->removeFromParent();
92 Program
->getFunctionList().insertAfter(F
->getIterator(), ClonedFunc
);
94 replaceFunctionCalls(*F
, *ClonedFunc
, ArgIndexesToKeep
);
95 // Rename Cloned Function to Old's name
96 std::string FName
= F
->getName();
98 ClonedFunc
->setName(FName
);
102 /// Counts the amount of arguments in non-declaration functions and prints their
103 /// respective name, index, and parent function name
104 static int countArguments(Module
*Program
) {
105 // TODO: Silence index with --quiet flag
106 outs() << "----------------------------\n";
107 outs() << "Param Index Reference:\n";
109 for (auto &F
: *Program
)
110 if (!F
.isDeclaration() && F
.arg_size()) {
111 outs() << " " << F
.getName() << "\n";
112 for (auto &A
: F
.args())
113 outs() << "\t" << ++ArgsCount
<< ": " << A
.getName() << "\n";
115 outs() << "----------------------------\n";
121 void llvm::reduceArgumentsDeltaPass(TestRunner
&Test
) {
122 outs() << "*** Reducing Arguments...\n";
123 int ArgCount
= countArguments(Test
.getProgram());
124 runDeltaPass(Test
, ArgCount
, extractArgumentsFromModule
);