Index: include/llvm/Transforms/Utils/SimplifyLibCalls.h =================================================================== --- include/llvm/Transforms/Utils/SimplifyLibCalls.h +++ include/llvm/Transforms/Utils/SimplifyLibCalls.h @@ -150,6 +150,8 @@ Value *optimizeIsDigit(CallInst *CI, IRBuilder<> &B); Value *optimizeIsAscii(CallInst *CI, IRBuilder<> &B); Value *optimizeToAscii(CallInst *CI, IRBuilder<> &B); + Value *optimizeAtoi(CallInst *CI, IRBuilder<> &B); + Value *optimizeStrtol(CallInst *CI, IRBuilder<> &B); // Formatting and IO Library Call Optimizations Value *optimizeErrorReporting(CallInst *CI, IRBuilder<> &B, Index: lib/Transforms/Utils/SimplifyLibCalls.cpp =================================================================== --- lib/Transforms/Utils/SimplifyLibCalls.cpp +++ lib/Transforms/Utils/SimplifyLibCalls.cpp @@ -1677,6 +1677,33 @@ ConstantInt::get(CI->getType(), 0x7F)); } +Value *LibCallSimplifier::optimizeAtoi(CallInst *CI, IRBuilder<> &B) { + StringRef Str; + if (!getConstantStringInfo(CI->getArgOperand(0), Str)) + return nullptr; + + return ConstantInt::get(CI->getType(), atoi(Str.str().c_str())); +} + +Value *LibCallSimplifier::optimizeStrtol(CallInst *CI, IRBuilder<> &B) { + StringRef Str; + if (!getConstantStringInfo(CI->getArgOperand(0), Str)) + return nullptr; + + char *End; + long int Number; + + if (ConstantInt *CInt = dyn_cast(CI->getArgOperand(2))) + Number = strtol(Str.str().c_str(), &End, CInt->getSExtValue()); + else + return nullptr; + + if (*End) + return nullptr; + + return ConstantInt::get(CI->getType(), Number); +} + //===----------------------------------------------------------------------===// // Formatting and IO Library Call Optimizations //===----------------------------------------------------------------------===// @@ -2271,6 +2298,10 @@ return optimizeIsAscii(CI, Builder); case LibFunc_toascii: return optimizeToAscii(CI, Builder); + case LibFunc_atoi: + return optimizeAtoi(CI, Builder); + case LibFunc_strtol: + return optimizeStrtol(CI, Builder); case LibFunc_printf: return optimizePrintF(CI, Builder); case LibFunc_sprintf: Index: test/Transforms/InstCombine/str-int.ll =================================================================== --- /dev/null +++ test/Transforms/InstCombine/str-int.ll @@ -0,0 +1,38 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt < %s -instcombine -S | FileCheck %s + +@.str = private unnamed_addr constant [3 x i8] c"12\00", align 1 + +define i32 @strtol_1() #0 { +; CHECK-LABEL: @strtol_1( +; CHECK-NEXT: ret i32 12 +; + %call = call i64 @strtol(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.str, i32 0, i32 0), i8** null, i32 10) #3 + %conv = trunc i64 %call to i32 + ret i32 %conv +} + +; Function Attrs: nounwind +declare i64 @strtol(i8*, i8**, i32) #1 + +; Function Attrs: noinline nounwind uwtable +define i32 @strtol_2() #0 { +; CHECK-LABEL: @strtol_2( +; CHECK-NEXT: ret i32 18 +; + %call = call i64 @strtol(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.str, i32 0, i32 0), i8** null, i32 16) #3 + %conv = trunc i64 %call to i32 + ret i32 %conv +} + +; Function Attrs: noinline nounwind uwtable +define i32 @atoi_test() #0 { +; CHECK-LABEL: @atoi_test( +; CHECK-NEXT: ret i32 12 +; + %call = call i32 @atoi(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.str, i32 0, i32 0)) #4 + ret i32 %call +} + +; Function Attrs: nounwind readonly +declare i32 @atoi(i8*) #2