[llvm] f8c9ceb - [SimplifyLibCalls] Add __strlen_chk.

George Burgess IV via llvm-commits llvm-commits at lists.llvm.org
Sat Feb 8 12:02:57 PST 2020


Author: George Burgess IV
Date: 2020-02-08T11:51:00-08:00
New Revision: f8c9ceb1ce9c71574d413a6391812d46d9f9edb3

URL: https://github.com/llvm/llvm-project/commit/f8c9ceb1ce9c71574d413a6391812d46d9f9edb3
DIFF: https://github.com/llvm/llvm-project/commit/f8c9ceb1ce9c71574d413a6391812d46d9f9edb3.diff

LOG: [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

Added: 
    llvm/test/Transforms/InstCombine/strlen_chk.ll

Modified: 
    llvm/include/llvm/Analysis/TargetLibraryInfo.def
    llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h
    llvm/lib/Analysis/TargetLibraryInfo.cpp
    llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
    llvm/unittests/Analysis/TargetLibraryInfoTest.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/Analysis/TargetLibraryInfo.def b/llvm/include/llvm/Analysis/TargetLibraryInfo.def
index afed404f04c0..daa096150f67 100644
--- a/llvm/include/llvm/Analysis/TargetLibraryInfo.def
+++ b/llvm/include/llvm/Analysis/TargetLibraryInfo.def
@@ -434,6 +434,9 @@ TLI_DEFINE_STRING_INTERNAL("__strlcat_chk")
 ///                      size_t dstsize);
 TLI_DEFINE_ENUM_INTERNAL(strlcpy_chk)
 TLI_DEFINE_STRING_INTERNAL("__strlcpy_chk")
+/// char *__strlen_chk(const char *s1, size_t s1size);
+TLI_DEFINE_ENUM_INTERNAL(strlen_chk)
+TLI_DEFINE_STRING_INTERNAL("__strlen_chk")
 /// char *strncat_chk(char *s1, const char *s2, size_t n, size_t s1size);
 TLI_DEFINE_ENUM_INTERNAL(strncat_chk)
 TLI_DEFINE_STRING_INTERNAL("__strncat_chk")

diff  --git a/llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h b/llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h
index 610668adcfa5..3dc832e4ce81 100644
--- a/llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h
+++ b/llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h
@@ -60,6 +60,7 @@ class FortifiedLibCallSimplifier {
   /// Str/Stp cpy are similar enough to be handled in the same functions.
   Value *optimizeStrpCpyChk(CallInst *CI, IRBuilder<> &B, LibFunc Func);
   Value *optimizeStrpNCpyChk(CallInst *CI, IRBuilder<> &B, LibFunc Func);
+  Value *optimizeStrLenChk(CallInst *CI, IRBuilder<> &B);
   Value *optimizeMemCCpyChk(CallInst *CI, IRBuilder<> &B);
   Value *optimizeSNPrintfChk(CallInst *CI, IRBuilder<> &B);
   Value *optimizeSPrintfChk(CallInst *CI,IRBuilder<> &B);

diff  --git a/llvm/lib/Analysis/TargetLibraryInfo.cpp b/llvm/lib/Analysis/TargetLibraryInfo.cpp
index c7238db43aab..08c2226b6f17 100644
--- a/llvm/lib/Analysis/TargetLibraryInfo.cpp
+++ b/llvm/lib/Analysis/TargetLibraryInfo.cpp
@@ -659,6 +659,11 @@ bool TargetLibraryInfoImpl::isValidProtoForLibFunc(const FunctionType &FTy,
             FTy.getParamType(1)->isPointerTy() &&
             FTy.getParamType(2)->isPointerTy() &&
             FTy.getReturnType()->isIntegerTy(32));
+  case LibFunc_strlen_chk:
+    --NumParams;
+    if (!IsSizeTTy(FTy.getParamType(NumParams)))
+      return false;
+    LLVM_FALLTHROUGH;
   case LibFunc_strlen:
     return (NumParams == 1 && FTy.getParamType(0)->isPointerTy() &&
             FTy.getReturnType()->isIntegerTy());

diff  --git a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
index d47e9691b37c..c4511c64779c 100644
--- a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
@@ -3093,6 +3093,10 @@ Value *LibCallSimplifier::optimizeCall(CallInst *CI) {
     // Try to further simplify the result.
     CallInst *SimplifiedCI = dyn_cast<CallInst>(SimplifiedFortifiedCI);
     if (SimplifiedCI && SimplifiedCI->getCalledFunction()) {
+      // Ensure that SimplifiedCI's uses are complete, since some calls have
+      // their uses analyzed.
+      replaceAllUsesWith(CI, SimplifiedCI);
+
       // Use an IR Builder from SimplifiedCI if available instead of CI
       // to guarantee we reach all uses we might replace later on.
       IRBuilder<> TmpBuilder(SimplifiedCI);
@@ -3354,6 +3358,14 @@ Value *FortifiedLibCallSimplifier::optimizeStrpCpyChk(CallInst *CI,
   return Ret;
 }
 
+Value *FortifiedLibCallSimplifier::optimizeStrLenChk(CallInst *CI,
+                                                     IRBuilder<> &B) {
+  if (isFortifiedCallFoldable(CI, 1, None, 0))
+    return emitStrLen(CI->getArgOperand(0), B, CI->getModule()->getDataLayout(),
+                      TLI);
+  return nullptr;
+}
+
 Value *FortifiedLibCallSimplifier::optimizeStrpNCpyChk(CallInst *CI,
                                                        IRBuilder<> &B,
                                                        LibFunc Func) {
@@ -3494,6 +3506,8 @@ Value *FortifiedLibCallSimplifier::optimizeCall(CallInst *CI) {
   case LibFunc_stpcpy_chk:
   case LibFunc_strcpy_chk:
     return optimizeStrpCpyChk(CI, Builder, Func);
+  case LibFunc_strlen_chk:
+    return optimizeStrLenChk(CI, Builder);
   case LibFunc_stpncpy_chk:
   case LibFunc_strncpy_chk:
     return optimizeStrpNCpyChk(CI, Builder, Func);

diff  --git a/llvm/test/Transforms/InstCombine/strlen_chk.ll b/llvm/test/Transforms/InstCombine/strlen_chk.ll
new file mode 100644
index 000000000000..b03bac7327c7
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/strlen_chk.ll
@@ -0,0 +1,47 @@
+; Test that __strlen_chk simplification works correctly.
+;
+; RUN: opt < %s -instcombine -S | FileCheck %s
+
+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"
+
+ at hello = constant [6 x i8] c"hello\00"
+ at hello_no_nul = constant [5 x i8] c"hello"
+
+declare i32 @__strlen_chk(i8*, i32)
+
+; Check __strlen_chk(string constant) -> strlen or constants
+
+; CHECK-LABEL: @unknown_str_known_object_size
+define i32 @unknown_str_known_object_size(i8* %c) {
+  ; CHECK: call i32 @__strlen_chk
+  %1 = call i32 @__strlen_chk(i8* %c, i32 8)
+  ret i32 %1
+}
+
+; CHECK-LABEL: @known_str_known_object_size
+define i32 @known_str_known_object_size(i8* %c) {
+  ; CHECK: ret i32 5
+  %1 = call i32 @__strlen_chk(i8* getelementptr inbounds ([6 x i8], [6 x i8]* @hello, i32 0, i32 0), i32 6)
+  ret i32 %1
+}
+
+; CHECK-LABEL: @known_str_too_small_object_size
+define i32 @known_str_too_small_object_size(i8* %c) {
+  ; CHECK: call i32 @__strlen_chk
+  %1 = call i32 @__strlen_chk(i8* getelementptr inbounds ([6 x i8], [6 x i8]* @hello, i32 0, i32 0), i32 5)
+  ret i32 %1
+}
+
+; CHECK-LABEL: @known_str_no_nul
+define i32 @known_str_no_nul(i8* %c) {
+  ; CHECK: call i32 @__strlen_chk
+  %1 = call i32 @__strlen_chk(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @hello_no_nul, i32 0, i32 0), i32 5)
+  ret i32 %1
+}
+
+; CHECK-LABEL: @unknown_str_unknown_object_size
+define i32 @unknown_str_unknown_object_size(i8* %c) {
+  ; CHECK: call i32 @strlen
+  %1 = call i32 @__strlen_chk(i8* %c, i32 -1)
+  ret i32 %1
+}

diff  --git a/llvm/unittests/Analysis/TargetLibraryInfoTest.cpp b/llvm/unittests/Analysis/TargetLibraryInfoTest.cpp
index 00b1e94863b7..965983f9f617 100644
--- a/llvm/unittests/Analysis/TargetLibraryInfoTest.cpp
+++ b/llvm/unittests/Analysis/TargetLibraryInfoTest.cpp
@@ -474,6 +474,7 @@ TEST_F(TargetLibraryInfoTest, ValidProto) {
       "declare i32 @__sprintf_chk(i8*, i32, i64, i8*, ...)\n"
       "declare i8* @__strcat_chk(i8*, i8*, i64)\n"
       "declare i64 @__strlcat_chk(i8*, i8*, i64, i64)\n"
+      "declare i64 @__strlen_chk(i8*, i64)\n"
       "declare i8* @__strncat_chk(i8*, i8*, i64, i64)\n"
       "declare i64 @__strlcpy_chk(i8*, i8*, i64, i64)\n"
       "declare i32 @__vsnprintf_chk(i8*, i64, i32, i64, i8*, %struct*)\n"


        


More information about the llvm-commits mailing list