Index: include/llvm/Transforms/Utils/BuildLibCalls.h
===================================================================
--- include/llvm/Transforms/Utils/BuildLibCalls.h
+++ include/llvm/Transforms/Utils/BuildLibCalls.h
@@ -63,6 +63,10 @@
   Value *emitStrChr(Value *Ptr, char C, IRBuilder<> &B,
                     const TargetLibraryInfo *TLI);
 
+  /// Emit a call to the strcmp function to the builder.
+  Value *emitStrCmp(Value *Ptr1, Value *Ptr2, IRBuilder<> &B,
+                    const DataLayout &DL, const TargetLibraryInfo *TLI);
+
   /// Emit a call to the strncmp function to the builder.
   Value *emitStrNCmp(Value *Ptr1, Value *Ptr2, Value *Len, IRBuilder<> &B,
                      const DataLayout &DL, const TargetLibraryInfo *TLI);
Index: lib/Transforms/Utils/BuildLibCalls.cpp
===================================================================
--- lib/Transforms/Utils/BuildLibCalls.cpp
+++ lib/Transforms/Utils/BuildLibCalls.cpp
@@ -835,6 +835,13 @@
                      {castToCStr(Ptr, B), ConstantInt::get(I32Ty, C)}, B, TLI);
 }
 
+Value *llvm::emitStrCmp(Value *Ptr1, Value *Ptr2, IRBuilder<> &B,
+                        const DataLayout &DL, const TargetLibraryInfo *TLI) {
+  return emitLibCall(LibFunc_strcmp, B.getInt32Ty(),
+                     {B.getInt8PtrTy(), B.getInt8PtrTy()},
+                     {castToCStr(Ptr1, B), castToCStr(Ptr2, B)}, B, TLI);
+}
+
 Value *llvm::emitStrNCmp(Value *Ptr1, Value *Ptr2, Value *Len, IRBuilder<> &B,
                          const DataLayout &DL, const TargetLibraryInfo *TLI) {
   LLVMContext &Context = B.GetInsertBlock()->getContext();
Index: lib/Transforms/Utils/SimplifyLibCalls.cpp
===================================================================
--- lib/Transforms/Utils/SimplifyLibCalls.cpp
+++ lib/Transforms/Utils/SimplifyLibCalls.cpp
@@ -379,21 +379,45 @@
 
 Value *LibCallSimplifier::optimizeStrNCmp(CallInst *CI, IRBuilder<> &B) {
   Value *Str1P = CI->getArgOperand(0), *Str2P = CI->getArgOperand(1);
+  Value *Len = CI->getArgOperand(2);
   if (Str1P == Str2P) // strncmp(x,x,n)  -> 0
     return ConstantInt::get(CI->getType(), 0);
 
   // Get the length argument if it is constant.
   uint64_t Length;
-  if (ConstantInt *LengthArg = dyn_cast<ConstantInt>(CI->getArgOperand(2)))
+  if (ConstantInt *LengthArg = dyn_cast<ConstantInt>(Len)) {
     Length = LengthArg->getZExtValue();
-  else
-    return nullptr;
+  } else {
+    // strncmp(x,y,strlen(x|y)+1) -> strcmp(x,y)
+    Value *Call;
+    if (match(Len, m_Add(m_Value(Call), m_One()))) {
+      auto *Strlen = dyn_cast<CallInst>(Call);
+      if (!Strlen)
+        return nullptr;
+
+      // Is the inner call strlen()?
+      Function *InnerCallee = Strlen->getCalledFunction();
+      if (!InnerCallee)
+        return nullptr;
+
+      LibFunc Func;
+      if (!TLI->getLibFunc(*InnerCallee, Func) || !TLI->has(Func) ||
+          Func != LibFunc_strlen)
+        return nullptr;
+
+      auto *StrlenStr = Strlen->getOperand(0);
+      if (StrlenStr != Str1P && StrlenStr != Str2P)
+        return nullptr;
+
+      return emitStrCmp(Str1P, Str2P, B, DL, TLI);
+    }
+  }
 
   if (Length == 0) // strncmp(x,y,0)   -> 0
     return ConstantInt::get(CI->getType(), 0);
 
   if (Length == 1) // strncmp(x,y,1) -> memcmp(x,y,1)
-    return emitMemCmp(Str1P, Str2P, CI->getArgOperand(2), B, DL, TLI);
+    return emitMemCmp(Str1P, Str2P, Len, B, DL, TLI);
 
   StringRef Str1, Str2;
   bool HasStr1 = getConstantStringInfo(Str1P, Str1);
Index: test/Transforms/InstCombine/strncmp-strlen.ll
===================================================================
--- test/Transforms/InstCombine/strncmp-strlen.ll
+++ test/Transforms/InstCombine/strncmp-strlen.ll
@@ -0,0 +1,97 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; Test that the strncmp library call simplifier works correctly.
+; RUN: opt < %s -instcombine -S | FileCheck %s
+
+declare i32 @strncmp(i8* nocapture, i8* nocapture, i64)
+declare i64 @strlen(i8* nocapture)
+declare void @extra_use(i64)
+
+define i32 @strncmp_strlen(i8* %s, i8* %k) {
+; CHECK-LABEL: @strncmp_strlen(
+; CHECK-NEXT:    [[STRCMP:%.*]] = call i32 @strcmp(i8* [[S:%.*]], i8* [[K:%.*]])
+; CHECK-NEXT:    ret i32 [[STRCMP]]
+;
+  %len = tail call i64 @strlen(i8* %s)
+  %len1 = add i64 %len, 1
+  %r = tail call i32 @strncmp(i8* %s, i8* %k, i64 %len1)
+  ret i32 %r
+}
+
+define i32 @strncmp_strlen2(i8* %s, i8* %k) {
+; CHECK-LABEL: @strncmp_strlen2(
+; CHECK-NEXT:    [[STRCMP:%.*]] = call i32 @strcmp(i8* [[S:%.*]], i8* [[K:%.*]])
+; CHECK-NEXT:    ret i32 [[STRCMP]]
+;
+  %len = tail call i64 @strlen(i8* %k)
+  %len1 = add i64 %len, 1
+  %r = tail call i32 @strncmp(i8* %s, i8* %k, i64 %len1)
+  ret i32 %r
+}
+
+define i32 @strncmp_strlen_multiuse(i8* %s, i8* %k) {
+; CHECK-LABEL: @strncmp_strlen_multiuse(
+; CHECK-NEXT:    [[LEN:%.*]] = tail call i64 @strlen(i8* [[S:%.*]])
+; CHECK-NEXT:    call void @extra_use(i64 [[LEN]])
+; CHECK-NEXT:    [[STRCMP:%.*]] = call i32 @strcmp(i8* [[S]], i8* [[K:%.*]])
+; CHECK-NEXT:    ret i32 [[STRCMP]]
+;
+  %len = tail call i64 @strlen(i8* %s)
+  call void @extra_use(i64 %len)
+  %len1 = add i64 %len, 1
+  %r = tail call i32 @strncmp(i8* %s, i8* %k, i64 %len1)
+  ret i32 %r
+}
+
+define i32 @strncmp_strlen_multiuse2(i8* %s, i8* %k) {
+; CHECK-LABEL: @strncmp_strlen_multiuse2(
+; CHECK-NEXT:    [[LEN:%.*]] = tail call i64 @strlen(i8* [[S:%.*]])
+; CHECK-NEXT:    [[LEN1:%.*]] = add i64 [[LEN]], 1
+; CHECK-NEXT:    call void @extra_use(i64 [[LEN1]])
+; CHECK-NEXT:    [[STRCMP:%.*]] = call i32 @strcmp(i8* [[S]], i8* [[K:%.*]])
+; CHECK-NEXT:    ret i32 [[STRCMP]]
+;
+  %len = tail call i64 @strlen(i8* %s)
+  %len1 = add i64 %len, 1
+  call void @extra_use(i64 %len1)
+  %r = tail call i32 @strncmp(i8* %s, i8* %k, i64 %len1)
+  ret i32 %r
+}
+
+; Negative tests
+
+define i32 @strncmp_strlen_neg1(i8* %s, i8* %k) {
+; CHECK-LABEL: @strncmp_strlen_neg1(
+; CHECK-NEXT:    [[LEN:%.*]] = tail call i64 @strlen(i8* [[S:%.*]])
+; CHECK-NEXT:    [[R:%.*]] = tail call i32 @strncmp(i8* [[S]], i8* [[K:%.*]], i64 [[LEN]])
+; CHECK-NEXT:    ret i32 [[R]]
+;
+  %len = tail call i64 @strlen(i8* %s)
+  %r = tail call i32 @strncmp(i8* %s, i8* %k, i64 %len)
+  ret i32 %r
+}
+
+define i32 @strncmp_strlen_neg2(i8* %s, i8* %k) {
+; CHECK-LABEL: @strncmp_strlen_neg2(
+; CHECK-NEXT:    [[LEN:%.*]] = tail call i64 @strlen(i8* [[S:%.*]])
+; CHECK-NEXT:    [[LEN1:%.*]] = add i64 [[LEN]], 2
+; CHECK-NEXT:    [[R:%.*]] = tail call i32 @strncmp(i8* [[S]], i8* [[K:%.*]], i64 [[LEN1]])
+; CHECK-NEXT:    ret i32 [[R]]
+;
+  %len = tail call i64 @strlen(i8* %s)
+  %len1 = add i64 %len, 2
+  %r = tail call i32 @strncmp(i8* %s, i8* %k, i64 %len1)
+  ret i32 %r
+}
+
+define i32 @strncmp_strlen_neg3(i8* %s, i8* %k, i8* %d) {
+; CHECK-LABEL: @strncmp_strlen_neg3(
+; CHECK-NEXT:    [[LEN:%.*]] = tail call i64 @strlen(i8* [[D:%.*]])
+; CHECK-NEXT:    [[LEN1:%.*]] = add i64 [[LEN]], 1
+; CHECK-NEXT:    [[R:%.*]] = tail call i32 @strncmp(i8* [[S:%.*]], i8* [[K:%.*]], i64 [[LEN1]])
+; CHECK-NEXT:    ret i32 [[R]]
+;
+  %len = tail call i64 @strlen(i8* %d)
+  %len1 = add i64 %len, 1
+  %r = tail call i32 @strncmp(i8* %s, i8* %k, i64 %len1)
+  ret i32 %r
+}