llvm.org GIT mirror llvm / 045af54
fix a miscompilation in printf optimizer. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@35713 91177308-0d34-0410-b5e6-96231b3b80d8 Chris Lattner 12 years ago
1 changed file(s) with 40 addition(s) and 42 deletion(s). Raw diff Collapse all Expand all
11881188 "Number of 'printf' calls simplified") {}
11891189
11901190 /// @brief Make sure that the "printf" function has the right prototype
1191 virtual bool ValidateCalledFunction(const Function* f, SimplifyLibCalls& SLC){
1191 virtual bool ValidateCalledFunction(const Function *F, SimplifyLibCalls &SLC){
11921192 // Just make sure this has at least 1 arguments
1193 return (f->arg_size() >= 1);
1193 return F->arg_size() >= 1;
11941194 }
11951195
11961196 /// @brief Perform the printf optimization.
1197 virtual bool OptimizeCall(CallInst* ci, SimplifyLibCalls& SLC) {
1197 virtual bool OptimizeCall(CallInst *CI, SimplifyLibCalls &SLC) {
11981198 // If the call has more than 2 operands, we can't optimize it
1199 if (ci->getNumOperands() > 3 || ci->getNumOperands() <= 2)
1199 if (CI->getNumOperands() != 3)
12001200 return false;
12011201
12021202 // If the result of the printf call is used, none of these optimizations
12031203 // can be made.
1204 if (!ci->use_empty())
1204 if (!CI->use_empty())
12051205 return false;
12061206
12071207 // All the optimizations depend on the length of the first argument and the
12081208 // fact that it is a constant string array. Check that now
1209 uint64_t len, StartIdx;
1210 ConstantArray* CA = 0;
1211 if (!GetConstantStringInfo(ci->getOperand(1), CA, len, StartIdx))
1212 return false;
1213
1214 if (len != 2 && len != 3)
1209 uint64_t FormatLen, FormatIdx;
1210 ConstantArray *CA = 0;
1211 if (!GetConstantStringInfo(CI->getOperand(1), CA, FormatLen, FormatIdx))
1212 return false;
1213
1214 if (FormatLen != 2 && FormatLen != 3)
12151215 return false;
12161216
12171217 // The first character has to be a %
1218 if (ConstantInt* CI = dyn_cast(CA->getOperand(0)))
1219 if (CI->getZExtValue() != '%')
1218 if (cast(CA->getOperand(FormatIdx))->getZExtValue() != '%')
1219 return false;
1220
1221 // Get the second character and switch on its value
1222 switch (cast(CA->getOperand(FormatIdx+1))->getZExtValue()) {
1223 default: return false;
1224 case 's': {
1225 if (FormatLen != 3 ||
1226 cast(CA->getOperand(FormatIdx+2))->getZExtValue() !='\n')
12201227 return false;
12211228
1222 // Get the second character and switch on its value
1223 ConstantInt* CI = dyn_cast(CA->getOperand(1));
1224 switch (CI->getZExtValue()) {
1225 case 's':
1226 {
1227 if (len != 3 ||
1228 dyn_cast(CA->getOperand(2))->getZExtValue() != '\n')
1229 return false;
1230
1231 // printf("%s\n",str) -> puts(str)
1232 std::vector args;
1233 new CallInst(SLC.get_puts(), CastToCStr(ci->getOperand(2), *ci),
1234 ci->getName(), ci);
1235 return ReplaceCallWith(ci, ConstantInt::get(Type::Int32Ty, len));
1236 }
1237 case 'c':
1238 {
1239 // printf("%c",c) -> putchar(c)
1240 if (len != 2)
1241 return false;
1242
1243 CastInst *Char = CastInst::createSExtOrBitCast(
1244 ci->getOperand(2), Type::Int32Ty, CI->getName()+".int", ci);
1245 new CallInst(SLC.get_putchar(), Char, "", ci);
1246 return ReplaceCallWith(ci, ConstantInt::get(Type::Int32Ty, 1));
1247 }
1248 default:
1229 // printf("%s\n",str) -> puts(str)
1230 new CallInst(SLC.get_puts(), CastToCStr(CI->getOperand(2), *CI),
1231 CI->getName(), CI);
1232 return ReplaceCallWith(CI, 0);
1233 }
1234 case 'c': {
1235 // printf("%c",c) -> putchar(c)
1236 if (FormatLen != 2)
12491237 return false;
1250 }
1251 return false;
1238
1239 Value *V = CI->getOperand(2);
1240 if (!isa(V->getType()) ||
1241 cast(V->getType())->getBitWidth() < 32)
1242 return false;
1243
1244 V = CastInst::createSExtOrBitCast(V, Type::Int32Ty, CI->getName()+".int",
1245 CI);
1246 new CallInst(SLC.get_putchar(), V, "", CI);
1247 return ReplaceCallWith(CI, 0);
1248 }
1249 }
12521250 }
12531251 } PrintfOptimizer;
12541252