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
