blob: d5cefa35a0c376afb5b9ea5be80e023e77d17493 [file] [log] [blame]
Chris Lattnerfd1cbbe2008-05-01 06:25:24 +00001//===- SimplifyLibCalls.cpp - Optimize specific well-known library calls --===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements a simple pass that applies a variety of small
11// optimizations for calls to specific well-known function calls (e.g. runtime
Chris Lattnere9f9a7e2009-09-03 05:19:59 +000012// library functions). Any optimization that takes the very simple form
13// "replace call to library function with simpler code that provides the same
14// result" belongs in this file.
Chris Lattnerfd1cbbe2008-05-01 06:25:24 +000015//
16//===----------------------------------------------------------------------===//
17
18#define DEBUG_TYPE "simplify-libcalls"
19#include "llvm/Transforms/Scalar.h"
Daniel Dunbar473955f2009-07-29 22:00:43 +000020#include "llvm/ADT/STLExtras.h"
Chandler Carruth06cb8ed2012-06-29 12:38:19 +000021#include "llvm/ADT/SmallPtrSet.h"
22#include "llvm/ADT/Statistic.h"
23#include "llvm/ADT/StringMap.h"
24#include "llvm/Analysis/ValueTracking.h"
Chandler Carruthd04a8d42012-12-03 16:50:05 +000025#include "llvm/Config/config.h" // FIXME: Shouldn't depend on host!
Chandler Carruth0b8c9a82013-01-02 11:36:10 +000026#include "llvm/IR/DataLayout.h"
27#include "llvm/IR/IRBuilder.h"
28#include "llvm/IR/LLVMContext.h"
29#include "llvm/IR/Module.h"
Chandler Carruthd04a8d42012-12-03 16:50:05 +000030#include "llvm/Pass.h"
Chad Rosierec7e92a2012-08-22 17:22:33 +000031#include "llvm/Support/CommandLine.h"
Chris Lattner56b4f2b2008-05-01 06:39:12 +000032#include "llvm/Support/Debug.h"
Daniel Dunbarf0443c12009-07-26 08:34:35 +000033#include "llvm/Support/raw_ostream.h"
Chandler Carruth06cb8ed2012-06-29 12:38:19 +000034#include "llvm/Target/TargetLibraryInfo.h"
Chandler Carruthd04a8d42012-12-03 16:50:05 +000035#include "llvm/Transforms/Utils/BuildLibCalls.h"
Chris Lattnerfd1cbbe2008-05-01 06:25:24 +000036using namespace llvm;
37
Nick Lewycky0f8df9a2009-01-04 20:27:34 +000038STATISTIC(NumAnnotated, "Number of attributes added to library functions");
Chris Lattnerfd1cbbe2008-05-01 06:25:24 +000039
40//===----------------------------------------------------------------------===//
41// Optimizer Base Class
42//===----------------------------------------------------------------------===//
43
44/// This class is the abstract base class for the set of optimizations that
45/// corresponds to one library call.
46namespace {
Chris Lattner3e8b6632009-09-02 06:11:42 +000047class LibCallOptimization {
Chris Lattnerfd1cbbe2008-05-01 06:25:24 +000048protected:
49 Function *Caller;
Micah Villmow3574eca2012-10-08 16:38:25 +000050 const DataLayout *TD;
Richard Osborne36498242011-03-03 13:17:51 +000051 const TargetLibraryInfo *TLI;
Owen Andersonfa5cbd62009-07-03 19:42:02 +000052 LLVMContext* Context;
Chris Lattnerfd1cbbe2008-05-01 06:25:24 +000053public:
Evan Chengeb8c6452010-03-24 20:19:04 +000054 LibCallOptimization() { }
Chris Lattnerfd1cbbe2008-05-01 06:25:24 +000055 virtual ~LibCallOptimization() {}
56
57 /// CallOptimizer - This pure virtual method is implemented by base classes to
58 /// do various optimizations. If this returns null then no transformation was
59 /// performed. If it returns CI, then it transformed the call and CI is to be
60 /// deleted. If it returns something else, replace CI with the new value and
61 /// delete CI.
Eric Christopher37c8b862009-10-07 21:14:25 +000062 virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B)
Eric Christopher7a61d702008-08-08 19:39:37 +000063 =0;
Eric Christopher37c8b862009-10-07 21:14:25 +000064
Micah Villmow3574eca2012-10-08 16:38:25 +000065 Value *OptimizeCall(CallInst *CI, const DataLayout *TD,
Richard Osborne36498242011-03-03 13:17:51 +000066 const TargetLibraryInfo *TLI, IRBuilder<> &B) {
Chris Lattnerfd1cbbe2008-05-01 06:25:24 +000067 Caller = CI->getParent()->getParent();
Dan Gohmanf14d9192009-08-18 00:48:13 +000068 this->TD = TD;
Richard Osborne36498242011-03-03 13:17:51 +000069 this->TLI = TLI;
Owen Andersonfa5cbd62009-07-03 19:42:02 +000070 if (CI->getCalledFunction())
Owen Andersone922c022009-07-22 00:24:57 +000071 Context = &CI->getCalledFunction()->getContext();
Rafael Espindolae96af562010-06-16 19:34:01 +000072
73 // We never change the calling convention.
74 if (CI->getCallingConv() != llvm::CallingConv::C)
75 return NULL;
76
Chris Lattnerfd1cbbe2008-05-01 06:25:24 +000077 return CallOptimizer(CI->getCalledFunction(), CI, B);
78 }
Chris Lattnerfd1cbbe2008-05-01 06:25:24 +000079};
80} // End anonymous namespace.
81
Chris Lattnerfd1cbbe2008-05-01 06:25:24 +000082
Chris Lattnerfd1cbbe2008-05-01 06:25:24 +000083//===----------------------------------------------------------------------===//
84// SimplifyLibCalls Pass Implementation
85//===----------------------------------------------------------------------===//
86
87namespace {
88 /// This pass optimizes well known library functions from libc and libm.
89 ///
Chris Lattner3e8b6632009-09-02 06:11:42 +000090 class SimplifyLibCalls : public FunctionPass {
Chris Lattnerafbf4832011-02-24 07:16:14 +000091 TargetLibraryInfo *TLI;
Nadav Rotema94d6e82012-07-24 10:51:42 +000092
Chris Lattnerfd1cbbe2008-05-01 06:25:24 +000093 StringMap<LibCallOptimization*> Optimizations;
Nadav Rotema94d6e82012-07-24 10:51:42 +000094
Nick Lewycky6cd0c042009-01-05 00:07:50 +000095 bool Modified; // This is only used by doInitialization.
Chris Lattnerfd1cbbe2008-05-01 06:25:24 +000096 public:
97 static char ID; // Pass identification
Meador Inge2920a712012-11-13 04:16:17 +000098 SimplifyLibCalls() : FunctionPass(ID) {
Owen Anderson081c34b2010-10-19 17:21:58 +000099 initializeSimplifyLibCallsPass(*PassRegistry::getPassRegistry());
100 }
Eli Friedman9d434db2011-11-17 01:27:36 +0000101 void AddOpt(LibFunc::Func F, LibCallOptimization* Opt);
Chad Rosierd7e25252012-08-22 16:52:57 +0000102 void AddOpt(LibFunc::Func F1, LibFunc::Func F2, LibCallOptimization* Opt);
103
Chris Lattnerfd1cbbe2008-05-01 06:25:24 +0000104 void InitOptimizations();
105 bool runOnFunction(Function &F);
106
Nick Lewycky0f8df9a2009-01-04 20:27:34 +0000107 void setDoesNotAccessMemory(Function &F);
108 void setOnlyReadsMemory(Function &F);
109 void setDoesNotThrow(Function &F);
110 void setDoesNotCapture(Function &F, unsigned n);
111 void setDoesNotAlias(Function &F, unsigned n);
Nick Lewycky6cd0c042009-01-05 00:07:50 +0000112 bool doInitialization(Module &M);
Nick Lewycky0f8df9a2009-01-04 20:27:34 +0000113
Chris Lattnere265ad82011-02-24 07:12:12 +0000114 void inferPrototypeAttributes(Function &F);
Chris Lattnerfd1cbbe2008-05-01 06:25:24 +0000115 virtual void getAnalysisUsage(AnalysisUsage &AU) const {
Chris Lattnerafbf4832011-02-24 07:16:14 +0000116 AU.addRequired<TargetLibraryInfo>();
Chris Lattnerfd1cbbe2008-05-01 06:25:24 +0000117 }
118 };
Chris Lattnerfd1cbbe2008-05-01 06:25:24 +0000119} // end anonymous namespace.
120
Chris Lattnerafbf4832011-02-24 07:16:14 +0000121char SimplifyLibCalls::ID = 0;
122
123INITIALIZE_PASS_BEGIN(SimplifyLibCalls, "simplify-libcalls",
124 "Simplify well-known library calls", false, false)
125INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfo)
126INITIALIZE_PASS_END(SimplifyLibCalls, "simplify-libcalls",
127 "Simplify well-known library calls", false, false)
Chris Lattnerfd1cbbe2008-05-01 06:25:24 +0000128
129// Public interface to the Simplify LibCalls pass.
130FunctionPass *llvm::createSimplifyLibCallsPass() {
Eric Christopher37c8b862009-10-07 21:14:25 +0000131 return new SimplifyLibCalls();
Chris Lattnerfd1cbbe2008-05-01 06:25:24 +0000132}
133
Eli Friedman9d434db2011-11-17 01:27:36 +0000134void SimplifyLibCalls::AddOpt(LibFunc::Func F, LibCallOptimization* Opt) {
135 if (TLI->has(F))
136 Optimizations[TLI->getName(F)] = Opt;
137}
138
Chad Rosierd7e25252012-08-22 16:52:57 +0000139void SimplifyLibCalls::AddOpt(LibFunc::Func F1, LibFunc::Func F2,
140 LibCallOptimization* Opt) {
141 if (TLI->has(F1) && TLI->has(F2))
142 Optimizations[TLI->getName(F1)] = Opt;
143}
144
Chris Lattnerfd1cbbe2008-05-01 06:25:24 +0000145/// Optimizations - Populate the Optimizations map with all the optimizations
146/// we know.
147void SimplifyLibCalls::InitOptimizations() {
Chris Lattnerfd1cbbe2008-05-01 06:25:24 +0000148}
149
150
151/// runOnFunction - Top level algorithm.
152///
153bool SimplifyLibCalls::runOnFunction(Function &F) {
Chris Lattnerafbf4832011-02-24 07:16:14 +0000154 TLI = &getAnalysis<TargetLibraryInfo>();
155
Chris Lattnerfd1cbbe2008-05-01 06:25:24 +0000156 if (Optimizations.empty())
157 InitOptimizations();
Eric Christopher37c8b862009-10-07 21:14:25 +0000158
Micah Villmow3574eca2012-10-08 16:38:25 +0000159 const DataLayout *TD = getAnalysisIfAvailable<DataLayout>();
Eric Christopher37c8b862009-10-07 21:14:25 +0000160
Owen Andersone922c022009-07-22 00:24:57 +0000161 IRBuilder<> Builder(F.getContext());
Chris Lattnerfd1cbbe2008-05-01 06:25:24 +0000162
163 bool Changed = false;
164 for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) {
165 for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ) {
166 // Ignore non-calls.
167 CallInst *CI = dyn_cast<CallInst>(I++);
168 if (!CI) continue;
Eric Christopher37c8b862009-10-07 21:14:25 +0000169
Chris Lattnerfd1cbbe2008-05-01 06:25:24 +0000170 // Ignore indirect calls and calls to non-external functions.
171 Function *Callee = CI->getCalledFunction();
172 if (Callee == 0 || !Callee->isDeclaration() ||
173 !(Callee->hasExternalLinkage() || Callee->hasDLLImportLinkage()))
174 continue;
Eric Christopher37c8b862009-10-07 21:14:25 +0000175
Chris Lattnerfd1cbbe2008-05-01 06:25:24 +0000176 // Ignore unknown calls.
Daniel Dunbarf0443c12009-07-26 08:34:35 +0000177 LibCallOptimization *LCO = Optimizations.lookup(Callee->getName());
178 if (!LCO) continue;
Eric Christopher37c8b862009-10-07 21:14:25 +0000179
Chris Lattnerfd1cbbe2008-05-01 06:25:24 +0000180 // Set the builder to the instruction after the call.
181 Builder.SetInsertPoint(BB, I);
Eric Christopher37c8b862009-10-07 21:14:25 +0000182
Devang Patela2ab3992011-03-09 21:27:52 +0000183 // Use debug location of CI for all new instructions.
184 Builder.SetCurrentDebugLocation(CI->getDebugLoc());
185
Chris Lattnerfd1cbbe2008-05-01 06:25:24 +0000186 // Try to optimize this call.
Richard Osborne36498242011-03-03 13:17:51 +0000187 Value *Result = LCO->OptimizeCall(CI, TD, TLI, Builder);
Chris Lattnerfd1cbbe2008-05-01 06:25:24 +0000188 if (Result == 0) continue;
189
David Greene6a6b90e2010-01-05 01:27:21 +0000190 DEBUG(dbgs() << "SimplifyLibCalls simplified: " << *CI;
191 dbgs() << " into: " << *Result << "\n");
Eric Christopher37c8b862009-10-07 21:14:25 +0000192
Chris Lattnerfd1cbbe2008-05-01 06:25:24 +0000193 // Something changed!
194 Changed = true;
Eric Christopher37c8b862009-10-07 21:14:25 +0000195
Chris Lattnerfd1cbbe2008-05-01 06:25:24 +0000196 // Inspect the instruction after the call (which was potentially just
197 // added) next.
198 I = CI; ++I;
Eric Christopher37c8b862009-10-07 21:14:25 +0000199
Chris Lattnerfd1cbbe2008-05-01 06:25:24 +0000200 if (CI != Result && !CI->use_empty()) {
201 CI->replaceAllUsesWith(Result);
202 if (!Result->hasName())
203 Result->takeName(CI);
204 }
205 CI->eraseFromParent();
206 }
207 }
208 return Changed;
209}
210
Nick Lewycky6cd0c042009-01-05 00:07:50 +0000211// Utility methods for doInitialization.
Nick Lewycky0f8df9a2009-01-04 20:27:34 +0000212
213void SimplifyLibCalls::setDoesNotAccessMemory(Function &F) {
214 if (!F.doesNotAccessMemory()) {
215 F.setDoesNotAccessMemory();
216 ++NumAnnotated;
217 Modified = true;
218 }
219}
220void SimplifyLibCalls::setOnlyReadsMemory(Function &F) {
221 if (!F.onlyReadsMemory()) {
222 F.setOnlyReadsMemory();
223 ++NumAnnotated;
224 Modified = true;
225 }
226}
227void SimplifyLibCalls::setDoesNotThrow(Function &F) {
228 if (!F.doesNotThrow()) {
229 F.setDoesNotThrow();
230 ++NumAnnotated;
231 Modified = true;
232 }
233}
234void SimplifyLibCalls::setDoesNotCapture(Function &F, unsigned n) {
235 if (!F.doesNotCapture(n)) {
236 F.setDoesNotCapture(n);
237 ++NumAnnotated;
238 Modified = true;
239 }
240}
241void SimplifyLibCalls::setDoesNotAlias(Function &F, unsigned n) {
242 if (!F.doesNotAlias(n)) {
243 F.setDoesNotAlias(n);
244 ++NumAnnotated;
245 Modified = true;
246 }
247}
248
Chris Lattnere265ad82011-02-24 07:12:12 +0000249
250void SimplifyLibCalls::inferPrototypeAttributes(Function &F) {
Chris Lattnerdb125cf2011-07-18 04:54:35 +0000251 FunctionType *FTy = F.getFunctionType();
Nadav Rotema94d6e82012-07-24 10:51:42 +0000252
Chris Lattnere265ad82011-02-24 07:12:12 +0000253 StringRef Name = F.getName();
254 switch (Name[0]) {
255 case 's':
256 if (Name == "strlen") {
257 if (FTy->getNumParams() != 1 || !FTy->getParamType(0)->isPointerTy())
258 return;
259 setOnlyReadsMemory(F);
260 setDoesNotThrow(F);
261 setDoesNotCapture(F, 1);
262 } else if (Name == "strchr" ||
263 Name == "strrchr") {
264 if (FTy->getNumParams() != 2 ||
265 !FTy->getParamType(0)->isPointerTy() ||
266 !FTy->getParamType(1)->isIntegerTy())
267 return;
268 setOnlyReadsMemory(F);
269 setDoesNotThrow(F);
270 } else if (Name == "strcpy" ||
271 Name == "stpcpy" ||
272 Name == "strcat" ||
273 Name == "strtol" ||
274 Name == "strtod" ||
275 Name == "strtof" ||
276 Name == "strtoul" ||
277 Name == "strtoll" ||
278 Name == "strtold" ||
279 Name == "strncat" ||
280 Name == "strncpy" ||
David Majnemerac782662012-05-15 11:46:21 +0000281 Name == "stpncpy" ||
Chris Lattnere265ad82011-02-24 07:12:12 +0000282 Name == "strtoull") {
283 if (FTy->getNumParams() < 2 ||
284 !FTy->getParamType(1)->isPointerTy())
285 return;
286 setDoesNotThrow(F);
287 setDoesNotCapture(F, 2);
288 } else if (Name == "strxfrm") {
289 if (FTy->getNumParams() != 3 ||
290 !FTy->getParamType(0)->isPointerTy() ||
291 !FTy->getParamType(1)->isPointerTy())
292 return;
293 setDoesNotThrow(F);
294 setDoesNotCapture(F, 1);
295 setDoesNotCapture(F, 2);
296 } else if (Name == "strcmp" ||
297 Name == "strspn" ||
298 Name == "strncmp" ||
299 Name == "strcspn" ||
300 Name == "strcoll" ||
301 Name == "strcasecmp" ||
302 Name == "strncasecmp") {
303 if (FTy->getNumParams() < 2 ||
304 !FTy->getParamType(0)->isPointerTy() ||
305 !FTy->getParamType(1)->isPointerTy())
306 return;
307 setOnlyReadsMemory(F);
308 setDoesNotThrow(F);
309 setDoesNotCapture(F, 1);
310 setDoesNotCapture(F, 2);
311 } else if (Name == "strstr" ||
312 Name == "strpbrk") {
313 if (FTy->getNumParams() != 2 || !FTy->getParamType(1)->isPointerTy())
314 return;
315 setOnlyReadsMemory(F);
316 setDoesNotThrow(F);
317 setDoesNotCapture(F, 2);
318 } else if (Name == "strtok" ||
319 Name == "strtok_r") {
320 if (FTy->getNumParams() < 2 || !FTy->getParamType(1)->isPointerTy())
321 return;
322 setDoesNotThrow(F);
323 setDoesNotCapture(F, 2);
324 } else if (Name == "scanf" ||
325 Name == "setbuf" ||
326 Name == "setvbuf") {
327 if (FTy->getNumParams() < 1 || !FTy->getParamType(0)->isPointerTy())
328 return;
329 setDoesNotThrow(F);
330 setDoesNotCapture(F, 1);
331 } else if (Name == "strdup" ||
332 Name == "strndup") {
333 if (FTy->getNumParams() < 1 || !FTy->getReturnType()->isPointerTy() ||
334 !FTy->getParamType(0)->isPointerTy())
335 return;
336 setDoesNotThrow(F);
337 setDoesNotAlias(F, 0);
338 setDoesNotCapture(F, 1);
339 } else if (Name == "stat" ||
340 Name == "sscanf" ||
341 Name == "sprintf" ||
342 Name == "statvfs") {
343 if (FTy->getNumParams() < 2 ||
344 !FTy->getParamType(0)->isPointerTy() ||
345 !FTy->getParamType(1)->isPointerTy())
346 return;
347 setDoesNotThrow(F);
348 setDoesNotCapture(F, 1);
349 setDoesNotCapture(F, 2);
350 } else if (Name == "snprintf") {
351 if (FTy->getNumParams() != 3 ||
352 !FTy->getParamType(0)->isPointerTy() ||
353 !FTy->getParamType(2)->isPointerTy())
354 return;
355 setDoesNotThrow(F);
356 setDoesNotCapture(F, 1);
357 setDoesNotCapture(F, 3);
358 } else if (Name == "setitimer") {
359 if (FTy->getNumParams() != 3 ||
360 !FTy->getParamType(1)->isPointerTy() ||
361 !FTy->getParamType(2)->isPointerTy())
362 return;
363 setDoesNotThrow(F);
364 setDoesNotCapture(F, 2);
365 setDoesNotCapture(F, 3);
366 } else if (Name == "system") {
367 if (FTy->getNumParams() != 1 ||
368 !FTy->getParamType(0)->isPointerTy())
369 return;
370 // May throw; "system" is a valid pthread cancellation point.
371 setDoesNotCapture(F, 1);
372 }
373 break;
374 case 'm':
375 if (Name == "malloc") {
376 if (FTy->getNumParams() != 1 ||
377 !FTy->getReturnType()->isPointerTy())
378 return;
379 setDoesNotThrow(F);
380 setDoesNotAlias(F, 0);
381 } else if (Name == "memcmp") {
382 if (FTy->getNumParams() != 3 ||
383 !FTy->getParamType(0)->isPointerTy() ||
384 !FTy->getParamType(1)->isPointerTy())
385 return;
386 setOnlyReadsMemory(F);
387 setDoesNotThrow(F);
388 setDoesNotCapture(F, 1);
389 setDoesNotCapture(F, 2);
390 } else if (Name == "memchr" ||
391 Name == "memrchr") {
392 if (FTy->getNumParams() != 3)
393 return;
394 setOnlyReadsMemory(F);
395 setDoesNotThrow(F);
396 } else if (Name == "modf" ||
397 Name == "modff" ||
398 Name == "modfl" ||
399 Name == "memcpy" ||
400 Name == "memccpy" ||
401 Name == "memmove") {
402 if (FTy->getNumParams() < 2 ||
403 !FTy->getParamType(1)->isPointerTy())
404 return;
405 setDoesNotThrow(F);
406 setDoesNotCapture(F, 2);
407 } else if (Name == "memalign") {
408 if (!FTy->getReturnType()->isPointerTy())
409 return;
410 setDoesNotAlias(F, 0);
411 } else if (Name == "mkdir" ||
412 Name == "mktime") {
413 if (FTy->getNumParams() == 0 ||
414 !FTy->getParamType(0)->isPointerTy())
415 return;
416 setDoesNotThrow(F);
417 setDoesNotCapture(F, 1);
418 }
419 break;
420 case 'r':
421 if (Name == "realloc") {
422 if (FTy->getNumParams() != 2 ||
423 !FTy->getParamType(0)->isPointerTy() ||
424 !FTy->getReturnType()->isPointerTy())
425 return;
426 setDoesNotThrow(F);
Nuno Lopesfd99cab2012-06-25 23:26:10 +0000427 setDoesNotAlias(F, 0);
Chris Lattnere265ad82011-02-24 07:12:12 +0000428 setDoesNotCapture(F, 1);
429 } else if (Name == "read") {
430 if (FTy->getNumParams() != 3 ||
431 !FTy->getParamType(1)->isPointerTy())
432 return;
433 // May throw; "read" is a valid pthread cancellation point.
434 setDoesNotCapture(F, 2);
435 } else if (Name == "rmdir" ||
436 Name == "rewind" ||
437 Name == "remove" ||
438 Name == "realpath") {
439 if (FTy->getNumParams() < 1 ||
440 !FTy->getParamType(0)->isPointerTy())
441 return;
442 setDoesNotThrow(F);
443 setDoesNotCapture(F, 1);
444 } else if (Name == "rename" ||
445 Name == "readlink") {
446 if (FTy->getNumParams() < 2 ||
447 !FTy->getParamType(0)->isPointerTy() ||
448 !FTy->getParamType(1)->isPointerTy())
449 return;
450 setDoesNotThrow(F);
451 setDoesNotCapture(F, 1);
452 setDoesNotCapture(F, 2);
453 }
454 break;
455 case 'w':
456 if (Name == "write") {
457 if (FTy->getNumParams() != 3 || !FTy->getParamType(1)->isPointerTy())
458 return;
459 // May throw; "write" is a valid pthread cancellation point.
460 setDoesNotCapture(F, 2);
461 }
462 break;
463 case 'b':
464 if (Name == "bcopy") {
465 if (FTy->getNumParams() != 3 ||
466 !FTy->getParamType(0)->isPointerTy() ||
467 !FTy->getParamType(1)->isPointerTy())
468 return;
469 setDoesNotThrow(F);
470 setDoesNotCapture(F, 1);
471 setDoesNotCapture(F, 2);
472 } else if (Name == "bcmp") {
473 if (FTy->getNumParams() != 3 ||
474 !FTy->getParamType(0)->isPointerTy() ||
475 !FTy->getParamType(1)->isPointerTy())
476 return;
477 setDoesNotThrow(F);
478 setOnlyReadsMemory(F);
479 setDoesNotCapture(F, 1);
480 setDoesNotCapture(F, 2);
481 } else if (Name == "bzero") {
482 if (FTy->getNumParams() != 2 || !FTy->getParamType(0)->isPointerTy())
483 return;
484 setDoesNotThrow(F);
485 setDoesNotCapture(F, 1);
486 }
487 break;
488 case 'c':
489 if (Name == "calloc") {
490 if (FTy->getNumParams() != 2 ||
491 !FTy->getReturnType()->isPointerTy())
492 return;
493 setDoesNotThrow(F);
494 setDoesNotAlias(F, 0);
495 } else if (Name == "chmod" ||
496 Name == "chown" ||
497 Name == "ctermid" ||
498 Name == "clearerr" ||
499 Name == "closedir") {
500 if (FTy->getNumParams() == 0 || !FTy->getParamType(0)->isPointerTy())
501 return;
502 setDoesNotThrow(F);
503 setDoesNotCapture(F, 1);
504 }
505 break;
506 case 'a':
507 if (Name == "atoi" ||
508 Name == "atol" ||
509 Name == "atof" ||
510 Name == "atoll") {
511 if (FTy->getNumParams() != 1 || !FTy->getParamType(0)->isPointerTy())
512 return;
513 setDoesNotThrow(F);
514 setOnlyReadsMemory(F);
515 setDoesNotCapture(F, 1);
516 } else if (Name == "access") {
517 if (FTy->getNumParams() != 2 || !FTy->getParamType(0)->isPointerTy())
518 return;
519 setDoesNotThrow(F);
520 setDoesNotCapture(F, 1);
521 }
522 break;
523 case 'f':
524 if (Name == "fopen") {
525 if (FTy->getNumParams() != 2 ||
526 !FTy->getReturnType()->isPointerTy() ||
527 !FTy->getParamType(0)->isPointerTy() ||
528 !FTy->getParamType(1)->isPointerTy())
529 return;
530 setDoesNotThrow(F);
531 setDoesNotAlias(F, 0);
532 setDoesNotCapture(F, 1);
533 setDoesNotCapture(F, 2);
534 } else if (Name == "fdopen") {
535 if (FTy->getNumParams() != 2 ||
536 !FTy->getReturnType()->isPointerTy() ||
537 !FTy->getParamType(1)->isPointerTy())
538 return;
539 setDoesNotThrow(F);
540 setDoesNotAlias(F, 0);
541 setDoesNotCapture(F, 2);
542 } else if (Name == "feof" ||
543 Name == "free" ||
544 Name == "fseek" ||
545 Name == "ftell" ||
546 Name == "fgetc" ||
547 Name == "fseeko" ||
548 Name == "ftello" ||
549 Name == "fileno" ||
550 Name == "fflush" ||
551 Name == "fclose" ||
552 Name == "fsetpos" ||
553 Name == "flockfile" ||
554 Name == "funlockfile" ||
555 Name == "ftrylockfile") {
556 if (FTy->getNumParams() == 0 || !FTy->getParamType(0)->isPointerTy())
557 return;
558 setDoesNotThrow(F);
559 setDoesNotCapture(F, 1);
560 } else if (Name == "ferror") {
561 if (FTy->getNumParams() != 1 || !FTy->getParamType(0)->isPointerTy())
562 return;
563 setDoesNotThrow(F);
564 setDoesNotCapture(F, 1);
565 setOnlyReadsMemory(F);
566 } else if (Name == "fputc" ||
567 Name == "fstat" ||
568 Name == "frexp" ||
569 Name == "frexpf" ||
570 Name == "frexpl" ||
571 Name == "fstatvfs") {
572 if (FTy->getNumParams() != 2 || !FTy->getParamType(1)->isPointerTy())
573 return;
574 setDoesNotThrow(F);
575 setDoesNotCapture(F, 2);
576 } else if (Name == "fgets") {
577 if (FTy->getNumParams() != 3 ||
578 !FTy->getParamType(0)->isPointerTy() ||
579 !FTy->getParamType(2)->isPointerTy())
580 return;
581 setDoesNotThrow(F);
582 setDoesNotCapture(F, 3);
583 } else if (Name == "fread" ||
584 Name == "fwrite") {
585 if (FTy->getNumParams() != 4 ||
586 !FTy->getParamType(0)->isPointerTy() ||
587 !FTy->getParamType(3)->isPointerTy())
588 return;
589 setDoesNotThrow(F);
590 setDoesNotCapture(F, 1);
591 setDoesNotCapture(F, 4);
592 } else if (Name == "fputs" ||
593 Name == "fscanf" ||
594 Name == "fprintf" ||
595 Name == "fgetpos") {
596 if (FTy->getNumParams() < 2 ||
597 !FTy->getParamType(0)->isPointerTy() ||
598 !FTy->getParamType(1)->isPointerTy())
599 return;
600 setDoesNotThrow(F);
601 setDoesNotCapture(F, 1);
602 setDoesNotCapture(F, 2);
603 }
604 break;
605 case 'g':
606 if (Name == "getc" ||
607 Name == "getlogin_r" ||
608 Name == "getc_unlocked") {
609 if (FTy->getNumParams() == 0 || !FTy->getParamType(0)->isPointerTy())
610 return;
611 setDoesNotThrow(F);
612 setDoesNotCapture(F, 1);
613 } else if (Name == "getenv") {
614 if (FTy->getNumParams() != 1 || !FTy->getParamType(0)->isPointerTy())
615 return;
616 setDoesNotThrow(F);
617 setOnlyReadsMemory(F);
618 setDoesNotCapture(F, 1);
619 } else if (Name == "gets" ||
620 Name == "getchar") {
621 setDoesNotThrow(F);
622 } else if (Name == "getitimer") {
623 if (FTy->getNumParams() != 2 || !FTy->getParamType(1)->isPointerTy())
624 return;
625 setDoesNotThrow(F);
626 setDoesNotCapture(F, 2);
627 } else if (Name == "getpwnam") {
628 if (FTy->getNumParams() != 1 || !FTy->getParamType(0)->isPointerTy())
629 return;
630 setDoesNotThrow(F);
631 setDoesNotCapture(F, 1);
632 }
633 break;
634 case 'u':
635 if (Name == "ungetc") {
636 if (FTy->getNumParams() != 2 || !FTy->getParamType(1)->isPointerTy())
637 return;
638 setDoesNotThrow(F);
639 setDoesNotCapture(F, 2);
640 } else if (Name == "uname" ||
641 Name == "unlink" ||
642 Name == "unsetenv") {
643 if (FTy->getNumParams() != 1 || !FTy->getParamType(0)->isPointerTy())
644 return;
645 setDoesNotThrow(F);
646 setDoesNotCapture(F, 1);
647 } else if (Name == "utime" ||
648 Name == "utimes") {
649 if (FTy->getNumParams() != 2 ||
650 !FTy->getParamType(0)->isPointerTy() ||
651 !FTy->getParamType(1)->isPointerTy())
652 return;
653 setDoesNotThrow(F);
654 setDoesNotCapture(F, 1);
655 setDoesNotCapture(F, 2);
656 }
657 break;
658 case 'p':
659 if (Name == "putc") {
660 if (FTy->getNumParams() != 2 || !FTy->getParamType(1)->isPointerTy())
661 return;
662 setDoesNotThrow(F);
663 setDoesNotCapture(F, 2);
664 } else if (Name == "puts" ||
665 Name == "printf" ||
666 Name == "perror") {
667 if (FTy->getNumParams() != 1 || !FTy->getParamType(0)->isPointerTy())
668 return;
669 setDoesNotThrow(F);
670 setDoesNotCapture(F, 1);
671 } else if (Name == "pread" ||
672 Name == "pwrite") {
673 if (FTy->getNumParams() != 4 || !FTy->getParamType(1)->isPointerTy())
674 return;
675 // May throw; these are valid pthread cancellation points.
676 setDoesNotCapture(F, 2);
677 } else if (Name == "putchar") {
678 setDoesNotThrow(F);
679 } else if (Name == "popen") {
680 if (FTy->getNumParams() != 2 ||
681 !FTy->getReturnType()->isPointerTy() ||
682 !FTy->getParamType(0)->isPointerTy() ||
683 !FTy->getParamType(1)->isPointerTy())
684 return;
685 setDoesNotThrow(F);
686 setDoesNotAlias(F, 0);
687 setDoesNotCapture(F, 1);
688 setDoesNotCapture(F, 2);
689 } else if (Name == "pclose") {
690 if (FTy->getNumParams() != 1 || !FTy->getParamType(0)->isPointerTy())
691 return;
692 setDoesNotThrow(F);
693 setDoesNotCapture(F, 1);
694 }
695 break;
696 case 'v':
697 if (Name == "vscanf") {
698 if (FTy->getNumParams() != 2 || !FTy->getParamType(1)->isPointerTy())
699 return;
700 setDoesNotThrow(F);
701 setDoesNotCapture(F, 1);
702 } else if (Name == "vsscanf" ||
703 Name == "vfscanf") {
704 if (FTy->getNumParams() != 3 ||
705 !FTy->getParamType(1)->isPointerTy() ||
706 !FTy->getParamType(2)->isPointerTy())
707 return;
708 setDoesNotThrow(F);
709 setDoesNotCapture(F, 1);
710 setDoesNotCapture(F, 2);
711 } else if (Name == "valloc") {
712 if (!FTy->getReturnType()->isPointerTy())
713 return;
714 setDoesNotThrow(F);
715 setDoesNotAlias(F, 0);
716 } else if (Name == "vprintf") {
717 if (FTy->getNumParams() != 2 || !FTy->getParamType(0)->isPointerTy())
718 return;
719 setDoesNotThrow(F);
720 setDoesNotCapture(F, 1);
721 } else if (Name == "vfprintf" ||
722 Name == "vsprintf") {
723 if (FTy->getNumParams() != 3 ||
724 !FTy->getParamType(0)->isPointerTy() ||
725 !FTy->getParamType(1)->isPointerTy())
726 return;
727 setDoesNotThrow(F);
728 setDoesNotCapture(F, 1);
729 setDoesNotCapture(F, 2);
730 } else if (Name == "vsnprintf") {
731 if (FTy->getNumParams() != 4 ||
732 !FTy->getParamType(0)->isPointerTy() ||
733 !FTy->getParamType(2)->isPointerTy())
734 return;
735 setDoesNotThrow(F);
736 setDoesNotCapture(F, 1);
737 setDoesNotCapture(F, 3);
738 }
739 break;
740 case 'o':
741 if (Name == "open") {
742 if (FTy->getNumParams() < 2 || !FTy->getParamType(0)->isPointerTy())
743 return;
744 // May throw; "open" is a valid pthread cancellation point.
745 setDoesNotCapture(F, 1);
746 } else if (Name == "opendir") {
747 if (FTy->getNumParams() != 1 ||
748 !FTy->getReturnType()->isPointerTy() ||
749 !FTy->getParamType(0)->isPointerTy())
750 return;
751 setDoesNotThrow(F);
752 setDoesNotAlias(F, 0);
753 setDoesNotCapture(F, 1);
754 }
755 break;
756 case 't':
757 if (Name == "tmpfile") {
758 if (!FTy->getReturnType()->isPointerTy())
759 return;
760 setDoesNotThrow(F);
761 setDoesNotAlias(F, 0);
762 } else if (Name == "times") {
763 if (FTy->getNumParams() != 1 || !FTy->getParamType(0)->isPointerTy())
764 return;
765 setDoesNotThrow(F);
766 setDoesNotCapture(F, 1);
767 }
768 break;
769 case 'h':
770 if (Name == "htonl" ||
771 Name == "htons") {
772 setDoesNotThrow(F);
773 setDoesNotAccessMemory(F);
774 }
775 break;
776 case 'n':
777 if (Name == "ntohl" ||
778 Name == "ntohs") {
779 setDoesNotThrow(F);
780 setDoesNotAccessMemory(F);
781 }
782 break;
783 case 'l':
784 if (Name == "lstat") {
785 if (FTy->getNumParams() != 2 ||
786 !FTy->getParamType(0)->isPointerTy() ||
787 !FTy->getParamType(1)->isPointerTy())
788 return;
789 setDoesNotThrow(F);
790 setDoesNotCapture(F, 1);
791 setDoesNotCapture(F, 2);
792 } else if (Name == "lchown") {
793 if (FTy->getNumParams() != 3 || !FTy->getParamType(0)->isPointerTy())
794 return;
795 setDoesNotThrow(F);
796 setDoesNotCapture(F, 1);
797 }
798 break;
799 case 'q':
800 if (Name == "qsort") {
801 if (FTy->getNumParams() != 4 || !FTy->getParamType(3)->isPointerTy())
802 return;
803 // May throw; places call through function pointer.
804 setDoesNotCapture(F, 4);
805 }
806 break;
807 case '_':
808 if (Name == "__strdup" ||
809 Name == "__strndup") {
810 if (FTy->getNumParams() < 1 ||
811 !FTy->getReturnType()->isPointerTy() ||
812 !FTy->getParamType(0)->isPointerTy())
813 return;
814 setDoesNotThrow(F);
815 setDoesNotAlias(F, 0);
816 setDoesNotCapture(F, 1);
817 } else if (Name == "__strtok_r") {
818 if (FTy->getNumParams() != 3 ||
819 !FTy->getParamType(1)->isPointerTy())
820 return;
821 setDoesNotThrow(F);
822 setDoesNotCapture(F, 2);
823 } else if (Name == "_IO_getc") {
824 if (FTy->getNumParams() != 1 || !FTy->getParamType(0)->isPointerTy())
825 return;
826 setDoesNotThrow(F);
827 setDoesNotCapture(F, 1);
828 } else if (Name == "_IO_putc") {
829 if (FTy->getNumParams() != 2 || !FTy->getParamType(1)->isPointerTy())
830 return;
831 setDoesNotThrow(F);
832 setDoesNotCapture(F, 2);
833 }
834 break;
835 case 1:
836 if (Name == "\1__isoc99_scanf") {
837 if (FTy->getNumParams() < 1 ||
838 !FTy->getParamType(0)->isPointerTy())
839 return;
840 setDoesNotThrow(F);
841 setDoesNotCapture(F, 1);
842 } else if (Name == "\1stat64" ||
843 Name == "\1lstat64" ||
844 Name == "\1statvfs64" ||
845 Name == "\1__isoc99_sscanf") {
846 if (FTy->getNumParams() < 1 ||
847 !FTy->getParamType(0)->isPointerTy() ||
848 !FTy->getParamType(1)->isPointerTy())
849 return;
850 setDoesNotThrow(F);
851 setDoesNotCapture(F, 1);
852 setDoesNotCapture(F, 2);
853 } else if (Name == "\1fopen64") {
854 if (FTy->getNumParams() != 2 ||
855 !FTy->getReturnType()->isPointerTy() ||
856 !FTy->getParamType(0)->isPointerTy() ||
857 !FTy->getParamType(1)->isPointerTy())
858 return;
859 setDoesNotThrow(F);
860 setDoesNotAlias(F, 0);
861 setDoesNotCapture(F, 1);
862 setDoesNotCapture(F, 2);
863 } else if (Name == "\1fseeko64" ||
864 Name == "\1ftello64") {
865 if (FTy->getNumParams() == 0 || !FTy->getParamType(0)->isPointerTy())
866 return;
867 setDoesNotThrow(F);
868 setDoesNotCapture(F, 1);
869 } else if (Name == "\1tmpfile64") {
870 if (!FTy->getReturnType()->isPointerTy())
871 return;
872 setDoesNotThrow(F);
873 setDoesNotAlias(F, 0);
874 } else if (Name == "\1fstat64" ||
875 Name == "\1fstatvfs64") {
876 if (FTy->getNumParams() != 2 || !FTy->getParamType(1)->isPointerTy())
877 return;
878 setDoesNotThrow(F);
879 setDoesNotCapture(F, 2);
880 } else if (Name == "\1open64") {
881 if (FTy->getNumParams() < 2 || !FTy->getParamType(0)->isPointerTy())
882 return;
883 // May throw; "open" is a valid pthread cancellation point.
884 setDoesNotCapture(F, 1);
885 }
886 break;
887 }
888}
889
Nick Lewycky6cd0c042009-01-05 00:07:50 +0000890/// doInitialization - Add attributes to well-known functions.
Nick Lewycky0f8df9a2009-01-04 20:27:34 +0000891///
Nick Lewycky6cd0c042009-01-05 00:07:50 +0000892bool SimplifyLibCalls::doInitialization(Module &M) {
Nick Lewycky0f8df9a2009-01-04 20:27:34 +0000893 Modified = false;
894 for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) {
895 Function &F = *I;
Chris Lattnere265ad82011-02-24 07:12:12 +0000896 if (F.isDeclaration() && F.hasName())
897 inferPrototypeAttributes(F);
Nick Lewycky0f8df9a2009-01-04 20:27:34 +0000898 }
899 return Modified;
900}
Chris Lattnerfd1cbbe2008-05-01 06:25:24 +0000901
902// TODO:
903// Additional cases that we need to add to this file:
904//
905// cbrt:
906// * cbrt(expN(X)) -> expN(x/3)
907// * cbrt(sqrt(x)) -> pow(x,1/6)
908// * cbrt(sqrt(x)) -> pow(x,1/9)
909//
Chris Lattnerfd1cbbe2008-05-01 06:25:24 +0000910// exp, expf, expl:
911// * exp(log(x)) -> x
912//
913// log, logf, logl:
914// * log(exp(x)) -> x
915// * log(x**y) -> y*log(x)
916// * log(exp(y)) -> y*log(e)
917// * log(exp2(y)) -> y*log(2)
918// * log(exp10(y)) -> y*log(10)
919// * log(sqrt(x)) -> 0.5*log(x)
920// * log(pow(x,y)) -> y*log(x)
921//
922// lround, lroundf, lroundl:
923// * lround(cnst) -> cnst'
924//
Chris Lattnerfd1cbbe2008-05-01 06:25:24 +0000925// pow, powf, powl:
926// * pow(exp(x),y) -> exp(x*y)
927// * pow(sqrt(x),y) -> pow(x,y*0.5)
928// * pow(pow(x,y),z)-> pow(x,y*z)
929//
Chris Lattnerfd1cbbe2008-05-01 06:25:24 +0000930// round, roundf, roundl:
931// * round(cnst) -> cnst'
932//
933// signbit:
934// * signbit(cnst) -> cnst'
935// * signbit(nncst) -> 0 (if pstv is a non-negative constant)
936//
937// sqrt, sqrtf, sqrtl:
938// * sqrt(expN(x)) -> expN(x*0.5)
939// * sqrt(Nroot(x)) -> pow(x,1/(2*N))
940// * sqrt(pow(x,y)) -> pow(|x|,y*0.5)
941//
Chris Lattner18c7f802012-02-05 02:29:43 +0000942// strchr:
943// * strchr(p, 0) -> strlen(p)
Chris Lattnerfd1cbbe2008-05-01 06:25:24 +0000944// tan, tanf, tanl:
945// * tan(atan(x)) -> x
946//
947// trunc, truncf, truncl:
948// * trunc(cnst) -> cnst'
949//
950//