//===------ SimplifyLibCalls.cpp - Library calls simplifier ---------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This is a utility pass used for testing the InstructionSimplify analysis.
// The analysis is applied to every instruction, and if it simplifies then the
// instruction is replaced by the simplification. If you are looking for a pass
// that performs serious instruction folding, use the instcombine pass instead.
//
//===----------------------------------------------------------------------===//
#include "llvm/Transforms/Utils/SimplifyLibCalls.h"
#include "llvm/DataLayout.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/Function.h"
#include "llvm/IRBuilder.h"
#include "llvm/LLVMContext.h"
#include "llvm/Target/TargetLibraryInfo.h"
#include "llvm/Transforms/Utils/BuildLibCalls.h"
using namespace llvm;
/// This class is the abstract base class for the set of optimizations that
/// corresponds to one library call.
namespace {
class LibCallOptimization {
protected:
Function *Caller;
const DataLayout *TD;
const TargetLibraryInfo *TLI;
const LibCallSimplifier *LCS;
LLVMContext* Context;
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 DataLayout *TD,
const TargetLibraryInfo *TLI,
const LibCallSimplifier *LCS, IRBuilder<> &B) {
Caller = CI->getParent()->getParent();
this->TD = TD;
this->TLI = TLI;
this->LCS = LCS;
if (CI->getCalledFunction())
Context = &CI->getCalledFunction()->getContext();
// We never change the calling convention.
if (CI->getCallingConv() != llvm::CallingConv::C)
return NULL;
return callOptimizer(CI->getCalledFunction(), CI, B);
}
};
//===----------------------------------------------------------------------===//
// Helper Functions
//===----------------------------------------------------------------------===//
/// 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;
}
//===----------------------------------------------------------------------===//
// Fortified Library Call Optimizations
//===----------------------------------------------------------------------===//
struct FortifiedLibCallOptimization : public LibCallOptimization {
protected:
virtual bool isFoldable(unsigned SizeCIOp, unsigned SizeArgOp,
bool isString) const = 0;
};
struct InstFortifiedLibCallOptimization : public FortifiedLibCallOptimization {
CallInst *CI;
bool isFoldable(unsigned SizeCIOp, unsigned SizeArgOp, bool isString) const {
if (CI->getArgOperand(SizeCIOp) == CI->getArgOperand(SizeArgOp))
return true;
if (ConstantInt *SizeCI =
dyn_cast<ConstantInt>(CI->getArgOperand(SizeCIOp))) {
if (SizeCI->isAllOnesValue())
return true;
if (isString) {
uint64_t Len = GetStringLength(CI->getArgOperand(SizeArgOp));
// If the length is 0 we don't know how long it is and so we can't
// remove the check.
if (Len == 0) return false;
return SizeCI->getZExtValue() >= Len;
}
if (ConstantInt *Arg = dyn_cast<ConstantInt>(
CI->getArgOperand(SizeArgOp)))
return SizeCI->getZExtValue() >= Arg->getZExtValue();
}
return false;
}
};
struct MemCpyChkOpt : public InstFortifiedLibCallOptimization {
virtual Value *callOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) {
this->CI = CI;
FunctionType *FT = Callee->getFunctionType();
LLVMContext &Context = CI->getParent()->getContext();
// Check if this has the right signature.
if (FT->getNumParams() != 4 || FT->getReturnType() !=