diff --git a/include/clang/Basic/TargetInfo.h b/include/clang/Basic/TargetInfo.h
index 047872d..c7d221f 100644
--- a/include/clang/Basic/TargetInfo.h
+++ b/include/clang/Basic/TargetInfo.h
@@ -62,7 +62,8 @@ protected:
   unsigned char FloatWidth, FloatAlign;
   unsigned char DoubleWidth, DoubleAlign;
   unsigned char LongDoubleWidth, LongDoubleAlign;
-  unsigned char LargeArrayMinWidth, LargeArrayAlign;
+  unsigned char LargeArrayMinWidth;
+  unsigned short LargeArrayMaxAlign;
   unsigned char LongWidth, LongAlign;
   unsigned char LongLongWidth, LongLongAlign;
   unsigned char SuitableAlign;
@@ -334,10 +335,14 @@ public:
   /// \brief Return the value for the C99 FLT_EVAL_METHOD macro.
   virtual unsigned getFloatEvalMethod() const { return 0; }
 
-  // getLargeArrayMinWidth/Align - Return the minimum array size that is
-  // 'large' and its alignment.
+  // Return the minimum array size that is 'large'.
   unsigned getLargeArrayMinWidth() const { return LargeArrayMinWidth; }
-  unsigned getLargeArrayAlign() const { return LargeArrayAlign; }
+
+  // Return the alignment for a large array.
+  virtual unsigned getLargeArrayAlign(unsigned Size) const { return 0; }
+
+  // Return the maximum value that getLargeArrayAlign can return.
+  unsigned getLargeArrayMaxAlign() const { return LargeArrayMaxAlign; }
 
   /// \brief Return the maximum width lock-free atomic operation which will
   /// ever be supported for the given target
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 0d1dc4e..d0a54f8 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -1305,11 +1305,13 @@ CharUnits ASTContext::getDeclAlign(const Decl *D, bool ForAlignof) const {
       if (const ArrayType *arrayType = getAsArrayType(T)) {
         unsigned MinWidth = Target->getLargeArrayMinWidth();
         if (!ForAlignof && MinWidth) {
-          if (isa<VariableArrayType>(arrayType))
-            Align = std::max(Align, Target->getLargeArrayAlign());
-          else if (isa<ConstantArrayType>(arrayType) &&
-                   MinWidth <= getTypeSize(cast<ConstantArrayType>(arrayType)))
-            Align = std::max(Align, Target->getLargeArrayAlign());
+          if (isa<VariableArrayType>(arrayType)) {
+            Align = std::max(Align, Target->getLargeArrayMaxAlign());
+          } else if (isa<ConstantArrayType>(arrayType)) {
+            unsigned Size = getTypeSize(cast<ConstantArrayType>(arrayType));
+            if (MinWidth <= Size)
+              Align = std::max(Align, Target->getLargeArrayAlign(Size));
+          }
         }
 
         // Walk through any array types while we're at it.
diff --git a/lib/Basic/TargetInfo.cpp b/lib/Basic/TargetInfo.cpp
index e993055..2f8df13 100644
--- a/lib/Basic/TargetInfo.cpp
+++ b/lib/Basic/TargetInfo.cpp
@@ -46,7 +46,7 @@ TargetInfo::TargetInfo(const llvm::Triple &T) : TargetOpts(), Triple(T) {
   LongDoubleWidth = 64;
   LongDoubleAlign = 64;
   LargeArrayMinWidth = 0;
-  LargeArrayAlign = 0;
+  LargeArrayMaxAlign = 0;
   MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 0;
   MaxVectorAlign = 0;
   SizeType = UnsignedLong;
diff --git a/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp
index 8b35c9a..656bfc5 100644
--- a/lib/Basic/Targets.cpp
+++ b/lib/Basic/Targets.cpp
@@ -3234,7 +3234,7 @@ public:
     LongDoubleWidth = 128;
     LongDoubleAlign = 128;
     LargeArrayMinWidth = 128;
-    LargeArrayAlign = 128;
+    LargeArrayMaxAlign = 256;
     SuitableAlign = 128;
     IntMaxType = SignedLong;
     UIntMaxType = UnsignedLong;
@@ -3257,6 +3257,14 @@ public:
     MaxAtomicPromoteWidth = 128;
     MaxAtomicInlineWidth = 64;
   }
+
+  unsigned getLargeArrayAlign(unsigned Size) const LLVM_OVERRIDE {
+    if (Size >= 256)
+      return 256;
+    assert(Size >= 128);
+    return 128;
+  }
+
   virtual BuiltinVaListKind getBuiltinVaListKind() const {
     return TargetInfo::X86_64ABIBuiltinVaList;
   }
diff --git a/test/CodeGen/align-x68_64.c b/test/CodeGen/align-x68_64.c
index cf128b4..648731e 100644
--- a/test/CodeGen/align-x68_64.c
+++ b/test/CodeGen/align-x68_64.c
@@ -7,5 +7,23 @@ void test1_g(void) {
   float x[4];
   test1_f(x);
 }
-// CHECK: @test1_g
+// CHECK-LABEL: define void @test1_g
 // CHECK: alloca [4 x float], align 16
+
+//PR17998
+
+void test2_f(char *);
+
+void test2_g(void) {
+  char x[32];
+  test2_f(x);
+}
+// CHECK-LABEL: define void @test2_g
+// CHECK: alloca [32 x i8], align 32
+
+void test3_g(int n) {
+  char x[n];
+  test2_f(x);
+}
+// CHECK-LABEL: define void @test3_g
+// CHECK: alloca i8, {{.*}}, align 32
diff --git a/test/CodeGenObjC/arc.m b/test/CodeGenObjC/arc.m
index 00cdb6f..5fb6090 100644
--- a/test/CodeGenObjC/arc.m
+++ b/test/CodeGenObjC/arc.m
@@ -459,10 +459,10 @@ void test13(void) {
 
 void test19() {
   // CHECK-LABEL: define void @test19()
-  // CHECK:      [[X:%.*]] = alloca [5 x i8*], align 16
+  // CHECK:      [[X:%.*]] = alloca [5 x i8*], align 32
   // CHECK: call void @llvm.lifetime.start
   // CHECK-NEXT: [[T0:%.*]] = bitcast [5 x i8*]* [[X]] to i8*
-  // CHECK: call void @llvm.memset.p0i8.i64(i8* [[T0]], i8 0, i64 40, i32 16, i1 false)
+  // CHECK: call void @llvm.memset.p0i8.i64(i8* [[T0]], i8 0, i64 40, i32 32, i1 false)
   id x[5];
 
   extern id test19_helper(void);
@@ -506,7 +506,7 @@ void test20(unsigned n) {
   // CHECK-NEXT: store i8* [[T0]], i8** [[SAVED_STACK]]
 
   // Allocate the VLA.
-  // CHECK-NEXT: [[VLA:%.*]] = alloca i8*, i64 [[DIM]], align 16
+  // CHECK-NEXT: [[VLA:%.*]] = alloca i8*, i64 [[DIM]], align 32
 
   // Zero-initialize.
   // CHECK-NEXT: [[T0:%.*]] = bitcast i8** [[VLA]] to i8*
@@ -548,7 +548,7 @@ void test21(unsigned n) {
 
   // Allocate the VLA.
   // CHECK-NEXT: [[T0:%.*]] = mul nuw i64 2, [[DIM]]
-  // CHECK-NEXT: [[VLA:%.*]] = alloca [3 x i8*], i64 [[T0]], align 16
+  // CHECK-NEXT: [[VLA:%.*]] = alloca [3 x i8*], i64 [[T0]], align 32
 
   // Zero-initialize.
   // CHECK-NEXT: [[T0:%.*]] = bitcast [3 x i8*]* [[VLA]] to i8*
diff --git a/test/CodeGenObjC/tentative-cfconstantstring.m b/test/CodeGenObjC/tentative-cfconstantstring.m
index 714c1a4..2486d9b 100644
--- a/test/CodeGenObjC/tentative-cfconstantstring.m
+++ b/test/CodeGenObjC/tentative-cfconstantstring.m
@@ -31,7 +31,7 @@ static inline void _inlineFunction() {
 }
 @end
 
-// CHECK: @__CFConstantStringClassReference = common global [24 x i32] zeroinitializer, align 16
+// CHECK: @__CFConstantStringClassReference = common global [24 x i32] zeroinitializer, align 32
 // CHECK: @_unnamed_cfstring_{{.*}} = private constant %struct.NSConstantString { i32* getelementptr inbounds ([24 x i32]* @__CFConstantStringClassReference, i32 0, i32 0)
 
 // CHECK-LABEL: define internal void @_inlineFunction()
