mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-06-13 04:38:24 +00:00
instcombine: Migrate printf optimizations
This patch migrates the printf optimizations from the simplify-libcalls pass into the instcombine library call simplifier. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@168604 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@ -102,6 +102,15 @@ static bool isOnlyUsedInEqualityComparison(Value *V, Value *With) {
|
||||
return true;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Fortified Library Call Optimizations
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -1312,6 +1321,94 @@ struct ToAsciiOpt : public LibCallOptimization {
|
||||
}
|
||||
};
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Formatting and IO Library Call Optimizations
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
struct PrintFOpt : public LibCallOptimization {
|
||||
Value *optimizeFixedFormatString(Function *Callee, CallInst *CI,
|
||||
IRBuilder<> &B) {
|
||||
// Check for a fixed format string.
|
||||
StringRef FormatStr;
|
||||
if (!getConstantStringInfo(CI->getArgOperand(0), FormatStr))
|
||||
return 0;
|
||||
|
||||
// Empty format string -> noop.
|
||||
if (FormatStr.empty()) // Tolerate printf's declared void.
|
||||
return CI->use_empty() ? (Value*)CI :
|
||||
ConstantInt::get(CI->getType(), 0);
|
||||
|
||||
// Do not do any of the following transformations if the printf return value
|
||||
// is used, in general the printf return value is not compatible with either
|
||||
// putchar() or puts().
|
||||
if (!CI->use_empty())
|
||||
return 0;
|
||||
|
||||
// printf("x") -> putchar('x'), even for '%'.
|
||||
if (FormatStr.size() == 1) {
|
||||
Value *Res = EmitPutChar(B.getInt32(FormatStr[0]), B, TD, TLI);
|
||||
if (CI->use_empty() || !Res) return Res;
|
||||
return B.CreateIntCast(Res, CI->getType(), true);
|
||||
}
|
||||
|
||||
// printf("foo\n") --> puts("foo")
|
||||
if (FormatStr[FormatStr.size()-1] == '\n' &&
|
||||
FormatStr.find('%') == std::string::npos) { // no format characters.
|
||||
// Create a string literal with no \n on it. We expect the constant merge
|
||||
// pass to be run after this pass, to merge duplicate strings.
|
||||
FormatStr = FormatStr.drop_back();
|
||||
Value *GV = B.CreateGlobalString(FormatStr, "str");
|
||||
Value *NewCI = EmitPutS(GV, B, TD, TLI);
|
||||
return (CI->use_empty() || !NewCI) ?
|
||||
NewCI :
|
||||
ConstantInt::get(CI->getType(), FormatStr.size()+1);
|
||||
}
|
||||
|
||||
// Optimize specific format strings.
|
||||
// printf("%c", chr) --> putchar(chr)
|
||||
if (FormatStr == "%c" && CI->getNumArgOperands() > 1 &&
|
||||
CI->getArgOperand(1)->getType()->isIntegerTy()) {
|
||||
Value *Res = EmitPutChar(CI->getArgOperand(1), B, TD, TLI);
|
||||
|
||||
if (CI->use_empty() || !Res) return Res;
|
||||
return B.CreateIntCast(Res, CI->getType(), true);
|
||||
}
|
||||
|
||||
// printf("%s\n", str) --> puts(str)
|
||||
if (FormatStr == "%s\n" && CI->getNumArgOperands() > 1 &&
|
||||
CI->getArgOperand(1)->getType()->isPointerTy()) {
|
||||
return EmitPutS(CI->getArgOperand(1), B, TD, TLI);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual Value *callOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) {
|
||||
// Require one fixed pointer argument and an integer/void result.
|
||||
FunctionType *FT = Callee->getFunctionType();
|
||||
if (FT->getNumParams() < 1 || !FT->getParamType(0)->isPointerTy() ||
|
||||
!(FT->getReturnType()->isIntegerTy() ||
|
||||
FT->getReturnType()->isVoidTy()))
|
||||
return 0;
|
||||
|
||||
if (Value *V = optimizeFixedFormatString(Callee, CI, B)) {
|
||||
return V;
|
||||
}
|
||||
|
||||
// printf(format, ...) -> iprintf(format, ...) if no floating point
|
||||
// arguments.
|
||||
if (TLI->has(LibFunc::iprintf) && !callHasFloatingPointArgument(CI)) {
|
||||
Module *M = B.GetInsertBlock()->getParent()->getParent();
|
||||
Constant *IPrintFFn =
|
||||
M->getOrInsertFunction("iprintf", FT, Callee->getAttributes());
|
||||
CallInst *New = cast<CallInst>(CI->clone());
|
||||
New->setCalledFunction(IPrintFFn);
|
||||
B.Insert(New);
|
||||
return New;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
} // End anonymous namespace.
|
||||
|
||||
namespace llvm {
|
||||
@ -1365,6 +1462,9 @@ class LibCallSimplifierImpl {
|
||||
IsAsciiOpt IsAscii;
|
||||
ToAsciiOpt ToAscii;
|
||||
|
||||
// Formatting and IO library call optimizations.
|
||||
PrintFOpt PrintF;
|
||||
|
||||
void initOptimizations();
|
||||
void addOpt(LibFunc::Func F, LibCallOptimization* Opt);
|
||||
void addOpt(LibFunc::Func F1, LibFunc::Func F2, LibCallOptimization* Opt);
|
||||
@ -1485,6 +1585,9 @@ void LibCallSimplifierImpl::initOptimizations() {
|
||||
addOpt(LibFunc::isdigit, &IsDigit);
|
||||
addOpt(LibFunc::isascii, &IsAscii);
|
||||
addOpt(LibFunc::toascii, &ToAscii);
|
||||
|
||||
// Formatting and IO library call optimizations.
|
||||
addOpt(LibFunc::printf, &PrintF);
|
||||
}
|
||||
|
||||
Value *LibCallSimplifierImpl::optimizeCall(CallInst *CI) {
|
||||
|
Reference in New Issue
Block a user