From 045af54275b7c1d13b35490e133b821e47095299 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Sat, 7 Apr 2007 01:18:36 +0000 Subject: fix a miscompilation in printf optimizer. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@35713 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/IPO/SimplifyLibCalls.cpp | 74 ++++++++++++++++----------------- 1 file changed, 36 insertions(+), 38 deletions(-) (limited to 'lib') diff --git a/lib/Transforms/IPO/SimplifyLibCalls.cpp b/lib/Transforms/IPO/SimplifyLibCalls.cpp index 96b5f3d77b..a3be34577f 100644 --- a/lib/Transforms/IPO/SimplifyLibCalls.cpp +++ b/lib/Transforms/IPO/SimplifyLibCalls.cpp @@ -1189,67 +1189,65 @@ public: "Number of 'printf' calls simplified") {} /// @brief Make sure that the "printf" function has the right prototype - virtual bool ValidateCalledFunction(const Function* f, SimplifyLibCalls& SLC){ + virtual bool ValidateCalledFunction(const Function *F, SimplifyLibCalls &SLC){ // Just make sure this has at least 1 arguments - return (f->arg_size() >= 1); + return F->arg_size() >= 1; } /// @brief Perform the printf optimization. - virtual bool OptimizeCall(CallInst* ci, SimplifyLibCalls& SLC) { + virtual bool OptimizeCall(CallInst *CI, SimplifyLibCalls &SLC) { // If the call has more than 2 operands, we can't optimize it - if (ci->getNumOperands() > 3 || ci->getNumOperands() <= 2) + if (CI->getNumOperands() != 3) return false; // If the result of the printf call is used, none of these optimizations // can be made. - if (!ci->use_empty()) + if (!CI->use_empty()) return false; // All the optimizations depend on the length of the first argument and the // fact that it is a constant string array. Check that now - uint64_t len, StartIdx; - ConstantArray* CA = 0; - if (!GetConstantStringInfo(ci->getOperand(1), CA, len, StartIdx)) + uint64_t FormatLen, FormatIdx; + ConstantArray *CA = 0; + if (!GetConstantStringInfo(CI->getOperand(1), CA, FormatLen, FormatIdx)) return false; - if (len != 2 && len != 3) + if (FormatLen != 2 && FormatLen != 3) return false; // The first character has to be a % - if (ConstantInt* CI = dyn_cast(CA->getOperand(0))) - if (CI->getZExtValue() != '%') - return false; + if (cast(CA->getOperand(FormatIdx))->getZExtValue() != '%') + return false; // Get the second character and switch on its value - ConstantInt* CI = dyn_cast(CA->getOperand(1)); - switch (CI->getZExtValue()) { - case 's': - { - if (len != 3 || - dyn_cast(CA->getOperand(2))->getZExtValue() != '\n') - return false; - - // printf("%s\n",str) -> puts(str) - std::vector args; - new CallInst(SLC.get_puts(), CastToCStr(ci->getOperand(2), *ci), - ci->getName(), ci); - return ReplaceCallWith(ci, ConstantInt::get(Type::Int32Ty, len)); - } - case 'c': - { - // printf("%c",c) -> putchar(c) - if (len != 2) - return false; + switch (cast(CA->getOperand(FormatIdx+1))->getZExtValue()) { + default: return false; + case 's': { + if (FormatLen != 3 || + cast(CA->getOperand(FormatIdx+2))->getZExtValue() !='\n') + return false; - CastInst *Char = CastInst::createSExtOrBitCast( - ci->getOperand(2), Type::Int32Ty, CI->getName()+".int", ci); - new CallInst(SLC.get_putchar(), Char, "", ci); - return ReplaceCallWith(ci, ConstantInt::get(Type::Int32Ty, 1)); - } - default: + // printf("%s\n",str) -> puts(str) + new CallInst(SLC.get_puts(), CastToCStr(CI->getOperand(2), *CI), + CI->getName(), CI); + return ReplaceCallWith(CI, 0); + } + case 'c': { + // printf("%c",c) -> putchar(c) + if (FormatLen != 2) + return false; + + Value *V = CI->getOperand(2); + if (!isa(V->getType()) || + cast(V->getType())->getBitWidth() < 32) return false; + + V = CastInst::createSExtOrBitCast(V, Type::Int32Ty, CI->getName()+".int", + CI); + new CallInst(SLC.get_putchar(), V, "", CI); + return ReplaceCallWith(CI, 0); + } } - return false; } } PrintfOptimizer; -- cgit v1.2.3