Index: test/Preprocessor/init.c
===================================================================
--- test/Preprocessor/init.c	(revision 192701)
+++ test/Preprocessor/init.c	(working copy)
@@ -406,6 +406,7 @@
 // ARMEABISOFTFP:#define __WINT_WIDTH__ 32
 // ARMEABISOFTFP:#define __arm 1
 // ARMEABISOFTFP:#define __arm__ 1
+// ARMEABISOFTFP-NOT:#define __ARM_ARCH_EXT_IDIV__
 
 // RUN: %clang_cc1 -E -dM -ffreestanding -triple=arm-none-linux-gnueabi < /dev/null | FileCheck -check-prefix ARMEABIHARDFP %s
 //
@@ -511,7 +512,28 @@
 // ARMEABIHARDFP:#define __WINT_WIDTH__ 32
 // ARMEABIHARDFP:#define __arm 1
 // ARMEABIHARDFP:#define __arm__ 1
+// ARMEABIHARDFP-NOT:#define __ARM_ARCH_EXT_IDIV__
 
+// Check that -mhwdiv works properly for targets which don't have the hwdiv feature enabled by default.
+
+// RUN: %clang -target arm -mhwdiv=arm -x c -E -dM %s -o - | FileCheck --check-prefix=ARMHWDIV-ARM %s
+// ARMHWDIV-ARM:#define __ARM_ARCH_EXT_IDIV__ 1
+
+// RUN: %clang -target arm -mthumb -mhwdiv=thumb -x c -E -dM %s -o - | FileCheck --check-prefix=THUMBHWDIV-THUMB %s
+// THUMBHWDIV-THUMB:#define __ARM_ARCH_EXT_IDIV__ 1
+
+// RUN: %clang -target arm -x c -E -dM %s -o - | FileCheck --check-prefix=ARM-FALSE %s
+// ARM-FALSE-NOT:#define __ARM_ARCH_EXT_IDIV__
+
+// RUN: %clang -target arm -mthumb -x c -E -dM %s -o - | FileCheck --check-prefix=THUMB-FALSE %s
+// THUMB-FALSE-NOT:#define __ARM_ARCH_EXT_IDIV__
+
+// RUN: %clang -target arm -mhwdiv=thumb -x c -E -dM %s -o - | FileCheck --check-prefix=THUMBHWDIV-ARM-FALSE %s
+// THUMBHWDIV-ARM-FALSE-NOT:#define __ARM_ARCH_EXT_IDIV__
+
+// RUN: %clang -target arm -mthumb -mhwdiv=arm -x c -E -dM %s -o - | FileCheck --check-prefix=ARMHWDIV-THUMB-FALSE %s
+// ARMHWDIV-THUMB-FALSE-NOT:#define __ARM_ARCH_EXT_IDIV__
+
 //
 // RUN: %clang_cc1 -E -dM -ffreestanding -triple=i386-none-none < /dev/null | FileCheck -check-prefix I386 %s
 //
Index: test/Driver/arm-hwdiv.c
===================================================================
--- test/Driver/arm-hwdiv.c	(revision 0)
+++ test/Driver/arm-hwdiv.c	(revision 0)
@@ -0,0 +1,39 @@
+// Test that different values of -mhwdiv pick correct ARM hwdiv target-feature(s).
+
+// RUN: %clang -### -target arm %s -o %t.o 2>&1 \
+// RUN:   | FileCheck --check-prefix=CHECK-DEFAULT %s
+// CHECK-DEFAULT-NOT: "-target-feature" "+hwdiv"
+// CHECK-DEFAULT-NOT: "-target-feature" "+hwdiv-arm"
+
+// RUN: %clang -### -target arm %s -mhwdiv=arm -o %t.o 2>&1 \
+// RUN:   | FileCheck --check-prefix=CHECK-ARM %s
+// CHECK-ARM: "-target-feature" "+hwdiv-arm"
+// CHECK-ARM: "-target-feature" "-hwdiv"
+
+// RUN: %clang -### -target arm %s -mhwdiv=thumb -o %t.o 2>&1 \
+// RUN:   | FileCheck --check-prefix=CHECK-THUMB %s
+// CHECK-THUMB: "-target-feature" "-hwdiv-arm"
+// CHECK-THUMB: "-target-feature" "+hwdiv"
+
+// RUN: %clang  -### -target arm %s -mhwdiv=arm,thumb -o %t.o 2>&1 \
+// RUN:   | FileCheck --check-prefix=CHECK-ARM-THUMB %s
+// CHECK-ARM-THUMB: "-target-feature" "+hwdiv-arm"
+// CHECK-ARM-THUMB: "-target-feature" "+hwdiv"
+
+// RUN: %clang  -### -target arm %s -mhwdiv=thumb,arm -o %t.o 2>&1 \
+// RUN:   | FileCheck --check-prefix=CHECK-THUMB-ARM %s
+// CHECK-THUMB-ARM: "-target-feature" "+hwdiv-arm"
+// CHECK-THUMB-ARM: "-target-feature" "+hwdiv"
+
+// RUN: %clang -### -target arm %s -mhwdiv=none -o %t.o 2>&1 \
+// RUN:   | FileCheck --check-prefix=CHECK-NONE %s
+// CHECK-NONE: "-target-feature" "-hwdiv-arm"
+// CHECK-NONE: "-target-feature" "-hwdiv"
+
+// Also check the alternative syntax.
+
+// RUN: %clang -### -target arm %s --mhwdiv arm -o %t.o 2>&1 \
+// RUN:   | FileCheck --check-prefix=CHECK-ALT %s
+// CHECK-ALT: "-target-feature" "+hwdiv-arm"
+// CHECK-ALT: "-target-feature" "-hwdiv"
+
Index: include/clang/Driver/Options.td
===================================================================
--- include/clang/Driver/Options.td	(revision 192701)
+++ include/clang/Driver/Options.td	(working copy)
@@ -956,6 +956,7 @@
 def mfloat_abi_EQ : Joined<["-"], "mfloat-abi=">, Group<m_Group>;
 def mfpmath_EQ : Joined<["-"], "mfpmath=">, Group<m_Group>;
 def mfpu_EQ : Joined<["-"], "mfpu=">, Group<m_Group>;
+def mhwdiv_EQ : Joined<["-"], "mhwdiv=">, Group<m_Group>;
 def mglobal_merge : Flag<["-"], "mglobal-merge">, Group<m_Group>;
 def mhard_float : Flag<["-"], "mhard-float">, Group<m_Group>;
 def miphoneos_version_min_EQ : Joined<["-"], "miphoneos-version-min=">, Group<m_Group>;
@@ -1264,6 +1265,7 @@
 // Double dash options, which are usually an alias for one of the previous
 // options.
 
+def _mhwdiv_EQ : Separate<["--"], "mhwdiv">, Alias<mhwdiv_EQ>;
 def _CLASSPATH_EQ : Joined<["--"], "CLASSPATH=">, Alias<fclasspath_EQ>;
 def _CLASSPATH : Separate<["--"], "CLASSPATH">, Alias<fclasspath_EQ>;
 def _all_warnings : Flag<["--"], "all-warnings">, Alias<Wall>;
Index: docs/UsersManual.rst
===================================================================
--- docs/UsersManual.rst	(revision 192701)
+++ docs/UsersManual.rst	(working copy)
@@ -1045,6 +1045,17 @@
    efficient model can be used. The TLS model can be overridden per
    variable using the ``tls_model`` attribute.
 
+.. option:: -mhwdiv=[values]
+
+   Select the ARM modes (arm or thumb) that support hardware division
+   instructions.
+
+   Valid values are: ``arm``, ``thumb`` and ``arm,thumb``.
+   This option is used to indicate which mode (arm or thumb) supports
+   hardware division instructions. This only applies to the ARM
+   architecture.
+
+
 Controlling Size of Debug Information
 -------------------------------------
 
Index: lib/Basic/Targets.cpp
===================================================================
--- lib/Basic/Targets.cpp	(revision 192701)
+++ lib/Basic/Targets.cpp	(working copy)
@@ -3556,6 +3556,12 @@
     NeonFPU = (1 << 3)
   };
 
+  // Possible HWDiv features.
+  enum HWDivMode {
+    HWDivThumb = (1 << 0),
+    HWDivARM = (1 << 1)
+  };
+
   static bool FPUModeIsVFP(FPUMode Mode) {
     return Mode & (VFP2FPU | VFP3FPU | VFP4FPU | NeonFPU);
   }
@@ -3575,6 +3581,7 @@
 
   unsigned IsAAPCS : 1;
   unsigned IsThumb : 1;
+  unsigned HWDiv : 2;
 
   // Initialized via features.
   unsigned SoftFloat : 1;
@@ -3727,6 +3746,7 @@
                                     DiagnosticsEngine &Diags) {
     FPU = 0;
     SoftFloat = SoftFloatABI = false;
+    HWDiv = 0;
     for (unsigned i = 0, e = Features.size(); i != e; ++i) {
       if (Features[i] == "+soft-float")
         SoftFloat = true;
@@ -3740,6 +3760,10 @@
         FPU |= VFP4FPU;
       else if (Features[i] == "+neon")
         FPU |= NeonFPU;
+      else if (Features[i] == "+hwdiv")
+        HWDiv |= HWDivThumb;
+      else if (Features[i] == "+hwdiv-arm")
+        HWDiv |= HWDivARM;
     }
 
     if (!(FPU & NeonFPU) && FPMath == FP_Neon) {
@@ -3769,6 +3793,8 @@
         .Case("softfloat", SoftFloat)
         .Case("thumb", IsThumb)
         .Case("neon", (FPU & NeonFPU) && !SoftFloat)
+        .Case("hwdiv", HWDiv & HWDivThumb)
+        .Case("hwdiv-arm", HWDiv & HWDivARM)
         .Default(false);
   }
   // FIXME: Should we actually have some table instead of these switches?
@@ -3862,6 +3888,8 @@
       if (CPUArch == "6T2" || IsARMv7)
         Builder.defineMacro("__thumb2__");
     }
+    if (((HWDiv & HWDivThumb) && IsThumb) || ((HWDiv & HWDivARM) && !IsThumb))
+      Builder.defineMacro("__ARM_ARCH_EXT_IDIV__", "1");
 
     // Note, this is always on in gcc, even though it doesn't make sense.
     Builder.defineMacro("__APCS_32__");
Index: lib/Driver/Tools.cpp
===================================================================
--- lib/Driver/Tools.cpp	(revision 192701)
+++ lib/Driver/Tools.cpp	(working copy)
@@ -596,6 +596,27 @@
     D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args);
 }
 
+// Handle -mhwdiv=.
+static void getARMHWDivFeatures(const Driver &D, const Arg *A,
+                              const ArgList &Args,
+                              std::vector<const char *> &Features) {
+  StringRef HWDiv = A->getValue();
+  if (HWDiv == "arm") {
+    Features.push_back("+hwdiv-arm");
+    Features.push_back("-hwdiv");
+  } else if (HWDiv == "thumb") {
+    Features.push_back("-hwdiv-arm");
+    Features.push_back("+hwdiv");
+  } else if (HWDiv == "arm,thumb" || HWDiv == "thumb,arm") {
+    Features.push_back("+hwdiv-arm");
+    Features.push_back("+hwdiv");
+  } else if (HWDiv == "none") {
+    Features.push_back("-hwdiv-arm");
+    Features.push_back("-hwdiv");
+  } else
+    D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args);
+}
+ 
 // Handle -mfpu=.
 //
 // FIXME: Centralize feature selection, defaulting shouldn't be also in the
@@ -740,6 +761,8 @@
   // Honor -mfpu=.
   if (const Arg *A = Args.getLastArg(options::OPT_mfpu_EQ))
     getARMFPUFeatures(D, A, Args, Features);
+  if (const Arg *A = Args.getLastArg(options::OPT_mhwdiv_EQ))
+    getARMHWDivFeatures(D, A, Args, Features);
 
   // Setting -msoft-float effectively disables NEON because of the GCC
   // implementation, although the same isn't true of VFP or VFP3.
