Author: Santanu Das
Date: 2026-05-25T18:24:12+05:30
New Revision: 84f95300d0f9efb45d5f1b76eb806c4772b16569

URL: 
https://github.com/llvm/llvm-project/commit/84f95300d0f9efb45d5f1b76eb806c4772b16569
DIFF: 
https://github.com/llvm/llvm-project/commit/84f95300d0f9efb45d5f1b76eb806c4772b16569.diff

LOG: [Hexagon] Support reserving R16-R28 registers via -ffixed-rN (#197208)

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.

---------

Co-authored-by: quic-santdas <[email protected]>

Added: 
    llvm/test/CodeGen/Hexagon/reserved-regs.ll

Modified: 
    clang/lib/Driver/ToolChains/Hexagon.cpp
    clang/test/Driver/hexagon-toolchain-elf.c
    llvm/lib/Target/Hexagon/Hexagon.td
    llvm/lib/Target/Hexagon/HexagonRegisterInfo.cpp
    llvm/lib/Target/Hexagon/HexagonSubtarget.h

Removed: 
    


################################################################################
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..b2a3ce750fbc0 100644
--- a/clang/test/Driver/hexagon-toolchain-elf.c
+++ b/clang/test/Driver/hexagon-toolchain-elf.c
@@ -544,14 +544,50 @@
 // 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-r19"
+// CHECK371-NOT: "+reserved-r{{(1[6-9]|2[0-8])}}"
 
 // 
-----------------------------------------------------------------------------
 // mcabac

diff  --git a/llvm/lib/Target/Hexagon/Hexagon.td 
b/llvm/lib/Target/Hexagon/Hexagon.td
index 6532cbd085c2d..ecb8a0a7a9738 100644
--- a/llvm/lib/Target/Hexagon/Hexagon.td
+++ b/llvm/lib/Target/Hexagon/Hexagon.td
@@ -116,8 +116,10 @@ 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,
+        "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 a56dfc5f58392..9bd614c7b79f8 100644
--- a/llvm/lib/Target/Hexagon/HexagonRegisterInfo.cpp
+++ b/llvm/lib/Target/Hexagon/HexagonRegisterInfo.cpp
@@ -205,8 +205,13 @@ 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};
+  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 dde32298b6889..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 ReservedR19 = false;
+  std::bitset<Hexagon::NUM_TARGET_REGS> UserReservedRegister;
   bool NoreturnStackElim = false;
 
 public:
@@ -286,7 +287,10 @@ class HexagonSubtarget : public HexagonGenSubtargetInfo {
   bool useHVX64BOps() const { return useHVXOps() && UseHVX64BOps; }
 
   bool hasMemNoShuf() const { return HasMemNoShuf; }
-  bool hasReservedR19() const { return ReservedR19; }
+  bool isRegisterReservedByUser(Register i) const override {
+    assert(i.id() < Hexagon::NUM_TARGET_REGS && "Register out of range");
+    return UserReservedRegister[i.id()];
+  }
   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


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

Reply via email to