[clang][modules] Don't prevent translation of FW_Private includes when explicitly...
[llvm-project.git] / llvm / tools / llvm-reduce / deltas / ReduceOperandsToArgs.cpp
blob30758aea1b4eda4a4de9ba00e45043cc1e4ad730
1 //===----------------------------------------------------------------------===//
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 //===----------------------------------------------------------------------===//
9 #include "ReduceOperandsToArgs.h"
10 #include "Delta.h"
11 #include "Utils.h"
12 #include "llvm/ADT/Sequence.h"
13 #include "llvm/IR/Constants.h"
14 #include "llvm/IR/InstIterator.h"
15 #include "llvm/IR/InstrTypes.h"
16 #include "llvm/IR/Instructions.h"
17 #include "llvm/Transforms/Utils/BasicBlockUtils.h"
18 #include "llvm/Transforms/Utils/Cloning.h"
20 using namespace llvm;
22 static bool canReplaceFunction(Function *F) {
23 return all_of(F->uses(), [](Use &Op) {
24 if (auto *CI = dyn_cast<CallBase>(Op.getUser()))
25 return &CI->getCalledOperandUse() == &Op;
26 return false;
27 });
30 static bool canReduceUse(Use &Op) {
31 Value *Val = Op.get();
32 Type *Ty = Val->getType();
34 // Only replace operands that can be passed-by-value.
35 if (!Ty->isFirstClassType())
36 return false;
38 // Don't pass labels/metadata as arguments.
39 if (Ty->isLabelTy() || Ty->isMetadataTy())
40 return false;
42 // No need to replace values that are already arguments.
43 if (isa<Argument>(Val))
44 return false;
46 // Do not replace literals.
47 if (isa<ConstantData>(Val))
48 return false;
50 // Do not convert direct function calls to indirect calls.
51 if (auto *CI = dyn_cast<CallBase>(Op.getUser()))
52 if (&CI->getCalledOperandUse() == &Op)
53 return false;
55 return true;
58 /// Goes over OldF calls and replaces them with a call to NewF.
59 static void replaceFunctionCalls(Function *OldF, Function *NewF) {
60 SmallVector<CallBase *> Callers;
61 for (Use &U : OldF->uses()) {
62 auto *CI = cast<CallBase>(U.getUser());
63 assert(&U == &CI->getCalledOperandUse());
64 assert(CI->getCalledFunction() == OldF);
65 Callers.push_back(CI);
68 // Call arguments for NewF.
69 SmallVector<Value *> Args(NewF->arg_size(), nullptr);
71 // Fill up the additional parameters with default values.
72 for (auto ArgIdx : llvm::seq<size_t>(OldF->arg_size(), NewF->arg_size())) {
73 Type *NewArgTy = NewF->getArg(ArgIdx)->getType();
74 Args[ArgIdx] = getDefaultValue(NewArgTy);
77 for (CallBase *CI : Callers) {
78 // Preserve the original function arguments.
79 for (auto Z : zip_first(CI->args(), Args))
80 std::get<1>(Z) = std::get<0>(Z);
82 // Also preserve operand bundles.
83 SmallVector<OperandBundleDef> OperandBundles;
84 CI->getOperandBundlesAsDefs(OperandBundles);
86 // Create the new function call.
87 CallBase *NewCI;
88 if (auto *II = dyn_cast<InvokeInst>(CI)) {
89 NewCI = InvokeInst::Create(NewF, cast<InvokeInst>(II)->getNormalDest(),
90 cast<InvokeInst>(II)->getUnwindDest(), Args,
91 OperandBundles, CI->getName());
92 } else {
93 assert(isa<CallInst>(CI));
94 NewCI = CallInst::Create(NewF, Args, OperandBundles, CI->getName());
96 NewCI->setCallingConv(NewF->getCallingConv());
98 // Do the replacement for this use.
99 if (!CI->use_empty())
100 CI->replaceAllUsesWith(NewCI);
101 ReplaceInstWithInst(CI, NewCI);
105 /// Add a new function argument to @p F for each use in @OpsToReplace, and
106 /// replace those operand values with the new function argument.
107 static void substituteOperandWithArgument(Function *OldF,
108 ArrayRef<Use *> OpsToReplace) {
109 if (OpsToReplace.empty())
110 return;
112 SetVector<Value *> UniqueValues;
113 for (Use *Op : OpsToReplace)
114 UniqueValues.insert(Op->get());
116 // Determine the new function's signature.
117 SmallVector<Type *> NewArgTypes;
118 llvm::append_range(NewArgTypes, OldF->getFunctionType()->params());
119 size_t ArgOffset = NewArgTypes.size();
120 for (Value *V : UniqueValues)
121 NewArgTypes.push_back(V->getType());
122 FunctionType *FTy =
123 FunctionType::get(OldF->getFunctionType()->getReturnType(), NewArgTypes,
124 OldF->getFunctionType()->isVarArg());
126 // Create the new function...
127 Function *NewF =
128 Function::Create(FTy, OldF->getLinkage(), OldF->getAddressSpace(),
129 OldF->getName(), OldF->getParent());
131 // In order to preserve function order, we move NewF behind OldF
132 NewF->removeFromParent();
133 OldF->getParent()->getFunctionList().insertAfter(OldF->getIterator(), NewF);
135 // Preserve the parameters of OldF.
136 ValueToValueMapTy VMap;
137 for (auto Z : zip_first(OldF->args(), NewF->args())) {
138 Argument &OldArg = std::get<0>(Z);
139 Argument &NewArg = std::get<1>(Z);
141 NewArg.setName(OldArg.getName()); // Copy the name over...
142 VMap[&OldArg] = &NewArg; // Add mapping to VMap
145 // Adjust the new parameters.
146 ValueToValueMapTy OldValMap;
147 for (auto Z : zip_first(UniqueValues, drop_begin(NewF->args(), ArgOffset))) {
148 Value *OldVal = std::get<0>(Z);
149 Argument &NewArg = std::get<1>(Z);
151 NewArg.setName(OldVal->getName());
152 OldValMap[OldVal] = &NewArg;
155 SmallVector<ReturnInst *, 8> Returns; // Ignore returns cloned.
156 CloneFunctionInto(NewF, OldF, VMap, CloneFunctionChangeType::LocalChangesOnly,
157 Returns, "", /*CodeInfo=*/nullptr);
159 // Replace the actual operands.
160 for (Use *Op : OpsToReplace) {
161 Value *NewArg = OldValMap.lookup(Op->get());
162 auto *NewUser = cast<Instruction>(VMap.lookup(Op->getUser()));
164 if (PHINode *NewPhi = dyn_cast<PHINode>(NewUser)) {
165 PHINode *OldPhi = cast<PHINode>(Op->getUser());
166 BasicBlock *OldBB = OldPhi->getIncomingBlock(*Op);
167 NewPhi->setIncomingValueForBlock(cast<BasicBlock>(VMap.lookup(OldBB)),
168 NewArg);
169 } else
170 NewUser->setOperand(Op->getOperandNo(), NewArg);
173 // Replace all OldF uses with NewF.
174 replaceFunctionCalls(OldF, NewF);
176 // Rename NewF to OldF's name.
177 std::string FName = OldF->getName().str();
178 OldF->replaceAllUsesWith(ConstantExpr::getBitCast(NewF, OldF->getType()));
179 OldF->eraseFromParent();
180 NewF->setName(FName);
183 static void reduceOperandsToArgs(Oracle &O, ReducerWorkItem &WorkItem) {
184 Module &Program = WorkItem.getModule();
186 SmallVector<Use *> OperandsToReduce;
187 for (Function &F : make_early_inc_range(Program.functions())) {
188 if (!canReplaceFunction(&F))
189 continue;
190 OperandsToReduce.clear();
191 for (Instruction &I : instructions(&F)) {
192 for (Use &Op : I.operands()) {
193 if (!canReduceUse(Op))
194 continue;
195 if (O.shouldKeep())
196 continue;
198 OperandsToReduce.push_back(&Op);
202 substituteOperandWithArgument(&F, OperandsToReduce);
206 void llvm::reduceOperandsToArgsDeltaPass(TestRunner &Test) {
207 runDeltaPass(Test, reduceOperandsToArgs,
208 "Converting operands to function arguments");