diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -2263,9 +2263,9 @@ def mno_fix_cortex_a53_835769 : Flag<["-"], "mno-fix-cortex-a53-835769">, Group, HelpText<"Don't workaround Cortex-A53 erratum 835769 (AArch64 only)">; -foreach i = {1-7,9-15,18,20-28} in - def ffixed_x#i : Flag<["-"], "ffixed-x"#i>, Group, - HelpText<"Reserve the "#i#" register (AArch64 only)">; +foreach i = {1-31} in + def ffixed_x#i : Flag<["-"], "ffixed-x"#i>, Group, + HelpText<"Reserve the "#i#" register (AArch64/RISC-V only)">; foreach i = {8-15,18} in def fcall_saved_x#i : Flag<["-"], "fcall-saved-x"#i>, Group, diff --git a/clang/lib/Driver/ToolChains/Arch/RISCV.cpp b/clang/lib/Driver/ToolChains/Arch/RISCV.cpp --- a/clang/lib/Driver/ToolChains/Arch/RISCV.cpp +++ b/clang/lib/Driver/ToolChains/Arch/RISCV.cpp @@ -367,6 +367,70 @@ if (MArch.hasValue() && !getArchFeatures(D, *MArch, Features, Args)) return; + // Handle features corresponding to "-ffixed-X" options + if (Args.hasArg(options::OPT_ffixed_x1)) + Features.push_back("+reserve-x1"); + if (Args.hasArg(options::OPT_ffixed_x2)) + Features.push_back("+reserve-x2"); + if (Args.hasArg(options::OPT_ffixed_x3)) + Features.push_back("+reserve-x3"); + if (Args.hasArg(options::OPT_ffixed_x4)) + Features.push_back("+reserve-x4"); + if (Args.hasArg(options::OPT_ffixed_x5)) + Features.push_back("+reserve-x5"); + if (Args.hasArg(options::OPT_ffixed_x6)) + Features.push_back("+reserve-x6"); + if (Args.hasArg(options::OPT_ffixed_x7)) + Features.push_back("+reserve-x7"); + if (Args.hasArg(options::OPT_ffixed_x8)) + Features.push_back("+reserve-x8"); + if (Args.hasArg(options::OPT_ffixed_x9)) + Features.push_back("+reserve-x9"); + if (Args.hasArg(options::OPT_ffixed_x10)) + Features.push_back("+reserve-x10"); + if (Args.hasArg(options::OPT_ffixed_x11)) + Features.push_back("+reserve-x11"); + if (Args.hasArg(options::OPT_ffixed_x12)) + Features.push_back("+reserve-x12"); + if (Args.hasArg(options::OPT_ffixed_x13)) + Features.push_back("+reserve-x13"); + if (Args.hasArg(options::OPT_ffixed_x14)) + Features.push_back("+reserve-x14"); + if (Args.hasArg(options::OPT_ffixed_x15)) + Features.push_back("+reserve-x15"); + if (Args.hasArg(options::OPT_ffixed_x16)) + Features.push_back("+reserve-x16"); + if (Args.hasArg(options::OPT_ffixed_x17)) + Features.push_back("+reserve-x17"); + if (Args.hasArg(options::OPT_ffixed_x18)) + Features.push_back("+reserve-x18"); + if (Args.hasArg(options::OPT_ffixed_x19)) + Features.push_back("+reserve-x19"); + if (Args.hasArg(options::OPT_ffixed_x20)) + Features.push_back("+reserve-x20"); + if (Args.hasArg(options::OPT_ffixed_x21)) + Features.push_back("+reserve-x21"); + if (Args.hasArg(options::OPT_ffixed_x22)) + Features.push_back("+reserve-x22"); + if (Args.hasArg(options::OPT_ffixed_x23)) + Features.push_back("+reserve-x23"); + if (Args.hasArg(options::OPT_ffixed_x24)) + Features.push_back("+reserve-x24"); + if (Args.hasArg(options::OPT_ffixed_x25)) + Features.push_back("+reserve-x25"); + if (Args.hasArg(options::OPT_ffixed_x26)) + Features.push_back("+reserve-x26"); + if (Args.hasArg(options::OPT_ffixed_x27)) + Features.push_back("+reserve-x27"); + if (Args.hasArg(options::OPT_ffixed_x28)) + Features.push_back("+reserve-x28"); + if (Args.hasArg(options::OPT_ffixed_x29)) + Features.push_back("+reserve-x29"); + if (Args.hasArg(options::OPT_ffixed_x30)) + Features.push_back("+reserve-x30"); + if (Args.hasArg(options::OPT_ffixed_x31)) + Features.push_back("+reserve-x31"); + // -mrelax is default, unless -mno-relax is specified. if (Args.hasFlag(options::OPT_mrelax, options::OPT_mno_relax, true)) Features.push_back("+relax"); diff --git a/clang/test/Driver/riscv-fixed-x-register.c b/clang/test/Driver/riscv-fixed-x-register.c new file mode 100644 --- /dev/null +++ b/clang/test/Driver/riscv-fixed-x-register.c @@ -0,0 +1,341 @@ +// RUN: %clang -target riscv32 -ffixed-x1 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-X1 < %t %s +// RUN: %clang -target riscv64 -ffixed-x1 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-X1 < %t %s +// CHECK-FIXED-X1: "-target-feature" "+reserve-x1" + +// RUN: %clang -target riscv32 -ffixed-x2 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-X2 < %t %s +// RUN: %clang -target riscv64 -ffixed-x2 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-X2 < %t %s +// CHECK-FIXED-X2: "-target-feature" "+reserve-x2" + +// RUN: %clang -target riscv32 -ffixed-x3 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-X3 < %t %s +// RUN: %clang -target riscv64 -ffixed-x3 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-X3 < %t %s +// CHECK-FIXED-X3: "-target-feature" "+reserve-x3" + +// RUN: %clang -target riscv32 -ffixed-x4 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-X4 < %t %s +// RUN: %clang -target riscv64 -ffixed-x4 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-X4 < %t %s +// CHECK-FIXED-X4: "-target-feature" "+reserve-x4" + +// RUN: %clang -target riscv32 -ffixed-x5 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-X5 < %t %s +// RUN: %clang -target riscv64 -ffixed-x5 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-X5 < %t %s +// CHECK-FIXED-X5: "-target-feature" "+reserve-x5" + +// RUN: %clang -target riscv32 -ffixed-x6 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-X6 < %t %s +// RUN: %clang -target riscv64 -ffixed-x6 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-X6 < %t %s +// CHECK-FIXED-X6: "-target-feature" "+reserve-x6" + +// RUN: %clang -target riscv32 -ffixed-x7 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-X7 < %t %s +// RUN: %clang -target riscv64 -ffixed-x7 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-X7 < %t %s +// CHECK-FIXED-X7: "-target-feature" "+reserve-x7" + +// RUN: %clang -target riscv32 -ffixed-x8 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-X8 < %t %s +// RUN: %clang -target riscv64 -ffixed-x8 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-X8 < %t %s +// CHECK-FIXED-X8: "-target-feature" "+reserve-x8" + +// RUN: %clang -target riscv32 -ffixed-x9 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-X9 < %t %s +// RUN: %clang -target riscv64 -ffixed-x9 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-X9 < %t %s +// CHECK-FIXED-X9: "-target-feature" "+reserve-x9" + +// RUN: %clang -target riscv32 -ffixed-x10 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-X10 < %t %s +// RUN: %clang -target riscv64 -ffixed-x10 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-X10 < %t %s +// CHECK-FIXED-X10: "-target-feature" "+reserve-x10" + +// RUN: %clang -target riscv32 -ffixed-x11 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-X11 < %t %s +// RUN: %clang -target riscv64 -ffixed-x11 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-X11 < %t %s +// CHECK-FIXED-X11: "-target-feature" "+reserve-x11" + +// RUN: %clang -target riscv32 -ffixed-x12 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-X12 < %t %s +// RUN: %clang -target riscv64 -ffixed-x12 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-X12 < %t %s +// CHECK-FIXED-X12: "-target-feature" "+reserve-x12" + +// RUN: %clang -target riscv32 -ffixed-x13 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-X13 < %t %s +// RUN: %clang -target riscv64 -ffixed-x13 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-X13 < %t %s +// CHECK-FIXED-X13: "-target-feature" "+reserve-x13" + +// RUN: %clang -target riscv32 -ffixed-x14 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-X14 < %t %s +// RUN: %clang -target riscv64 -ffixed-x14 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-X14 < %t %s +// CHECK-FIXED-X14: "-target-feature" "+reserve-x14" + +// RUN: %clang -target riscv32 -ffixed-x15 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-X15 < %t %s +// RUN: %clang -target riscv64 -ffixed-x15 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-X15 < %t %s +// CHECK-FIXED-X15: "-target-feature" "+reserve-x15" + +// RUN: %clang -target riscv32 -ffixed-x16 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-X16 < %t %s +// RUN: %clang -target riscv64 -ffixed-x16 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-X16 < %t %s +// CHECK-FIXED-X16: "-target-feature" "+reserve-x16" + +// RUN: %clang -target riscv32 -ffixed-x17 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-X17 < %t %s +// RUN: %clang -target riscv64 -ffixed-x17 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-X17 < %t %s +// CHECK-FIXED-X17: "-target-feature" "+reserve-x17" + +// RUN: %clang -target riscv32 -ffixed-x18 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-X18 < %t %s +// RUN: %clang -target riscv64 -ffixed-x18 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-X18 < %t %s +// CHECK-FIXED-X18: "-target-feature" "+reserve-x18" + +// RUN: %clang -target riscv32 -ffixed-x19 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-X19 < %t %s +// RUN: %clang -target riscv64 -ffixed-x19 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-X19 < %t %s +// CHECK-FIXED-X19: "-target-feature" "+reserve-x19" + +// RUN: %clang -target riscv32 -ffixed-x20 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-X20 < %t %s +// RUN: %clang -target riscv64 -ffixed-x20 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-X20 < %t %s +// CHECK-FIXED-X20: "-target-feature" "+reserve-x20" + +// RUN: %clang -target riscv32 -ffixed-x21 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-X21 < %t %s +// RUN: %clang -target riscv64 -ffixed-x21 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-X21 < %t %s +// CHECK-FIXED-X21: "-target-feature" "+reserve-x21" + +// RUN: %clang -target riscv32 -ffixed-x22 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-X22 < %t %s +// RUN: %clang -target riscv64 -ffixed-x22 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-X22 < %t %s +// CHECK-FIXED-X22: "-target-feature" "+reserve-x22" + +// RUN: %clang -target riscv32 -ffixed-x23 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-X23 < %t %s +// RUN: %clang -target riscv64 -ffixed-x23 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-X23 < %t %s +// CHECK-FIXED-X23: "-target-feature" "+reserve-x23" + +// RUN: %clang -target riscv32 -ffixed-x24 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-X24 < %t %s +// RUN: %clang -target riscv64 -ffixed-x24 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-X24 < %t %s +// CHECK-FIXED-X24: "-target-feature" "+reserve-x24" + +// RUN: %clang -target riscv32 -ffixed-x25 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-X25 < %t %s +// RUN: %clang -target riscv64 -ffixed-x25 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-X25 < %t %s +// CHECK-FIXED-X25: "-target-feature" "+reserve-x25" + +// RUN: %clang -target riscv32 -ffixed-x26 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-X26 < %t %s +// RUN: %clang -target riscv64 -ffixed-x26 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-X26 < %t %s +// CHECK-FIXED-X26: "-target-feature" "+reserve-x26" + +// RUN: %clang -target riscv32 -ffixed-x27 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-X27 < %t %s +// RUN: %clang -target riscv64 -ffixed-x27 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-X27 < %t %s +// CHECK-FIXED-X27: "-target-feature" "+reserve-x27" + +// RUN: %clang -target riscv32 -ffixed-x28 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-X28 < %t %s +// RUN: %clang -target riscv64 -ffixed-x28 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-X28 < %t %s +// CHECK-FIXED-X28: "-target-feature" "+reserve-x28" + +// RUN: %clang -target riscv32 -ffixed-x29 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-X29 < %t %s +// RUN: %clang -target riscv64 -ffixed-x29 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-X29 < %t %s +// CHECK-FIXED-X29: "-target-feature" "+reserve-x29" + +// RUN: %clang -target riscv32 -ffixed-x30 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-X30 < %t %s +// RUN: %clang -target riscv64 -ffixed-x30 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-X30 < %t %s +// CHECK-FIXED-X30: "-target-feature" "+reserve-x30" + +// RUN: %clang -target riscv32 -ffixed-x31 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-X31 < %t %s +// RUN: %clang -target riscv64 -ffixed-x31 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-X31 < %t %s +// CHECK-FIXED-X31: "-target-feature" "+reserve-x31" + +// Test multiple of reserve-x# options together. +// RUN: %clang -target riscv32 \ +// RUN: -ffixed-x1 \ +// RUN: -ffixed-x2 \ +// RUN: -ffixed-x18 \ +// RUN: -### %s 2> %t +// RUN: FileCheck \ +// RUN: --check-prefix=CHECK-FIXED-X1 \ +// RUN: --check-prefix=CHECK-FIXED-X2 \ +// RUN: --check-prefix=CHECK-FIXED-X18 \ +// RUN: < %t %s +// RUN: %clang -target riscv64 \ +// RUN: -ffixed-x1 \ +// RUN: -ffixed-x2 \ +// RUN: -ffixed-x18 \ +// RUN: -### %s 2> %t +// RUN: FileCheck \ +// RUN: --check-prefix=CHECK-FIXED-X1 \ +// RUN: --check-prefix=CHECK-FIXED-X2 \ +// RUN: --check-prefix=CHECK-FIXED-X18 \ +// RUN: < %t %s + +// Test all reserve-x# options together. +// RUN: %clang -target riscv32 \ +// RUN: -ffixed-x1 \ +// RUN: -ffixed-x2 \ +// RUN: -ffixed-x3 \ +// RUN: -ffixed-x4 \ +// RUN: -ffixed-x5 \ +// RUN: -ffixed-x6 \ +// RUN: -ffixed-x7 \ +// RUN: -ffixed-x8 \ +// RUN: -ffixed-x9 \ +// RUN: -ffixed-x10 \ +// RUN: -ffixed-x11 \ +// RUN: -ffixed-x12 \ +// RUN: -ffixed-x13 \ +// RUN: -ffixed-x14 \ +// RUN: -ffixed-x15 \ +// RUN: -ffixed-x16 \ +// RUN: -ffixed-x17 \ +// RUN: -ffixed-x18 \ +// RUN: -ffixed-x19 \ +// RUN: -ffixed-x20 \ +// RUN: -ffixed-x21 \ +// RUN: -ffixed-x22 \ +// RUN: -ffixed-x23 \ +// RUN: -ffixed-x24 \ +// RUN: -ffixed-x25 \ +// RUN: -ffixed-x26 \ +// RUN: -ffixed-x27 \ +// RUN: -ffixed-x28 \ +// RUN: -ffixed-x29 \ +// RUN: -ffixed-x30 \ +// RUN: -ffixed-x31 \ +// RUN: -### %s 2> %t +// RUN: FileCheck \ +// RUN: --check-prefix=CHECK-FIXED-X1 \ +// RUN: --check-prefix=CHECK-FIXED-X2 \ +// RUN: --check-prefix=CHECK-FIXED-X3 \ +// RUN: --check-prefix=CHECK-FIXED-X4 \ +// RUN: --check-prefix=CHECK-FIXED-X5 \ +// RUN: --check-prefix=CHECK-FIXED-X6 \ +// RUN: --check-prefix=CHECK-FIXED-X7 \ +// RUN: --check-prefix=CHECK-FIXED-X8 \ +// RUN: --check-prefix=CHECK-FIXED-X9 \ +// RUN: --check-prefix=CHECK-FIXED-X10 \ +// RUN: --check-prefix=CHECK-FIXED-X11 \ +// RUN: --check-prefix=CHECK-FIXED-X12 \ +// RUN: --check-prefix=CHECK-FIXED-X13 \ +// RUN: --check-prefix=CHECK-FIXED-X14 \ +// RUN: --check-prefix=CHECK-FIXED-X15 \ +// RUN: --check-prefix=CHECK-FIXED-X16 \ +// RUN: --check-prefix=CHECK-FIXED-X17 \ +// RUN: --check-prefix=CHECK-FIXED-X18 \ +// RUN: --check-prefix=CHECK-FIXED-X19 \ +// RUN: --check-prefix=CHECK-FIXED-X20 \ +// RUN: --check-prefix=CHECK-FIXED-X21 \ +// RUN: --check-prefix=CHECK-FIXED-X22 \ +// RUN: --check-prefix=CHECK-FIXED-X23 \ +// RUN: --check-prefix=CHECK-FIXED-X24 \ +// RUN: --check-prefix=CHECK-FIXED-X25 \ +// RUN: --check-prefix=CHECK-FIXED-X26 \ +// RUN: --check-prefix=CHECK-FIXED-X27 \ +// RUN: --check-prefix=CHECK-FIXED-X28 \ +// RUN: --check-prefix=CHECK-FIXED-X29 \ +// RUN: --check-prefix=CHECK-FIXED-X30 \ +// RUN: --check-prefix=CHECK-FIXED-X31 \ +// RUN: < %t %s +// RUN: %clang -target riscv64 \ +// RUN: -ffixed-x1 \ +// RUN: -ffixed-x2 \ +// RUN: -ffixed-x3 \ +// RUN: -ffixed-x4 \ +// RUN: -ffixed-x5 \ +// RUN: -ffixed-x6 \ +// RUN: -ffixed-x7 \ +// RUN: -ffixed-x8 \ +// RUN: -ffixed-x9 \ +// RUN: -ffixed-x10 \ +// RUN: -ffixed-x11 \ +// RUN: -ffixed-x12 \ +// RUN: -ffixed-x13 \ +// RUN: -ffixed-x14 \ +// RUN: -ffixed-x15 \ +// RUN: -ffixed-x16 \ +// RUN: -ffixed-x17 \ +// RUN: -ffixed-x18 \ +// RUN: -ffixed-x19 \ +// RUN: -ffixed-x20 \ +// RUN: -ffixed-x21 \ +// RUN: -ffixed-x22 \ +// RUN: -ffixed-x23 \ +// RUN: -ffixed-x24 \ +// RUN: -ffixed-x25 \ +// RUN: -ffixed-x26 \ +// RUN: -ffixed-x27 \ +// RUN: -ffixed-x28 \ +// RUN: -ffixed-x29 \ +// RUN: -ffixed-x30 \ +// RUN: -ffixed-x31 \ +// RUN: -### %s 2> %t +// RUN: FileCheck \ +// RUN: --check-prefix=CHECK-FIXED-X1 \ +// RUN: --check-prefix=CHECK-FIXED-X2 \ +// RUN: --check-prefix=CHECK-FIXED-X3 \ +// RUN: --check-prefix=CHECK-FIXED-X4 \ +// RUN: --check-prefix=CHECK-FIXED-X5 \ +// RUN: --check-prefix=CHECK-FIXED-X6 \ +// RUN: --check-prefix=CHECK-FIXED-X7 \ +// RUN: --check-prefix=CHECK-FIXED-X8 \ +// RUN: --check-prefix=CHECK-FIXED-X9 \ +// RUN: --check-prefix=CHECK-FIXED-X10 \ +// RUN: --check-prefix=CHECK-FIXED-X11 \ +// RUN: --check-prefix=CHECK-FIXED-X12 \ +// RUN: --check-prefix=CHECK-FIXED-X13 \ +// RUN: --check-prefix=CHECK-FIXED-X14 \ +// RUN: --check-prefix=CHECK-FIXED-X15 \ +// RUN: --check-prefix=CHECK-FIXED-X16 \ +// RUN: --check-prefix=CHECK-FIXED-X17 \ +// RUN: --check-prefix=CHECK-FIXED-X18 \ +// RUN: --check-prefix=CHECK-FIXED-X19 \ +// RUN: --check-prefix=CHECK-FIXED-X20 \ +// RUN: --check-prefix=CHECK-FIXED-X21 \ +// RUN: --check-prefix=CHECK-FIXED-X22 \ +// RUN: --check-prefix=CHECK-FIXED-X23 \ +// RUN: --check-prefix=CHECK-FIXED-X24 \ +// RUN: --check-prefix=CHECK-FIXED-X25 \ +// RUN: --check-prefix=CHECK-FIXED-X26 \ +// RUN: --check-prefix=CHECK-FIXED-X27 \ +// RUN: --check-prefix=CHECK-FIXED-X28 \ +// RUN: --check-prefix=CHECK-FIXED-X29 \ +// RUN: --check-prefix=CHECK-FIXED-X30 \ +// RUN: --check-prefix=CHECK-FIXED-X31 \ +// RUN: < %t %s diff --git a/llvm/lib/Target/RISCV/RISCV.td b/llvm/lib/Target/RISCV/RISCV.td --- a/llvm/lib/Target/RISCV/RISCV.td +++ b/llvm/lib/Target/RISCV/RISCV.td @@ -69,6 +69,11 @@ : SubtargetFeature<"relax", "EnableLinkerRelax", "true", "Enable Linker relaxation.">; +foreach i = {1-31} in + def FeatureReserveX#i : + SubtargetFeature<"reserve-x"#i, "UserReservedRegister[RISCV::X"#i#"]", + "true", "Reserve X"#i>; + //===----------------------------------------------------------------------===// // Named operands for CSR instructions. //===----------------------------------------------------------------------===// diff --git a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp --- a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp @@ -18,6 +18,7 @@ #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/RegisterScavenging.h" +#include "llvm/IR/DiagnosticInfo.h" #include "llvm/MC/MCDwarf.h" using namespace llvm; @@ -131,6 +132,12 @@ if (StackSize == 0 && !MFI.adjustsStack()) return; + // If the stack pointer has been marked as reserved, then produce an error if + // the frame requires stack allocation + if (STI.isRegisterReservedByUser(SPReg)) + MF.getFunction().getContext().diagnose(DiagnosticInfoUnsupported{ + MF.getFunction(), "Stack pointer required, but has been reserved."}); + uint64_t FirstSPAdjustAmount = getFirstSPAdjustAmount(MF); // Split the SP adjustment to reduce the offsets of callee saved spill. if (FirstSPAdjustAmount) @@ -167,6 +174,10 @@ // Generate new FP. if (hasFP(MF)) { + if (STI.isRegisterReservedByUser(FPReg)) + MF.getFunction().getContext().diagnose(DiagnosticInfoUnsupported{ + MF.getFunction(), "Frame pointer required, but has been reserved."}); + adjustReg(MBB, MBBI, DL, FPReg, SPReg, StackSize - RVFI->getVarArgsSaveSize(), MachineInstr::FrameSetup); diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.h b/llvm/lib/Target/RISCV/RISCVISelLowering.h --- a/llvm/lib/Target/RISCV/RISCVISelLowering.h +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.h @@ -210,6 +210,12 @@ Value *AlignedAddr, Value *CmpVal, Value *NewVal, Value *Mask, AtomicOrdering Ord) const override; + + /// Generate error diagnostics if any register used by CC has been marked + /// reserved. + void validateCCReservedRegs( + const SmallVectorImpl> &Regs, + MachineFunction &MF) const; }; } diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -2247,6 +2247,16 @@ Glue = Chain.getValue(1); } + // Validate that none of the argument registers have been marked as + // reserved, if so report an error. Do the same for the return address if this + // is not a tailcall. + validateCCReservedRegs(RegsToPass, MF); + if (!IsTailCall && + MF.getSubtarget().isRegisterReservedByUser(RISCV::X1)) + MF.getFunction().getContext().diagnose(DiagnosticInfoUnsupported{ + MF.getFunction(), + "Return address register required, but has been reserved."}); + // If the callee is a GlobalAddress/ExternalSymbol node, turn it into a // TargetGlobalAddress/TargetExternalSymbol node so that legalize won't // split it and then direct call can be matched by PseudoCALL. @@ -2362,6 +2372,9 @@ const SmallVectorImpl &Outs, const SmallVectorImpl &OutVals, const SDLoc &DL, SelectionDAG &DAG) const { + const MachineFunction &MF = DAG.getMachineFunction(); + const RISCVSubtarget &STI = MF.getSubtarget(); + // Stores the assignment of the return value to a location. SmallVector RVLocs; @@ -2391,6 +2404,13 @@ Register RegLo = VA.getLocReg(); assert(RegLo < RISCV::X31 && "Invalid register pair"); Register RegHi = RegLo + 1; + + if (STI.isRegisterReservedByUser(RegLo) || + STI.isRegisterReservedByUser(RegHi)) + MF.getFunction().getContext().diagnose(DiagnosticInfoUnsupported{ + MF.getFunction(), + "Return value register required, but has been reserved."}); + Chain = DAG.getCopyToReg(Chain, DL, RegLo, Lo, Glue); Glue = Chain.getValue(1); RetOps.push_back(DAG.getRegister(RegLo, MVT::i32)); @@ -2402,6 +2422,11 @@ Val = convertValVTToLocVT(DAG, Val, VA, DL); Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), Val, Glue); + if (STI.isRegisterReservedByUser(VA.getLocReg())) + MF.getFunction().getContext().diagnose(DiagnosticInfoUnsupported{ + MF.getFunction(), + "Return value register required, but has been reserved."}); + // Guarantee that all emitted copies are stuck together. Glue = Chain.getValue(1); RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT())); @@ -2440,6 +2465,19 @@ return DAG.getNode(RISCVISD::RET_FLAG, DL, MVT::Other, RetOps); } +void RISCVTargetLowering::validateCCReservedRegs( + const SmallVectorImpl> &Regs, + MachineFunction &MF) const { + const Function &F = MF.getFunction(); + const RISCVSubtarget &STI = MF.getSubtarget(); + + if (std::any_of(std::begin(Regs), std::end(Regs), [&STI](auto Reg) { + return STI.isRegisterReservedByUser(Reg.first); + })) + F.getContext().diagnose(DiagnosticInfoUnsupported{ + F, "Argument register required, but has been reserved."}); +} + const char *RISCVTargetLowering::getTargetNodeName(unsigned Opcode) const { switch ((RISCVISD::NodeType)Opcode) { case RISCVISD::FIRST_NUMBER: diff --git a/llvm/lib/Target/RISCV/RISCVRegisterInfo.h b/llvm/lib/Target/RISCV/RISCVRegisterInfo.h --- a/llvm/lib/Target/RISCV/RISCVRegisterInfo.h +++ b/llvm/lib/Target/RISCV/RISCVRegisterInfo.h @@ -30,6 +30,8 @@ const MCPhysReg *getCalleeSavedRegs(const MachineFunction *MF) const override; BitVector getReservedRegs(const MachineFunction &MF) const override; + bool isAsmClobberable(const MachineFunction &MF, + unsigned PhysReg) const override; bool isConstantPhysReg(unsigned PhysReg) const override; diff --git a/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp b/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp --- a/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp +++ b/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp @@ -69,6 +69,12 @@ const TargetFrameLowering *TFI = getFrameLowering(MF); BitVector Reserved(getNumRegs()); + // Mark any registers requested to be reserved as such + for (size_t Reg = 0; Reg < getNumRegs(); Reg++) { + if (MF.getSubtarget().isRegisterReservedByUser(Reg)) + markSuperRegs(Reserved, Reg); + } + // Use markSuperRegs to ensure any register aliases are also reserved markSuperRegs(Reserved, RISCV::X0); // zero markSuperRegs(Reserved, RISCV::X1); // ra @@ -81,6 +87,11 @@ return Reserved; } +bool RISCVRegisterInfo::isAsmClobberable(const MachineFunction &MF, + unsigned PhysReg) const { + return !MF.getSubtarget().isRegisterReservedByUser(PhysReg); +} + bool RISCVRegisterInfo::isConstantPhysReg(unsigned PhysReg) const { return PhysReg == RISCV::X0; } diff --git a/llvm/lib/Target/RISCV/RISCVSubtarget.h b/llvm/lib/Target/RISCV/RISCVSubtarget.h --- a/llvm/lib/Target/RISCV/RISCVSubtarget.h +++ b/llvm/lib/Target/RISCV/RISCVSubtarget.h @@ -46,6 +46,7 @@ unsigned XLen = 32; MVT XLenVT = MVT::i32; RISCVABI::ABI TargetABI = RISCVABI::ABI_Unknown; + BitVector UserReservedRegister; RISCVFrameLowering FrameLowering; RISCVInstrInfo InstrInfo; RISCVRegisterInfo RegInfo; @@ -93,6 +94,10 @@ MVT getXLenVT() const { return XLenVT; } unsigned getXLen() const { return XLen; } RISCVABI::ABI getTargetABI() const { return TargetABI; } + bool isRegisterReservedByUser(Register i) const { + assert(i < RISCV::NUM_TARGET_REGS && "Register out of range"); + return UserReservedRegister[i]; + } protected: // GlobalISel related APIs. diff --git a/llvm/lib/Target/RISCV/RISCVSubtarget.cpp b/llvm/lib/Target/RISCV/RISCVSubtarget.cpp --- a/llvm/lib/Target/RISCV/RISCVSubtarget.cpp +++ b/llvm/lib/Target/RISCV/RISCVSubtarget.cpp @@ -50,6 +50,7 @@ RISCVSubtarget::RISCVSubtarget(const Triple &TT, StringRef CPU, StringRef FS, StringRef ABIName, const TargetMachine &TM) : RISCVGenSubtargetInfo(TT, CPU, FS), + UserReservedRegister(RISCV::NUM_TARGET_REGS), FrameLowering(initializeSubtargetDependencies(TT, CPU, FS, ABIName)), InstrInfo(*this), RegInfo(getHwMode()), TLInfo(TM, *this) { CallLoweringInfo.reset(new RISCVCallLowering(*getTargetLowering())); diff --git a/llvm/test/CodeGen/RISCV/reserved-reg-errors.ll b/llvm/test/CodeGen/RISCV/reserved-reg-errors.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/reserved-reg-errors.ll @@ -0,0 +1,36 @@ +; RUN: not llc -mtriple=riscv32 -mattr=+reserve-x1 < %s 2>&1 | FileCheck %s -check-prefix=X1 +; RUN: not llc -mtriple=riscv64 -mattr=+reserve-x1 < %s 2>&1 | FileCheck %s -check-prefix=X1 +; RUN: not llc -mtriple=riscv32 -mattr=+reserve-x2 < %s 2>&1 | FileCheck %s -check-prefix=X2 +; RUN: not llc -mtriple=riscv64 -mattr=+reserve-x2 < %s 2>&1 | FileCheck %s -check-prefix=X2 +; RUN: not llc -mtriple=riscv32 -mattr=+reserve-x8 < %s 2>&1 | FileCheck %s -check-prefix=X8 +; RUN: not llc -mtriple=riscv64 -mattr=+reserve-x8 < %s 2>&1 | FileCheck %s -check-prefix=X8 +; RUN: not llc -mtriple=riscv32 -mattr=+reserve-x10 < %s 2>&1 | FileCheck %s -check-prefix=X10 +; RUN: not llc -mtriple=riscv64 -mattr=+reserve-x10 < %s 2>&1 | FileCheck %s -check-prefix=X10 +; RUN: llc -mtriple=riscv32 -mattr=+reserve-x11 < %s 2>&1 | FileCheck %s -check-prefix=X11 +; RUN: llc -mtriple=riscv32 -mattr=+reserve-x11 < %s 2>&1 | FileCheck %s -check-prefix=X11 +; RUN: llc -mtriple=riscv32 <%s +; RUN: llc -mtriple=riscv64 <%s + +; This tests combinations when we would expect an error to be produced because +; a reserved register is required by the default ABI. The final test checks no +; errors are produced when no registers are reserved. + +define i32 @caller(i32 %a) #0 { +; X1: in function caller {{.*}} Return address register required, but has been reserved. +; X2: in function caller {{.*}} Stack pointer required, but has been reserved. +; X8: in function caller {{.*}} Frame pointer required, but has been reserved. +; X10: in function caller {{.*}} Argument register required, but has been reserved. +; X10: in function caller {{.*}} Return value register required, but has been reserved. + %call = call i32 @callee(i32 0) + ret i32 %call +} + +declare i32 @callee(i32 %a) + +define void @clobber() { +; X11: warning: inline asm clobber list contains reserved registers: X11 + call void asm sideeffect "nop", "~{x11}"() + ret void +} + +attributes #0 = { "frame-pointer"="all" } diff --git a/llvm/test/CodeGen/RISCV/reserved-regs.ll b/llvm/test/CodeGen/RISCV/reserved-regs.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/reserved-regs.ll @@ -0,0 +1,130 @@ +; RUN: llc -mtriple=riscv32 -mattr=+reserve-x3 -verify-machineinstrs < %s | FileCheck %s -check-prefix=X3 +; RUN: llc -mtriple=riscv64 -mattr=+reserve-x3 -verify-machineinstrs < %s | FileCheck %s -check-prefix=X3 +; RUN: llc -mtriple=riscv32 -mattr=+reserve-x4 -verify-machineinstrs < %s | FileCheck %s -check-prefix=X4 +; RUN: llc -mtriple=riscv64 -mattr=+reserve-x4 -verify-machineinstrs < %s | FileCheck %s -check-prefix=X4 +; RUN: llc -mtriple=riscv32 -mattr=+reserve-x5 -verify-machineinstrs < %s | FileCheck %s -check-prefix=X5 +; RUN: llc -mtriple=riscv64 -mattr=+reserve-x5 -verify-machineinstrs < %s | FileCheck %s -check-prefix=X5 +; RUN: llc -mtriple=riscv32 -mattr=+reserve-x6 -verify-machineinstrs < %s | FileCheck %s -check-prefix=X6 +; RUN: llc -mtriple=riscv64 -mattr=+reserve-x6 -verify-machineinstrs < %s | FileCheck %s -check-prefix=X6 +; RUN: llc -mtriple=riscv32 -mattr=+reserve-x7 -verify-machineinstrs < %s | FileCheck %s -check-prefix=X7 +; RUN: llc -mtriple=riscv64 -mattr=+reserve-x7 -verify-machineinstrs < %s | FileCheck %s -check-prefix=X7 +; RUN: llc -mtriple=riscv32 -mattr=+reserve-x8 -verify-machineinstrs < %s | FileCheck %s -check-prefix=X8 +; RUN: llc -mtriple=riscv64 -mattr=+reserve-x8 -verify-machineinstrs < %s | FileCheck %s -check-prefix=X8 +; RUN: llc -mtriple=riscv32 -mattr=+reserve-x9 -verify-machineinstrs < %s | FileCheck %s -check-prefix=X9 +; RUN: llc -mtriple=riscv64 -mattr=+reserve-x9 -verify-machineinstrs < %s | FileCheck %s -check-prefix=X9 +; RUN: llc -mtriple=riscv32 -mattr=+reserve-x10 -verify-machineinstrs < %s | FileCheck %s -check-prefix=X10 +; RUN: llc -mtriple=riscv64 -mattr=+reserve-x10 -verify-machineinstrs < %s | FileCheck %s -check-prefix=X10 +; RUN: llc -mtriple=riscv32 -mattr=+reserve-x11 -verify-machineinstrs < %s | FileCheck %s -check-prefix=X11 +; RUN: llc -mtriple=riscv64 -mattr=+reserve-x11 -verify-machineinstrs < %s | FileCheck %s -check-prefix=X11 +; RUN: llc -mtriple=riscv32 -mattr=+reserve-x12 -verify-machineinstrs < %s | FileCheck %s -check-prefix=X12 +; RUN: llc -mtriple=riscv64 -mattr=+reserve-x12 -verify-machineinstrs < %s | FileCheck %s -check-prefix=X12 +; RUN: llc -mtriple=riscv32 -mattr=+reserve-x13 -verify-machineinstrs < %s | FileCheck %s -check-prefix=X13 +; RUN: llc -mtriple=riscv64 -mattr=+reserve-x13 -verify-machineinstrs < %s | FileCheck %s -check-prefix=X13 +; RUN: llc -mtriple=riscv32 -mattr=+reserve-x14 -verify-machineinstrs < %s | FileCheck %s -check-prefix=X14 +; RUN: llc -mtriple=riscv64 -mattr=+reserve-x14 -verify-machineinstrs < %s | FileCheck %s -check-prefix=X14 +; RUN: llc -mtriple=riscv32 -mattr=+reserve-x15 -verify-machineinstrs < %s | FileCheck %s -check-prefix=X15 +; RUN: llc -mtriple=riscv64 -mattr=+reserve-x15 -verify-machineinstrs < %s | FileCheck %s -check-prefix=X15 +; RUN: llc -mtriple=riscv32 -mattr=+reserve-x16 -verify-machineinstrs < %s | FileCheck %s -check-prefix=X16 +; RUN: llc -mtriple=riscv64 -mattr=+reserve-x16 -verify-machineinstrs < %s | FileCheck %s -check-prefix=X16 +; RUN: llc -mtriple=riscv32 -mattr=+reserve-x17 -verify-machineinstrs < %s | FileCheck %s -check-prefix=X17 +; RUN: llc -mtriple=riscv64 -mattr=+reserve-x17 -verify-machineinstrs < %s | FileCheck %s -check-prefix=X17 +; RUN: llc -mtriple=riscv32 -mattr=+reserve-x18 -verify-machineinstrs < %s | FileCheck %s -check-prefix=X18 +; RUN: llc -mtriple=riscv64 -mattr=+reserve-x18 -verify-machineinstrs < %s | FileCheck %s -check-prefix=X18 +; RUN: llc -mtriple=riscv32 -mattr=+reserve-x19 -verify-machineinstrs < %s | FileCheck %s -check-prefix=X19 +; RUN: llc -mtriple=riscv64 -mattr=+reserve-x19 -verify-machineinstrs < %s | FileCheck %s -check-prefix=X19 +; RUN: llc -mtriple=riscv32 -mattr=+reserve-x20 -verify-machineinstrs < %s | FileCheck %s -check-prefix=X20 +; RUN: llc -mtriple=riscv64 -mattr=+reserve-x20 -verify-machineinstrs < %s | FileCheck %s -check-prefix=X20 +; RUN: llc -mtriple=riscv32 -mattr=+reserve-x21 -verify-machineinstrs < %s | FileCheck %s -check-prefix=X21 +; RUN: llc -mtriple=riscv64 -mattr=+reserve-x21 -verify-machineinstrs < %s | FileCheck %s -check-prefix=X21 +; RUN: llc -mtriple=riscv32 -mattr=+reserve-x22 -verify-machineinstrs < %s | FileCheck %s -check-prefix=X22 +; RUN: llc -mtriple=riscv64 -mattr=+reserve-x22 -verify-machineinstrs < %s | FileCheck %s -check-prefix=X22 +; RUN: llc -mtriple=riscv32 -mattr=+reserve-x23 -verify-machineinstrs < %s | FileCheck %s -check-prefix=X23 +; RUN: llc -mtriple=riscv64 -mattr=+reserve-x23 -verify-machineinstrs < %s | FileCheck %s -check-prefix=X23 +; RUN: llc -mtriple=riscv32 -mattr=+reserve-x24 -verify-machineinstrs < %s | FileCheck %s -check-prefix=X24 +; RUN: llc -mtriple=riscv64 -mattr=+reserve-x24 -verify-machineinstrs < %s | FileCheck %s -check-prefix=X24 +; RUN: llc -mtriple=riscv32 -mattr=+reserve-x25 -verify-machineinstrs < %s | FileCheck %s -check-prefix=X25 +; RUN: llc -mtriple=riscv64 -mattr=+reserve-x25 -verify-machineinstrs < %s | FileCheck %s -check-prefix=X25 +; RUN: llc -mtriple=riscv32 -mattr=+reserve-x26 -verify-machineinstrs < %s | FileCheck %s -check-prefix=X26 +; RUN: llc -mtriple=riscv64 -mattr=+reserve-x26 -verify-machineinstrs < %s | FileCheck %s -check-prefix=X26 +; RUN: llc -mtriple=riscv32 -mattr=+reserve-x27 -verify-machineinstrs < %s | FileCheck %s -check-prefix=X27 +; RUN: llc -mtriple=riscv64 -mattr=+reserve-x27 -verify-machineinstrs < %s | FileCheck %s -check-prefix=X27 +; RUN: llc -mtriple=riscv32 -mattr=+reserve-x28 -verify-machineinstrs < %s | FileCheck %s -check-prefix=X28 +; RUN: llc -mtriple=riscv64 -mattr=+reserve-x28 -verify-machineinstrs < %s | FileCheck %s -check-prefix=X28 +; RUN: llc -mtriple=riscv32 -mattr=+reserve-x29 -verify-machineinstrs < %s | FileCheck %s -check-prefix=X29 +; RUN: llc -mtriple=riscv64 -mattr=+reserve-x29 -verify-machineinstrs < %s | FileCheck %s -check-prefix=X29 +; RUN: llc -mtriple=riscv32 -mattr=+reserve-x30 -verify-machineinstrs < %s | FileCheck %s -check-prefix=X30 +; RUN: llc -mtriple=riscv64 -mattr=+reserve-x30 -verify-machineinstrs < %s | FileCheck %s -check-prefix=X30 +; RUN: llc -mtriple=riscv32 -mattr=+reserve-x31 -verify-machineinstrs < %s | FileCheck %s -check-prefix=X31 +; RUN: llc -mtriple=riscv64 -mattr=+reserve-x31 -verify-machineinstrs < %s | FileCheck %s -check-prefix=X31 + +; This program is free to use all registers, but needs a stack pointer for +; spill values, so do not test for reserving the stack pointer. + +; Used to exhaust all registers +@var = global [32 x i64] zeroinitializer + +define void @foo() { + %1 = load volatile [32 x i64], [32 x i64]* @var + store volatile [32 x i64] %1, [32 x i64]* @var + +; X3-NOT: lw gp, +; X3-NOT: ld gp, +; X4-NOT: lw tp, +; X4-NOT: ld tp, +; X5-NOT: lw t0, +; X5-NOT: ld t0, +; X6-NOT: lw t1, +; X6-NOT: ld t1, +; X7-NOT: lw t2, +; X7-NOT: ld t2, +; X8-NOT: lw s0, +; X8-NOT: ld s0, +; X9-NOT: lw s1, +; X9-NOT: ld s1, +; X10-NOT: lw a0, +; X10-NOT: ld a0, +; X11-NOT: lw a1, +; X11-NOT: ld a1, +; X12-NOT: lw a2, +; X12-NOT: ld a2, +; X13-NOT: lw a3, +; X13-NOT: ld a3, +; X14-NOT: lw a4, +; X14-NOT: ld a4, +; X15-NOT: lw a5, +; X15-NOT: ld a5, +; X16-NOT: lw a6, +; X16-NOT: ld a6, +; X17-NOT: lw a7, +; X17-NOT: ld a7, +; X18-NOT: lw s2, +; X18-NOT: ld s2, +; X19-NOT: lw s3, +; X19-NOT: ld s3, +; X20-NOT: lw s4, +; X20-NOT: ld s4, +; X21-NOT: lw s5, +; X21-NOT: ld s5, +; X22-NOT: lw s6, +; X22-NOT: ld s6, +; X23-NOT: lw s7, +; X23-NOT: ld s7, +; X24-NOT: lw s8, +; X24-NOT: ld s8, +; X25-NOT: lw s9, +; X25-NOT: ld s9, +; X26-NOT: lw s10, +; X26-NOT: ld s10, +; X27-NOT: lw s11, +; X27-NOT: ld s11, +; X28-NOT: lw t3, +; X28-NOT: ld t3, +; X29-NOT: lw t4, +; X29-NOT: ld t4, +; X30-NOT: lw t5, +; X30-NOT: ld t5, +; X31-NOT: lw t6, +; X31-NOT: ld t6, + + ret void +}