"llvm/lib/Target/git@repo.hca.bsc.es:rferrer/llvm-epi-0.8.git" did not exist on "f9ae1c6001cf8b5f26cfb25980312fc525fae1e7"
Newer
Older
//===- SimplifyLibCalls.cpp - Optimize specific well-known library calls --===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements a simple pass that applies a variety of small
// optimizations for calls to specific well-known function calls (e.g. runtime
// library functions). For example, a call to the function "exit(3)" that
// occurs within the main() function can be transformed into a simple "return 3"
// instruction. Any optimization that takes this form (replace call to library
// function with simpler code that provides the same result) belongs in this
// file.
//
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "simplify-libcalls"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Intrinsics.h"
#include "llvm/Module.h"
#include "llvm/Pass.h"
#include "llvm/Support/IRBuilder.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/Target/TargetData.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Config/config.h"
using namespace llvm;
STATISTIC(NumSimplified, "Number of library calls simplified");
STATISTIC(NumAnnotated, "Number of attributes added to library functions");
//===----------------------------------------------------------------------===//
// Optimizer Base Class
//===----------------------------------------------------------------------===//
/// This class is the abstract base class for the set of optimizations that
/// corresponds to one library call.
namespace {
class VISIBILITY_HIDDEN LibCallOptimization {
protected:
Function *Caller;
const TargetData *TD;
public:
LibCallOptimization() { }
virtual ~LibCallOptimization() {}
/// CallOptimizer - This pure virtual method is implemented by base classes to
/// do various optimizations. If this returns null then no transformation was
/// performed. If it returns CI, then it transformed the call and CI is to be
/// deleted. If it returns something else, replace CI with the new value and
/// delete CI.
virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B)
=0;
Value *OptimizeCall(CallInst *CI, const TargetData &TD, IRBuilder<> &B) {
Caller = CI->getParent()->getParent();
this->TD = &TD;
return CallOptimizer(CI->getCalledFunction(), CI, B);
}
/// CastToCStr - Return V if it is an i8*, otherwise cast it to i8*.
Value *CastToCStr(Value *V, IRBuilder<> &B);
/// EmitStrLen - Emit a call to the strlen function to the builder, for the
/// specified pointer. Ptr is required to be some pointer type, and the
/// return value has 'intptr_t' type.
Value *EmitStrLen(Value *Ptr, IRBuilder<> &B);
/// EmitMemCpy - Emit a call to the memcpy function to the builder. This
/// always expects that the size has type 'intptr_t' and Dst/Src are pointers.
Value *EmitMemCpy(Value *Dst, Value *Src, Value *Len,
unsigned Align, IRBuilder<> &B);
/// EmitMemChr - Emit a call to the memchr function. This assumes that Ptr is
/// a pointer, Val is an i32 value, and Len is an 'intptr_t' value.
Value *EmitMemChr(Value *Ptr, Value *Val, Value *Len, IRBuilder<> &B);
/// EmitMemCmp - Emit a call to the memcmp function.
Value *EmitMemCmp(Value *Ptr1, Value *Ptr2, Value *Len, IRBuilder<> &B);
/// EmitMemSet - Emit a call to the memset function
Value *EmitMemSet(Value *Dst, Value *Val, Value *Len, IRBuilder<> &B);
/// EmitUnaryFloatFnCall - Emit a call to the unary function named 'Name' (e.g.
/// 'floor'). This function is known to take a single of type matching 'Op'
/// and returns one value with the same type. If 'Op' is a long double, 'l'
/// is added as the suffix of name, if 'Op' is a float, we add a 'f' suffix.
Value *EmitUnaryFloatFnCall(Value *Op, const char *Name, IRBuilder<> &B);
/// EmitPutChar - Emit a call to the putchar function. This assumes that Char
/// is an integer.
void EmitPutChar(Value *Char, IRBuilder<> &B);
/// EmitPutS - Emit a call to the puts function. This assumes that Str is
/// some pointer.
void EmitPutS(Value *Str, IRBuilder<> &B);
/// EmitFPutC - Emit a call to the fputc function. This assumes that Char is
/// an i32, and File is a pointer to FILE.
void EmitFPutC(Value *Char, Value *File, IRBuilder<> &B);
/// EmitFPutS - Emit a call to the puts function. Str is required to be a
/// pointer and File is a pointer to FILE.
void EmitFPutS(Value *Str, Value *File, IRBuilder<> &B);
/// EmitFWrite - Emit a call to the fwrite function. This assumes that Ptr is
/// a pointer, Size is an 'intptr_t', and File is a pointer to FILE.
void EmitFWrite(Value *Ptr, Value *Size, Value *File, IRBuilder<> &B);
};
} // End anonymous namespace.
/// CastToCStr - Return V if it is an i8*, otherwise cast it to i8*.
Value *LibCallOptimization::CastToCStr(Value *V, IRBuilder<> &B) {
return B.CreateBitCast(V, PointerType::getUnqual(Type::Int8Ty), "cstr");
}
/// EmitStrLen - Emit a call to the strlen function to the builder, for the
/// specified pointer. This always returns an integer value of size intptr_t.
Value *LibCallOptimization::EmitStrLen(Value *Ptr, IRBuilder<> &B) {
Module *M = Caller->getParent();
AttributeWithIndex AWI[2];
AWI[0] = AttributeWithIndex::get(1, Attribute::NoCapture);
AWI[1] = AttributeWithIndex::get(~0u, Attribute::ReadOnly |
Attribute::NoUnwind);
Constant *StrLen =M->getOrInsertFunction("strlen", AttrListPtr::get(AWI, 2),
TD->getIntPtrType(),
PointerType::getUnqual(Type::Int8Ty),
NULL);
return B.CreateCall(StrLen, CastToCStr(Ptr, B), "strlen");
}
/// EmitMemCpy - Emit a call to the memcpy function to the builder. This always
/// expects that the size has type 'intptr_t' and Dst/Src are pointers.
Value *LibCallOptimization::EmitMemCpy(Value *Dst, Value *Src, Value *Len,
unsigned Align, IRBuilder<> &B) {
Module *M = Caller->getParent();
Intrinsic::ID IID = Intrinsic::memcpy;
const Type *Tys[1];
Tys[0] = Len->getType();
Value *MemCpy = Intrinsic::getDeclaration(M, IID, Tys, 1);
return B.CreateCall4(MemCpy, CastToCStr(Dst, B), CastToCStr(Src, B), Len,
ConstantInt::get(Type::Int32Ty, Align));
}
/// EmitMemChr - Emit a call to the memchr function. This assumes that Ptr is
/// a pointer, Val is an i32 value, and Len is an 'intptr_t' value.
Value *LibCallOptimization::EmitMemChr(Value *Ptr, Value *Val,
Value *Len, IRBuilder<> &B) {
Module *M = Caller->getParent();
AttributeWithIndex AWI;
AWI = AttributeWithIndex::get(~0u, Attribute::ReadOnly | Attribute::NoUnwind);
Value *MemChr = M->getOrInsertFunction("memchr", AttrListPtr::get(&AWI, 1),
PointerType::getUnqual(Type::Int8Ty),
PointerType::getUnqual(Type::Int8Ty),
Type::Int32Ty, TD->getIntPtrType(),
NULL);
return B.CreateCall3(MemChr, CastToCStr(Ptr, B), Val, Len, "memchr");
}
/// EmitMemCmp - Emit a call to the memcmp function.
Value *LibCallOptimization::EmitMemCmp(Value *Ptr1, Value *Ptr2,
Value *Len, IRBuilder<> &B) {
Module *M = Caller->getParent();
AttributeWithIndex AWI[3];
AWI[0] = AttributeWithIndex::get(1, Attribute::NoCapture);
AWI[1] = AttributeWithIndex::get(2, Attribute::NoCapture);
AWI[2] = AttributeWithIndex::get(~0u, Attribute::ReadOnly |
Attribute::NoUnwind);
Value *MemCmp = M->getOrInsertFunction("memcmp", AttrListPtr::get(AWI, 3),
Type::Int32Ty,
PointerType::getUnqual(Type::Int8Ty),
PointerType::getUnqual(Type::Int8Ty),
TD->getIntPtrType(), NULL);
return B.CreateCall3(MemCmp, CastToCStr(Ptr1, B), CastToCStr(Ptr2, B),
Len, "memcmp");
}
/// EmitMemSet - Emit a call to the memset function
Value *LibCallOptimization::EmitMemSet(Value *Dst, Value *Val,
Value *Len, IRBuilder<> &B) {
Module *M = Caller->getParent();
Intrinsic::ID IID = Intrinsic::memset;
const Type *Tys[1];
Tys[0] = Len->getType();
Value *MemSet = Intrinsic::getDeclaration(M, IID, Tys, 1);
Value *Align = ConstantInt::get(Type::Int32Ty, 1);
return B.CreateCall4(MemSet, CastToCStr(Dst, B), Val, Len, Align);
}
/// EmitUnaryFloatFnCall - Emit a call to the unary function named 'Name' (e.g.
/// 'floor'). This function is known to take a single of type matching 'Op' and
/// returns one value with the same type. If 'Op' is a long double, 'l' is
/// added as the suffix of name, if 'Op' is a float, we add a 'f' suffix.
Value *LibCallOptimization::EmitUnaryFloatFnCall(Value *Op, const char *Name,
IRBuilder<> &B) {
char NameBuffer[20];
if (Op->getType() != Type::DoubleTy) {
// If we need to add a suffix, copy into NameBuffer.
unsigned NameLen = strlen(Name);
assert(NameLen < sizeof(NameBuffer)-2);
memcpy(NameBuffer, Name, NameLen);
if (Op->getType() == Type::FloatTy)
NameBuffer[NameLen] = 'f'; // floorf
else
NameBuffer[NameLen] = 'l'; // floorl
NameBuffer[NameLen+1] = 0;
Name = NameBuffer;
}
Module *M = Caller->getParent();
Value *Callee = M->getOrInsertFunction(Name, Op->getType(),
Op->getType(), NULL);
return B.CreateCall(Callee, Op, Name);
}
/// EmitPutChar - Emit a call to the putchar function. This assumes that Char
/// is an integer.
void LibCallOptimization::EmitPutChar(Value *Char, IRBuilder<> &B) {
Module *M = Caller->getParent();
Value *F = M->getOrInsertFunction("putchar", Type::Int32Ty,
Type::Int32Ty, NULL);
B.CreateCall(F, B.CreateIntCast(Char, Type::Int32Ty, "chari"), "putchar");
}
/// EmitPutS - Emit a call to the puts function. This assumes that Str is
/// some pointer.
void LibCallOptimization::EmitPutS(Value *Str, IRBuilder<> &B) {
Module *M = Caller->getParent();
AttributeWithIndex AWI[2];
AWI[0] = AttributeWithIndex::get(1, Attribute::NoCapture);
AWI[1] = AttributeWithIndex::get(~0u, Attribute::NoUnwind);
Value *F = M->getOrInsertFunction("puts", AttrListPtr::get(AWI, 2),
Type::Int32Ty,
PointerType::getUnqual(Type::Int8Ty), NULL);
B.CreateCall(F, CastToCStr(Str, B), "puts");
}
/// EmitFPutC - Emit a call to the fputc function. This assumes that Char is
/// an integer and File is a pointer to FILE.
void LibCallOptimization::EmitFPutC(Value *Char, Value *File, IRBuilder<> &B) {
Module *M = Caller->getParent();
AttributeWithIndex AWI[2];
AWI[0] = AttributeWithIndex::get(2, Attribute::NoCapture);
AWI[1] = AttributeWithIndex::get(~0u, Attribute::NoUnwind);
Constant *F;
if (isa<PointerType>(File->getType()))
F = M->getOrInsertFunction("fputc", AttrListPtr::get(AWI, 2), Type::Int32Ty,
Type::Int32Ty, File->getType(), NULL);
else
F = M->getOrInsertFunction("fputc", Type::Int32Ty, Type::Int32Ty,
File->getType(), NULL);
Char = B.CreateIntCast(Char, Type::Int32Ty, "chari");
B.CreateCall2(F, Char, File, "fputc");
}
/// EmitFPutS - Emit a call to the puts function. Str is required to be a
/// pointer and File is a pointer to FILE.
void LibCallOptimization::EmitFPutS(Value *Str, Value *File, IRBuilder<> &B) {
Module *M = Caller->getParent();
AttributeWithIndex AWI[3];
AWI[0] = AttributeWithIndex::get(1, Attribute::NoCapture);
AWI[1] = AttributeWithIndex::get(2, Attribute::NoCapture);
AWI[2] = AttributeWithIndex::get(~0u, Attribute::NoUnwind);
Constant *F;
if (isa<PointerType>(File->getType()))
F = M->getOrInsertFunction("fputs", AttrListPtr::get(AWI, 3), Type::Int32Ty,
PointerType::getUnqual(Type::Int8Ty),
File->getType(), NULL);
else
F = M->getOrInsertFunction("fputs", Type::Int32Ty,
PointerType::getUnqual(Type::Int8Ty),
File->getType(), NULL);
B.CreateCall2(F, CastToCStr(Str, B), File, "fputs");
}
/// EmitFWrite - Emit a call to the fwrite function. This assumes that Ptr is
/// a pointer, Size is an 'intptr_t', and File is a pointer to FILE.
void LibCallOptimization::EmitFWrite(Value *Ptr, Value *Size, Value *File,
IRBuilder<> &B) {
Module *M = Caller->getParent();
AttributeWithIndex AWI[3];
AWI[0] = AttributeWithIndex::get(1, Attribute::NoCapture);
AWI[1] = AttributeWithIndex::get(4, Attribute::NoCapture);
AWI[2] = AttributeWithIndex::get(~0u, Attribute::NoUnwind);
Constant *F;
if (isa<PointerType>(File->getType()))
F = M->getOrInsertFunction("fwrite", AttrListPtr::get(AWI, 3),
TD->getIntPtrType(),
PointerType::getUnqual(Type::Int8Ty),
TD->getIntPtrType(), TD->getIntPtrType(),
File->getType(), NULL);
else
F = M->getOrInsertFunction("fwrite", TD->getIntPtrType(),
PointerType::getUnqual(Type::Int8Ty),
TD->getIntPtrType(), TD->getIntPtrType(),
File->getType(), NULL);
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
B.CreateCall4(F, CastToCStr(Ptr, B), Size,
ConstantInt::get(TD->getIntPtrType(), 1), File);
}
//===----------------------------------------------------------------------===//
// Helper Functions
//===----------------------------------------------------------------------===//
/// GetStringLengthH - If we can compute the length of the string pointed to by
/// the specified pointer, return 'len+1'. If we can't, return 0.
static uint64_t GetStringLengthH(Value *V, SmallPtrSet<PHINode*, 32> &PHIs) {
// Look through noop bitcast instructions.
if (BitCastInst *BCI = dyn_cast<BitCastInst>(V))
return GetStringLengthH(BCI->getOperand(0), PHIs);
// If this is a PHI node, there are two cases: either we have already seen it
// or we haven't.
if (PHINode *PN = dyn_cast<PHINode>(V)) {
if (!PHIs.insert(PN))
return ~0ULL; // already in the set.
// If it was new, see if all the input strings are the same length.
uint64_t LenSoFar = ~0ULL;
for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) {
uint64_t Len = GetStringLengthH(PN->getIncomingValue(i), PHIs);
if (Len == 0) return 0; // Unknown length -> unknown.
if (Len == ~0ULL) continue;
if (Len != LenSoFar && LenSoFar != ~0ULL)
return 0; // Disagree -> unknown.
LenSoFar = Len;
}
// Success, all agree.
return LenSoFar;
}
// strlen(select(c,x,y)) -> strlen(x) ^ strlen(y)
if (SelectInst *SI = dyn_cast<SelectInst>(V)) {
uint64_t Len1 = GetStringLengthH(SI->getTrueValue(), PHIs);
if (Len1 == 0) return 0;
uint64_t Len2 = GetStringLengthH(SI->getFalseValue(), PHIs);
if (Len2 == 0) return 0;
if (Len1 == ~0ULL) return Len2;
if (Len2 == ~0ULL) return Len1;
if (Len1 != Len2) return 0;
return Len1;
}
// If the value is not a GEP instruction nor a constant expression with a
// GEP instruction, then return unknown.
User *GEP = 0;
if (GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(V)) {
GEP = GEPI;
} else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) {
if (CE->getOpcode() != Instruction::GetElementPtr)
return 0;
GEP = CE;
} else {
return 0;
}
// Make sure the GEP has exactly three arguments.
if (GEP->getNumOperands() != 3)
return 0;
// Check to make sure that the first operand of the GEP is an integer and
// has value 0 so that we are sure we're indexing into the initializer.
if (ConstantInt *Idx = dyn_cast<ConstantInt>(GEP->getOperand(1))) {
if (!Idx->isZero())
return 0;
} else
return 0;
// If the second index isn't a ConstantInt, then this is a variable index
// into the array. If this occurs, we can't say anything meaningful about
// the string.
uint64_t StartIdx = 0;
if (ConstantInt *CI = dyn_cast<ConstantInt>(GEP->getOperand(2)))
StartIdx = CI->getZExtValue();
else
return 0;
// The GEP instruction, constant or instruction, must reference a global
// variable that is a constant and is initialized. The referenced constant
// initializer is the array that we'll use for optimization.
GlobalVariable* GV = dyn_cast<GlobalVariable>(GEP->getOperand(0));
if (!GV || !GV->isConstant() || !GV->hasInitializer())
return 0;
Constant *GlobalInit = GV->getInitializer();
// Handle the ConstantAggregateZero case, which is a degenerate case. The
// initializer is constant zero so the length of the string must be zero.
if (isa<ConstantAggregateZero>(GlobalInit))
return 1; // Len = 0 offset by 1.
// Must be a Constant Array
ConstantArray *Array = dyn_cast<ConstantArray>(GlobalInit);
if (!Array || Array->getType()->getElementType() != Type::Int8Ty)
return false;
// Get the number of elements in the array
uint64_t NumElts = Array->getType()->getNumElements();
// Traverse the constant array from StartIdx (derived above) which is
// the place the GEP refers to in the array.
for (unsigned i = StartIdx; i != NumElts; ++i) {
Constant *Elt = Array->getOperand(i);
ConstantInt *CI = dyn_cast<ConstantInt>(Elt);
if (!CI) // This array isn't suitable, non-int initializer.
return 0;
if (CI->isZero())
return i-StartIdx+1; // We found end of string, success!
}
return 0; // The array isn't null terminated, conservatively return 'unknown'.
}
/// GetStringLength - If we can compute the length of the string pointed to by
/// the specified pointer, return 'len+1'. If we can't, return 0.
static uint64_t GetStringLength(Value *V) {
if (!isa<PointerType>(V->getType())) return 0;
SmallPtrSet<PHINode*, 32> PHIs;
uint64_t Len = GetStringLengthH(V, PHIs);
// If Len is ~0ULL, we had an infinite phi cycle: this is dead code, so return
// an empty string as a length.
return Len == ~0ULL ? 1 : Len;
}
/// IsOnlyUsedInZeroEqualityComparison - Return true if it only matters that the
/// value is equal or not-equal to zero.
static bool IsOnlyUsedInZeroEqualityComparison(Value *V) {
for (Value::use_iterator UI = V->use_begin(), E = V->use_end();
UI != E; ++UI) {
if (ICmpInst *IC = dyn_cast<ICmpInst>(*UI))
if (IC->isEquality())
if (Constant *C = dyn_cast<Constant>(IC->getOperand(1)))
if (C->isNullValue())
continue;
// Unknown instruction.
return false;
}
return true;
}
//===----------------------------------------------------------------------===//
// Miscellaneous LibCall Optimizations
//===----------------------------------------------------------------------===//
Bill Wendling
committed
namespace {
//===---------------------------------------===//
// 'exit' Optimizations
/// ExitOpt - int main() { exit(4); } --> int main() { return 4; }
struct VISIBILITY_HIDDEN ExitOpt : public LibCallOptimization {
virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) {
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
// Verify we have a reasonable prototype for exit.
if (Callee->arg_size() == 0 || !CI->use_empty())
return 0;
// Verify the caller is main, and that the result type of main matches the
// argument type of exit.
if (!Caller->isName("main") || !Caller->hasExternalLinkage() ||
Caller->getReturnType() != CI->getOperand(1)->getType())
return 0;
TerminatorInst *OldTI = CI->getParent()->getTerminator();
// Create the return after the call.
ReturnInst *RI = B.CreateRet(CI->getOperand(1));
// Drop all successor phi node entries.
for (unsigned i = 0, e = OldTI->getNumSuccessors(); i != e; ++i)
OldTI->getSuccessor(i)->removePredecessor(CI->getParent());
// Erase all instructions from after our return instruction until the end of
// the block.
BasicBlock::iterator FirstDead = RI; ++FirstDead;
CI->getParent()->getInstList().erase(FirstDead, CI->getParent()->end());
return CI;
}
};
//===----------------------------------------------------------------------===//
// String and Memory LibCall Optimizations
//===----------------------------------------------------------------------===//
//===---------------------------------------===//
// 'strcat' Optimizations
struct VISIBILITY_HIDDEN StrCatOpt : public LibCallOptimization {
virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) {
// Verify the "strcat" function prototype.
const FunctionType *FT = Callee->getFunctionType();
if (FT->getNumParams() != 2 ||
FT->getReturnType() != PointerType::getUnqual(Type::Int8Ty) ||
FT->getParamType(0) != FT->getReturnType() ||
FT->getParamType(1) != FT->getReturnType())
return 0;
// Extract some information from the instruction
Value *Dst = CI->getOperand(1);
Value *Src = CI->getOperand(2);
// See if we can get the length of the input string.
uint64_t Len = GetStringLength(Src);
--Len; // Unbias length.
// Handle the simple, do-nothing case: strcat(x, "") -> x
if (Len == 0)
return Dst;
EmitStrLenMemCpy(Src, Dst, Len, B);
return Dst;
}
void EmitStrLenMemCpy(Value *Src, Value *Dst, uint64_t Len, IRBuilder<> &B) {
// We need to find the end of the destination string. That's where the
// memory is to be moved to. We just generate a call to strlen.
Value *DstLen = EmitStrLen(Dst, B);
// Now that we have the destination's length, we must index into the
// destination's pointer to get the actual memcpy destination (end of
// the string .. we're concatenating).
Value *CpyDst = B.CreateGEP(Dst, DstLen, "endptr");
// We have enough information to now generate the memcpy call to do the
// concatenation for us. Make a memcpy to copy the nul byte with align = 1.
EmitMemCpy(CpyDst, Src, ConstantInt::get(TD->getIntPtrType(), Len+1), 1, B);
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
}
};
//===---------------------------------------===//
// 'strncat' Optimizations
struct VISIBILITY_HIDDEN StrNCatOpt : public StrCatOpt {
virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) {
// Verify the "strncat" function prototype.
const FunctionType *FT = Callee->getFunctionType();
if (FT->getNumParams() != 3 ||
FT->getReturnType() != PointerType::getUnqual(Type::Int8Ty) ||
FT->getParamType(0) != FT->getReturnType() ||
FT->getParamType(1) != FT->getReturnType() ||
!isa<IntegerType>(FT->getParamType(2)))
return 0;
// Extract some information from the instruction
Value *Dst = CI->getOperand(1);
Value *Src = CI->getOperand(2);
uint64_t Len;
// We don't do anything if length is not constant
if (ConstantInt *LengthArg = dyn_cast<ConstantInt>(CI->getOperand(3)))
Len = LengthArg->getZExtValue();
else
return 0;
// See if we can get the length of the input string.
uint64_t SrcLen = GetStringLength(Src);
if (SrcLen == 0) return 0;
--SrcLen; // Unbias length.
// Handle the simple, do-nothing cases:
// strncat(x, "", c) -> x
// strncat(x, c, 0) -> x
if (SrcLen == 0 || Len == 0) return Dst;
// We don't optimize this case
if (Len < SrcLen) return 0;
// strncat(x, s, c) -> strcat(x, s)
// s is constant so the strcat can be optimized further
EmitStrLenMemCpy(Src, Dst, SrcLen, B);
return Dst;
}
};
//===---------------------------------------===//
// 'strchr' Optimizations
struct VISIBILITY_HIDDEN StrChrOpt : public LibCallOptimization {
virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) {
// Verify the "strchr" function prototype.
const FunctionType *FT = Callee->getFunctionType();
if (FT->getNumParams() != 2 ||
FT->getReturnType() != PointerType::getUnqual(Type::Int8Ty) ||
FT->getParamType(0) != FT->getReturnType())
return 0;
Value *SrcStr = CI->getOperand(1);
// If the second operand is non-constant, see if we can compute the length
// of the input string and turn this into memchr.
ConstantInt *CharC = dyn_cast<ConstantInt>(CI->getOperand(2));
if (CharC == 0) {
uint64_t Len = GetStringLength(SrcStr);
if (Len == 0 || FT->getParamType(1) != Type::Int32Ty) // memchr needs i32.
return 0;
return EmitMemChr(SrcStr, CI->getOperand(2), // include nul.
ConstantInt::get(TD->getIntPtrType(), Len), B);
}
// Otherwise, the character is a constant, see if the first argument is
// a string literal. If so, we can constant fold.
std::string Str;
if (!GetConstantStringInfo(SrcStr, Str))
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
// strchr can find the nul character.
Str += '\0';
char CharValue = CharC->getSExtValue();
// Compute the offset.
uint64_t i = 0;
while (1) {
if (i == Str.size()) // Didn't find the char. strchr returns null.
return Constant::getNullValue(CI->getType());
// Did we find our match?
if (Str[i] == CharValue)
break;
++i;
}
// strchr(s+n,c) -> gep(s+n+i,c)
Value *Idx = ConstantInt::get(Type::Int64Ty, i);
return B.CreateGEP(SrcStr, Idx, "strchr");
}
};
//===---------------------------------------===//
// 'strcmp' Optimizations
struct VISIBILITY_HIDDEN StrCmpOpt : public LibCallOptimization {
virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) {
// Verify the "strcmp" function prototype.
const FunctionType *FT = Callee->getFunctionType();
if (FT->getNumParams() != 2 || FT->getReturnType() != Type::Int32Ty ||
FT->getParamType(0) != FT->getParamType(1) ||
FT->getParamType(0) != PointerType::getUnqual(Type::Int8Ty))
return 0;
Value *Str1P = CI->getOperand(1), *Str2P = CI->getOperand(2);
if (Str1P == Str2P) // strcmp(x,x) -> 0
return ConstantInt::get(CI->getType(), 0);
std::string Str1, Str2;
bool HasStr1 = GetConstantStringInfo(Str1P, Str1);
bool HasStr2 = GetConstantStringInfo(Str2P, Str2);
if (HasStr1 && Str1.empty()) // strcmp("", x) -> *x
return B.CreateZExt(B.CreateLoad(Str2P, "strcmpload"), CI->getType());
if (HasStr2 && Str2.empty()) // strcmp(x,"") -> *x
return B.CreateZExt(B.CreateLoad(Str1P, "strcmpload"), CI->getType());
// strcmp(x, y) -> cnst (if both x and y are constant strings)
if (HasStr1 && HasStr2)
return ConstantInt::get(CI->getType(), strcmp(Str1.c_str(),Str2.c_str()));
// strcmp(P, "x") -> memcmp(P, "x", 2)
uint64_t Len1 = GetStringLength(Str1P);
uint64_t Len2 = GetStringLength(Str2P);
if (Len1 || Len2) {
// Choose the smallest Len excluding 0 which means 'unknown'.
if (!Len1 || (Len2 && Len2 < Len1))
Len1 = Len2;
return EmitMemCmp(Str1P, Str2P,
ConstantInt::get(TD->getIntPtrType(), Len1), B);
}
return 0;
}
};
//===---------------------------------------===//
// 'strncmp' Optimizations
struct VISIBILITY_HIDDEN StrNCmpOpt : public LibCallOptimization {
virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) {
// Verify the "strncmp" function prototype.
const FunctionType *FT = Callee->getFunctionType();
if (FT->getNumParams() != 3 || FT->getReturnType() != Type::Int32Ty ||
FT->getParamType(0) != FT->getParamType(1) ||
FT->getParamType(0) != PointerType::getUnqual(Type::Int8Ty) ||
!isa<IntegerType>(FT->getParamType(2)))
return 0;
Value *Str1P = CI->getOperand(1), *Str2P = CI->getOperand(2);
if (Str1P == Str2P) // strncmp(x,x,n) -> 0
return ConstantInt::get(CI->getType(), 0);
// Get the length argument if it is constant.
uint64_t Length;
if (ConstantInt *LengthArg = dyn_cast<ConstantInt>(CI->getOperand(3)))
Length = LengthArg->getZExtValue();
else
return 0;
if (Length == 0) // strncmp(x,y,0) -> 0
return ConstantInt::get(CI->getType(), 0);
std::string Str1, Str2;
bool HasStr1 = GetConstantStringInfo(Str1P, Str1);
bool HasStr2 = GetConstantStringInfo(Str2P, Str2);
if (HasStr1 && Str1.empty()) // strncmp("", x, n) -> *x
return B.CreateZExt(B.CreateLoad(Str2P, "strcmpload"), CI->getType());
if (HasStr2 && Str2.empty()) // strncmp(x, "", n) -> *x
return B.CreateZExt(B.CreateLoad(Str1P, "strcmpload"), CI->getType());
// strncmp(x, y) -> cnst (if both x and y are constant strings)
return ConstantInt::get(CI->getType(),
strncmp(Str1.c_str(), Str2.c_str(), Length));
return 0;
}
};
//===---------------------------------------===//
// 'strcpy' Optimizations
struct VISIBILITY_HIDDEN StrCpyOpt : public LibCallOptimization {
virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) {
// Verify the "strcpy" function prototype.
const FunctionType *FT = Callee->getFunctionType();
if (FT->getNumParams() != 2 || FT->getReturnType() != FT->getParamType(0) ||
FT->getParamType(0) != FT->getParamType(1) ||
FT->getParamType(0) != PointerType::getUnqual(Type::Int8Ty))
return 0;
Value *Dst = CI->getOperand(1), *Src = CI->getOperand(2);
if (Dst == Src) // strcpy(x,x) -> x
return Src;
// See if we can get the length of the input string.
uint64_t Len = GetStringLength(Src);
// We have enough information to now generate the memcpy call to do the
// concatenation for us. Make a memcpy to copy the nul byte with align = 1.
EmitMemCpy(Dst, Src, ConstantInt::get(TD->getIntPtrType(), Len), 1, B);
return Dst;
}
};
//===---------------------------------------===//
// 'strncpy' Optimizations
struct VISIBILITY_HIDDEN StrNCpyOpt : public LibCallOptimization {
virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) {
const FunctionType *FT = Callee->getFunctionType();
if (FT->getNumParams() != 3 || FT->getReturnType() != FT->getParamType(0) ||
FT->getParamType(0) != FT->getParamType(1) ||
FT->getParamType(0) != PointerType::getUnqual(Type::Int8Ty) ||
!isa<IntegerType>(FT->getParamType(2)))
return 0;
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
Value *Dst = CI->getOperand(1);
Value *Src = CI->getOperand(2);
Value *LenOp = CI->getOperand(3);
// See if we can get the length of the input string.
uint64_t SrcLen = GetStringLength(Src);
if (SrcLen == 0) return 0;
--SrcLen;
if (SrcLen == 0) {
// strncpy(x, "", y) -> memset(x, '\0', y, 1)
EmitMemSet(Dst, ConstantInt::get(Type::Int8Ty, '\0'), LenOp, B);
return Dst;
}
uint64_t Len;
if (ConstantInt *LengthArg = dyn_cast<ConstantInt>(LenOp))
Len = LengthArg->getZExtValue();
else
return 0;
if (Len == 0) return Dst; // strncpy(x, y, 0) -> x
// Let strncpy handle the zero padding
if (Len > SrcLen+1) return 0;
// strncpy(x, s, c) -> memcpy(x, s, c, 1) [s and c are constant]
EmitMemCpy(Dst, Src, ConstantInt::get(TD->getIntPtrType(), Len), 1, B);
return Dst;
}
};
//===---------------------------------------===//
// 'strlen' Optimizations
struct VISIBILITY_HIDDEN StrLenOpt : public LibCallOptimization {
virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) {
const FunctionType *FT = Callee->getFunctionType();
if (FT->getNumParams() != 1 ||
FT->getParamType(0) != PointerType::getUnqual(Type::Int8Ty) ||
!isa<IntegerType>(FT->getReturnType()))
return 0;
Value *Src = CI->getOperand(1);
// Constant folding: strlen("xyz") -> 3
if (uint64_t Len = GetStringLength(Src))
return ConstantInt::get(CI->getType(), Len-1);
// Handle strlen(p) != 0.
if (!IsOnlyUsedInZeroEqualityComparison(CI)) return 0;
// strlen(x) != 0 --> *x != 0
// strlen(x) == 0 --> *x == 0
return B.CreateZExt(B.CreateLoad(Src, "strlenfirst"), CI->getType());
}
};
Nick Lewycky
committed
//===---------------------------------------===//
// 'strto*' Optimizations
struct VISIBILITY_HIDDEN StrToOpt : public LibCallOptimization {
virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) {
const FunctionType *FT = Callee->getFunctionType();
if ((FT->getNumParams() != 2 && FT->getNumParams() != 3) ||
!isa<PointerType>(FT->getParamType(0)) ||
!isa<PointerType>(FT->getParamType(1)))
return 0;
Value *EndPtr = CI->getOperand(2);
if (isa<ConstantPointerNull>(EndPtr)) {
CI->setOnlyReadsMemory();
Nick Lewycky
committed
CI->addAttribute(1, Attribute::NoCapture);
Nick Lewycky
committed
return 0;
}
};
//===---------------------------------------===//
// 'memcmp' Optimizations
struct VISIBILITY_HIDDEN MemCmpOpt : public LibCallOptimization {
virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) {
const FunctionType *FT = Callee->getFunctionType();
if (FT->getNumParams() != 3 || !isa<PointerType>(FT->getParamType(0)) ||
!isa<PointerType>(FT->getParamType(1)) ||
FT->getReturnType() != Type::Int32Ty)
return 0;
Value *LHS = CI->getOperand(1), *RHS = CI->getOperand(2);
if (LHS == RHS) // memcmp(s,s,x) -> 0
return Constant::getNullValue(CI->getType());
// Make sure we have a constant length.
ConstantInt *LenC = dyn_cast<ConstantInt>(CI->getOperand(3));
uint64_t Len = LenC->getZExtValue();
if (Len == 0) // memcmp(s1,s2,0) -> 0
return Constant::getNullValue(CI->getType());
if (Len == 1) { // memcmp(S1,S2,1) -> *LHS - *RHS
Value *LHSV = B.CreateLoad(CastToCStr(LHS, B), "lhsv");
Value *RHSV = B.CreateLoad(CastToCStr(RHS, B), "rhsv");
return B.CreateSExt(B.CreateSub(LHSV, RHSV, "chardiff"), CI->getType());
// memcmp(S1,S2,2) != 0 -> (*(short*)LHS ^ *(short*)RHS) != 0
// memcmp(S1,S2,4) != 0 -> (*(int*)LHS ^ *(int*)RHS) != 0
if ((Len == 2 || Len == 4) && IsOnlyUsedInZeroEqualityComparison(CI)) {
const Type *PTy = PointerType::getUnqual(Len == 2 ?
Type::Int16Ty : Type::Int32Ty);
LHS = B.CreateBitCast(LHS, PTy, "tmp");
RHS = B.CreateBitCast(RHS, PTy, "tmp");
LoadInst *LHSV = B.CreateLoad(LHS, "lhsv");
LoadInst *RHSV = B.CreateLoad(RHS, "rhsv");
LHSV->setAlignment(1); RHSV->setAlignment(1); // Unaligned loads.
return B.CreateZExt(B.CreateXor(LHSV, RHSV, "shortdiff"), CI->getType());
}
return 0;
}
};
//===---------------------------------------===//
// 'memcpy' Optimizations
struct VISIBILITY_HIDDEN MemCpyOpt : public LibCallOptimization {
virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) {
const FunctionType *FT = Callee->getFunctionType();
if (FT->getNumParams() != 3 || FT->getReturnType() != FT->getParamType(0) ||
!isa<PointerType>(FT->getParamType(0)) ||
!isa<PointerType>(FT->getParamType(1)) ||
FT->getParamType(2) != TD->getIntPtrType())
return 0;
// memcpy(x, y, n) -> llvm.memcpy(x, y, n, 1)
EmitMemCpy(CI->getOperand(1), CI->getOperand(2), CI->getOperand(3), 1, B);
return CI->getOperand(1);
}
};
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
//===---------------------------------------===//
// 'memmove' Optimizations
struct VISIBILITY_HIDDEN MemMoveOpt : public LibCallOptimization {
virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) {
const FunctionType *FT = Callee->getFunctionType();
if (FT->getNumParams() != 3 || FT->getReturnType() != FT->getParamType(0) ||
!isa<PointerType>(FT->getParamType(0)) ||
!isa<PointerType>(FT->getParamType(1)) ||
FT->getParamType(2) != TD->getIntPtrType())
return 0;
// memmove(x, y, n) -> llvm.memmove(x, y, n, 1)
Module *M = Caller->getParent();
Intrinsic::ID IID = Intrinsic::memmove;
const Type *Tys[1];
Tys[0] = TD->getIntPtrType();
Value *MemMove = Intrinsic::getDeclaration(M, IID, Tys, 1);
Value *Dst = CastToCStr(CI->getOperand(1), B);
Value *Src = CastToCStr(CI->getOperand(2), B);
Value *Size = CI->getOperand(3);
Value *Align = ConstantInt::get(Type::Int32Ty, 1);
B.CreateCall4(MemMove, Dst, Src, Size, Align);
return CI->getOperand(1);
}
};
//===---------------------------------------===//
// 'memset' Optimizations
struct VISIBILITY_HIDDEN MemSetOpt : public LibCallOptimization {
virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) {
const FunctionType *FT = Callee->getFunctionType();
if (FT->getNumParams() != 3 || FT->getReturnType() != FT->getParamType(0) ||
!isa<PointerType>(FT->getParamType(0)) ||
FT->getParamType(1) != TD->getIntPtrType() ||
FT->getParamType(2) != TD->getIntPtrType())
return 0;
// memset(p, v, n) -> llvm.memset(p, v, n, 1)
Value *Val = B.CreateTrunc(CI->getOperand(2), Type::Int8Ty);
EmitMemSet(CI->getOperand(1), Val, CI->getOperand(3), B);
return CI->getOperand(1);
}
};
//===----------------------------------------------------------------------===//
// Math Library Optimizations
//===----------------------------------------------------------------------===//
//===---------------------------------------===//
// 'pow*' Optimizations
struct VISIBILITY_HIDDEN PowOpt : public LibCallOptimization {
virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) {
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
const FunctionType *FT = Callee->getFunctionType();
// Just make sure this has 2 arguments of the same FP type, which match the
// result type.
if (FT->getNumParams() != 2 || FT->getReturnType() != FT->getParamType(0) ||
FT->getParamType(0) != FT->getParamType(1) ||
!FT->getParamType(0)->isFloatingPoint())
return 0;
Value *Op1 = CI->getOperand(1), *Op2 = CI->getOperand(2);
if (ConstantFP *Op1C = dyn_cast<ConstantFP>(Op1)) {
if (Op1C->isExactlyValue(1.0)) // pow(1.0, x) -> 1.0
return Op1C;
if (Op1C->isExactlyValue(2.0)) // pow(2.0, x) -> exp2(x)
return EmitUnaryFloatFnCall(Op2, "exp2", B);
}
ConstantFP *Op2C = dyn_cast<ConstantFP>(Op2);
if (Op2C == 0) return 0;
if (Op2C->getValueAPF().isZero()) // pow(x, 0.0) -> 1.0
return ConstantFP::get(CI->getType(), 1.0);
if (Op2C->isExactlyValue(0.5)) {
// FIXME: This is not safe for -0.0 and -inf. This can only be done when
// 'unsafe' math optimizations are allowed.
// x pow(x, 0.5) sqrt(x)
// ---------------------------------------------