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

>From 0a323e2484bc5e7ad407d5e1275d10f0e1eaddde Mon Sep 17 00:00:00 2001
From: quic-santdas <[email protected]>
Date: Tue, 12 May 2026 07:14:00 -0700
Subject: [PATCH 1/4] [Hexagon] Support reserving R16-R28 registers via
 -ffixed-rN

Extend register reservation from R19-only to R16-R28.
This allows users to reserve callee-saved registers (R16-R27)
and R28 via command-line flags -ffixed-r16 through -ffixed-r28.
The single bool ReservedR19 is replaced with an array-based
approach (ReservedR[32]) to scale cleanly across all
supported registers.
---
 clang/lib/Driver/ToolChains/Hexagon.cpp       | 23 ++++++++--
 clang/test/Driver/hexagon-toolchain-elf.c     | 42 ++++++++++++++++++-
 llvm/lib/Target/Hexagon/Hexagon.td            |  5 ++-
 .../Target/Hexagon/HexagonRegisterInfo.cpp    | 10 ++++-
 llvm/lib/Target/Hexagon/HexagonSubtarget.h    |  4 +-
 5 files changed, 73 insertions(+), 11 deletions(-)

diff --git a/clang/lib/Driver/ToolChains/Hexagon.cpp 
b/clang/lib/Driver/ToolChains/Hexagon.cpp
index 41f03e01b69c1..ce3fd5110953a 100644
--- a/clang/lib/Driver/ToolChains/Hexagon.cpp
+++ b/clang/lib/Driver/ToolChains/Hexagon.cpp
@@ -790,9 +790,26 @@ void HexagonToolChain::addClangTargetOptions(const ArgList 
&DriverArgs,
                           UseInitArrayDefault))
     CC1Args.push_back("-fno-use-init-array");
 
-  if (DriverArgs.hasArg(options::OPT_ffixed_r19)) {
-    CC1Args.push_back("-target-feature");
-    CC1Args.push_back("+reserved-r19");
+  static const std::pair<options::ID, const char *> FixedRegs[] = {
+      {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"},
+  };
+  for (const auto &[Opt, Feature] : FixedRegs) {
+    if (DriverArgs.hasArg(Opt)) {
+      CC1Args.push_back("-target-feature");
+      CC1Args.push_back(Feature);
+    }
   }
   if (isAutoHVXEnabled(DriverArgs)) {
     CC1Args.push_back("-mllvm");
diff --git a/clang/test/Driver/hexagon-toolchain-elf.c 
b/clang/test/Driver/hexagon-toolchain-elf.c
index 6de646a0f836a..83797b731563a 100644
--- a/clang/test/Driver/hexagon-toolchain-elf.c
+++ b/clang/test/Driver/hexagon-toolchain-elf.c
@@ -544,14 +544,52 @@
 // CHECK360:      {{hexagon-link|ld}}
 
 // 
-----------------------------------------------------------------------------
-// ffixed-r19
-// 
-----------------------------------------------------------------------------
+// ffixed-r16 through ffixed-r28
+// 
-----------------------------------------------------------------------------
+// RUN: %clang -### --target=hexagon-unknown-elf -ffixed-r16 %s 2>&1 \
+// RUN:        | FileCheck --check-prefix=CHECK-R16 %s
+// CHECK-R16: "-target-feature" "+reserved-r16"
+// RUN: %clang -### --target=hexagon-unknown-elf -ffixed-r17 %s 2>&1 \
+// RUN:        | FileCheck --check-prefix=CHECK-R17 %s
+// CHECK-R17: "-target-feature" "+reserved-r17"
+// RUN: %clang -### --target=hexagon-unknown-elf -ffixed-r18 %s 2>&1 \
+// RUN:        | FileCheck --check-prefix=CHECK-R18 %s
+// CHECK-R18: "-target-feature" "+reserved-r18"
 // RUN: %clang -### --target=hexagon-unknown-elf -ffixed-r19 %s 2>&1 \
 // RUN:        | FileCheck --check-prefix=CHECK370 %s
 // CHECK370: "-target-feature" "+reserved-r19"
+// RUN: %clang -### --target=hexagon-unknown-elf -ffixed-r20 %s 2>&1 \
+// RUN:        | FileCheck --check-prefix=CHECK-R20 %s
+// CHECK-R20: "-target-feature" "+reserved-r20"
+// RUN: %clang -### --target=hexagon-unknown-elf -ffixed-r21 %s 2>&1 \
+// RUN:        | FileCheck --check-prefix=CHECK-R21 %s
+// CHECK-R21: "-target-feature" "+reserved-r21"
+// RUN: %clang -### --target=hexagon-unknown-elf -ffixed-r22 %s 2>&1 \
+// RUN:        | FileCheck --check-prefix=CHECK-R22 %s
+// CHECK-R22: "-target-feature" "+reserved-r22"
+// RUN: %clang -### --target=hexagon-unknown-elf -ffixed-r23 %s 2>&1 \
+// RUN:        | FileCheck --check-prefix=CHECK-R23 %s
+// CHECK-R23: "-target-feature" "+reserved-r23"
+// RUN: %clang -### --target=hexagon-unknown-elf -ffixed-r24 %s 2>&1 \
+// RUN:        | FileCheck --check-prefix=CHECK-R24 %s
+// CHECK-R24: "-target-feature" "+reserved-r24"
+// RUN: %clang -### --target=hexagon-unknown-elf -ffixed-r25 %s 2>&1 \
+// RUN:        | FileCheck --check-prefix=CHECK-R25 %s
+// CHECK-R25: "-target-feature" "+reserved-r25"
+// RUN: %clang -### --target=hexagon-unknown-elf -ffixed-r26 %s 2>&1 \
+// RUN:        | FileCheck --check-prefix=CHECK-R26 %s
+// CHECK-R26: "-target-feature" "+reserved-r26"
+// RUN: %clang -### --target=hexagon-unknown-elf -ffixed-r27 %s 2>&1 \
+// RUN:        | FileCheck --check-prefix=CHECK-R27 %s
+// CHECK-R27: "-target-feature" "+reserved-r27"
+// RUN: %clang -### --target=hexagon-unknown-elf -ffixed-r28 %s 2>&1 \
+// RUN:        | FileCheck --check-prefix=CHECK-R28 %s
+// CHECK-R28: "-target-feature" "+reserved-r28"
 // RUN: %clang -### --target=hexagon-unknown-elf %s 2>&1 \
 // RUN:        | FileCheck --check-prefix=CHECK371 %s
+// CHECK371-NOT: "+reserved-r16"
 // CHECK371-NOT: "+reserved-r19"
+// CHECK371-NOT: "+reserved-r28"
 
 // 
-----------------------------------------------------------------------------
 // mcabac
diff --git a/llvm/lib/Target/Hexagon/Hexagon.td 
b/llvm/lib/Target/Hexagon/Hexagon.td
index 6532cbd085c2d..24052476d2fc4 100644
--- a/llvm/lib/Target/Hexagon/Hexagon.td
+++ b/llvm/lib/Target/Hexagon/Hexagon.td
@@ -116,8 +116,9 @@ 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">;
-def FeatureReservedR19: SubtargetFeature<"reserved-r19", "ReservedR19",
-      "true", "Reserve register R19">;
+foreach i = {16-28} in
+    def FeatureReservedR#i : SubtargetFeature<"reserved-r"#i,
+        "ReservedR["#i#"]", "true", "Reserve register R"#i>;
 def FeatureNoreturnStackElim: SubtargetFeature<"noreturn-stack-elim",
       "NoreturnStackElim", "true",
       "Eliminate stack allocation in a noreturn function when possible">;
diff --git a/llvm/lib/Target/Hexagon/HexagonRegisterInfo.cpp 
b/llvm/lib/Target/Hexagon/HexagonRegisterInfo.cpp
index a56dfc5f58392..999b6dc239b3d 100644
--- a/llvm/lib/Target/Hexagon/HexagonRegisterInfo.cpp
+++ b/llvm/lib/Target/Hexagon/HexagonRegisterInfo.cpp
@@ -205,8 +205,14 @@ BitVector HexagonRegisterInfo::getReservedRegs(const 
MachineFunction &MF)
   for (auto Reg : Hexagon_MC::GetVectRegRev())
     Reserved.set(Reg);
 
-  if (MF.getSubtarget<HexagonSubtarget>().hasReservedR19())
-    Reserved.set(Hexagon::R19);
+  static const MCPhysReg RRegs[] = {
+      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};
+  const auto &HST = MF.getSubtarget<HexagonSubtarget>();
+  for (unsigned i = 0; i < std::size(RRegs); ++i)
+    if (HST.isRRegReserved(i + 16))
+      Reserved.set(RRegs[i]);
 
   Register AP =
       MF.getInfo<HexagonMachineFunctionInfo>()->getStackAlignBaseReg();
diff --git a/llvm/lib/Target/Hexagon/HexagonSubtarget.h 
b/llvm/lib/Target/Hexagon/HexagonSubtarget.h
index dde32298b6889..559f90e64df25 100644
--- a/llvm/lib/Target/Hexagon/HexagonSubtarget.h
+++ b/llvm/lib/Target/Hexagon/HexagonSubtarget.h
@@ -63,7 +63,7 @@ class HexagonSubtarget : public HexagonGenSubtargetInfo {
   bool HasPreV65 = false;
   bool HasMemNoShuf = false;
   bool EnableDuplex = false;
-  bool ReservedR19 = false;
+  bool ReservedR[32] = {};
   bool NoreturnStackElim = false;
 
 public:
@@ -286,7 +286,7 @@ class HexagonSubtarget : public HexagonGenSubtargetInfo {
   bool useHVX64BOps() const { return useHVXOps() && UseHVX64BOps; }
 
   bool hasMemNoShuf() const { return HasMemNoShuf; }
-  bool hasReservedR19() const { return ReservedR19; }
+  bool isRRegReserved(unsigned i) const { return ReservedR[i]; }
   bool usePredicatedCalls() const;
 
   bool noreturnStackElim() const { return NoreturnStackElim; }

>From b09bee8a408e407fcfb4a1e64bc15d124dfb2cfd Mon Sep 17 00:00:00 2001
From: quic-santdas <[email protected]>
Date: Wed, 13 May 2026 07:07:24 -0700
Subject: [PATCH 2/4] Fixed the formatting via clang-format

---
 llvm/lib/Target/Hexagon/HexagonRegisterInfo.cpp | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/llvm/lib/Target/Hexagon/HexagonRegisterInfo.cpp 
b/llvm/lib/Target/Hexagon/HexagonRegisterInfo.cpp
index 999b6dc239b3d..88205358874f3 100644
--- a/llvm/lib/Target/Hexagon/HexagonRegisterInfo.cpp
+++ b/llvm/lib/Target/Hexagon/HexagonRegisterInfo.cpp
@@ -206,9 +206,9 @@ BitVector HexagonRegisterInfo::getReservedRegs(const 
MachineFunction &MF)
     Reserved.set(Reg);
 
   static const MCPhysReg RRegs[] = {
-      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};
+      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};
   const auto &HST = MF.getSubtarget<HexagonSubtarget>();
   for (unsigned i = 0; i < std::size(RRegs); ++i)
     if (HST.isRRegReserved(i + 16))

>From d9f18aafe3b9889596f5a3bdc1611f5db2204f3a Mon Sep 17 00:00:00 2001
From: quic-santdas <[email protected]>
Date: Tue, 19 May 2026 07:06:39 -0700
Subject: [PATCH 3/4] Addressed comments by quic-k

1. Added codegen test.
2. Modified clang test to add a regex.
3. Added assertion check for reserved register verification.
---
 clang/test/Driver/hexagon-toolchain-elf.c  |  4 +--
 llvm/lib/Target/Hexagon/HexagonSubtarget.h |  5 +++-
 llvm/test/CodeGen/Hexagon/reserved-regs.ll | 30 ++++++++++++++++++++++
 3 files changed, 35 insertions(+), 4 deletions(-)
 create mode 100644 llvm/test/CodeGen/Hexagon/reserved-regs.ll

diff --git a/clang/test/Driver/hexagon-toolchain-elf.c 
b/clang/test/Driver/hexagon-toolchain-elf.c
index 83797b731563a..b2a3ce750fbc0 100644
--- a/clang/test/Driver/hexagon-toolchain-elf.c
+++ b/clang/test/Driver/hexagon-toolchain-elf.c
@@ -587,9 +587,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-r16"
-// CHECK371-NOT: "+reserved-r19"
-// CHECK371-NOT: "+reserved-r28"
+// CHECK371-NOT: "+reserved-r{{(1[6-9]|2[0-8])}}"
 
 // 
-----------------------------------------------------------------------------
 // mcabac
diff --git a/llvm/lib/Target/Hexagon/HexagonSubtarget.h 
b/llvm/lib/Target/Hexagon/HexagonSubtarget.h
index 559f90e64df25..950246d95d1f4 100644
--- a/llvm/lib/Target/Hexagon/HexagonSubtarget.h
+++ b/llvm/lib/Target/Hexagon/HexagonSubtarget.h
@@ -286,7 +286,10 @@ class HexagonSubtarget : public HexagonGenSubtargetInfo {
   bool useHVX64BOps() const { return useHVXOps() && UseHVX64BOps; }
 
   bool hasMemNoShuf() const { return HasMemNoShuf; }
-  bool isRRegReserved(unsigned i) const { return ReservedR[i]; }
+  bool isRRegReserved(unsigned i) const {
+    assert(i >= 16 && i <= 28 && "Register index out of reservable range");
+    return ReservedR[i];
+  }
   bool usePredicatedCalls() const;
 
   bool noreturnStackElim() const { return NoreturnStackElim; }
diff --git a/llvm/test/CodeGen/Hexagon/reserved-regs.ll 
b/llvm/test/CodeGen/Hexagon/reserved-regs.ll
new file mode 100644
index 0000000000000..80e5d77ba2964
--- /dev/null
+++ b/llvm/test/CodeGen/Hexagon/reserved-regs.ll
@@ -0,0 +1,30 @@
+; RUN: llc -mtriple=hexagon -O2 < %s | FileCheck -check-prefix=CHECK-DEFAULT %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.
+
+declare void @bar()
+
+define i32 @pressure(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f) {
+  %v1 = add i32 %a, %b
+  %v2 = mul i32 %v1, %c
+  %v3 = sub i32 %v2, %d
+  %v4 = add i32 %v3, %e
+  %v5 = mul i32 %v4, %f
+  call void @bar()
+  %v6 = add i32 %v5, %v1
+  %v7 = sub i32 %v6, %v2
+  %v8 = add i32 %v7, %v3
+  %v9 = mul i32 %v8, %v4
+  %v10 = sub i32 %v9, %v5
+  ret i32 %v10
+}
+
+; CHECK-DEFAULT: r16
+; CHECK-DEFAULT: r17
+; CHECK-R16-NOT: r16
+; CHECK-R16R17-NOT: r16
+; CHECK-R16R17-NOT: r17

>From 29a60c8b36cb266c8fc0d652bd3380f5a36bb704 Mon Sep 17 00:00:00 2001
From: quic-santdas <[email protected]>
Date: Wed, 20 May 2026 07:30:53 -0700
Subject: [PATCH 4/4] Addressed comments by quic-saravan

Leveraged enum defined in tablegen to store reserved
registers as bit values.
Used TargetSubtargetInfo::isRegisterReservedByUser() API
instead of creating a custom function.
---
 llvm/lib/Target/Hexagon/Hexagon.td              | 3 ++-
 llvm/lib/Target/Hexagon/HexagonRegisterInfo.cpp | 7 +++----
 llvm/lib/Target/Hexagon/HexagonSubtarget.h      | 9 +++++----
 3 files changed, 10 insertions(+), 9 deletions(-)

diff --git a/llvm/lib/Target/Hexagon/Hexagon.td 
b/llvm/lib/Target/Hexagon/Hexagon.td
index 24052476d2fc4..ecb8a0a7a9738 100644
--- a/llvm/lib/Target/Hexagon/Hexagon.td
+++ b/llvm/lib/Target/Hexagon/Hexagon.td
@@ -118,7 +118,8 @@ def FeatureDuplex: SubtargetFeature<"duplex", 
"EnableDuplex", "true",
       "Enable generation of duplex instruction">;
 foreach i = {16-28} in
     def FeatureReservedR#i : SubtargetFeature<"reserved-r"#i,
-        "ReservedR["#i#"]", "true", "Reserve register R"#i>;
+        "UserReservedRegister[Hexagon::R"#i#"]",
+        "true", "Reserve register R"#i>;
 def FeatureNoreturnStackElim: SubtargetFeature<"noreturn-stack-elim",
       "NoreturnStackElim", "true",
       "Eliminate stack allocation in a noreturn function when possible">;
diff --git a/llvm/lib/Target/Hexagon/HexagonRegisterInfo.cpp 
b/llvm/lib/Target/Hexagon/HexagonRegisterInfo.cpp
index 88205358874f3..9bd614c7b79f8 100644
--- a/llvm/lib/Target/Hexagon/HexagonRegisterInfo.cpp
+++ b/llvm/lib/Target/Hexagon/HexagonRegisterInfo.cpp
@@ -209,10 +209,9 @@ BitVector HexagonRegisterInfo::getReservedRegs(const 
MachineFunction &MF)
       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};
-  const auto &HST = MF.getSubtarget<HexagonSubtarget>();
-  for (unsigned i = 0; i < std::size(RRegs); ++i)
-    if (HST.isRRegReserved(i + 16))
-      Reserved.set(RRegs[i]);
+  for (MCPhysReg Reg : RRegs)
+    if (MF.getSubtarget().isRegisterReservedByUser(Reg))
+      Reserved.set(Reg);
 
   Register AP =
       MF.getInfo<HexagonMachineFunctionInfo>()->getStackAlignBaseReg();
diff --git a/llvm/lib/Target/Hexagon/HexagonSubtarget.h 
b/llvm/lib/Target/Hexagon/HexagonSubtarget.h
index 950246d95d1f4..2019bbf64b365 100644
--- a/llvm/lib/Target/Hexagon/HexagonSubtarget.h
+++ b/llvm/lib/Target/Hexagon/HexagonSubtarget.h
@@ -25,6 +25,7 @@
 #include "llvm/CodeGen/TargetSubtargetInfo.h"
 #include "llvm/MC/MCInstrItineraries.h"
 #include "llvm/Support/Alignment.h"
+#include <bitset>
 #include <memory>
 #include <string>
 #include <vector>
@@ -63,7 +64,7 @@ class HexagonSubtarget : public HexagonGenSubtargetInfo {
   bool HasPreV65 = false;
   bool HasMemNoShuf = false;
   bool EnableDuplex = false;
-  bool ReservedR[32] = {};
+  std::bitset<Hexagon::NUM_TARGET_REGS> UserReservedRegister;
   bool NoreturnStackElim = false;
 
 public:
@@ -286,9 +287,9 @@ class HexagonSubtarget : public HexagonGenSubtargetInfo {
   bool useHVX64BOps() const { return useHVXOps() && UseHVX64BOps; }
 
   bool hasMemNoShuf() const { return HasMemNoShuf; }
-  bool isRRegReserved(unsigned i) const {
-    assert(i >= 16 && i <= 28 && "Register index out of reservable range");
-    return ReservedR[i];
+  bool isRegisterReservedByUser(Register i) const override {
+    assert(i.id() < Hexagon::NUM_TARGET_REGS && "Register out of range");
+    return UserReservedRegister[i.id()];
   }
   bool usePredicatedCalls() const;
 

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

Reply via email to