diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h
index 3cc4b7d009fbe30825ace5731cda3536ae63fa64..b4d9040c4b30c72d7df52a359ccb54b7bdbf2906 100644
--- a/include/clang/AST/Expr.h
+++ b/include/clang/AST/Expr.h
@@ -459,6 +459,10 @@ public:
   /// \brief Returns whether this expression refers to a vector element.
   bool refersToVectorElement() const;
 
+  /// \brief Returns whether this expression refers to a global register
+  /// variable.
+  bool refersToGlobalRegisterVar() const;
+
   /// \brief Returns whether this expression has a placeholder type.
   bool hasPlaceholderType() const {
     return getType()->isPlaceholderType();
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index c300d6fe423b8054b528fecda1b43d67b540c850..65670f454beb684d0d535f09598c8fa4c6108460 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -6385,9 +6385,9 @@ let CategoryName = "Inline Assembly Issue" in {
     "remove the cast or build with -fheinous-gnu-extensions">;
   def err_invalid_asm_value_for_constraint
       : Error <"value '%0' out of range for constraint '%1'">;
-  def err_asm_bitfield_in_memory_constraint
-      : Error <"reference to a bit-field in asm "
-      "%select{input|output}0 with a memory constraint '%1'">;
+  def err_asm_non_addr_value_in_memory_constraint : Error <
+    "reference to a %select{bit-field|vector element|global register variable}0"
+    " in asm %select{input|output}1 with a memory constraint '%2'">;
 
   def warn_asm_label_on_auto_decl : Warning<
     "ignored asm label '%0' on automatic variable">;
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index 4882f536d5276ff85da8301cb564c316ac0b2f07..89f47f980c9c601ebbacd62522da8310fc532dcf 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -3437,6 +3437,18 @@ bool Expr::refersToVectorElement() const {
   return false;
 }
 
+bool Expr::refersToGlobalRegisterVar() const {
+  const Expr *E = this->IgnoreParenImpCasts();
+
+  if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
+    if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl()))
+      if (VD->getStorageClass() == SC_Register &&
+          VD->hasAttr<AsmLabelAttr>() && !VD->isLocalVarDecl())
+        return true;
+
+  return false;
+}
+
 /// isArrow - Return true if the base expression is a pointer to vector,
 /// return false if the base expression is a vector.
 bool ExtVectorElementExpr::isArrow() const {
diff --git a/lib/Sema/SemaStmtAsm.cpp b/lib/Sema/SemaStmtAsm.cpp
index 8e584919363419481b2b4060495cd591b8bc950d..799689f199516d2d0be5f927ade17ec5ad29e790 100644
--- a/lib/Sema/SemaStmtAsm.cpp
+++ b/lib/Sema/SemaStmtAsm.cpp
@@ -107,6 +107,37 @@ static bool CheckNakedParmReference(Expr *E, Sema &S) {
   return false;
 }
 
+/// \brief Returns true if given expression is not compatible with inline
+/// assembly's memory constraint; false otherwise.
+static bool checkExprMemoryConstraintCompat(Sema &S, Expr *E,
+                                            TargetInfo::ConstraintInfo &Info,
+                                            bool is_input_expr) {
+  enum {
+    ExprBitfield = 0,
+    ExprVectorElt,
+    ExprGlobalRegVar,
+    ExprSafeType
+  } EType = ExprSafeType;
+
+  // Bitfields, vector elements and global register variables are not
+  // compatible.
+  if (E->refersToBitField())
+    EType = ExprBitfield;
+  else if (E->refersToVectorElement())
+    EType = ExprVectorElt;
+  else if (E->refersToGlobalRegisterVar())
+    EType = ExprGlobalRegVar;
+
+  if (EType != ExprSafeType) {
+    S.Diag(E->getLocStart(), diag::err_asm_non_addr_value_in_memory_constraint)
+        << EType << is_input_expr << Info.getConstraintStr()
+        << E->getSourceRange();
+    return true;
+  }
+
+  return false;
+}
+
 StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
                                  bool IsVolatile, unsigned NumOutputs,
                                  unsigned NumInputs, IdentifierInfo **Names,
@@ -154,13 +185,10 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
     if (CheckNakedParmReference(OutputExpr, *this))
       return StmtError();
 
-    // Bitfield can't be referenced with a pointer.
-    if (Info.allowsMemory() && OutputExpr->refersToBitField())
-      return StmtError(Diag(OutputExpr->getLocStart(),
-                            diag::err_asm_bitfield_in_memory_constraint)
-                       << 1
-                       << Info.getConstraintStr()
-                       << OutputExpr->getSourceRange());
+    // Check that the output expression is compatible with memory constraint.
+    if (Info.allowsMemory() &&
+        checkExprMemoryConstraintCompat(*this, OutputExpr, Info, false))
+      return StmtError();
 
     OutputConstraintInfos.push_back(Info);
 
@@ -238,13 +266,10 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
     if (CheckNakedParmReference(InputExpr, *this))
       return StmtError();
 
-    // Bitfield can't be referenced with a pointer.
-    if (Info.allowsMemory() && InputExpr->refersToBitField())
-      return StmtError(Diag(InputExpr->getLocStart(),
-                            diag::err_asm_bitfield_in_memory_constraint)
-                       << 0
-                       << Info.getConstraintStr()
-                       << InputExpr->getSourceRange());
+    // Check that the input expression is compatible with memory constraint.
+    if (Info.allowsMemory() &&
+        checkExprMemoryConstraintCompat(*this, InputExpr, Info, true))
+      return StmtError();
 
     // Only allow void types for memory constraints.
     if (Info.allowsMemory() && !Info.allowsRegister()) {
diff --git a/test/Sema/asm.c b/test/Sema/asm.c
index 1a1e02993a723e343856b2f81ad906e5cc3bd4bc..9ed8d843eaffad941fd138e1b0dca22376abf6d2 100644
--- a/test/Sema/asm.c
+++ b/test/Sema/asm.c
@@ -211,13 +211,28 @@ typedef struct test16_foo {
   unsigned int field2 : 2;
   unsigned int field3 : 3;
 } test16_foo;
-test16_foo x;
+typedef __attribute__((vector_size(16))) int test16_bar;
+register int test16_baz asm("rbx");
+
 void test16()
 {
+  test16_foo a;
+  test16_bar b;
+
+  __asm__("movl $5, %0"
+          : "=rm" (a.field2)); // expected-error {{reference to a bit-field in asm input with a memory constraint '=rm'}}
+  __asm__("movl $5, %0"
+          :
+          : "m" (a.field3)); // expected-error {{reference to a bit-field in asm output with a memory constraint 'm'}}
+  __asm__("movl $5, %0"
+          : "=rm" (b[2])); // expected-error {{reference to a vector element in asm input with a memory constraint '=rm'}}
+  __asm__("movl $5, %0"
+          :
+          : "m" (b[3])); // expected-error {{reference to a vector element in asm output with a memory constraint 'm'}}
   __asm__("movl $5, %0"
-          : "=rm" (x.field2)); // expected-error {{reference to a bit-field in asm output with a memory constraint '=rm'}}
+          : "=rm" (test16_baz)); // expected-error {{reference to a global register variable in asm input with a memory constraint '=rm'}}
   __asm__("movl $5, %0"
           :
-          : "m" (x.field3)); // expected-error {{reference to a bit-field in asm input with a memory constraint 'm'}}
+          : "m" (test16_baz)); // expected-error {{reference to a global register variable in asm output with a memory constraint 'm'}}
 }