instcombine: Migrate fprintf optimizations

This patch migrates the fprintf optimizations from the simplify-libcalls
pass into the instcombine library call simplifier.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@168891 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Meador Inge
2012-11-29 15:45:33 +00:00
parent 2aac385417
commit 28d52913ab
6 changed files with 158 additions and 152 deletions
+1 -93
View File
@@ -81,19 +81,6 @@ public:
} // End anonymous namespace.
//===----------------------------------------------------------------------===//
// Helper Functions
//===----------------------------------------------------------------------===//
static bool CallHasFloatingPointArgument(const CallInst *CI) {
for (CallInst::const_op_iterator it = CI->op_begin(), e = CI->op_end();
it != e; ++it) {
if ((*it)->getType()->isFloatingPointTy())
return true;
}
return false;
}
namespace {
//===----------------------------------------------------------------------===//
// Formatting and IO Optimizations
@@ -160,84 +147,6 @@ struct FPutsOpt : public LibCallOptimization {
}
};
//===---------------------------------------===//
// 'fprintf' Optimizations
struct FPrintFOpt : public LibCallOptimization {
Value *OptimizeFixedFormatString(Function *Callee, CallInst *CI,
IRBuilder<> &B) {
// All the optimizations depend on the format string.
StringRef FormatStr;
if (!getConstantStringInfo(CI->getArgOperand(1), FormatStr))
return 0;
// fprintf(F, "foo") --> fwrite("foo", 3, 1, F)
if (CI->getNumArgOperands() == 2) {
for (unsigned i = 0, e = FormatStr.size(); i != e; ++i)
if (FormatStr[i] == '%') // Could handle %% -> % if we cared.
return 0; // We found a format specifier.
// These optimizations require DataLayout.
if (!TD) return 0;
Value *NewCI = EmitFWrite(CI->getArgOperand(1),
ConstantInt::get(TD->getIntPtrType(*Context),
FormatStr.size()),
CI->getArgOperand(0), B, TD, TLI);
return NewCI ? ConstantInt::get(CI->getType(), FormatStr.size()) : 0;
}
// The remaining optimizations require the format string to be "%s" or "%c"
// and have an extra operand.
if (FormatStr.size() != 2 || FormatStr[0] != '%' ||
CI->getNumArgOperands() < 3)
return 0;
// Decode the second character of the format string.
if (FormatStr[1] == 'c') {
// fprintf(F, "%c", chr) --> fputc(chr, F)
if (!CI->getArgOperand(2)->getType()->isIntegerTy()) return 0;
Value *NewCI = EmitFPutC(CI->getArgOperand(2), CI->getArgOperand(0), B,
TD, TLI);
return NewCI ? ConstantInt::get(CI->getType(), 1) : 0;
}
if (FormatStr[1] == 's') {
// fprintf(F, "%s", str) --> fputs(str, F)
if (!CI->getArgOperand(2)->getType()->isPointerTy() || !CI->use_empty())
return 0;
return EmitFPutS(CI->getArgOperand(2), CI->getArgOperand(0), B, TD, TLI);
}
return 0;
}
virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) {
// Require two fixed paramters as pointers and integer result.
FunctionType *FT = Callee->getFunctionType();
if (FT->getNumParams() != 2 || !FT->getParamType(0)->isPointerTy() ||
!FT->getParamType(1)->isPointerTy() ||
!FT->getReturnType()->isIntegerTy())
return 0;
if (Value *V = OptimizeFixedFormatString(Callee, CI, B)) {
return V;
}
// fprintf(stream, format, ...) -> fiprintf(stream, format, ...) if no
// floating point arguments.
if (TLI->has(LibFunc::fiprintf) && !CallHasFloatingPointArgument(CI)) {
Module *M = B.GetInsertBlock()->getParent()->getParent();
Constant *FIPrintFFn =
M->getOrInsertFunction("fiprintf", FT, Callee->getAttributes());
CallInst *New = cast<CallInst>(CI->clone());
New->setCalledFunction(FIPrintFFn);
B.Insert(New);
return New;
}
return 0;
}
};
//===---------------------------------------===//
// 'puts' Optimizations
@@ -280,7 +189,7 @@ namespace {
StringMap<LibCallOptimization*> Optimizations;
// Formatting and IO Optimizations
FWriteOpt FWrite; FPutsOpt FPuts; FPrintFOpt FPrintF;
FWriteOpt FWrite; FPutsOpt FPuts;
PutsOpt Puts;
bool Modified; // This is only used by doInitialization.
@@ -339,7 +248,6 @@ void SimplifyLibCalls::InitOptimizations() {
// Formatting and IO Optimizations
AddOpt(LibFunc::fwrite, &FWrite);
AddOpt(LibFunc::fputs, &FPuts);
Optimizations["fprintf"] = &FPrintF;
Optimizations["puts"] = &Puts;
}