1 //===-- PartialSpecialization.cpp - Specialize for common constants--------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This pass finds function arguments that are often a common constant and
11 // specializes a version of the called function for that constant.
13 // This pass simply does the cloning for functions it specializes. It depends
14 // on IPSCCP and DAE to clean up the results.
16 // The initial heuristic favors constant arguments that are used in control
19 //===----------------------------------------------------------------------===//
21 #define DEBUG_TYPE "partialspecialization"
22 #include "llvm/Transforms/IPO.h"
23 #include "llvm/Constant.h"
24 #include "llvm/Instructions.h"
25 #include "llvm/Module.h"
26 #include "llvm/Pass.h"
27 #include "llvm/ADT/Statistic.h"
28 #include "llvm/Transforms/Utils/Cloning.h"
29 #include "llvm/Support/CallSite.h"
30 #include "llvm/Support/Compiler.h"
31 #include "llvm/ADT/DenseSet.h"
35 STATISTIC(numSpecialized
, "Number of specialized functions created");
37 // Call must be used at least occasionally
38 static const int CallsMin
= 5;
40 // Must have 10% of calls having the same constant to specialize on
41 static const double ConstValPercent
= .1;
44 class VISIBILITY_HIDDEN PartSpec
: public ModulePass
{
45 void scanForInterest(Function
&, SmallVector
<int, 6>&);
46 int scanDistribution(Function
&, int, std::map
<Constant
*, int>&);
48 static char ID
; // Pass identification, replacement for typeid
49 PartSpec() : ModulePass(&ID
) {}
50 bool runOnModule(Module
&M
);
54 char PartSpec::ID
= 0;
55 static RegisterPass
<PartSpec
>
56 X("partialspecialization", "Partial Specialization");
58 // Specialize F by replacing the arguments (keys) in replacements with the
59 // constants (values). Replace all calls to F with those constants with
60 // a call to the specialized function. Returns the specialized function
62 SpecializeFunction(Function
* F
,
63 DenseMap
<const Value
*, Value
*>& replacements
) {
64 // arg numbers of deleted arguments
65 DenseSet
<unsigned> deleted
;
66 for (DenseMap
<const Value
*, Value
*>::iterator
67 repb
= replacements
.begin(), repe
= replacements
.end();
69 deleted
.insert(cast
<Argument
>(repb
->first
)->getArgNo());
71 Function
* NF
= CloneFunction(F
, replacements
);
72 NF
->setLinkage(GlobalValue::InternalLinkage
);
73 F
->getParent()->getFunctionList().push_back(NF
);
75 for (Value::use_iterator ii
= F
->use_begin(), ee
= F
->use_end();
77 Value::use_iterator i
= ii
;
79 if (isa
<CallInst
>(i
) || isa
<InvokeInst
>(i
)) {
80 CallSite
CS(cast
<Instruction
>(i
));
81 if (CS
.getCalledFunction() == F
) {
83 SmallVector
<Value
*, 6> args
;
84 for (unsigned x
= 0; x
< CS
.arg_size(); ++x
)
85 if (!deleted
.count(x
))
86 args
.push_back(CS
.getArgument(x
));
88 if (CallInst
*CI
= dyn_cast
<CallInst
>(i
)) {
89 NCall
= CallInst::Create(NF
, args
.begin(), args
.end(),
91 cast
<CallInst
>(NCall
)->setTailCall(CI
->isTailCall());
92 cast
<CallInst
>(NCall
)->setCallingConv(CI
->getCallingConv());
94 InvokeInst
*II
= cast
<InvokeInst
>(i
);
95 NCall
= InvokeInst::Create(NF
, II
->getNormalDest(),
97 args
.begin(), args
.end(),
99 cast
<InvokeInst
>(NCall
)->setCallingConv(II
->getCallingConv());
101 CS
.getInstruction()->replaceAllUsesWith(NCall
);
102 CS
.getInstruction()->eraseFromParent();
110 bool PartSpec::runOnModule(Module
&M
) {
111 bool Changed
= false;
112 for (Module::iterator I
= M
.begin(); I
!= M
.end(); ++I
) {
114 if (F
.isDeclaration() || F
.mayBeOverridden()) continue;
115 SmallVector
<int, 6> interestingArgs
;
116 scanForInterest(F
, interestingArgs
);
118 // Find the first interesting Argument that we can specialize on
119 // If there are multiple interesting Arguments, then those will be found
120 // when processing the cloned function.
121 bool breakOuter
= false;
122 for (unsigned int x
= 0; !breakOuter
&& x
< interestingArgs
.size(); ++x
) {
123 std::map
<Constant
*, int> distribution
;
124 int total
= scanDistribution(F
, interestingArgs
[x
], distribution
);
125 if (total
> CallsMin
)
126 for (std::map
<Constant
*, int>::iterator ii
= distribution
.begin(),
127 ee
= distribution
.end(); ii
!= ee
; ++ii
)
128 if (total
> ii
->second
&& ii
->first
&&
129 ii
->second
> total
* ConstValPercent
) {
130 DenseMap
<const Value
*, Value
*> m
;
131 Function::arg_iterator arg
= F
.arg_begin();
132 for (int y
= 0; y
< interestingArgs
[x
]; ++y
)
134 m
[&*arg
] = ii
->first
;
135 SpecializeFunction(&F
, m
);
145 /// scanForInterest - This function decides which arguments would be worth
147 void PartSpec::scanForInterest(Function
& F
, SmallVector
<int, 6>& args
) {
148 for(Function::arg_iterator ii
= F
.arg_begin(), ee
= F
.arg_end();
150 for(Value::use_iterator ui
= ii
->use_begin(), ue
= ii
->use_end();
153 bool interesting
= false;
155 if (isa
<CmpInst
>(ui
)) interesting
= true;
156 else if (isa
<CallInst
>(ui
))
157 interesting
= ui
->getOperand(0) == ii
;
158 else if (isa
<InvokeInst
>(ui
))
159 interesting
= ui
->getOperand(0) == ii
;
160 else if (isa
<SwitchInst
>(ui
)) interesting
= true;
161 else if (isa
<BranchInst
>(ui
)) interesting
= true;
164 args
.push_back(std::distance(F
.arg_begin(), ii
));
171 /// scanDistribution - Construct a histogram of constants for arg of F at arg.
172 int PartSpec::scanDistribution(Function
& F
, int arg
,
173 std::map
<Constant
*, int>& dist
) {
174 bool hasIndirect
= false;
176 for(Value::use_iterator ii
= F
.use_begin(), ee
= F
.use_end();
178 if ((isa
<CallInst
>(ii
) || isa
<InvokeInst
>(ii
))
179 && ii
->getOperand(0) == &F
) {
180 ++dist
[dyn_cast
<Constant
>(ii
->getOperand(arg
+ 1))];
185 // Preserve the original address taken function even if all other uses
186 // will be specialized.
187 if (hasIndirect
) ++total
;
191 ModulePass
* llvm::createPartialSpecializationPass() { return new PartSpec(); }