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
