Index: clang/docs/ClangCommandLineReference.rst
===================================================================
--- clang/docs/ClangCommandLineReference.rst
+++ clang/docs/ClangCommandLineReference.rst
@@ -2292,6 +2292,14 @@
 
 AARCH64
 -------
+.. option:: -ffixed-x16
+
+Reserve the x16 register (AArch64 only)
+
+.. option:: -ffixed-x17
+
+Reserve the x17 register (AArch64 only)
+
 .. option:: -ffixed-x18
 
 Reserve the x18 register (AArch64 only)
Index: clang/include/clang/Driver/Options.td
===================================================================
--- clang/include/clang/Driver/Options.td
+++ clang/include/clang/Driver/Options.td
@@ -1959,6 +1959,10 @@
 def mno_fix_cortex_a53_835769 : Flag<["-"], "mno-fix-cortex-a53-835769">,
   Group<m_aarch64_Features_Group>,
   HelpText<"Don't workaround Cortex-A53 erratum 835769 (AArch64 only)">;
+def ffixed_x16 : Flag<["-"], "ffixed-x16">, Group<m_aarch64_Features_Group>,
+  HelpText<"Reserve the x16 register (AArch64 only)">;
+def ffixed_x17 : Flag<["-"], "ffixed-x17">, Group<m_aarch64_Features_Group>,
+  HelpText<"Reserve the x17 register (AArch64 only)">;
 def ffixed_x18 : Flag<["-"], "ffixed-x18">, Group<m_aarch64_Features_Group>,
   HelpText<"Reserve the x18 register (AArch64 only)">;
 
Index: clang/lib/Driver/ToolChains/Arch/AArch64.cpp
===================================================================
--- clang/lib/Driver/ToolChains/Arch/AArch64.cpp
+++ clang/lib/Driver/ToolChains/Arch/AArch64.cpp
@@ -195,6 +195,12 @@
     if (A->getOption().matches(options::OPT_mno_unaligned_access))
       Features.push_back("+strict-align");
 
+  if (Args.hasArg(options::OPT_ffixed_x16))
+    Features.push_back("+reserve-x16");
+
+  if (Args.hasArg(options::OPT_ffixed_x17))
+    Features.push_back("+reserve-x17");
+
   if (Args.hasArg(options::OPT_ffixed_x18))
     Features.push_back("+reserve-x18");
 
Index: clang/test/Driver/aarch64-fixed-x16.c
===================================================================
--- /dev/null
+++ clang/test/Driver/aarch64-fixed-x16.c
@@ -0,0 +1,4 @@
+// RUN: %clang -target aarch64-none-gnu -ffixed-x16 -### %s 2> %t
+// RUN: FileCheck --check-prefix=CHECK-FIXED-X16 < %t %s
+
+// CHECK-FIXED-X16: "-target-feature" "+reserve-x16"
Index: clang/test/Driver/aarch64-fixed-x17.c
===================================================================
--- /dev/null
+++ clang/test/Driver/aarch64-fixed-x17.c
@@ -0,0 +1,4 @@
+// RUN: %clang -target aarch64-none-gnu -ffixed-x17 -### %s 2> %t
+// RUN: FileCheck --check-prefix=CHECK-FIXED-X17 < %t %s
+
+// CHECK-FIXED-X17: "-target-feature" "+reserve-x17"
Index: llvm/lib/Target/AArch64/AArch64.td
===================================================================
--- llvm/lib/Target/AArch64/AArch64.td
+++ llvm/lib/Target/AArch64/AArch64.td
@@ -72,6 +72,14 @@
                                           "Disallow all unaligned memory "
                                           "access">;
 
+def FeatureReserveX16 : SubtargetFeature<"reserve-x16", "ReserveX16", "true",
+                                         "Reserve X16, making it unavailable "
+                                         "as a GPR">;
+
+def FeatureReserveX17 : SubtargetFeature<"reserve-x17", "ReserveX17", "true",
+                                         "Reserve X17, making it unavailable "
+                                         "as a GPR">;
+
 def FeatureReserveX18 : SubtargetFeature<"reserve-x18", "ReserveX18", "true",
                                          "Reserve X18, making it unavailable "
                                          "as a GPR">;
Index: llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
===================================================================
--- llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -4851,11 +4851,19 @@
                                                   SelectionDAG &DAG) const {
   unsigned Reg = StringSwitch<unsigned>(RegName)
                        .Case("sp", AArch64::SP)
+                       .Case("x16", AArch64::X16)
+                       .Case("w16", AArch64::W16)
+                       .Case("x17", AArch64::X17)
+                       .Case("w17", AArch64::W17)
                        .Case("x18", AArch64::X18)
                        .Case("w18", AArch64::W18)
                        .Default(0);
-  if ((Reg == AArch64::X18 || Reg == AArch64::W18) &&
-      !Subtarget->isX18Reserved())
+  if (((Reg == AArch64::X16 || Reg == AArch64::W16) &&
+      !Subtarget->isX16Reserved()) ||
+      ((Reg == AArch64::X17 || Reg == AArch64::W17) &&
+      !Subtarget->isX17Reserved()) ||
+      ((Reg == AArch64::X18 || Reg == AArch64::W18) &&
+      !Subtarget->isX18Reserved()))
     Reg = 0;
   if (Reg)
     return Reg;
Index: llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp
===================================================================
--- llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp
+++ llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp
@@ -134,6 +134,12 @@
   if (TFI->hasFP(MF) || TT.isOSDarwin())
     markSuperRegs(Reserved, AArch64::W29);
 
+  if (MF.getSubtarget<AArch64Subtarget>().isX16Reserved())
+    markSuperRegs(Reserved, AArch64::W16); // Platform register
+
+  if (MF.getSubtarget<AArch64Subtarget>().isX17Reserved())
+    markSuperRegs(Reserved, AArch64::W17); // Platform register
+
   if (MF.getSubtarget<AArch64Subtarget>().isX18Reserved())
     markSuperRegs(Reserved, AArch64::W18); // Platform register
 
@@ -156,6 +162,12 @@
   case AArch64::WSP:
   case AArch64::WZR:
     return true;
+  case AArch64::X16:
+  case AArch64::W16:
+    return MF.getSubtarget<AArch64Subtarget>().isX16Reserved();
+  case AArch64::X17:
+  case AArch64::W17:
+    return MF.getSubtarget<AArch64Subtarget>().isX17Reserved();
   case AArch64::X18:
   case AArch64::W18:
     return MF.getSubtarget<AArch64Subtarget>().isX18Reserved();
@@ -430,6 +442,10 @@
   case AArch64::GPR64commonRegClassID:
     return 32 - 1                                   // XZR/SP
               - (TFI->hasFP(MF) || TT.isOSDarwin()) // FP
+              - MF.getSubtarget<AArch64Subtarget>()
+                    .isX16Reserved() // X16 reserved as platform register
+              - MF.getSubtarget<AArch64Subtarget>()
+                    .isX17Reserved() // X17 reserved as platform register
               - MF.getSubtarget<AArch64Subtarget>()
                     .isX18Reserved() // X18 reserved as platform register
               - hasBasePointer(MF);  // X19
Index: llvm/lib/Target/AArch64/AArch64Subtarget.h
===================================================================
--- llvm/lib/Target/AArch64/AArch64Subtarget.h
+++ llvm/lib/Target/AArch64/AArch64Subtarget.h
@@ -128,6 +128,12 @@
   unsigned MaxJumpTableSize = 0;
   unsigned WideningBaseCost = 0;
 
+  // ReserveX16 - X16 is not available as a general purpose register.
+  bool ReserveX16 = false;
+
+  // ReserveX17 - X17 is not available as a general purpose register.
+  bool ReserveX17 = false;
+
   // ReserveX18 - X18 is not available as a general purpose register.
   bool ReserveX18;
 
@@ -215,6 +221,8 @@
     return MinVectorRegisterBitWidth;
   }
 
+  bool isX16Reserved() const { return ReserveX16; }
+  bool isX17Reserved() const { return ReserveX17; }
   bool isX18Reserved() const { return ReserveX18; }
   bool hasFPARMv8() const { return HasFPARMv8; }
   bool hasNEON() const { return HasNEON; }
Index: llvm/test/CodeGen/AArch64/arm64-platform-reg.ll
===================================================================
--- llvm/test/CodeGen/AArch64/arm64-platform-reg.ll
+++ llvm/test/CodeGen/AArch64/arm64-platform-reg.ll
@@ -1,8 +1,11 @@
-; RUN: llc -mtriple=arm64-apple-ios -mattr=+reserve-x18 -o - %s | FileCheck %s --check-prefix=CHECK-RESERVE-X18
-; RUN: llc -mtriple=arm64-freebsd-gnu -mattr=+reserve-x18 -o - %s | FileCheck %s --check-prefix=CHECK-RESERVE-X18
+; RUN: llc -mtriple=aarch64-fuchsia -mattr=+reserve-x16 -o - %s | FileCheck %s --check-prefix=CHECK-RESERVE --check-prefix=CHECK-RESERVE-X16
+; RUN: llc -mtriple=aarch64-fuchsia -mattr=+reserve-x17 -o - %s | FileCheck %s --check-prefix=CHECK-RESERVE --check-prefix=CHECK-RESERVE-X17
+; RUN: llc -mtriple=arm64-apple-ios -mattr=+reserve-x18 -o - %s | FileCheck %s --check-prefix=CHECK-RESERVE --check-prefix=CHECK-RESERVE-X18
+; RUN: llc -mtriple=arm64-freebsd-gnu -mattr=+reserve-x18 -o - %s | FileCheck %s --check-prefix=CHECK-RESERVE --check-prefix=CHECK-RESERVE-X18
+; RUN: llc -mtriple=aarch64-fuchsia -mattr=+reserve-x16,+reserve-x17,+reserve-x18 -o - %s | FileCheck %s --check-prefix=CHECK-RESERVE --check-prefix=CHECK-RESERVE-X16 --check-prefix=CHECK-RESERVE-X17 --check-prefix=CHECK-RESERVE-X18
 ; RUN: llc -mtriple=arm64-linux-gnu -o - %s | FileCheck %s
-; RUN: llc -mtriple=aarch64-fuchsia -o - %s | FileCheck %s --check-prefix=CHECK-RESERVE-X18
-; RUN: llc -mtriple=aarch64-windows -o - %s | FileCheck %s --check-prefix=CHECK-RESERVE-X18
+; RUN: llc -mtriple=aarch64-fuchsia -o - %s | FileCheck %s --check-prefix=CHECK-RESERVE --check-prefix=CHECK-RESERVE-X18
+; RUN: llc -mtriple=aarch64-windows -o - %s | FileCheck %s --check-prefix=CHECK-RESERVE --check-prefix=CHECK-RESERVE-X18
 
 ; x18 is reserved as a platform register on Darwin but not on other
 ; systems. Create loads of register pressure and make sure this is respected.
@@ -19,11 +22,15 @@
 ; CHECK: ldr x18
 ; CHECK: str x18
 
-; CHECK-RESERVE-X18-NOT: ldr fp
+; CHECK-RESERVE-NOT: ldr fp
+; CHECK-RESERVE-X16-NOT: ldr x16
+; CHECK-RESERVE-X17-NOT: ldr x17
 ; CHECK-RESERVE-X18-NOT: ldr x18
-; CHECK-RESERVE-X18: Spill
-; CHECK-RESERVE-X18-NOT: ldr fp
+; CHECK-RESERVE: Spill
+; CHECK-RESERVE-NOT: ldr fp
+; CHECK-RESERVE-X16-NOT: ldr x16
+; CHECK-RESERVE-X17-NOT: ldr x17
 ; CHECK-RESERVE-X18-NOT: ldr x18
-; CHECK-RESERVE-X18: ret
+; CHECK-RESERVE: ret
   ret void
 }