diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h
index 48e3451f25770b041226c6f2dfc34e1fe75cded2..b6f8c735cc83429384fb102a1c619a4524dc7732 100644
--- a/include/clang/AST/ASTContext.h
+++ b/include/clang/AST/ASTContext.h
@@ -1691,6 +1691,10 @@ public:
   /// beneficial for performance to overalign a data type.
   unsigned getPreferredTypeAlign(const Type *T) const;
 
+  /// \brief Return the default alignment for __attribute__((aligned)) on
+  /// this target, to be used if no alignment value is specified.
+  unsigned getTargetDefaultAlignForAttributeAligned(void) const;
+
   /// \brief Return the alignment in bits that should be given to a
   /// global variable with type \p T.
   unsigned getAlignOfGlobalVar(QualType T) const;
diff --git a/include/clang/Basic/TargetInfo.h b/include/clang/Basic/TargetInfo.h
index 1d6485a56e9340f2e4382ce6a50132963792ff1b..8406205c7fd9ddc4422c3aee0b8c0f35476414ee 100644
--- a/include/clang/Basic/TargetInfo.h
+++ b/include/clang/Basic/TargetInfo.h
@@ -66,6 +66,7 @@ protected:
   unsigned char LongWidth, LongAlign;
   unsigned char LongLongWidth, LongLongAlign;
   unsigned char SuitableAlign;
+  unsigned char DefaultAlignForAttributeAligned;
   unsigned char MinGlobalAlign;
   unsigned char MaxAtomicPromoteWidth, MaxAtomicInlineWidth;
   unsigned short MaxVectorAlign;
@@ -314,6 +315,12 @@ public:
   /// object with a fundamental alignment requirement.
   unsigned getSuitableAlign() const { return SuitableAlign; }
 
+  /// \brief Return the default alignment for __attribute__((aligned)) on
+  /// this target, to be used if no alignment value is specified.
+  unsigned getDefaultAlignForAttributeAligned() const {
+    return DefaultAlignForAttributeAligned;
+  }
+
   /// getMinGlobalAlign - Return the minimum alignment of a global variable,
   /// unless its alignment is explicitly reduced via attributes.
   unsigned getMinGlobalAlign() const { return MinGlobalAlign; }
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index c54a006d26a765bd30ccdffc47a811361c4d47b0..4d6a51bf1924196a7d189aaf6ff137c66bd8ee87 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -1817,6 +1817,13 @@ unsigned ASTContext::getPreferredTypeAlign(const Type *T) const {
   return ABIAlign;
 }
 
+/// getTargetDefaultAlignForAttributeAligned - Return the default alignment
+/// for __attribute__((aligned)) on this target, to be used if no alignment
+/// value is specified.
+unsigned ASTContext::getTargetDefaultAlignForAttributeAligned(void) const {
+  return getTargetInfo().getDefaultAlignForAttributeAligned();
+}
+
 /// getAlignOfGlobalVar - Return the alignment in bits that should be given
 /// to a global variable of the specified type.
 unsigned ASTContext::getAlignOfGlobalVar(QualType T) const {
diff --git a/lib/Basic/TargetInfo.cpp b/lib/Basic/TargetInfo.cpp
index 871bbd5ef43f9e13bda6af5b93037bfe5b8ffc8a..330258b025b5f5c9d11cda6ad45c523378dc4f79 100644
--- a/lib/Basic/TargetInfo.cpp
+++ b/lib/Basic/TargetInfo.cpp
@@ -36,6 +36,7 @@ TargetInfo::TargetInfo(const llvm::Triple &T) : TargetOpts(), Triple(T) {
   LongWidth = LongAlign = 32;
   LongLongWidth = LongLongAlign = 64;
   SuitableAlign = 64;
+  DefaultAlignForAttributeAligned = 128;
   MinGlobalAlign = 0;
   HalfWidth = 16;
   HalfAlign = 16;
diff --git a/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp
index 1f81bcd46d4fd0a9c16c8bde06a111becfe2fbaa..047cf0d5b5c04686940bfd8c4bb53a2ebb01d200 100644
--- a/lib/Basic/Targets.cpp
+++ b/lib/Basic/Targets.cpp
@@ -5521,6 +5521,7 @@ public:
     LongDoubleWidth = 128;
     LongDoubleAlign = 64;
     LongDoubleFormat = &llvm::APFloat::IEEEquad;
+    DefaultAlignForAttributeAligned = 64;
     MinGlobalAlign = 16;
     DescriptionString = "E-m:e-i1:8:16-i8:8:16-i64:64-f128:64-a:8:16-n32:64";
     MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64;
diff --git a/test/Sema/struct-packed-align.c b/test/Sema/struct-packed-align.c
index 291de6762cd18354152c518b5b8d25de2afba121..417c30308ca3b0d6f268518d4c9f5a5d079c2458 100644
--- a/test/Sema/struct-packed-align.c
+++ b/test/Sema/struct-packed-align.c
@@ -55,13 +55,16 @@ struct __attribute__((aligned(8))) as1 {
 extern int e1[sizeof(struct as1) == 8 ? 1 : -1];
 extern int e2[__alignof(struct as1) == 8 ? 1 : -1];
 
-// FIXME: Will need to force arch once max usable alignment isn't hard
-// coded.
 struct __attribute__((aligned)) as1_2 {
     char c;
 };
+#ifdef __s390x__
+extern int e1_2[sizeof(struct as1_2) == 8 ? 1 : -1];
+extern int e2_2[__alignof(struct as1_2) == 8 ? 1 : -1];
+#else
 extern int e1_2[sizeof(struct as1_2) == 16 ? 1 : -1];
 extern int e2_2[__alignof(struct as1_2) == 16 ? 1 : -1];
+#endif
 
 struct as2 {
     char c;
diff --git a/utils/TableGen/ClangAttrEmitter.cpp b/utils/TableGen/ClangAttrEmitter.cpp
index c1d1a1dbe6d40ba328fd092c46ddf5b760634305..58857b91a9aa7de71a9bec8b65e0e274654cd1cc 100644
--- a/utils/TableGen/ClangAttrEmitter.cpp
+++ b/utils/TableGen/ClangAttrEmitter.cpp
@@ -413,15 +413,14 @@ namespace {
       // FIXME: Do not do the calculation here
       // FIXME: Handle types correctly
       // A null pointer means maximum alignment
-      // FIXME: Load the platform-specific maximum alignment, rather than
-      //        16, the x86 max.
       OS << "unsigned " << getAttrName() << "Attr::get" << getUpperName()
          << "(ASTContext &Ctx) const {\n";
       OS << "  assert(!is" << getUpperName() << "Dependent());\n";
       OS << "  if (is" << getLowerName() << "Expr)\n";
-      OS << "    return (" << getLowerName() << "Expr ? " << getLowerName()
-         << "Expr->EvaluateKnownConstInt(Ctx).getZExtValue() : 16)"
-         << "* Ctx.getCharWidth();\n";
+      OS << "    return " << getLowerName() << "Expr ? " << getLowerName()
+         << "Expr->EvaluateKnownConstInt(Ctx).getZExtValue()"
+         << " * Ctx.getCharWidth() : "
+         << "Ctx.getTargetDefaultAlignForAttributeAligned();\n";
       OS << "  else\n";
       OS << "    return 0; // FIXME\n";
       OS << "}\n";