https://github.com/quic-santdas updated 
https://github.com/llvm/llvm-project/pull/205733

>From d27e557cfa8e90fac4b1638b2cb4720476671902 Mon Sep 17 00:00:00 2001
From: quic-santdas <[email protected]>
Date: Wed, 24 Jun 2026 22:55:48 -0700
Subject: [PATCH 1/2] [Hexagon] Allow reservation of caller saved registers via
 -ffixed-rXX

Previously, hexagon allowed only callee saved registers to be reserved
since reserving caller saved regs can create problems, since it
cannot be sure that the callee (from a different module) also
reserves the register.

The responsibility of reserving register and managing it is now
on the user.
---
 clang/include/clang/Options/Options.td        |  9 +++--
 clang/lib/Driver/ToolChains/Hexagon.cpp       | 10 ++++++
 clang/test/Driver/hexagon-toolchain-elf.c     | 36 +++++++++++++++++--
 llvm/lib/Target/Hexagon/Hexagon.td            |  2 +-
 .../Target/Hexagon/HexagonRegisterInfo.cpp    |  2 ++
 llvm/test/CodeGen/Hexagon/reserved-regs.ll    |  6 ++++
 6 files changed, 58 insertions(+), 7 deletions(-)

diff --git a/clang/include/clang/Options/Options.td 
b/clang/include/clang/Options/Options.td
index 4fc9f4d4c3472..125ac5ca366c9 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -5680,7 +5680,7 @@ def mno_restrict_it: Flag<["-"], "mno-restrict-it">, 
Group<m_arm_Features_Group>
   HelpText<"Allow generation of complex IT blocks.">;
 def marm : Flag<["-"], "marm">, Alias<mno_thumb>;
 def ffixed_r9 : Flag<["-"], "ffixed-r9">, Group<m_Group>,
-  HelpText<"Reserve the r9 register (ARM/x86_64 only)">;
+  HelpText<"Reserve the r9 register (ARM/Hexagon/x86_64 only)">;
 def mno_movt : Flag<["-"], "mno-movt">, Group<m_arm_Features_Group>,
   HelpText<"Disallow use of movt/movw pairs (ARM only)">;
 def mcrc : Flag<["-"], "mcrc">, Group<m_Group>,
@@ -7041,6 +7041,9 @@ def mhexagon_hvx_ieee_fp : Flag<["-"], "mhvx-ieee-fp">,
 def mno_hexagon_hvx_ieee_fp : Flag<["-"], "mno-hvx-ieee-fp">,
   Group<m_hexagon_Features_Group>,
   HelpText<"Disable Hexagon HVX IEEE floating-point">;
+foreach i = {6-7} in
+    def ffixed_r#i : Flag<["-"], "ffixed-r"#i>, Group<f_Group>,
+    HelpText<"Reserve register r"#i#" (Hexagon only)">;
 def ffixed_r19: Flag<["-"], "ffixed-r19">, Group<f_Group>,
   HelpText<"Reserve register r19 (Hexagon/x86_64 only; x86_64 requires APX 
EGPR)">;
 } // let Flags = [TargetSpecific]
@@ -7374,10 +7377,10 @@ def ffixed_edi : Flag<["-"], "ffixed-edi">, 
Group<m_Group>,
                  HelpText<"Reserve the edi register (x86 only)">;
 foreach i = {8, 10-15} in
     def ffixed_r#i : Flag<["-"], "ffixed-r"#i>, Group<m_Group>,
-    HelpText<"Reserve the r"#i#" register (x86_64 only)">;
+    HelpText<"Reserve the r"#i#" register (Hexagon/x86_64 only)">;
 foreach i = {16-18,20-31} in
     def ffixed_r#i : Flag<["-"], "ffixed-r"#i>, Group<m_Group>,
-    HelpText<"Reserve the r"#i#" register (x86_64 with APX EGPR only)">;
+    HelpText<"Reserve the r"#i#" register (Hexagon/x86_64 only; x86_64 
requires APX EGPR)">;
 
 } // let Flags = [TargetSpecific]
 
diff --git a/clang/lib/Driver/ToolChains/Hexagon.cpp 
b/clang/lib/Driver/ToolChains/Hexagon.cpp
index 3643c0d4e526c..e779647386616 100644
--- a/clang/lib/Driver/ToolChains/Hexagon.cpp
+++ b/clang/lib/Driver/ToolChains/Hexagon.cpp
@@ -790,6 +790,16 @@ void HexagonToolChain::addClangTargetOptions(const ArgList 
&DriverArgs,
     CC1Args.push_back("-fno-use-init-array");
 
   static const std::pair<options::ID, const char *> FixedRegs[] = {
+      {options::OPT_ffixed_r6, "+reserved-r6"},
+      {options::OPT_ffixed_r7, "+reserved-r7"},
+      {options::OPT_ffixed_r8, "+reserved-r8"},
+      {options::OPT_ffixed_r9, "+reserved-r9"},
+      {options::OPT_ffixed_r10, "+reserved-r10"},
+      {options::OPT_ffixed_r11, "+reserved-r11"},
+      {options::OPT_ffixed_r12, "+reserved-r12"},
+      {options::OPT_ffixed_r13, "+reserved-r13"},
+      {options::OPT_ffixed_r14, "+reserved-r14"},
+      {options::OPT_ffixed_r15, "+reserved-r15"},
       {options::OPT_ffixed_r16, "+reserved-r16"},
       {options::OPT_ffixed_r17, "+reserved-r17"},
       {options::OPT_ffixed_r18, "+reserved-r18"},
diff --git a/clang/test/Driver/hexagon-toolchain-elf.c 
b/clang/test/Driver/hexagon-toolchain-elf.c
index b2a3ce750fbc0..fce6f3e250136 100644
--- a/clang/test/Driver/hexagon-toolchain-elf.c
+++ b/clang/test/Driver/hexagon-toolchain-elf.c
@@ -544,8 +544,38 @@
 // CHECK360:      {{hexagon-link|ld}}
 
 // 
-----------------------------------------------------------------------------
-// ffixed-r16 through ffixed-r28
-// 
-----------------------------------------------------------------------------
+// ffixed-r6 through ffixed-r28
+// 
-----------------------------------------------------------------------------
+// RUN: %clang -### --target=hexagon-unknown-elf -ffixed-r6 %s 2>&1 \
+// RUN:        | FileCheck --check-prefix=CHECK-R6 %s
+// CHECK-R6: "-target-feature" "+reserved-r6"
+// RUN: %clang -### --target=hexagon-unknown-elf -ffixed-r7 %s 2>&1 \
+// RUN:        | FileCheck --check-prefix=CHECK-R7 %s
+// CHECK-R7: "-target-feature" "+reserved-r7"
+// RUN: %clang -### --target=hexagon-unknown-elf -ffixed-r8 %s 2>&1 \
+// RUN:        | FileCheck --check-prefix=CHECK-R8 %s
+// CHECK-R8: "-target-feature" "+reserved-r8"
+// RUN: %clang -### --target=hexagon-unknown-elf -ffixed-r9 %s 2>&1 \
+// RUN:        | FileCheck --check-prefix=CHECK-R9 %s
+// CHECK-R9: "-target-feature" "+reserved-r9"
+// RUN: %clang -### --target=hexagon-unknown-elf -ffixed-r10 %s 2>&1 \
+// RUN:        | FileCheck --check-prefix=CHECK-R10 %s
+// CHECK-R10: "-target-feature" "+reserved-r10"
+// RUN: %clang -### --target=hexagon-unknown-elf -ffixed-r11 %s 2>&1 \
+// RUN:        | FileCheck --check-prefix=CHECK-R11 %s
+// CHECK-R11: "-target-feature" "+reserved-r11"
+// RUN: %clang -### --target=hexagon-unknown-elf -ffixed-r12 %s 2>&1 \
+// RUN:        | FileCheck --check-prefix=CHECK-R12 %s
+// CHECK-R12: "-target-feature" "+reserved-r12"
+// RUN: %clang -### --target=hexagon-unknown-elf -ffixed-r13 %s 2>&1 \
+// RUN:        | FileCheck --check-prefix=CHECK-R13 %s
+// CHECK-R13: "-target-feature" "+reserved-r13"
+// RUN: %clang -### --target=hexagon-unknown-elf -ffixed-r14 %s 2>&1 \
+// RUN:        | FileCheck --check-prefix=CHECK-R14 %s
+// CHECK-R14: "-target-feature" "+reserved-r14"
+// RUN: %clang -### --target=hexagon-unknown-elf -ffixed-r15 %s 2>&1 \
+// RUN:        | FileCheck --check-prefix=CHECK-R15 %s
+// CHECK-R15: "-target-feature" "+reserved-r15"
 // RUN: %clang -### --target=hexagon-unknown-elf -ffixed-r16 %s 2>&1 \
 // RUN:        | FileCheck --check-prefix=CHECK-R16 %s
 // CHECK-R16: "-target-feature" "+reserved-r16"
@@ -587,7 +617,7 @@
 // CHECK-R28: "-target-feature" "+reserved-r28"
 // RUN: %clang -### --target=hexagon-unknown-elf %s 2>&1 \
 // RUN:        | FileCheck --check-prefix=CHECK371 %s
-// CHECK371-NOT: "+reserved-r{{(1[6-9]|2[0-8])}}"
+// CHECK371-NOT: "+reserved-r{{([6-9]|1[0-9]|2[0-8])}}"
 
 // 
-----------------------------------------------------------------------------
 // mcabac
diff --git a/llvm/lib/Target/Hexagon/Hexagon.td 
b/llvm/lib/Target/Hexagon/Hexagon.td
index ecb8a0a7a9738..b6fe3b4c80777 100644
--- a/llvm/lib/Target/Hexagon/Hexagon.td
+++ b/llvm/lib/Target/Hexagon/Hexagon.td
@@ -116,7 +116,7 @@ def FeatureSmallData: SubtargetFeature<"small-data", 
"UseSmallData", "true",
       "Allow GP-relative addressing of global variables">;
 def FeatureDuplex: SubtargetFeature<"duplex", "EnableDuplex", "true",
       "Enable generation of duplex instruction">;
-foreach i = {16-28} in
+foreach i = {6-28} in
     def FeatureReservedR#i : SubtargetFeature<"reserved-r"#i,
         "UserReservedRegister[Hexagon::R"#i#"]",
         "true", "Reserve register R"#i>;
diff --git a/llvm/lib/Target/Hexagon/HexagonRegisterInfo.cpp 
b/llvm/lib/Target/Hexagon/HexagonRegisterInfo.cpp
index 9bd614c7b79f8..63d6717ad7b68 100644
--- a/llvm/lib/Target/Hexagon/HexagonRegisterInfo.cpp
+++ b/llvm/lib/Target/Hexagon/HexagonRegisterInfo.cpp
@@ -206,6 +206,8 @@ BitVector HexagonRegisterInfo::getReservedRegs(const 
MachineFunction &MF)
     Reserved.set(Reg);
 
   static const MCPhysReg RRegs[] = {
+      Hexagon::R6,  Hexagon::R7,  Hexagon::R8,  Hexagon::R9,  Hexagon::R10,
+      Hexagon::R11, Hexagon::R12, Hexagon::R13, Hexagon::R14, Hexagon::R15,
       Hexagon::R16, Hexagon::R17, Hexagon::R18, Hexagon::R19, Hexagon::R20,
       Hexagon::R21, Hexagon::R22, Hexagon::R23, Hexagon::R24, Hexagon::R25,
       Hexagon::R26, Hexagon::R27, Hexagon::R28};
diff --git a/llvm/test/CodeGen/Hexagon/reserved-regs.ll 
b/llvm/test/CodeGen/Hexagon/reserved-regs.ll
index 80e5d77ba2964..9d2d172276b42 100644
--- a/llvm/test/CodeGen/Hexagon/reserved-regs.ll
+++ b/llvm/test/CodeGen/Hexagon/reserved-regs.ll
@@ -1,10 +1,13 @@
 ; RUN: llc -mtriple=hexagon -O2 < %s | FileCheck -check-prefix=CHECK-DEFAULT %s
+; RUN: llc -mtriple=hexagon -mattr=+reserved-r6 -O2 < %s | FileCheck 
-check-prefix=CHECK-R6 %s
+; RUN: llc -mtriple=hexagon -mattr=+reserved-r6,+reserved-r7 -O2 < %s | 
FileCheck -check-prefix=CHECK-R6R7 %s
 ; RUN: llc -mtriple=hexagon -mattr=+reserved-r16 -O2 < %s | FileCheck 
-check-prefix=CHECK-R16 %s
 ; RUN: llc -mtriple=hexagon -mattr=+reserved-r16,+reserved-r17 -O2 < %s | 
FileCheck -check-prefix=CHECK-R16R17 %s
 
 ; Test that reserved registers are not used by the register allocator.
 ; The function has a call, forcing values to be placed in callee-saved
 ; registers (R16-R27). Reserving a register must prevent its use.
+; Caller-saved registers (R6-R15) can also be reserved.
 
 declare void @bar()
 
@@ -25,6 +28,9 @@ define i32 @pressure(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, 
i32 %f) {
 
 ; CHECK-DEFAULT: r16
 ; CHECK-DEFAULT: r17
+; CHECK-R6-NOT: r6
+; CHECK-R6R7-NOT: r6
+; CHECK-R6R7-NOT: r7
 ; CHECK-R16-NOT: r16
 ; CHECK-R16R17-NOT: r16
 ; CHECK-R16R17-NOT: r17

>From 107e17e2878c59bf8556c13de777cd06ae040fcf Mon Sep 17 00:00:00 2001
From: quic-santdas <[email protected]>
Date: Fri, 3 Jul 2026 02:36:53 -0700
Subject: [PATCH 2/2] Addressed comments by asaravan

---
 .../clang/Basic/DiagnosticDriverKinds.td      |  5 ++
 clang/include/clang/Options/Options.td        |  4 +-
 clang/lib/Driver/ToolChains/Hexagon.cpp       | 58 ++++++++++---------
 clang/test/Driver/hexagon-toolchain-elf.c     | 17 ++++++
 4 files changed, 56 insertions(+), 28 deletions(-)

diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td 
b/clang/include/clang/Basic/DiagnosticDriverKinds.td
index 8edac14f4972a..44b0b77b98c5b 100644
--- a/clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -171,6 +171,11 @@ def warn_drv_unsupported_option_for_processor : Warning<
 def warn_drv_unsupported_option_for_runtime : Warning<
   "ignoring '%0' option as it is not currently supported for runtime '%1'">,
   InGroup<OptionIgnored>;
+def warn_drv_hexagon_reserved_caller_saved_reg : Warning<
+  "reserving the caller-saved register '%0' may lead to incorrect code if it "
+  "is not also reserved in all other translation units and libraries; you are "
+  "responsible for ensuring the register is managed consistently">,
+  InGroup<DiagGroup<"hexagon-reserved-caller-saved">>;
 def warn_drv_unsupported_openmp_library : Warning<
   "the library '%0=%1' is not supported, OpenMP will not be enabled">,
   InGroup<OptionIgnored>;
diff --git a/clang/include/clang/Options/Options.td 
b/clang/include/clang/Options/Options.td
index 125ac5ca366c9..a1da8f4df559e 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -7042,9 +7042,9 @@ def mno_hexagon_hvx_ieee_fp : Flag<["-"], 
"mno-hvx-ieee-fp">,
   Group<m_hexagon_Features_Group>,
   HelpText<"Disable Hexagon HVX IEEE floating-point">;
 foreach i = {6-7} in
-    def ffixed_r#i : Flag<["-"], "ffixed-r"#i>, Group<f_Group>,
+    def ffixed_r#i : Flag<["-"], "ffixed-r"#i>, Group<m_Group>,
     HelpText<"Reserve register r"#i#" (Hexagon only)">;
-def ffixed_r19: Flag<["-"], "ffixed-r19">, Group<f_Group>,
+def ffixed_r19: Flag<["-"], "ffixed-r19">, Group<m_Group>,
   HelpText<"Reserve register r19 (Hexagon/x86_64 only; x86_64 requires APX 
EGPR)">;
 } // let Flags = [TargetSpecific]
 def mmemops : Flag<["-"], "mmemops">, Group<m_hexagon_Features_Group>,
diff --git a/clang/lib/Driver/ToolChains/Hexagon.cpp 
b/clang/lib/Driver/ToolChains/Hexagon.cpp
index e779647386616..28442e7d6928a 100644
--- a/clang/lib/Driver/ToolChains/Hexagon.cpp
+++ b/clang/lib/Driver/ToolChains/Hexagon.cpp
@@ -789,33 +789,39 @@ void HexagonToolChain::addClangTargetOptions(const 
ArgList &DriverArgs,
                           UseInitArrayDefault))
     CC1Args.push_back("-fno-use-init-array");
 
-  static const std::pair<options::ID, const char *> FixedRegs[] = {
-      {options::OPT_ffixed_r6, "+reserved-r6"},
-      {options::OPT_ffixed_r7, "+reserved-r7"},
-      {options::OPT_ffixed_r8, "+reserved-r8"},
-      {options::OPT_ffixed_r9, "+reserved-r9"},
-      {options::OPT_ffixed_r10, "+reserved-r10"},
-      {options::OPT_ffixed_r11, "+reserved-r11"},
-      {options::OPT_ffixed_r12, "+reserved-r12"},
-      {options::OPT_ffixed_r13, "+reserved-r13"},
-      {options::OPT_ffixed_r14, "+reserved-r14"},
-      {options::OPT_ffixed_r15, "+reserved-r15"},
-      {options::OPT_ffixed_r16, "+reserved-r16"},
-      {options::OPT_ffixed_r17, "+reserved-r17"},
-      {options::OPT_ffixed_r18, "+reserved-r18"},
-      {options::OPT_ffixed_r19, "+reserved-r19"},
-      {options::OPT_ffixed_r20, "+reserved-r20"},
-      {options::OPT_ffixed_r21, "+reserved-r21"},
-      {options::OPT_ffixed_r22, "+reserved-r22"},
-      {options::OPT_ffixed_r23, "+reserved-r23"},
-      {options::OPT_ffixed_r24, "+reserved-r24"},
-      {options::OPT_ffixed_r25, "+reserved-r25"},
-      {options::OPT_ffixed_r26, "+reserved-r26"},
-      {options::OPT_ffixed_r27, "+reserved-r27"},
-      {options::OPT_ffixed_r28, "+reserved-r28"},
+  // The bool marks caller-saved (scratch) registers in the Hexagon ABI.
+  // Reserving those only behaves correctly if every other translation unit and
+  // library reserves them too, so we warn when the user does so.
+  static const std::tuple<options::ID, const char *, bool> FixedRegs[] = {
+      {options::OPT_ffixed_r6, "+reserved-r6", true},
+      {options::OPT_ffixed_r7, "+reserved-r7", true},
+      {options::OPT_ffixed_r8, "+reserved-r8", true},
+      {options::OPT_ffixed_r9, "+reserved-r9", true},
+      {options::OPT_ffixed_r10, "+reserved-r10", true},
+      {options::OPT_ffixed_r11, "+reserved-r11", true},
+      {options::OPT_ffixed_r12, "+reserved-r12", true},
+      {options::OPT_ffixed_r13, "+reserved-r13", true},
+      {options::OPT_ffixed_r14, "+reserved-r14", true},
+      {options::OPT_ffixed_r15, "+reserved-r15", true},
+      {options::OPT_ffixed_r16, "+reserved-r16", false},
+      {options::OPT_ffixed_r17, "+reserved-r17", false},
+      {options::OPT_ffixed_r18, "+reserved-r18", false},
+      {options::OPT_ffixed_r19, "+reserved-r19", false},
+      {options::OPT_ffixed_r20, "+reserved-r20", false},
+      {options::OPT_ffixed_r21, "+reserved-r21", false},
+      {options::OPT_ffixed_r22, "+reserved-r22", false},
+      {options::OPT_ffixed_r23, "+reserved-r23", false},
+      {options::OPT_ffixed_r24, "+reserved-r24", false},
+      {options::OPT_ffixed_r25, "+reserved-r25", false},
+      {options::OPT_ffixed_r26, "+reserved-r26", false},
+      {options::OPT_ffixed_r27, "+reserved-r27", false},
+      {options::OPT_ffixed_r28, "+reserved-r28", false},
   };
-  for (const auto &[Opt, Feature] : FixedRegs) {
-    if (DriverArgs.hasArg(Opt)) {
+  for (const auto &[Opt, Feature, IsCallerSaved] : FixedRegs) {
+    if (Arg *A = DriverArgs.getLastArg(Opt)) {
+      if (IsCallerSaved)
+        getDriver().Diag(diag::warn_drv_hexagon_reserved_caller_saved_reg)
+            << A->getOption().getName();
       CC1Args.push_back("-target-feature");
       CC1Args.push_back(Feature);
     }
diff --git a/clang/test/Driver/hexagon-toolchain-elf.c 
b/clang/test/Driver/hexagon-toolchain-elf.c
index fce6f3e250136..2832a8393feb7 100644
--- a/clang/test/Driver/hexagon-toolchain-elf.c
+++ b/clang/test/Driver/hexagon-toolchain-elf.c
@@ -619,6 +619,23 @@
 // RUN:        | FileCheck --check-prefix=CHECK371 %s
 // CHECK371-NOT: "+reserved-r{{([6-9]|1[0-9]|2[0-8])}}"
 
+// 
-----------------------------------------------------------------------------
+// Reserving a caller-saved register (r6-r15) warns; a callee-saved one
+// (r16-r28) does not. The warning can be silenced with -Wno-....
+// 
-----------------------------------------------------------------------------
+// RUN: %clang -### --target=hexagon-unknown-elf -ffixed-r6 %s 2>&1 \
+// RUN:        | FileCheck --check-prefix=CHECK-WARN-R6 %s
+// CHECK-WARN-R6: warning: reserving the caller-saved register 'ffixed-r6'
+// RUN: %clang -### --target=hexagon-unknown-elf -ffixed-r15 %s 2>&1 \
+// RUN:        | FileCheck --check-prefix=CHECK-WARN-R15 %s
+// CHECK-WARN-R15: warning: reserving the caller-saved register 'ffixed-r15'
+// RUN: %clang -### --target=hexagon-unknown-elf -ffixed-r16 %s 2>&1 \
+// RUN:        | FileCheck --check-prefix=CHECK-NOWARN %s
+// RUN: %clang -### --target=hexagon-unknown-elf -ffixed-r6 \
+// RUN:        -Wno-hexagon-reserved-caller-saved %s 2>&1 \
+// RUN:        | FileCheck --check-prefix=CHECK-NOWARN %s
+// CHECK-NOWARN-NOT: warning: reserving the caller-saved register
+
 // 
-----------------------------------------------------------------------------
 // mcabac
 // 
-----------------------------------------------------------------------------

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to