Author: Santanu Das Date: 2026-07-06T11:19:28+05:30 New Revision: a280b1b4f84186255c41a989312ab01ee4c30b88
URL: https://github.com/llvm/llvm-project/commit/a280b1b4f84186255c41a989312ab01ee4c30b88 DIFF: https://github.com/llvm/llvm-project/commit/a280b1b4f84186255c41a989312ab01ee4c30b88.diff LOG: [Hexagon] Allow reservation of caller saved registers via -ffixed-rXX (#205733) 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. However, a warning will be displayed if the user tries to reserve a caller saved register. --------- Co-authored-by: quic-santdas <[email protected]> Added: Modified: clang/include/clang/Basic/DiagnosticDriverKinds.td clang/include/clang/Options/Options.td 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/test/CodeGen/Hexagon/reserved-regs.ll Removed: ################################################################################ diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td index 3f8fc16e346cf..ae3eecc60fc78 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 35b0390bd2fc0..e6e8a46b846c8 100644 --- a/clang/include/clang/Options/Options.td +++ b/clang/include/clang/Options/Options.td @@ -5699,7 +5699,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>, @@ -7063,7 +7063,10 @@ 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">; -def ffixed_r19: Flag<["-"], "ffixed-r19">, Group<f_Group>, +foreach i = {6-7} in + 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<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>, @@ -7396,10 +7399,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 fd2ec694abb2f..827b0e6201428 100644 --- a/clang/lib/Driver/ToolChains/Hexagon.cpp +++ b/clang/lib/Driver/ToolChains/Hexagon.cpp @@ -806,23 +806,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_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 b2a3ce750fbc0..2832a8393feb7 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,24 @@ // 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])}}" + +// ----------------------------------------------------------------------------- +// 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 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 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
