diff --git a/docs/tools/clang.pod b/docs/tools/clang.pod
index 8f61568..425a91e 100644
--- a/docs/tools/clang.pod
+++ b/docs/tools/clang.pod
@@ -303,6 +303,14 @@ This flag sets the default visibility level.
 This flag specifies that variables without initializers get common linkage.  It
 can be disabled with B<-fno-common>.
 
+=item B<-ftls-model>
+
+Set the default thread-local storage (TLS) model to use for thread-local
+variables. Valid values are: "global-dynamic", "local-dynamic", "initial-exec"
+and "local-exec". The default is "global-dynamic". The default model can be
+overridden with the tls_model attribute. The compiler will try to choose a more
+efficient model if possible.
+
 =item B<-flto> B<-emit-llvm>
 
 Generate output files in LLVM formats, suitable for link time optimization. When
diff --git a/include/clang/Basic/LangOptions.def b/include/clang/Basic/LangOptions.def
index b525e43..7f653ca 100644
--- a/include/clang/Basic/LangOptions.def
+++ b/include/clang/Basic/LangOptions.def
@@ -144,6 +144,8 @@ LANGOPT(BlocksRuntimeOptional , 1, 0, "optional blocks runtime")
 ENUM_LANGOPT(GC, GCMode, 2, NonGC, "Objective-C Garbage Collection mode")
 ENUM_LANGOPT(VisibilityMode, Visibility, 3, DefaultVisibility, 
              "symbol visibility")
+BENIGN_ENUM_LANGOPT(DefaultTLSModel, TLSModel, 2, GeneralDynamicTLSModel,
+                    "default TLS model")
 ENUM_LANGOPT(StackProtector, StackProtectorMode, 2, SSPOff, 
              "stack protector mode")
 ENUM_LANGOPT(SignedOverflowBehavior, SignedOverflowBehaviorTy, 2, SOB_Undefined,
diff --git a/include/clang/Basic/LangOptions.h b/include/clang/Basic/LangOptions.h
index 9c3b011..dd24a05 100644
--- a/include/clang/Basic/LangOptions.h
+++ b/include/clang/Basic/LangOptions.h
@@ -55,6 +55,13 @@ public:
     SOB_Trapping    // -ftrapv
   };
 
+  enum TLSModel {
+    GeneralDynamicTLSModel,
+    LocalDynamicTLSModel,
+    InitialExecTLSModel,
+    LocalExecTLSModel
+  };
+
 public:
   clang::ObjCRuntime ObjCRuntime;
 
diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td
index da22046..e16acce 100644
--- a/include/clang/Driver/CC1Options.td
+++ b/include/clang/Driver/CC1Options.td
@@ -408,6 +408,8 @@ def static_define : Flag<"-static-define">,
   HelpText<"Should __STATIC__ be defined">;
 def stack_protector : Separate<"-stack-protector">,
   HelpText<"Enable stack protectors">;
+def ftlsmodel : Separate<"-ftls-model">,
+  HelpText<"Default TLS model">;
 def fvisibility : Separate<"-fvisibility">,
   HelpText<"Default symbol visibility">;
 def ftemplate_depth : Separate<"-ftemplate-depth">,
diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td
index b6d352a..20731c7 100644
--- a/include/clang/Driver/Options.td
+++ b/include/clang/Driver/Options.td
@@ -642,6 +642,7 @@ def Wframe_larger_than_EQ : Joined<"-Wframe-larger-than=">, Alias<Wframe_larger_
 def fterminated_vtables : Flag<"-fterminated-vtables">, Alias<fapple_kext>;
 def fthreadsafe_statics : Flag<"-fthreadsafe-statics">, Group<f_Group>;
 def ftime_report : Flag<"-ftime-report">, Group<f_Group>, Flags<[CC1Option]>;
+def ftlsmodel_EQ : Joined<"-ftls-model=">, Group<f_Group>;
 def ftrapv : Flag<"-ftrapv">, Group<f_Group>, Flags<[CC1Option]>,
   HelpText<"Trap on integer overflow">;
 def ftrapv_handler_EQ : Joined<"-ftrapv-handler=">, Group<f_Group>,
diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp
index 08a9382..64a9e09 100644
--- a/lib/CodeGen/CGDecl.cpp
+++ b/lib/CodeGen/CGDecl.cpp
@@ -183,26 +183,20 @@ CodeGenFunction::CreateStaticVarDecl(const VarDecl &D,
   else
     Name = GetStaticDeclName(*this, D, Separator);
 
-  llvm::GlobalVariable::ThreadLocalMode TLM;
-  TLM = D.isThreadSpecified() ? llvm::GlobalVariable::GeneralDynamicTLSModel
-                              : llvm::GlobalVariable::NotThreadLocal;
-
-  // Set the TLS mode if it it's explicitly specified.
-  if (D.hasAttr<TLSModelAttr>()) {
-    assert(D.isThreadSpecified() && "Can't have TLS model on non-tls var.");
-    const TLSModelAttr *Attr = D.getAttr<TLSModelAttr>();
-    TLM = CodeGenModule::GetLLVMTLSModel(Attr->getModel());
-  }
-
   llvm::Type *LTy = CGM.getTypes().ConvertTypeForMem(Ty);
   llvm::GlobalVariable *GV =
     new llvm::GlobalVariable(CGM.getModule(), LTy,
                              Ty.isConstant(getContext()), Linkage,
-                             CGM.EmitNullConstant(D.getType()), Name, 0, TLM,
+                             CGM.EmitNullConstant(D.getType()), Name, 0,
+                             llvm::GlobalVariable::NotThreadLocal,
                              CGM.getContext().getTargetAddressSpace(Ty));
   GV->setAlignment(getContext().getDeclAlign(&D).getQuantity());
   if (Linkage != llvm::GlobalValue::InternalLinkage)
     GV->setVisibility(CurFn->getVisibility());
+
+  if (D.isThreadSpecified())
+    CodeGenModule::setTLSMode(GV, D);
+
   return GV;
 }
 
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp
index 8c1588b..bee0772 100644
--- a/lib/CodeGen/CodeGenModule.cpp
+++ b/lib/CodeGen/CodeGenModule.cpp
@@ -258,6 +258,45 @@ void CodeGenModule::setGlobalVisibility(llvm::GlobalValue *GV,
     GV->setVisibility(GetLLVMVisibility(LV.visibility()));
 }
 
+static llvm::GlobalVariable::ThreadLocalMode GetLLVMTLSModel(StringRef S) {
+  return llvm::StringSwitch<llvm::GlobalVariable::ThreadLocalMode>(S)
+      .Case("global-dynamic", llvm::GlobalVariable::GeneralDynamicTLSModel)
+      .Case("local-dynamic", llvm::GlobalVariable::LocalDynamicTLSModel)
+      .Case("initial-exec", llvm::GlobalVariable::InitialExecTLSModel)
+      .Case("local-exec", llvm::GlobalVariable::LocalExecTLSModel)
+      .Default(llvm::GlobalVariable::NotThreadLocal);
+}
+
+static llvm::GlobalVariable::ThreadLocalMode GetLLVMTLSModel(
+    LangOptions::TLSModel M) {
+  switch (M) {
+  case LangOptions::GeneralDynamicTLSModel:
+    return llvm::GlobalVariable::GeneralDynamicTLSModel;
+  case LangOptions::LocalDynamicTLSModel:
+    return llvm::GlobalVariable::LocalDynamicTLSModel;
+  case LangOptions::InitialExecTLSModel:
+    return llvm::GlobalVariable::InitialExecTLSModel;
+  case LangOptions::LocalExecTLSModel:
+    return llvm::GlobalVariable::LocalExecTLSModel;
+  }
+  llvm_unreachable("Invalid TLS model!");
+}
+
+void CodeGenModule::setTLSMode(llvm::GlobalVariable* GV, const VarDecl &D) {
+  assert(D.isThreadSpecified() && "setting TLS mode on non-TLS var!");
+
+  llvm::GlobalVariable::ThreadLocalMode TLM;
+  TLM = GetLLVMTLSModel(D.getASTContext().getLangOpts().getDefaultTLSModel());
+
+  // Override the TLS mode if it it's explicitly specified.
+  if (D.hasAttr<TLSModelAttr>()) {
+    const TLSModelAttr *Attr = D.getAttr<TLSModelAttr>();
+    TLM = GetLLVMTLSModel(Attr->getModel());
+  }
+
+  GV->setThreadLocalMode(TLM);
+}
+
 /// Set the symbol visibility of type information (vtable and RTTI)
 /// associated with the given type.
 void CodeGenModule::setTypeVisibility(llvm::GlobalValue *GV,
@@ -1210,13 +1249,8 @@ CodeGenModule::GetOrCreateLLVMGlobal(StringRef MangledName,
         GV->setVisibility(GetLLVMVisibility(LV.visibility()));
     }
 
-    GV->setThreadLocal(D->isThreadSpecified());
-
-    // Set the TLS model if it it's explicitly specified.
-    if (D->hasAttr<TLSModelAttr>()) {
-      const TLSModelAttr *Attr = D->getAttr<TLSModelAttr>();
-      GV->setThreadLocalMode(GetLLVMTLSModel(Attr->getModel()));
-    }
+    if (D->isThreadSpecified())
+      setTLSMode(GV, *D);
   }
 
   if (AddrSpace != Ty->getAddressSpace())
diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h
index d1ecfec..8471c65 100644
--- a/lib/CodeGen/CodeGenModule.h
+++ b/lib/CodeGen/CodeGenModule.h
@@ -472,6 +472,10 @@ public:
   /// GlobalValue.
   void setGlobalVisibility(llvm::GlobalValue *GV, const NamedDecl *D) const;
 
+  /// setTLSMode - Set the TLS mode for the given LLVM GlobalVariable
+  /// for the thread-local variable declaration D.
+  static void setTLSMode(llvm::GlobalVariable* GV, const VarDecl &D);
+
   /// TypeVisibilityKind - The kind of global variable that is passed to 
   /// setTypeVisibility
   enum TypeVisibilityKind {
@@ -496,15 +500,6 @@ public:
     llvm_unreachable("unknown visibility!");
   }
 
-  static llvm::GlobalVariable::ThreadLocalMode GetLLVMTLSModel(StringRef S) {
-    return llvm::StringSwitch<llvm::GlobalVariable::ThreadLocalMode>(S)
-        .Case("global-dynamic", llvm::GlobalVariable::GeneralDynamicTLSModel)
-        .Case("local-dynamic", llvm::GlobalVariable::LocalDynamicTLSModel)
-        .Case("initial-exec", llvm::GlobalVariable::InitialExecTLSModel)
-        .Case("local-exec", llvm::GlobalVariable::LocalExecTLSModel)
-        .Default(llvm::GlobalVariable::NotThreadLocal);
-  }
-
   llvm::Constant *GetAddrOfGlobal(GlobalDecl GD) {
     if (isa<CXXConstructorDecl>(GD.getDecl()))
       return GetAddrOfCXXConstructor(cast<CXXConstructorDecl>(GD.getDecl()),
diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp
index 27a222a..45eb00c 100644
--- a/lib/Driver/Tools.cpp
+++ b/lib/Driver/Tools.cpp
@@ -2188,6 +2188,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
     CmdArgs.push_back(A->getValue(Args));
   }
 
+  if (const Arg *A = Args.getLastArg(options::OPT_ftlsmodel_EQ)) {
+    CmdArgs.push_back("-ftls-model");
+    CmdArgs.push_back(A->getValue(Args));
+  }
+
   Args.AddLastArg(CmdArgs, options::OPT_fvisibility_inlines_hidden);
 
   // -fhosted is default.
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index 8a95c80..a9883ba 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -788,7 +788,19 @@ static void LangOptsToArgs(const LangOptions &Opts, ToArgsList &Res) {
   
   if (Opts.AppleKext)
     Res.push_back("-fapple-kext");
-  
+
+  if (Opts.getDefaultTLSModel() != LangOptions::GeneralDynamicTLSModel) {
+    Res.push_back("-ftls-model");
+    if (Opts.getDefaultTLSModel() == LangOptions::LocalDynamicTLSModel)
+      Res.push_back("local-dynamic");
+    else if (Opts.getDefaultTLSModel() == LangOptions::InitialExecTLSModel)
+      Res.push_back("initial-exec");
+    else if (Opts.getDefaultTLSModel() == LangOptions::LocalExecTLSModel)
+      Res.push_back("local-exec");
+    else
+      llvm_unreachable("Invalid TLS model!");
+  }
+
   if (Opts.getVisibilityMode() != DefaultVisibility) {
     Res.push_back("-fvisibility");
     if (Opts.getVisibilityMode() == HiddenVisibility) {
@@ -1934,6 +1946,19 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
   if (Args.hasArg(OPT_fvisibility_inlines_hidden))
     Opts.InlineVisibilityHidden = 1;
 
+  StringRef Model = Args.getLastArgValue(OPT_ftlsmodel, "global-dynamic");
+  if (Model == "global-dynamic")
+    Opts.setDefaultTLSModel(LangOptions::GeneralDynamicTLSModel);
+  else if (Model == "local-dynamic")
+    Opts.setDefaultTLSModel(LangOptions::LocalDynamicTLSModel);
+  else if (Model == "initial-exec")
+    Opts.setDefaultTLSModel(LangOptions::InitialExecTLSModel);
+  else if (Model == "local-exec")
+    Opts.setDefaultTLSModel(LangOptions::LocalExecTLSModel);
+  else
+    Diags.Report(diag::err_drv_invalid_value)
+        << Args.getLastArg(OPT_ftlsmodel)->getAsString(Args) << Model;
+
   if (Args.hasArg(OPT_ftrapv)) {
     Opts.setSignedOverflowBehavior(LangOptions::SOB_Trapping);
     // Set the handler, if one is specified.
diff --git a/test/CodeGen/tls-model.c b/test/CodeGen/tls-model.c
new file mode 100644
index 0000000..f3767d9
--- /dev/null
+++ b/test/CodeGen/tls-model.c
@@ -0,0 +1,28 @@
+// RUN: %clang_cc1 %s -triple x86_64-pc-linux-gnu -emit-llvm -o - | FileCheck %s -check-prefix=CHECK-GD
+// RUN: %clang_cc1 %s -triple x86_64-pc-linux-gnu -ftls-model global-dynamic -emit-llvm -o - | FileCheck %s -check-prefix=CHECK-GD
+// RUN: %clang_cc1 %s -triple x86_64-pc-linux-gnu -ftls-model local-dynamic -emit-llvm -o - | FileCheck %s -check-prefix=CHECK-LD
+// RUN: %clang_cc1 %s -triple x86_64-pc-linux-gnu -ftls-model initial-exec -emit-llvm -o - | FileCheck %s -check-prefix=CHECK-IE
+// RUN: %clang_cc1 %s -triple x86_64-pc-linux-gnu -ftls-model local-exec -emit-llvm -o - | FileCheck %s -check-prefix=CHECK-LE
+
+int __thread x;
+int f() {
+  static int __thread y;
+  return y++;
+}
+int __thread __attribute__((tls_model("initial-exec"))) z;
+
+// CHECK-GD: @f.y = internal thread_local global i32 0
+// CHECK-GD: @x = thread_local global i32 0
+// CHECK-GD: @z = thread_local(initialexec) global i32 0
+
+// CHECK-LD: @f.y = internal thread_local(localdynamic) global i32 0
+// CHECK-LD: @x = thread_local(localdynamic) global i32 0
+// CHECK-LD: @z = thread_local(initialexec) global i32 0
+
+// CHECK-IE: @f.y = internal thread_local(initialexec) global i32 0
+// CHECK-IE: @x = thread_local(initialexec) global i32 0
+// CHECK-IE: @z = thread_local(initialexec) global i32 0
+
+// CHECK-LE: @f.y = internal thread_local(localexec) global i32 0
+// CHECK-LE: @x = thread_local(localexec) global i32 0
+// CHECK-LE: @z = thread_local(initialexec) global i32 0
