Index: lib/Transforms/Instrumentation/MemorySanitizer.cpp
===================================================================
--- lib/Transforms/Instrumentation/MemorySanitizer.cpp
+++ lib/Transforms/Instrumentation/MemorySanitizer.cpp
@@ -718,14 +718,36 @@
                             IRB.CreatePointerCast(Addr, IRB.getInt8PtrTy()),
                             Origin});
       } else {
-        Value *Cmp = IRB.CreateICmpNE(
-            ConvertedShadow, getCleanShadow(ConvertedShadow), "_mscmp");
-        Instruction *CheckTerm = SplitBlockAndInsertIfThen(
-            Cmp, &*IRB.GetInsertPoint(), false, MS.OriginStoreWeights);
-        IRBuilder<> IRBNew(CheckTerm);
-        paintOrigin(IRBNew, updateOrigin(Origin, IRBNew),
-                    getOriginPtr(Addr, IRBNew, Alignment), StoreSize,
-                    OriginAlignment);
+        if (ArrayType *AT = dyn_cast<ArrayType>(ConvertedShadow->getType())) {
+          // For ArrayType we need to apply the icmp to each element (since the
+          // the instruction does not support array types).
+          Value *CleanShadow = getCleanShadow(ConvertedShadow);
+          for (int i = 0, s = AT->getNumElements(); i < s; i++) {
+            Value *ConvertedShadowElem = IRB.CreateExtractValue(
+                ConvertedShadow, i);
+            Value *CleanShadowElem = IRB.CreateExtractValue(CleanShadow, i);
+            Value *Cmp = IRB.CreateICmpNE(
+                ConvertedShadowElem, CleanShadowElem, "_mscmp");
+
+            Instruction *CheckTerm = SplitBlockAndInsertIfThen(
+                Cmp, &*IRB.GetInsertPoint(), false, MS.OriginStoreWeights);
+            IRB.SetInsertPoint(CheckTerm);
+
+            IRBuilder<> IRBNew(CheckTerm);
+            paintOrigin(IRBNew, updateOrigin(Origin, IRBNew),
+                        getOriginPtr(Addr, IRBNew, Alignment), StoreSize,
+                        OriginAlignment);
+          }
+        } else {
+          Value *Cmp = IRB.CreateICmpNE(
+              ConvertedShadow, getCleanShadow(ConvertedShadow), "_mscmp");
+          Instruction *CheckTerm = SplitBlockAndInsertIfThen(
+              Cmp, &*IRB.GetInsertPoint(), false, MS.OriginStoreWeights);
+          IRBuilder<> IRBNew(CheckTerm);
+          paintOrigin(IRBNew, updateOrigin(Origin, IRBNew),
+                      getOriginPtr(Addr, IRBNew, Alignment), StoreSize,
+                      OriginAlignment);
+        }
       }
     }
   }
Index: test/Instrumentation/MemorySanitizer/origin-array.ll
===================================================================
--- /dev/null
+++ test/Instrumentation/MemorySanitizer/origin-array.ll
@@ -0,0 +1,72 @@
+; RUN: opt < %s -msan -msan-check-access-address=0 -msan-track-origins=2 -S | FileCheck %s
+
+target datalayout = "e-m:e-i64:64-i128:128-n32:64-S128"
+target triple = "aarch64-unknown-linux-gnu"
+
+; Check origin handling of array types.  Since the instrumentation will
+; potentially creates icmp instruction to check origin values, it requires
+; the intrumentation pass to create icmp for each element.
+
+%struct.mypair = type { i64, i32 }
+
+; Function Attrs: nounwind
+define [2 x i64] @_Z12my_make_pairli(i64 %x, i32 %y) {
+entry:
+  %retval = alloca %struct.mypair, align 8
+  %x.addr = alloca i64, align 8
+  %y.addr = alloca i32, align 4
+  store i64 %x, i64* %x.addr, align 8
+  store i32 %y, i32* %y.addr, align 4
+  %0 = load i64, i64* %x.addr, align 8
+  %x1 = getelementptr inbounds %struct.mypair, %struct.mypair* %retval, i32 0, i32 0
+  store i64 %0, i64* %x1, align 8
+  %1 = load i32, i32* %y.addr, align 4
+  %y2 = getelementptr inbounds %struct.mypair, %struct.mypair* %retval, i32 0, i32 1
+  store i32 %1, i32* %y2, align 8
+  %2 = bitcast %struct.mypair* %retval to [2 x i64]*
+  %3 = load [2 x i64], [2 x i64]* %2, align 8
+  ret [2 x i64] %3
+}
+
+; Function Attrs: nounwind
+define i32 @_Z3fooi(i32 %p) #0 {
+entry:
+  %p.addr = alloca i32, align 4
+  %z = alloca %struct.mypair, align 8
+  store i32 %p, i32* %p.addr, align 4
+  %0 = load i32, i32* %p.addr, align 4
+  %conv = sext i32 %0 to i64
+  %call = call [2 x i64] @_Z12my_make_pairli(i64 %conv, i32 0)
+  %1 = bitcast %struct.mypair* %z to [2 x i64]*
+  store [2 x i64] %call, [2 x i64]* %1, align 8
+  %x = getelementptr inbounds %struct.mypair, %struct.mypair* %z, i32 0, i32 0
+  %2 = load i64, i64* %x, align 8
+  %y = getelementptr inbounds %struct.mypair, %struct.mypair* %z, i32 0, i32 1
+  %3 = load i32, i32* %y, align 8
+  %conv1 = sext i32 %3 to i64
+  %add = add nsw i64 %2, %conv1
+  %conv2 = trunc i64 %add to i32
+  ret i32 %conv2
+}
+
+; CHECK-LABEL: @_Z3fooi
+; CHECK: load {{.*}} @__msan_param_tls
+; CHECK: [[ORIGIN:%[01-9a-z]+]] = load {{.*}} @__msan_retval_origin_tls
+; CHECK: store {{.*}}
+
+; Extract and compare the first element.
+; CHECK: {{.*}} extractvalue {{.*}} 0
+; CHECK: icmp
+; CHECK: br i1 {{.*}}
+; CHECK: ; <label>{{.*}}
+; CHECK: [[ORIGIN2:%[01-9a-z]+]] = call i32 @__msan_chain_origin(i32 {{.*}}[[ORIGIN]])
+
+; And then the second element.
+; CHECK: store {{.*}}
+; CHECK: {{.*}} extractvalue {{.*}} 1
+; CHECK: icmp
+; CHECK: br i1 {{.*}}
+; CHECK: ; <label>{{.*}}
+; CHECK: [[ORIGIN2:%[01-9a-z]+]] = call i32 @__msan_chain_origin(i32 {{.*}}[[ORIGIN]])
+
+attributes #0 = { nounwind sanitize_memory "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="generic" "target-features"="+neon" "unsafe-fp-math"="false" "use-soft-float"="false" }