//
// The LLVM Compiler Infrastructure
//
-// This file was developed by Reid Spencer and is distributed under the
-// University of Illinois Open Source License. See LICENSE.TXT for details.
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
#include "llvm/Instructions.h"
#include "llvm/Module.h"
#include "llvm/Pass.h"
-#include "llvm/ADT/hash_map"
+#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Config/config.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Transforms/IPO.h"
+#include <cstring>
using namespace llvm;
/// This statistic keeps track of the total number of library calls that have
reset(M);
bool result = false;
- hash_map<std::string, LibCallOptimization*> OptznMap;
+ StringMap<LibCallOptimization*> OptznMap;
for (LibCallOptimization *Optzn = OptList; Optzn; Optzn = Optzn->getNext())
OptznMap[Optzn->getFunctionName()] = Optzn;
continue;
// Get the optimization class that pertains to this function
- hash_map<std::string, LibCallOptimization*>::iterator OMI =
+ StringMap<LibCallOptimization*>::iterator OMI =
OptznMap.find(FI->getName());
if (OMI == OptznMap.end()) continue;
Constant *get_puts() {
if (!puts_func)
puts_func = M->getOrInsertFunction("puts", Type::Int32Ty,
- PointerType::get(Type::Int8Ty),
+ PointerType::getUnqual(Type::Int8Ty),
NULL);
return puts_func;
}
Constant *get_fputs(const Type* FILEptr_type) {
if (!fputs_func)
fputs_func = M->getOrInsertFunction("fputs", Type::Int32Ty,
- PointerType::get(Type::Int8Ty),
+ PointerType::getUnqual(Type::Int8Ty),
FILEptr_type, NULL);
return fputs_func;
}
Constant *get_fwrite(const Type* FILEptr_type) {
if (!fwrite_func)
fwrite_func = M->getOrInsertFunction("fwrite", TD->getIntPtrType(),
- PointerType::get(Type::Int8Ty),
+ PointerType::getUnqual(Type::Int8Ty),
TD->getIntPtrType(),
TD->getIntPtrType(),
FILEptr_type, NULL);
Constant *get_strcpy() {
if (!strcpy_func)
strcpy_func = M->getOrInsertFunction("strcpy",
- PointerType::get(Type::Int8Ty),
- PointerType::get(Type::Int8Ty),
- PointerType::get(Type::Int8Ty),
+ PointerType::getUnqual(Type::Int8Ty),
+ PointerType::getUnqual(Type::Int8Ty),
+ PointerType::getUnqual(Type::Int8Ty),
NULL);
return strcpy_func;
}
Constant *get_strlen() {
if (!strlen_func)
strlen_func = M->getOrInsertFunction("strlen", TD->getIntPtrType(),
- PointerType::get(Type::Int8Ty),
+ PointerType::getUnqual(Type::Int8Ty),
NULL);
return strlen_func;
}
Constant *get_memchr() {
if (!memchr_func)
memchr_func = M->getOrInsertFunction("memchr",
- PointerType::get(Type::Int8Ty),
- PointerType::get(Type::Int8Ty),
+ PointerType::getUnqual(Type::Int8Ty),
+ PointerType::getUnqual(Type::Int8Ty),
Type::Int32Ty, TD->getIntPtrType(),
NULL);
return memchr_func;
/// @brief Return a Function* for the memcpy libcall
Constant *get_memcpy() {
if (!memcpy_func) {
- const Type *SBP = PointerType::get(Type::Int8Ty);
+ const Type *SBP = PointerType::getUnqual(Type::Int8Ty);
const char *N = TD->getIntPtrType() == Type::Int32Ty ?
"llvm.memcpy.i32" : "llvm.memcpy.i64";
memcpy_func = M->getOrInsertFunction(N, Type::VoidTy, SBP, SBP,
virtual bool ValidateCalledFunction(const Function *F, SimplifyLibCalls &SLC){
const FunctionType *FT = F->getFunctionType();
return FT->getNumParams() == 2 &&
- FT->getReturnType() == PointerType::get(Type::Int8Ty) &&
+ FT->getReturnType() == PointerType::getUnqual(Type::Int8Ty) &&
FT->getParamType(0) == FT->getReturnType() &&
FT->getParamType(1) == FT->getReturnType();
}
virtual bool ValidateCalledFunction(const Function *F, SimplifyLibCalls &SLC){
const FunctionType *FT = F->getFunctionType();
return FT->getNumParams() == 2 &&
- FT->getReturnType() == PointerType::get(Type::Int8Ty) &&
+ FT->getReturnType() == PointerType::getUnqual(Type::Int8Ty) &&
FT->getParamType(0) == FT->getReturnType() &&
isa<IntegerType>(FT->getParamType(1));
}
const FunctionType *FT = F->getFunctionType();
return FT->getReturnType() == Type::Int32Ty && FT->getNumParams() == 2 &&
FT->getParamType(0) == FT->getParamType(1) &&
- FT->getParamType(0) == PointerType::get(Type::Int8Ty);
+ FT->getParamType(0) == PointerType::getUnqual(Type::Int8Ty);
}
/// @brief Perform the strcmp optimization
const FunctionType *FT = F->getFunctionType();
return FT->getReturnType() == Type::Int32Ty && FT->getNumParams() == 3 &&
FT->getParamType(0) == FT->getParamType(1) &&
- FT->getParamType(0) == PointerType::get(Type::Int8Ty) &&
+ FT->getParamType(0) == PointerType::getUnqual(Type::Int8Ty) &&
isa<IntegerType>(FT->getParamType(2));
return false;
}
return FT->getNumParams() == 2 &&
FT->getParamType(0) == FT->getParamType(1) &&
FT->getReturnType() == FT->getParamType(0) &&
- FT->getParamType(0) == PointerType::get(Type::Int8Ty);
+ FT->getParamType(0) == PointerType::getUnqual(Type::Int8Ty);
}
/// @brief Perform the strcpy optimization
// If the constant string's length is zero we can optimize this by just
// doing a store of 0 at the first byte of the destination
- if (SrcStr.size() == 0) {
+ if (SrcStr.empty()) {
new StoreInst(ConstantInt::get(Type::Int8Ty, 0), Dst, CI);
return ReplaceCallWith(CI, Dst);
}
virtual bool ValidateCalledFunction(const Function *F, SimplifyLibCalls &SLC){
const FunctionType *FT = F->getFunctionType();
return FT->getNumParams() == 1 &&
- FT->getParamType(0) == PointerType::get(Type::Int8Ty) &&
+ FT->getParamType(0) == PointerType::getUnqual(Type::Int8Ty) &&
isa<IntegerType>(FT->getReturnType());
}
return ReplaceCallWith(CI, Constant::getNullValue(CI->getType()));
case 1: {
// memcmp(S1,S2,1) -> *(ubyte*)S1 - *(ubyte*)S2
- const Type *UCharPtr = PointerType::get(Type::Int8Ty);
+ const Type *UCharPtr = PointerType::getUnqual(Type::Int8Ty);
CastInst *Op1Cast = CastInst::create(
Instruction::BitCast, LHS, UCharPtr, LHS->getName(), CI);
CastInst *Op2Cast = CastInst::create(
// TODO: IF both are aligned, use a short load/compare.
// memcmp(S1,S2,2) -> S1[0]-S2[0] | S1[1]-S2[1] iff only ==/!= 0 matters
- const Type *UCharPtr = PointerType::get(Type::Int8Ty);
+ const Type *UCharPtr = PointerType::getUnqual(Type::Int8Ty);
CastInst *Op1Cast = CastInst::create(
Instruction::BitCast, LHS, UCharPtr, LHS->getName(), CI);
CastInst *Op2Cast = CastInst::create(
}
} memcmpOptimizer;
+/// This LibCallOptimization will simplify a call to the memcpy library
+/// function. It simply converts them into calls to llvm.memcpy.*;
+/// the resulting call should be optimized later.
+/// @brief Simplify the memcpy library function.
+struct VISIBILITY_HIDDEN MemCpyOptimization : public LibCallOptimization {
+public:
+ MemCpyOptimization() : LibCallOptimization("memcpy",
+ "Number of 'memcpy' calls simplified") {}
+
+ /// @brief Make sure that the "memcpy" function has the right prototype
+ virtual bool ValidateCalledFunction(const Function *F, SimplifyLibCalls &SLC){
+ const FunctionType *FT = F->getFunctionType();
+ const Type* voidPtr = PointerType::getUnqual(Type::Int8Ty);
+ return FT->getReturnType() == voidPtr && FT->getNumParams() == 3 &&
+ FT->getParamType(0) == voidPtr &&
+ FT->getParamType(1) == voidPtr &&
+ FT->getParamType(2) == SLC.getIntPtrType();
+ }
+
+ /// @brief Perform the memcpy optimization
+ virtual bool OptimizeCall(CallInst *CI, SimplifyLibCalls &SLC) {
+ Value *MemcpyOps[] = {
+ CI->getOperand(1), CI->getOperand(2), CI->getOperand(3),
+ ConstantInt::get(Type::Int32Ty, 1) // align = 1 always.
+ };
+ new CallInst(SLC.get_memcpy(), MemcpyOps, MemcpyOps + 4, "", CI);
+ // memcpy always returns the destination
+ return ReplaceCallWith(CI, CI->getOperand(1));
+ }
+} MemCpyOptimizer;
/// This LibCallOptimization will simplify a call to the memcpy library
/// function by expanding it out to a single store of size 0, 1, 2, 4, or 8
// Cast source and dest to the right sized primitive and then load/store
CastInst* SrcCast = CastInst::create(Instruction::BitCast,
- src, PointerType::get(castType), src->getName()+".cast", ci);
+ src, PointerType::getUnqual(castType), src->getName()+".cast", ci);
CastInst* DestCast = CastInst::create(Instruction::BitCast,
- dest, PointerType::get(castType),dest->getName()+".cast", ci);
+ dest, PointerType::getUnqual(castType),dest->getName()+".cast", ci);
LoadInst* LI = new LoadInst(SrcCast,SrcCast->getName()+".val",ci);
new StoreInst(LI, DestCast, ci);
return ReplaceCallWith(ci, 0);
}
// Cast dest to the right sized primitive and then load/store
- CastInst* DestCast = new BitCastInst(dest, PointerType::get(castType),
+ CastInst* DestCast = new BitCastInst(dest, PointerType::getUnqual(castType),
dest->getName()+".cast", ci);
new StoreInst(ConstantInt::get(castType,fill_value),DestCast, ci);
return ReplaceCallWith(ci, 0);
/// @brief Perform the pow optimization.
virtual bool OptimizeCall(CallInst *ci, SimplifyLibCalls &SLC) {
const Type *Ty = cast<Function>(ci->getOperand(0))->getReturnType();
+ if (Ty!=Type::FloatTy && Ty!=Type::DoubleTy)
+ return false; // FIXME long double not yet supported
Value* base = ci->getOperand(1);
Value* expn = ci->getOperand(2);
if (ConstantFP *Op1 = dyn_cast<ConstantFP>(base)) {
- if (Ty!=Type::FloatTy && Ty!=Type::DoubleTy)
- return false; // FIXME long double not yet supported
if (Op1->isExactlyValue(1.0)) // pow(1.0,x) -> 1.0
return ReplaceCallWith(ci, ConstantFP::get(Ty,
Ty==Type::FloatTy ? APFloat(1.0f) : APFloat(1.0)));
} else if (ConstantFP* Op2 = dyn_cast<ConstantFP>(expn)) {
- if (Ty!=Type::FloatTy && Ty!=Type::DoubleTy)
- return false; // FIXME long double not yet supported
if (Op2->getValueAPF().isZero()) {
// pow(x,0.0) -> 1.0
return ReplaceCallWith(ci, ConstantFP::get(Ty,
Init, "str",
CI->getParent()->getParent()->getParent());
// Cast GV to be a pointer to char.
- GV = ConstantExpr::getBitCast(GV, PointerType::get(Type::Int8Ty));
+ GV = ConstantExpr::getBitCast(GV, PointerType::getUnqual(Type::Int8Ty));
new CallInst(SLC.get_puts(), GV, "", CI);
if (CI->use_empty()) return ReplaceCallWith(CI, 0);
+ // The return value from printf includes the \n we just removed, so +1.
return ReplaceCallWith(CI,
- ConstantInt::get(CI->getType(), FormatStr.size()));
+ ConstantInt::get(CI->getType(),
+ FormatStr.size()+1));
}
virtual bool ValidateCalledFunction(const Function *F, SimplifyLibCalls &SLC){
const FunctionType *FT = F->getFunctionType();
return FT->getNumParams() == 2 && // two fixed arguments.
- FT->getParamType(1) == PointerType::get(Type::Int8Ty) &&
+ FT->getParamType(1) == PointerType::getUnqual(Type::Int8Ty) &&
isa<PointerType>(FT->getParamType(0)) &&
isa<IntegerType>(FT->getReturnType());
}
virtual bool ValidateCalledFunction(const Function *F, SimplifyLibCalls &SLC){
const FunctionType *FT = F->getFunctionType();
return FT->getNumParams() == 2 && // two fixed arguments.
- FT->getParamType(1) == PointerType::get(Type::Int8Ty) &&
+ FT->getParamType(1) == PointerType::getUnqual(Type::Int8Ty) &&
FT->getParamType(0) == FT->getParamType(1) &&
isa<IntegerType>(FT->getReturnType());
}
virtual bool ValidateCalledFunction(const Function *F, SimplifyLibCalls &SLC){
const FunctionType *FT = F->getFunctionType();
return FT->getNumParams() == 4 &&
- FT->getParamType(0) == PointerType::get(Type::Int8Ty) &&
+ FT->getParamType(0) == PointerType::getUnqual(Type::Int8Ty) &&
FT->getParamType(1) == FT->getParamType(2) &&
isa<IntegerType>(FT->getParamType(1)) &&
isa<PointerType>(FT->getParamType(3)) &&
static Value *CastToCStr(Value *V, Instruction *IP) {
assert(isa<PointerType>(V->getType()) &&
"Can't cast non-pointer type to C string type");
- const Type *SBPTy = PointerType::get(Type::Int8Ty);
+ const Type *SBPTy = PointerType::getUnqual(Type::Int8Ty);
if (V->getType() != SBPTy)
return new BitCastInst(V, SBPTy, V->getName(), IP);
return V;