Skip to content

Commit f8c9ceb

Browse files
committed
[SimplifyLibCalls] Add __strlen_chk.
Bionic has had `__strlen_chk` for a while. Optimizing that into a constant is quite profitable, when possible. Differential Revision: https://reviews.llvm.org/D74079
1 parent a148b9e commit f8c9ceb

File tree

6 files changed

+71
-0
lines changed

6 files changed

+71
-0
lines changed

llvm/include/llvm/Analysis/TargetLibraryInfo.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,9 @@ TLI_DEFINE_STRING_INTERNAL("__strlcat_chk")
434434
/// size_t dstsize);
435435
TLI_DEFINE_ENUM_INTERNAL(strlcpy_chk)
436436
TLI_DEFINE_STRING_INTERNAL("__strlcpy_chk")
437+
/// char *__strlen_chk(const char *s1, size_t s1size);
438+
TLI_DEFINE_ENUM_INTERNAL(strlen_chk)
439+
TLI_DEFINE_STRING_INTERNAL("__strlen_chk")
437440
/// char *strncat_chk(char *s1, const char *s2, size_t n, size_t s1size);
438441
TLI_DEFINE_ENUM_INTERNAL(strncat_chk)
439442
TLI_DEFINE_STRING_INTERNAL("__strncat_chk")

llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ class FortifiedLibCallSimplifier {
6060
/// Str/Stp cpy are similar enough to be handled in the same functions.
6161
Value *optimizeStrpCpyChk(CallInst *CI, IRBuilder<> &B, LibFunc Func);
6262
Value *optimizeStrpNCpyChk(CallInst *CI, IRBuilder<> &B, LibFunc Func);
63+
Value *optimizeStrLenChk(CallInst *CI, IRBuilder<> &B);
6364
Value *optimizeMemCCpyChk(CallInst *CI, IRBuilder<> &B);
6465
Value *optimizeSNPrintfChk(CallInst *CI, IRBuilder<> &B);
6566
Value *optimizeSPrintfChk(CallInst *CI,IRBuilder<> &B);

llvm/lib/Analysis/TargetLibraryInfo.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -659,6 +659,11 @@ bool TargetLibraryInfoImpl::isValidProtoForLibFunc(const FunctionType &FTy,
659659
FTy.getParamType(1)->isPointerTy() &&
660660
FTy.getParamType(2)->isPointerTy() &&
661661
FTy.getReturnType()->isIntegerTy(32));
662+
case LibFunc_strlen_chk:
663+
--NumParams;
664+
if (!IsSizeTTy(FTy.getParamType(NumParams)))
665+
return false;
666+
LLVM_FALLTHROUGH;
662667
case LibFunc_strlen:
663668
return (NumParams == 1 && FTy.getParamType(0)->isPointerTy() &&
664669
FTy.getReturnType()->isIntegerTy());

llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3093,6 +3093,10 @@ Value *LibCallSimplifier::optimizeCall(CallInst *CI) {
30933093
// Try to further simplify the result.
30943094
CallInst *SimplifiedCI = dyn_cast<CallInst>(SimplifiedFortifiedCI);
30953095
if (SimplifiedCI && SimplifiedCI->getCalledFunction()) {
3096+
// Ensure that SimplifiedCI's uses are complete, since some calls have
3097+
// their uses analyzed.
3098+
replaceAllUsesWith(CI, SimplifiedCI);
3099+
30963100
// Use an IR Builder from SimplifiedCI if available instead of CI
30973101
// to guarantee we reach all uses we might replace later on.
30983102
IRBuilder<> TmpBuilder(SimplifiedCI);
@@ -3354,6 +3358,14 @@ Value *FortifiedLibCallSimplifier::optimizeStrpCpyChk(CallInst *CI,
33543358
return Ret;
33553359
}
33563360

3361+
Value *FortifiedLibCallSimplifier::optimizeStrLenChk(CallInst *CI,
3362+
IRBuilder<> &B) {
3363+
if (isFortifiedCallFoldable(CI, 1, None, 0))
3364+
return emitStrLen(CI->getArgOperand(0), B, CI->getModule()->getDataLayout(),
3365+
TLI);
3366+
return nullptr;
3367+
}
3368+
33573369
Value *FortifiedLibCallSimplifier::optimizeStrpNCpyChk(CallInst *CI,
33583370
IRBuilder<> &B,
33593371
LibFunc Func) {
@@ -3494,6 +3506,8 @@ Value *FortifiedLibCallSimplifier::optimizeCall(CallInst *CI) {
34943506
case LibFunc_stpcpy_chk:
34953507
case LibFunc_strcpy_chk:
34963508
return optimizeStrpCpyChk(CI, Builder, Func);
3509+
case LibFunc_strlen_chk:
3510+
return optimizeStrLenChk(CI, Builder);
34973511
case LibFunc_stpncpy_chk:
34983512
case LibFunc_strncpy_chk:
34993513
return optimizeStrpNCpyChk(CI, Builder, Func);
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
; Test that __strlen_chk simplification works correctly.
2+
;
3+
; RUN: opt < %s -instcombine -S | FileCheck %s
4+
5+
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
6+
7+
@hello = constant [6 x i8] c"hello\00"
8+
@hello_no_nul = constant [5 x i8] c"hello"
9+
10+
declare i32 @__strlen_chk(i8*, i32)
11+
12+
; Check __strlen_chk(string constant) -> strlen or constants
13+
14+
; CHECK-LABEL: @unknown_str_known_object_size
15+
define i32 @unknown_str_known_object_size(i8* %c) {
16+
; CHECK: call i32 @__strlen_chk
17+
%1 = call i32 @__strlen_chk(i8* %c, i32 8)
18+
ret i32 %1
19+
}
20+
21+
; CHECK-LABEL: @known_str_known_object_size
22+
define i32 @known_str_known_object_size(i8* %c) {
23+
; CHECK: ret i32 5
24+
%1 = call i32 @__strlen_chk(i8* getelementptr inbounds ([6 x i8], [6 x i8]* @hello, i32 0, i32 0), i32 6)
25+
ret i32 %1
26+
}
27+
28+
; CHECK-LABEL: @known_str_too_small_object_size
29+
define i32 @known_str_too_small_object_size(i8* %c) {
30+
; CHECK: call i32 @__strlen_chk
31+
%1 = call i32 @__strlen_chk(i8* getelementptr inbounds ([6 x i8], [6 x i8]* @hello, i32 0, i32 0), i32 5)
32+
ret i32 %1
33+
}
34+
35+
; CHECK-LABEL: @known_str_no_nul
36+
define i32 @known_str_no_nul(i8* %c) {
37+
; CHECK: call i32 @__strlen_chk
38+
%1 = call i32 @__strlen_chk(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @hello_no_nul, i32 0, i32 0), i32 5)
39+
ret i32 %1
40+
}
41+
42+
; CHECK-LABEL: @unknown_str_unknown_object_size
43+
define i32 @unknown_str_unknown_object_size(i8* %c) {
44+
; CHECK: call i32 @strlen
45+
%1 = call i32 @__strlen_chk(i8* %c, i32 -1)
46+
ret i32 %1
47+
}

llvm/unittests/Analysis/TargetLibraryInfoTest.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,7 @@ TEST_F(TargetLibraryInfoTest, ValidProto) {
474474
"declare i32 @__sprintf_chk(i8*, i32, i64, i8*, ...)\n"
475475
"declare i8* @__strcat_chk(i8*, i8*, i64)\n"
476476
"declare i64 @__strlcat_chk(i8*, i8*, i64, i64)\n"
477+
"declare i64 @__strlen_chk(i8*, i64)\n"
477478
"declare i8* @__strncat_chk(i8*, i8*, i64, i64)\n"
478479
"declare i64 @__strlcpy_chk(i8*, i8*, i64, i64)\n"
479480
"declare i32 @__vsnprintf_chk(i8*, i64, i32, i64, i8*, %struct*)\n"

0 commit comments

Comments
 (0)