1 //===-- AutoUpgrade.cpp - Implement auto-upgrade helper functions ---------===//
3 // The LLVM Compiler Infrastructure
5 // This file was developed by Reid Spencer and is distributed under the
6 // University of Illinois Open Source License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file implements the auto-upgrade helper functions
12 //===----------------------------------------------------------------------===//
14 #include "llvm/Assembly/AutoUpgrade.h"
15 #include "llvm/Constants.h"
16 #include "llvm/DerivedTypes.h"
17 #include "llvm/Function.h"
18 #include "llvm/Module.h"
19 #include "llvm/Instructions.h"
20 #include "llvm/Intrinsics.h"
21 #include "llvm/SymbolTable.h"
25 static Function *getUpgradedUnaryFn(Function *F) {
26 const std::string &Name = F->getName();
27 Module *M = F->getParent();
28 switch (F->getReturnType()->getTypeID()) {
32 return M->getOrInsertFunction(Name+".i8",
33 Type::UByteTy, Type::UByteTy, NULL);
34 case Type::UShortTyID:
36 return M->getOrInsertFunction(Name+".i16",
37 Type::UShortTy, Type::UShortTy, NULL);
40 return M->getOrInsertFunction(Name+".i32",
41 Type::UIntTy, Type::UIntTy, NULL);
44 return M->getOrInsertFunction(Name+".i64",
45 Type::ULongTy, Type::ULongTy, NULL);
47 return M->getOrInsertFunction(Name+".f32",
48 Type::FloatTy, Type::FloatTy, NULL);
49 case Type::DoubleTyID:
50 return M->getOrInsertFunction(Name+".f64",
51 Type::DoubleTy, Type::DoubleTy, NULL);
55 static Function *getUpgradedIntrinsic(Function *F) {
56 // If there's no function, we can't get the argument type.
59 // Get the Function's name.
60 const std::string& Name = F->getName();
62 // Quickly eliminate it, if it's not a candidate.
63 if (Name.length() <= 8 || Name[0] != 'l' || Name[1] != 'l' ||
64 Name[2] != 'v' || Name[3] != 'm' || Name[4] != '.')
67 Module *M = F->getParent();
71 if (Name == "llvm.bswap") return getUpgradedUnaryFn(F);
74 if (Name == "llvm.ctpop" || Name == "llvm.ctlz" || Name == "llvm.cttz")
75 return getUpgradedUnaryFn(F);
78 if (Name == "llvm.dbg.stoppoint") {
79 if (F->getReturnType() != Type::VoidTy) {
80 return M->getOrInsertFunction(Name, Type::VoidTy,
83 F->getFunctionType()->getParamType(3),
86 } else if (Name == "llvm.dbg.func.start") {
87 if (F->getReturnType() != Type::VoidTy) {
88 return M->getOrInsertFunction(Name, Type::VoidTy,
89 F->getFunctionType()->getParamType(0),
92 } else if (Name == "llvm.dbg.region.start") {
93 if (F->getReturnType() != Type::VoidTy) {
94 return M->getOrInsertFunction(Name, Type::VoidTy, NULL);
96 } else if (Name == "llvm.dbg.region.end") {
97 if (F->getReturnType() != Type::VoidTy) {
98 return M->getOrInsertFunction(Name, Type::VoidTy, NULL);
100 } else if (Name == "llvm.dbg.declare") {
106 if (Name == "llvm.isunordered" && F->arg_begin() != F->arg_end()) {
107 if (F->arg_begin()->getType() == Type::FloatTy)
108 return M->getOrInsertFunction(Name+".f32", F->getFunctionType());
109 if (F->arg_begin()->getType() == Type::DoubleTy)
110 return M->getOrInsertFunction(Name+".f64", F->getFunctionType());
114 if (Name == "llvm.memcpy" || Name == "llvm.memset" ||
115 Name == "llvm.memmove") {
116 if (F->getFunctionType()->getParamType(2) == Type::UIntTy ||
117 F->getFunctionType()->getParamType(2) == Type::IntTy)
118 return M->getOrInsertFunction(Name+".i32", Type::VoidTy,
119 PointerType::get(Type::SByteTy),
120 F->getFunctionType()->getParamType(1),
121 Type::UIntTy, Type::UIntTy, NULL);
122 if (F->getFunctionType()->getParamType(2) == Type::ULongTy ||
123 F->getFunctionType()->getParamType(2) == Type::LongTy)
124 return M->getOrInsertFunction(Name+".i64", Type::VoidTy,
125 PointerType::get(Type::SByteTy),
126 F->getFunctionType()->getParamType(1),
127 Type::ULongTy, Type::UIntTy, NULL);
131 if (Name == "llvm.sqrt")
132 return getUpgradedUnaryFn(F);
138 // Occasionally upgraded function call site arguments need to be permutated to
139 // some new order. The result of getArgumentPermutation is an array of size
140 // F->getFunctionType()getNumParams() indicating the new operand order. A value
141 // of zero in the array indicates replacing with UndefValue for the arg type.
142 // NULL is returned if there is no permutation. It's assumed that the function
143 // name is in the form "llvm.?????"
144 static unsigned *getArgumentPermutation(Function* F) {
145 // Get the Function's name.
146 const std::string& Name = F->getName();
149 if (Name == "llvm.dbg.stoppoint") {
150 static unsigned Permutation[] = { 2, 3, 4 };
151 assert(F->getFunctionType()->getNumParams() ==
152 (sizeof(Permutation) / sizeof(unsigned)) &&
153 "Permutation is wrong length");
161 // UpgradeIntrinsicFunction - Convert overloaded intrinsic function names to
162 // their non-overloaded variants by appending the appropriate suffix based on
163 // the argument types.
164 Function *llvm::UpgradeIntrinsicFunction(Function* F) {
165 // See if its one of the name's we're interested in.
166 if (Function *R = getUpgradedIntrinsic(F)) {
167 std::cerr << "WARNING: change " << F->getName() << " to "
168 << R->getName() << "\n";
175 Instruction* llvm::MakeUpgradedCall(Function *F,
176 const std::vector<Value*> &Params,
177 BasicBlock *BB, bool isTailCall,
178 unsigned CallingConv) {
179 assert(F && "Need a Function to make a CallInst");
180 assert(BB && "Need a BasicBlock to make a CallInst");
182 // Convert the params
183 bool signedArg = false;
184 std::vector<Value*> Oprnds;
185 for (std::vector<Value*>::const_iterator PI = Params.begin(),
186 PE = Params.end(); PI != PE; ++PI) {
187 const Type* opTy = (*PI)->getType();
188 if (opTy->isSigned()) {
191 new CastInst(*PI,opTy->getUnsignedVersion(), "autoupgrade_cast");
192 BB->getInstList().push_back(cast);
193 Oprnds.push_back(cast);
196 Oprnds.push_back(*PI);
199 Instruction *result = new CallInst(F, Oprnds);
200 if (result->getType() != Type::VoidTy) result->setName("autoupgrade_call");
201 if (isTailCall) cast<CallInst>(result)->setTailCall();
202 if (CallingConv) cast<CallInst>(result)->setCallingConv(CallingConv);
204 const Type* newTy = F->getReturnType()->getUnsignedVersion();
205 CastInst* final = new CastInst(result, newTy, "autoupgrade_uncast");
206 BB->getInstList().push_back(result);
212 // UpgradeIntrinsicCall - In the BC reader, change a call to an intrinsic to be
213 // a call to an upgraded intrinsic. We may have to permute the order or promote
214 // some arguments with a cast.
215 void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) {
216 Function *F = CI->getCalledFunction();
218 const FunctionType *NewFnTy = NewFn->getFunctionType();
219 std::vector<Value*> Oprnds;
221 unsigned *Permutation = getArgumentPermutation(NewFn);
222 unsigned N = NewFnTy->getNumParams();
225 for (unsigned i = 0; i != N; ++i) {
226 unsigned p = Permutation[i];
229 Value *V = CI->getOperand(p);
230 if (V->getType() != NewFnTy->getParamType(i))
231 V = new CastInst(V, NewFnTy->getParamType(i), V->getName(), CI);
234 Oprnds.push_back(UndefValue::get(NewFnTy->getParamType(i)));
237 assert(N == (CI->getNumOperands() - 1) &&
238 "Upgraded function needs permutation");
239 for (unsigned i = 0; i != N; ++i) {
240 Value *V = CI->getOperand(i + 1);
241 if (V->getType() != NewFnTy->getParamType(i))
242 V = new CastInst(V, NewFnTy->getParamType(i), V->getName(), CI);
247 bool NewIsVoid = NewFn->getReturnType() == Type::VoidTy;
249 CallInst *NewCI = new CallInst(NewFn, Oprnds,
250 NewIsVoid ? "" : CI->getName(),
252 NewCI->setTailCall(CI->isTailCall());
253 NewCI->setCallingConv(CI->getCallingConv());
255 if (!CI->use_empty()) {
257 CI->replaceAllUsesWith(UndefValue::get(CI->getType()));
259 Instruction *RetVal = NewCI;
261 if (F->getReturnType() != NewFn->getReturnType()) {
262 RetVal = new CastInst(NewCI, NewFn->getReturnType(),
263 NewCI->getName(), CI);
264 NewCI->moveBefore(RetVal);
267 CI->replaceAllUsesWith(RetVal);
270 CI->eraseFromParent();
273 bool llvm::UpgradeCallsToIntrinsic(Function* F) {
274 if (Function* NewFn = UpgradeIntrinsicFunction(F)) {
275 for (Value::use_iterator UI = F->use_begin(), UE = F->use_end();
277 if (CallInst* CI = dyn_cast<CallInst>(*UI++))
278 UpgradeIntrinsicCall(CI, NewFn);
281 F->eraseFromParent();