diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -3385,24 +3385,40 @@
   // Mark any parameters that are known to be non-null with the nonnull
   // attribute.  This is helpful for inlining calls to functions with null
   // checks on their arguments.
-  SmallVector<unsigned, 4> ArgNos;
+  // Likewise mark parameters that are known not captured from parent attributes
+  // as nocapture.
+  SmallVector<unsigned, 4> ArgNosNonNull, ArgNosNoCapture;
+  SmallPtrSet<Value *, 4> NoCaptureParentArguments;
   unsigned ArgNo = 0;
+  if (auto *BB = Call.getParent())
+    if (auto *PF = BB->getParent())
+      for (unsigned I = 0; I < PF->arg_size(); ++I)
+        if (PF->getArg(I)->hasNoCaptureAttr())
+          NoCaptureParentArguments.insert(PF->getArg(I));
 
   for (Value *V : Call.args()) {
     if (V->getType()->isPointerTy() &&
         !Call.paramHasAttr(ArgNo, Attribute::NonNull) &&
         isKnownNonZero(V, DL, 0, &AC, &Call, &DT))
-      ArgNos.push_back(ArgNo);
+      ArgNosNonNull.push_back(ArgNo);
+    if (!Call.paramHasAttr(ArgNo, Attribute::NoCapture) &&
+        NoCaptureParentArguments.contains(V))
+      ArgNosNoCapture.push_back(ArgNo);
+
     ArgNo++;
   }
 
   assert(ArgNo == Call.arg_size() && "Call arguments not processed correctly.");
 
-  if (!ArgNos.empty()) {
+  if (!ArgNosNonNull.empty() || !ArgNosNoCapture.empty()) {
     AttributeList AS = Call.getAttributes();
     LLVMContext &Ctx = Call.getContext();
-    AS = AS.addParamAttribute(Ctx, ArgNos,
-                              Attribute::get(Ctx, Attribute::NonNull));
+    if (!ArgNosNonNull.empty())
+      AS = AS.addParamAttribute(Ctx, ArgNosNonNull,
+                                Attribute::get(Ctx, Attribute::NonNull));
+    if (!ArgNosNoCapture.empty())
+      AS = AS.addParamAttribute(Ctx, ArgNosNoCapture,
+                                Attribute::get(Ctx, Attribute::NoCapture));
     Call.setAttributes(AS);
     Changed = true;
   }
diff --git a/llvm/test/Analysis/BasicAA/nocapture.ll b/llvm/test/Analysis/BasicAA/nocapture.ll
--- a/llvm/test/Analysis/BasicAA/nocapture.ll
+++ b/llvm/test/Analysis/BasicAA/nocapture.ll
@@ -18,9 +18,9 @@
 define i32 @test4(ptr noalias nocapture %p) nounwind {
 ; CHECK: call void @test3
 ; CHECK: store i32 0, ptr %p
+; CHECK: %x = load ptr, ptr %q
 ; CHECK: store i32 1, ptr %x
-; CHECK: %y = load i32, ptr %p
-; CHECK: ret i32 %y
+; CHECK: ret i32 0
 entry:
        %q = alloca ptr
        ; Here test3 might store %p to %q. This doesn't violate %p's nocapture
diff --git a/llvm/test/Transforms/InstCombine/nocapture-attribute.ll b/llvm/test/Transforms/InstCombine/nocapture-attribute.ll
--- a/llvm/test/Transforms/InstCombine/nocapture-attribute.ll
+++ b/llvm/test/Transforms/InstCombine/nocapture-attribute.ll
@@ -17,7 +17,7 @@
 define void @a0_nocapture_a1_a2_maybe_capture(ptr nocapture %a0, ptr %a1, ptr %a2) {
 ; CHECK-LABEL: define void @a0_nocapture_a1_a2_maybe_capture
 ; CHECK-SAME: (ptr nocapture [[A0:%.*]], ptr [[A1:%.*]], ptr [[A2:%.*]]) {
-; CHECK-NEXT:    tail call void @ptrs_maybe_capture(ptr [[A0]], ptr [[A1]], ptr [[A2]])
+; CHECK-NEXT:    tail call void @ptrs_maybe_capture(ptr nocapture [[A0]], ptr [[A1]], ptr [[A2]])
 ; CHECK-NEXT:    ret void
 ;
   tail call void @ptrs_maybe_capture(ptr %a0, ptr %a1, ptr %a2)
@@ -27,7 +27,7 @@
 define void @a2_nocapture2x_a1_maybe_capture(ptr %a0, ptr %a1, ptr nocapture %a2) {
 ; CHECK-LABEL: define void @a2_nocapture2x_a1_maybe_capture
 ; CHECK-SAME: (ptr [[A0:%.*]], ptr [[A1:%.*]], ptr nocapture [[A2:%.*]]) {
-; CHECK-NEXT:    tail call void @ptrs_maybe_capture(ptr [[A2]], ptr [[A1]], ptr [[A2]])
+; CHECK-NEXT:    tail call void @ptrs_maybe_capture(ptr nocapture [[A2]], ptr [[A1]], ptr nocapture [[A2]])
 ; CHECK-NEXT:    ret void
 ;
   tail call void @ptrs_maybe_capture(ptr %a2, ptr %a1, ptr %a2)
@@ -37,7 +37,7 @@
 define void @a0_a1_a2_nocapture(ptr nocapture %a0, ptr nocapture %a1, ptr nocapture %a2) {
 ; CHECK-LABEL: define void @a0_a1_a2_nocapture
 ; CHECK-SAME: (ptr nocapture [[A0:%.*]], ptr nocapture [[A1:%.*]], ptr nocapture [[A2:%.*]]) {
-; CHECK-NEXT:    tail call void @ptrs_maybe_capture(ptr [[A0]], ptr [[A1]], ptr [[A2]])
+; CHECK-NEXT:    tail call void @ptrs_maybe_capture(ptr nocapture [[A0]], ptr nocapture [[A1]], ptr nocapture [[A2]])
 ; CHECK-NEXT:    ret void
 ;
   tail call void @ptrs_maybe_capture(ptr %a0, ptr %a1, ptr %a2)