/// specified pointer and character. Ptr is required to be some pointer type,
/// and the return value has 'i8*' type.
Value *EmitStrChr(Value *Ptr, char C, IRBuilder<> &B);
+
+ /// EmitStrCpy - Emit a call to the strcpy function to the builder, for the
+ /// specified pointer arguments.
+ Value *EmitStrCpy(Value *Dst, Value *Src, 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.
/// 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.
+ /// 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,
const AttrListPtr &Attrs);
Constant *StrLen =M->getOrInsertFunction("strlen", AttrListPtr::get(AWI, 2),
TD->getIntPtrType(*Context),
- Type::getInt8PtrTy(*Context),
+ Type::getInt8PtrTy(*Context),
NULL);
CallInst *CI = B.CreateCall(StrLen, CastToCStr(Ptr, B), "strlen");
if (const Function *F = dyn_cast<Function>(StrLen->stripPointerCasts()))
Module *M = Caller->getParent();
AttributeWithIndex AWI =
AttributeWithIndex::get(~0u, Attribute::ReadOnly | Attribute::NoUnwind);
-
+
const Type *I8Ptr = Type::getInt8PtrTy(*Context);
const Type *I32Ty = Type::getInt32Ty(*Context);
Constant *StrChr = M->getOrInsertFunction("strchr", AttrListPtr::get(&AWI, 1),
return CI;
}
+/// EmitStrCpy - Emit a call to the strcpy function to the builder, for the
+/// specified pointer arguments.
+Value *LibCallOptimization::EmitStrCpy(Value *Dst, Value *Src, IRBuilder<> &B) {
+ Module *M = Caller->getParent();
+ AttributeWithIndex AWI[2];
+ AWI[0] = AttributeWithIndex::get(2, Attribute::NoCapture);
+ AWI[1] = AttributeWithIndex::get(~0u, Attribute::NoUnwind);
+ const Type *I8Ptr = Type::getInt8PtrTy(*Context);
+ Value *StrCpy = M->getOrInsertFunction("strcpy", AttrListPtr::get(AWI, 2),
+ I8Ptr, I8Ptr, I8Ptr, NULL);
+ CallInst *CI = B.CreateCall2(StrCpy, CastToCStr(Dst, B), CastToCStr(Src, B),
+ "strcpy");
+ if (const Function *F = dyn_cast<Function>(StrCpy->stripPointerCasts()))
+ CI->setCallingConv(F->getCallingConv());
+ return CI;
+}
/// 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.
AWI = AttributeWithIndex::get(~0u, Attribute::ReadOnly | Attribute::NoUnwind);
Value *MemChr = M->getOrInsertFunction("memchr", AttrListPtr::get(&AWI, 1),
- Type::getInt8PtrTy(*Context),
- Type::getInt8PtrTy(*Context),
+ Type::getInt8PtrTy(*Context),
+ Type::getInt8PtrTy(*Context),
Type::getInt32Ty(*Context),
- TD->getIntPtrType(*Context),
+ TD->getIntPtrType(*Context),
NULL);
CallInst *CI = B.CreateCall3(MemChr, CastToCStr(Ptr, B), Val, Len, "memchr");
Value *MemCmp = M->getOrInsertFunction("memcmp", AttrListPtr::get(AWI, 3),
Type::getInt32Ty(*Context),
- Type::getInt8PtrTy(*Context),
- Type::getInt8PtrTy(*Context),
+ Type::getInt8PtrTy(*Context),
+ Type::getInt8PtrTy(*Context),
TD->getIntPtrType(*Context), NULL);
CallInst *CI = B.CreateCall3(MemCmp, CastToCStr(Ptr1, B), CastToCStr(Ptr2, B),
Len, "memcmp");
Type::getInt32Ty(*Context), NULL);
CallInst *CI = B.CreateCall(PutChar,
B.CreateIntCast(Char,
- Type::getInt32Ty(*Context),
- /*isSigned*/true,
- "chari"),
+ Type::getInt32Ty(*Context),
+ /*isSigned*/true,
+ "chari"),
"putchar");
if (const Function *F = dyn_cast<Function>(PutChar->stripPointerCasts()))
Value *PutS = M->getOrInsertFunction("puts", AttrListPtr::get(AWI, 2),
Type::getInt32Ty(*Context),
- Type::getInt8PtrTy(*Context),
+ Type::getInt8PtrTy(*Context),
NULL);
CallInst *CI = B.CreateCall(PutS, CastToCStr(Str, B), "puts");
if (const Function *F = dyn_cast<Function>(PutS->stripPointerCasts()))
Constant *F;
if (isa<PointerType>(File->getType()))
F = M->getOrInsertFunction("fputc", AttrListPtr::get(AWI, 2),
- Type::getInt32Ty(*Context),
+ Type::getInt32Ty(*Context),
Type::getInt32Ty(*Context), File->getType(),
- NULL);
+ NULL);
else
F = M->getOrInsertFunction("fputc",
- Type::getInt32Ty(*Context),
- Type::getInt32Ty(*Context),
+ Type::getInt32Ty(*Context),
+ Type::getInt32Ty(*Context),
File->getType(), NULL);
Char = B.CreateIntCast(Char, Type::getInt32Ty(*Context), /*isSigned*/true,
"chari");
Constant *F;
if (isa<PointerType>(File->getType()))
F = M->getOrInsertFunction("fputs", AttrListPtr::get(AWI, 3),
- Type::getInt32Ty(*Context),
+ Type::getInt32Ty(*Context),
Type::getInt8PtrTy(*Context),
File->getType(), NULL);
else
TD->getIntPtrType(*Context),
Type::getInt8PtrTy(*Context),
TD->getIntPtrType(*Context),
- TD->getIntPtrType(*Context),
+ TD->getIntPtrType(*Context),
File->getType(), NULL);
else
F = M->getOrInsertFunction("fwrite", TD->getIntPtrType(*Context),
Type::getInt8PtrTy(*Context),
TD->getIntPtrType(*Context),
- TD->getIntPtrType(*Context),
+ TD->getIntPtrType(*Context),
File->getType(), NULL);
CallInst *CI = B.CreateCall4(F, CastToCStr(Ptr, B), Size,
ConstantInt::get(TD->getIntPtrType(*Context), 1), File);
// Must be a Constant Array
ConstantArray *Array = dyn_cast<ConstantArray>(GlobalInit);
- if (!Array ||
- Array->getType()->getElementType() != Type::getInt8Ty(V->getContext()))
+ if (!Array || !Array->getType()->getElementType()->isInteger(8))
return false;
// Get the number of elements in the array
if (!TD) return 0;
uint64_t Len = GetStringLength(SrcStr);
- if (Len == 0 ||
- FT->getParamType(1) != Type::getInt32Ty(*Context)) // memchr needs i32.
+ if (Len == 0 || !FT->getParamType(1)->isInteger(32)) // memchr needs i32.
return 0;
return EmitMemChr(SrcStr, CI->getOperand(2), // include nul.
// Verify the "strcmp" function prototype.
const FunctionType *FT = Callee->getFunctionType();
if (FT->getNumParams() != 2 ||
- FT->getReturnType() != Type::getInt32Ty(*Context) ||
+ !FT->getReturnType()->isInteger(32) ||
FT->getParamType(0) != FT->getParamType(1) ||
FT->getParamType(0) != Type::getInt8PtrTy(*Context))
return 0;
// Verify the "strncmp" function prototype.
const FunctionType *FT = Callee->getFunctionType();
if (FT->getNumParams() != 3 ||
- FT->getReturnType() != Type::getInt32Ty(*Context) ||
+ !FT->getReturnType()->isInteger(32) ||
FT->getParamType(0) != FT->getParamType(1) ||
FT->getParamType(0) != Type::getInt8PtrTy(*Context) ||
!isa<IntegerType>(FT->getParamType(2)))
// fold strstr(x, x) -> x.
if (CI->getOperand(1) == CI->getOperand(2))
return B.CreateBitCast(CI->getOperand(1), CI->getType());
-
+
// See if either input string is a constant string.
std::string SearchStr, ToFindStr;
bool HasStr1 = GetConstantStringInfo(CI->getOperand(1), SearchStr);
bool HasStr2 = GetConstantStringInfo(CI->getOperand(2), ToFindStr);
-
+
// fold strstr(x, "") -> x.
if (HasStr2 && ToFindStr.empty())
return B.CreateBitCast(CI->getOperand(1), CI->getType());
-
+
// If both strings are known, constant fold it.
if (HasStr1 && HasStr2) {
std::string::size_type Offset = SearchStr.find(ToFindStr);
-
+
if (Offset == std::string::npos) // strstr("foo", "bar") -> null
return Constant::getNullValue(CI->getType());
Result = B.CreateConstInBoundsGEP1_64(Result, Offset, "strstr");
return B.CreateBitCast(Result, CI->getType());
}
-
+
// fold strstr(x, "y") -> strchr(x, 'y').
if (HasStr2 && ToFindStr.size() == 1)
return B.CreateBitCast(EmitStrChr(CI->getOperand(1), ToFindStr[0], B),
return 0;
}
};
-
+
//===---------------------------------------===//
// 'memcmp' Optimizations
const FunctionType *FT = Callee->getFunctionType();
if (FT->getNumParams() != 3 || !isa<PointerType>(FT->getParamType(0)) ||
!isa<PointerType>(FT->getParamType(1)) ||
- FT->getReturnType() != Type::getInt32Ty(*Context))
+ !FT->getReturnType()->isInteger(32))
return 0;
Value *LHS = CI->getOperand(1), *RHS = CI->getOperand(2);
// Object Size Checking Optimizations
//===----------------------------------------------------------------------===//
-//===---------------------------------------===//
-// 'object size'
-namespace {
-struct SizeOpt : public LibCallOptimization {
- virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) {
- // TODO: We can do more with this, but delaying to here should be no change
- // in behavior.
- ConstantInt *Const = dyn_cast<ConstantInt>(CI->getOperand(2));
-
- if (!Const) return 0;
-
- const Type *Ty = Callee->getFunctionType()->getReturnType();
-
- if (Const->getZExtValue() == 0)
- return Constant::getAllOnesValue(Ty);
- else
- return ConstantInt::get(Ty, 0);
- }
-};
-}
-
//===---------------------------------------===//
// 'memcpy_chk' Optimizations
}
};
+struct StrCpyChkOpt : 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)))
+ return 0;
+
+ ConstantInt *SizeCI = dyn_cast<ConstantInt>(CI->getOperand(3));
+ if (!SizeCI)
+ return 0;
+
+ // If a) we don't have any length information, or b) we know this will
+ // fit then just lower to a plain strcpy. Otherwise we'll keep our
+ // strcpy_chk call which may fail at runtime if the size is too long.
+ // TODO: It might be nice to get a maximum length out of the possible
+ // string lengths for varying.
+ if (SizeCI->isAllOnesValue() ||
+ SizeCI->getZExtValue() >= GetStringLength(CI->getOperand(2)))
+ return EmitStrCpy(CI->getOperand(1), CI->getOperand(2), B);
+
+ return 0;
+ }
+};
+
+
//===----------------------------------------------------------------------===//
// Math Library Optimizations
//===----------------------------------------------------------------------===//
Module *M = Caller->getParent();
Value *Callee = M->getOrInsertFunction(Name, Op->getType(),
Op->getType(),
- Type::getInt32Ty(*Context),NULL);
+ Type::getInt32Ty(*Context),NULL);
CallInst *CI = B.CreateCall2(Callee, One, LdExpArg);
if (const Function *F = dyn_cast<Function>(Callee->stripPointerCasts()))
CI->setCallingConv(F->getCallingConv());
// Just make sure this has 2 arguments of the same FP type, which match the
// result type.
if (FT->getNumParams() != 1 ||
- FT->getReturnType() != Type::getInt32Ty(*Context) ||
+ !FT->getReturnType()->isInteger(32) ||
!isa<IntegerType>(FT->getParamType(0)))
return 0;
const FunctionType *FT = Callee->getFunctionType();
// We require integer(i32)
if (FT->getNumParams() != 1 || !isa<IntegerType>(FT->getReturnType()) ||
- FT->getParamType(0) != Type::getInt32Ty(*Context))
+ !FT->getParamType(0)->isInteger(32))
return 0;
// isdigit(c) -> (c-'0') <u 10
const FunctionType *FT = Callee->getFunctionType();
// We require integer(i32)
if (FT->getNumParams() != 1 || !isa<IntegerType>(FT->getReturnType()) ||
- FT->getParamType(0) != Type::getInt32Ty(*Context))
+ !FT->getParamType(0)->isInteger(32))
return 0;
// isascii(c) -> c <u 128
const FunctionType *FT = Callee->getFunctionType();
// We require i32(i32)
if (FT->getNumParams() != 1 || FT->getReturnType() != FT->getParamType(0) ||
- FT->getParamType(0) != Type::getInt32Ty(*Context))
+ !FT->getParamType(0)->isInteger(32))
return 0;
// isascii(c) -> c & 0x7f
// sprintf(str, fmt) -> llvm.memcpy(str, fmt, strlen(fmt)+1, 1)
EmitMemCpy(CI->getOperand(1), CI->getOperand(2), // Copy the nul byte.
- ConstantInt::get(TD->getIntPtrType(*Context), FormatStr.size()+1),1,B);
+ ConstantInt::get
+ (TD->getIntPtrType(*Context), FormatStr.size()+1),1,B);
return ConstantInt::get(CI->getType(), FormatStr.size());
}
// These optimizations require TargetData.
if (!TD) return 0;
- EmitFWrite(CI->getOperand(2), ConstantInt::get(TD->getIntPtrType(*Context),
- FormatStr.size()),
+ EmitFWrite(CI->getOperand(2),
+ ConstantInt::get(TD->getIntPtrType(*Context),
+ FormatStr.size()),
CI->getOperand(1), B);
return ConstantInt::get(CI->getType(), FormatStr.size());
}
FWriteOpt FWrite; FPutsOpt FPuts; FPrintFOpt FPrintF;
// Object Size Checking
- SizeOpt ObjectSize;
MemCpyChkOpt MemCpyChk; MemSetChkOpt MemSetChk; MemMoveChkOpt MemMoveChk;
+ StrCpyChkOpt StrCpyChk;
bool Modified; // This is only used by doInitialization.
public:
Optimizations["fprintf"] = &FPrintF;
// Object Size Checking
- Optimizations["llvm.objectsize.i32"] = &ObjectSize;
- Optimizations["llvm.objectsize.i64"] = &ObjectSize;
Optimizations["__memcpy_chk"] = &MemCpyChk;
Optimizations["__memset_chk"] = &MemSetChk;
Optimizations["__memmove_chk"] = &MemMoveChk;
+ Optimizations["__strcpy_chk"] = &StrCpyChk;
}
Value *Result = LCO->OptimizeCall(CI, TD, Builder);
if (Result == 0) continue;
- DEBUG(errs() << "SimplifyLibCalls simplified: " << *CI;
- errs() << " into: " << *Result << "\n");
+ DEBUG(dbgs() << "SimplifyLibCalls simplified: " << *CI;
+ dbgs() << " into: " << *Result << "\n");
// Something changed!
Changed = true;