Index: clang/include/clang/Driver/Options.td =================================================================== --- clang/include/clang/Driver/Options.td +++ clang/include/clang/Driver/Options.td @@ -3999,6 +3999,13 @@ def m68040 : Flag<["-"], "m68040">, Group; def m68060 : Flag<["-"], "m68060">, Group; +foreach i = {0-6} in + def ffixed_a#i : Flag<["-"], "ffixed-a"#i>, Group, + HelpText<"Reserve the a"#i#" register (M68k only)">; +foreach i = {0-7} in + def ffixed_d#i : Flag<["-"], "ffixed-d"#i>, Group, + HelpText<"Reserve the d"#i#" register (M68k only)">; + // X86 feature flags def mx87 : Flag<["-"], "mx87">, Group; def mno_x87 : Flag<["-"], "mno-x87">, Group; Index: clang/lib/Driver/ToolChains/Arch/M68k.cpp =================================================================== --- clang/lib/Driver/ToolChains/Arch/M68k.cpp +++ clang/lib/Driver/ToolChains/Arch/M68k.cpp @@ -72,6 +72,38 @@ m68k::FloatABI FloatABI = m68k::getM68kFloatABI(D, Args); if (FloatABI == m68k::FloatABI::Soft) Features.push_back("-hard-float"); + + // Handle '-ffixed-' flags + if (Args.hasArg(options::OPT_ffixed_a0)) + Features.push_back("+reserve-a0"); + if (Args.hasArg(options::OPT_ffixed_a1)) + Features.push_back("+reserve-a1"); + if (Args.hasArg(options::OPT_ffixed_a2)) + Features.push_back("+reserve-a2"); + if (Args.hasArg(options::OPT_ffixed_a3)) + Features.push_back("+reserve-a3"); + if (Args.hasArg(options::OPT_ffixed_a4)) + Features.push_back("+reserve-a4"); + if (Args.hasArg(options::OPT_ffixed_a5)) + Features.push_back("+reserve-a5"); + if (Args.hasArg(options::OPT_ffixed_a6)) + Features.push_back("+reserve-a6"); + if (Args.hasArg(options::OPT_ffixed_d0)) + Features.push_back("+reserve-d0"); + if (Args.hasArg(options::OPT_ffixed_d1)) + Features.push_back("+reserve-d1"); + if (Args.hasArg(options::OPT_ffixed_d2)) + Features.push_back("+reserve-d2"); + if (Args.hasArg(options::OPT_ffixed_d3)) + Features.push_back("+reserve-d3"); + if (Args.hasArg(options::OPT_ffixed_d4)) + Features.push_back("+reserve-d4"); + if (Args.hasArg(options::OPT_ffixed_d5)) + Features.push_back("+reserve-d5"); + if (Args.hasArg(options::OPT_ffixed_d6)) + Features.push_back("+reserve-d6"); + if (Args.hasArg(options::OPT_ffixed_d7)) + Features.push_back("+reserve-d7"); } m68k::FloatABI m68k::getM68kFloatABI(const Driver &D, const ArgList &Args) { Index: clang/test/Driver/m68k-fixed-register.c =================================================================== --- /dev/null +++ clang/test/Driver/m68k-fixed-register.c @@ -0,0 +1,60 @@ +// RUN: %clang -target m68k -ffixed-a0 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-A0 < %t %s +// CHECK-FIXED-A0: "-target-feature" "+reserve-a0" + +// RUN: %clang -target m68k -ffixed-a1 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-A1 < %t %s +// CHECK-FIXED-A1: "-target-feature" "+reserve-a1" + +// RUN: %clang -target m68k -ffixed-a2 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-A2 < %t %s +// CHECK-FIXED-A2: "-target-feature" "+reserve-a2" + +// RUN: %clang -target m68k -ffixed-a3 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-A3 < %t %s +// CHECK-FIXED-A3: "-target-feature" "+reserve-a3" + +// RUN: %clang -target m68k -ffixed-a4 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-A4 < %t %s +// CHECK-FIXED-A4: "-target-feature" "+reserve-a4" + +// RUN: %clang -target m68k -ffixed-a5 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-A5 < %t %s +// CHECK-FIXED-A5: "-target-feature" "+reserve-a5" + +// RUN: %clang -target m68k -ffixed-a6 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-A6 < %t %s +// CHECK-FIXED-A6: "-target-feature" "+reserve-a6" + +// RUN: %clang -target m68k -ffixed-d0 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-D0 < %t %s +// CHECK-FIXED-D0: "-target-feature" "+reserve-d0" + +// RUN: %clang -target m68k -ffixed-d1 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-D1 < %t %s +// CHECK-FIXED-D1: "-target-feature" "+reserve-d1" + +// RUN: %clang -target m68k -ffixed-d2 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-D2 < %t %s +// CHECK-FIXED-D2: "-target-feature" "+reserve-d2" + +// RUN: %clang -target m68k -ffixed-d3 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-D3 < %t %s +// CHECK-FIXED-D3: "-target-feature" "+reserve-d3" + +// RUN: %clang -target m68k -ffixed-d4 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-D4 < %t %s +// CHECK-FIXED-D4: "-target-feature" "+reserve-d4" + +// RUN: %clang -target m68k -ffixed-d5 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-D5 < %t %s +// CHECK-FIXED-D5: "-target-feature" "+reserve-d5" + +// RUN: %clang -target m68k -ffixed-d6 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-D6 < %t %s +// CHECK-FIXED-D6: "-target-feature" "+reserve-d6" + +// RUN: %clang -target m68k -ffixed-d7 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-D7 < %t %s +// CHECK-FIXED-D7: "-target-feature" "+reserve-d7" + Index: llvm/lib/Target/M68k/M68k.td =================================================================== --- llvm/lib/Target/M68k/M68k.td +++ llvm/lib/Target/M68k/M68k.td @@ -47,6 +47,15 @@ "Is M68060 ISA supported", [ FeatureISA40 ]>; +foreach i = {0-6} in + def FeatureReserveA#i : + SubtargetFeature<"reserve-a"#i, "UserReservedRegister[M68k::A"#i#"]", + "true", "Reserve A"#i#" register">; +foreach i = {0-7} in + def FeatureReserveD#i : + SubtargetFeature<"reserve-d"#i, "UserReservedRegister[M68k::D"#i#"]", + "true", "Reserve D"#i#" register">; + //===----------------------------------------------------------------------===// // M68k processors supported. //===----------------------------------------------------------------------===// Index: llvm/lib/Target/M68k/M68kRegisterInfo.cpp =================================================================== --- llvm/lib/Target/M68k/M68kRegisterInfo.cpp +++ llvm/lib/Target/M68k/M68kRegisterInfo.cpp @@ -133,6 +133,12 @@ } }; + // Registers reserved by users + for (size_t Reg = 0, Total = getNumRegs(); Reg != Total; ++Reg) { + if (MF.getSubtarget().isRegisterReservedByUser(Reg)) + setBitVector(Reg); + } + setBitVector(M68k::PC); setBitVector(M68k::SP); Index: llvm/lib/Target/M68k/M68kSubtarget.h =================================================================== --- llvm/lib/Target/M68k/M68kSubtarget.h +++ llvm/lib/Target/M68k/M68kSubtarget.h @@ -18,6 +18,7 @@ #include "M68kISelLowering.h" #include "M68kInstrInfo.h" +#include "llvm/ADT/BitVector.h" #include "llvm/CodeGen/SelectionDAGTargetInfo.h" #include "llvm/CodeGen/TargetSubtargetInfo.h" #include "llvm/IR/DataLayout.h" @@ -47,6 +48,8 @@ enum SubtargetEnum { M00, M10, M20, M30, M40, M60 }; SubtargetEnum SubtargetKind = M00; + BitVector UserReservedRegister; + InstrItineraryData InstrItins; /// Small section is used. @@ -95,6 +98,11 @@ bool isPositionIndependent() const; + bool isRegisterReservedByUser(Register R) const { + assert(R < M68k::NUM_TARGET_REGS && "Register out of range"); + return UserReservedRegister[R]; + } + /// Classify a global variable reference for the current subtarget according /// to how we should reference it in a non-pcrel context. unsigned char classifyLocalReference(const GlobalValue *GV) const; Index: llvm/lib/Target/M68k/M68kSubtarget.cpp =================================================================== --- llvm/lib/Target/M68k/M68kSubtarget.cpp +++ llvm/lib/Target/M68k/M68kSubtarget.cpp @@ -47,7 +47,8 @@ M68kSubtarget::M68kSubtarget(const Triple &TT, StringRef CPU, StringRef FS, const M68kTargetMachine &TM) - : M68kGenSubtargetInfo(TT, CPU, /*TuneCPU*/ CPU, FS), TM(TM), TSInfo(), + : M68kGenSubtargetInfo(TT, CPU, /*TuneCPU*/ CPU, FS), + UserReservedRegister(M68k::NUM_TARGET_REGS), TM(TM), TSInfo(), InstrInfo(initializeSubtargetDependencies(CPU, TT, FS, TM)), FrameLowering(*this, this->getStackAlignment()), TLInfo(TM, *this), TargetTriple(TT) {} Index: llvm/test/CodeGen/M68k/reserved-regs.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/M68k/reserved-regs.ll @@ -0,0 +1,70 @@ +; RUN: llc -mtriple=m68k -mattr="+reserve-a0" < %s | FileCheck --check-prefix=A0 %s +; RUN: llc -mtriple=m68k -mattr="+reserve-a1" < %s | FileCheck --check-prefix=A1 %s +; RUN: llc -mtriple=m68k -mattr="+reserve-a2" < %s | FileCheck --check-prefix=A2 %s +; RUN: llc -mtriple=m68k -mattr="+reserve-a3" < %s | FileCheck --check-prefix=A3 %s +; RUN: llc -mtriple=m68k -mattr="+reserve-a4" < %s | FileCheck --check-prefix=A4 %s +; RUN: llc -mtriple=m68k -mattr="+reserve-a5" < %s | FileCheck --check-prefix=A5 %s +; RUN: llc -mtriple=m68k -mattr="+reserve-a6" < %s | FileCheck --check-prefix=A6 %s +; RUN: llc -mtriple=m68k -mattr="+reserve-d0" < %s | FileCheck --check-prefix=D0 %s +; RUN: llc -mtriple=m68k -mattr="+reserve-d1" < %s | FileCheck --check-prefix=D1 %s +; RUN: llc -mtriple=m68k -mattr="+reserve-d2" < %s | FileCheck --check-prefix=D2 %s +; RUN: llc -mtriple=m68k -mattr="+reserve-d3" < %s | FileCheck --check-prefix=D3 %s +; RUN: llc -mtriple=m68k -mattr="+reserve-d4" < %s | FileCheck --check-prefix=D4 %s +; RUN: llc -mtriple=m68k -mattr="+reserve-d5" < %s | FileCheck --check-prefix=D5 %s +; RUN: llc -mtriple=m68k -mattr="+reserve-d6" < %s | FileCheck --check-prefix=D6 %s +; RUN: llc -mtriple=m68k -mattr="+reserve-d7" < %s | FileCheck --check-prefix=D7 %s + +; Used to exhaust all registers +; +; A better way to do this might be: +; ``` +; @var = global [16 x i32] zeroinitializer +; ... +; %tmp = load load volatile [16 x i32], [16 x i32]* @var +; store volatile [16 x i32] %tmp, [16 x i32]* @var +; ``` +; Which is copied from `test/CodeGen/RISCV/reserved-regs.ll`. +; But currently we have problem doing codegen for the above snippet +; (https://bugs.llvm.org/show_bug.cgi?id=50377). +define void @foo(i32* nocapture readonly %a, i32* nocapture readonly %b, i32* nocapture readonly %c, i32* nocapture readonly %d, + i32* nocapture readonly %a1, i32* nocapture readonly %b1, i32* nocapture readonly %c1, i32* nocapture readonly %d1, + i32* nocapture readonly %a2, i32* nocapture readonly %b2, i32* nocapture readonly %c2, i32* nocapture readonly %d2, + i32* nocapture readonly %a3, i32* nocapture readonly %b3, i32* nocapture readonly %c3, i32* nocapture readonly %d3) { +entry: + %0 = load i32, i32* %a, align 4 + %1 = load i32, i32* %b, align 4 + %2 = load i32, i32* %c, align 4 + %3 = load i32, i32* %d, align 4 + %4 = load i32, i32* %a1, align 4 + %5 = load i32, i32* %b1, align 4 + %6 = load i32, i32* %c1, align 4 + %7 = load i32, i32* %d1, align 4 + %8 = load i32, i32* %a2, align 4 + %9 = load i32, i32* %b2, align 4 + %10 = load i32, i32* %c2, align 4 + %11 = load i32, i32* %d2, align 4 + %12 = load i32, i32* %a3, align 4 + %13 = load i32, i32* %b3, align 4 + %14 = load i32, i32* %c3, align 4 + %15 = load i32, i32* %d3, align 4 + ; A0-NOT: %a0 + ; A1-NOT: %a1 + ; A2-NOT: %a2 + ; A3-NOT: %a3 + ; A4-NOT: %a4 + ; A5-NOT: %a5 + ; A6-NOT: %a6 + ; D0-NOT: %d0 + ; D1-NOT: %d1 + ; D2-NOT: %d2 + ; D3-NOT: %d3 + ; D4-NOT: %d4 + ; D5-NOT: %d5 + ; D6-NOT: %d6 + ; D7-NOT: %d7 + tail call void @bar(i32 %0, i32 %1, i32 %2, i32 %3, i32 %4, i32 %5, i32 %6, i32 %7, i32 %8, i32 %9, i32 %10, i32 %11, i32 %12, i32 %13, i32 %14, i32 %15) + ret void +} + +declare void @bar(i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32) +