Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Overhaul the TargetMachine and LLVMTargetMachine Classes #111234

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 9 additions & 9 deletions llvm/docs/WritingAnLLVMBackend.rst
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ To make your target actually do something, you need to implement a subclass of
``lib/Target/DummyTargetMachine.cpp``, but any file in the ``lib/Target``
directory will be built and should work. To use LLVM's target independent code
generator, you should do what all current machine backends do: create a
subclass of ``LLVMTargetMachine``. (To create a target from scratch, create a
subclass of ``CodeGenCommonTMImpl``. (To create a target from scratch, create a
subclass of ``TargetMachine``.)

To get LLVM to actually build and link your target, you need to run ``cmake``
Expand All @@ -165,15 +165,15 @@ located in the main ``CMakeLists.txt``.
Target Machine
==============

``LLVMTargetMachine`` is designed as a base class for targets implemented with
the LLVM target-independent code generator. The ``LLVMTargetMachine`` class
``CodeGenCommonTMImpl`` is designed as a base class for targets implemented with
the LLVM target-independent code generator. The ``CodeGenCommonTMImpl`` class
should be specialized by a concrete target class that implements the various
virtual methods. ``LLVMTargetMachine`` is defined as a subclass of
``TargetMachine`` in ``include/llvm/Target/TargetMachine.h``. The
``TargetMachine`` class implementation (``TargetMachine.cpp``) also processes
numerous command-line options.
virtual methods. ``CodeGenCommonTMImpl`` is defined as a subclass of
``TargetMachine`` in ``include/llvm/CodeGen/CodeGenCommonTMImpl.h``. The
``TargetMachine`` class implementation (``include/llvm/Target/TargetMachine.cpp``)
also processes numerous command-line options.

To create a concrete target-specific subclass of ``LLVMTargetMachine``, start
To create a concrete target-specific subclass of ``CodeGenCommonTMImpl``, start
by copying an existing ``TargetMachine`` class and header. You should name the
files that you create to reflect your specific target. For instance, for the
SPARC target, name the files ``SparcTargetMachine.h`` and
Expand All @@ -197,7 +197,7 @@ simply return a class member.

class Module;

class SparcTargetMachine : public LLVMTargetMachine {
class SparcTargetMachine : public CodeGenCommonTMImpl {
const DataLayout DataLayout; // Calculates type size & alignment
SparcSubtarget Subtarget;
SparcInstrInfo InstrInfo;
Expand Down
92 changes: 92 additions & 0 deletions llvm/include/llvm/CodeGen/CodeGenCommonTMImpl.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
//===-- CodeGenCommonTMImpl.h -----------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
///
/// \file This file describes the CodeGenCommonTMImpl class, which
/// implements a set of functionality used by \c TargetMachine classes in
/// LLVM that make use of the target-independent code generator.
//===----------------------------------------------------------------------===//
#ifndef LLVM_CODEGEN_CODEGENCOMMONTMIMPL_H
#define LLVM_CODEGEN_CODEGENCOMMONTMIMPL_H
#include "llvm/Target/TargetMachine.h"

namespace llvm {

/// \brief implements a set of functionality in the \c TargetMachine class
/// for targets that make use of the independent code generator (CodeGen)
/// library. Must not be used directly in code unless to inherit its
/// implementation.
class CodeGenCommonTMImpl : public TargetMachine {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this name needs work. CodeGenTargetMachine maybe?

Copy link
Contributor Author

@matinraayai matinraayai Oct 5, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Originally I named it CodeGenTargetMachine, but I picked an ugly name on purpose to remind people not to use this class directly in their code unless they are subclassing it for their targets.

Again, my goal was to remove the need to static cast every time you need a CodeGen-specific feature of the TargetMachine, it's already in the interface. The target of choice has the freedom to not use it and either a) start from scratch in order to use the target-independent code generator, or b) use its own code generation scheme.

This is essentially the best middle ground I found between completely removing LLVMTargetMachine and not breaking the compilation process. With this change, it's as if LLVMTargetMachine was removed from the user's perspective. Meanwhile, this shouldn't cause any havoc on the toolchain compilation process, as all library requirements remain the same (i.e. there's no requirement to link to CodeGen unless you're using the CodeGen-related TM interfaces).

Copy link
Contributor

@arsenm arsenm Oct 9, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still should probably go for the less ugly name (at least the TM part)

protected: // Can only create subclasses.
CodeGenCommonTMImpl(const Target &T, StringRef DataLayoutString,
const Triple &TT, StringRef CPU, StringRef FS,
const TargetOptions &Options, Reloc::Model RM,
CodeModel::Model CM, CodeGenOptLevel OL);

void initAsmInfo();

public:
/// Get a TargetTransformInfo implementation for the target.
///
/// The TTI returned uses the common code generator to answer queries about
/// the IR.
TargetTransformInfo getTargetTransformInfo(const Function &F) const override;
Comment on lines +33 to +37
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TargetTransformInfo isn't really part of the CodeGen interface. This should probably move up to TargetMachine.

I see that TTI does make a little use of TM. Seems to be for managing subtarget instances, plus a few of the odd fields that really should come from the module

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's because it's already in the TargetMachine interface:

https://github.com/matinraayai/llvm-project/blob/b52f940b385cabf51c96004a5d17e3bf0b1cd2e1/llvm/include/llvm/Target/TargetMachine.h#L368

There's no function in CodeGenTargetMachine that is not inherited in TargetMachine; CodeGenTargetMachine is only a collection of TargetMachine interface implementations commonly shared among all targets in LLVM, where all use the target-independent code generator.


/// Create a pass configuration object to be used by addPassToEmitX methods
/// for generating a pipeline of CodeGen passes.
virtual TargetPassConfig *createPassConfig(PassManagerBase &PM) override;

/// Add passes to the specified pass manager to get the specified file
/// emitted. Typically this will involve several steps of code generation.
/// \p MMIWP is an optional parameter that, if set to non-nullptr,
/// will be used to set the MachineModuloInfo for this PM.
bool
addPassesToEmitFile(PassManagerBase &PM, raw_pwrite_stream &Out,
raw_pwrite_stream *DwoOut, CodeGenFileType FileType,
bool DisableVerify = true,
MachineModuleInfoWrapperPass *MMIWP = nullptr) override;

/// Add passes to the specified pass manager to get machine code emitted with
/// the MCJIT. This method returns true if machine code is not supported. It
/// fills the MCContext Ctx pointer which can be used to build custom
/// MCStreamer.
bool addPassesToEmitMC(PassManagerBase &PM, MCContext *&Ctx,
raw_pwrite_stream &Out,
bool DisableVerify = true) override;

/// Adds an AsmPrinter pass to the pipeline that prints assembly or
/// machine code from the MI representation.
bool addAsmPrinter(PassManagerBase &PM, raw_pwrite_stream &Out,
raw_pwrite_stream *DwoOut, CodeGenFileType FileType,
MCContext &Context) override;

Expected<std::unique_ptr<MCStreamer>>
createMCStreamer(raw_pwrite_stream &Out, raw_pwrite_stream *DwoOut,
CodeGenFileType FileType, MCContext &Ctx) override;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In #108690 I'm also trying to use callbacks to avoid these functions in new pass manager.

};

/// Helper method for getting the code model, returning Default if
/// CM does not have a value. The tiny and kernel models will produce
/// an error, so targets that support them or require more complex codemodel
/// selection logic should implement and call their own getEffectiveCodeModel.
inline CodeModel::Model
getEffectiveCodeModel(std::optional<CodeModel::Model> CM,
CodeModel::Model Default) {
if (CM) {
// By default, targets do not support the tiny and kernel models.
if (*CM == CodeModel::Tiny)
report_fatal_error("Target does not support the tiny CodeModel", false);
if (*CM == CodeModel::Kernel)
report_fatal_error("Target does not support the kernel CodeModel", false);
return *CM;
}
return Default;
}

} // namespace llvm

#endif
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing end of file line

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be fixed, but please check this again. My editor either doesn't show it to me or puts too many whitespaces at the end, causing clang format to complain.

8 changes: 4 additions & 4 deletions llvm/include/llvm/CodeGen/MachineFunction.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ class DILocation;
class Function;
class GISelChangeObserver;
class GlobalValue;
class LLVMTargetMachine;
class TargetMachine;
class MachineConstantPool;
class MachineFrameInfo;
class MachineFunction;
Expand Down Expand Up @@ -256,7 +256,7 @@ struct LandingPadInfo {

class LLVM_ABI MachineFunction {
Function &F;
const LLVMTargetMachine &Target;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd expect all of the references in the codegen infrastructure to refer to the codegen dependent subclass

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think there's a need anymore. I'm hoping CodeGenCommonTMImpl is treated as just a set of function implementation, and there won't be any hard requirement on subclassing it if you want to use the target independent code generator (CodeGen) library.

In other words, a Target can just ignore everything in CodeGenCommonTMImpl and start from scratch, but still use the CodeGen library.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you're in MachineFunction, you are definitely using CodeGen. So why wouldn't MachineFunction reference the lowest common subclass for codegen?

const TargetMachine &Target;
const TargetSubtargetInfo *STI;
MCContext &Ctx;

Expand Down Expand Up @@ -634,7 +634,7 @@ class LLVM_ABI MachineFunction {
/// for instructions that have a stack spill fused into them.
const static unsigned int DebugOperandMemNumber;

MachineFunction(Function &F, const LLVMTargetMachine &Target,
MachineFunction(Function &F, const TargetMachine &Target,
const TargetSubtargetInfo &STI, MCContext &Ctx,
unsigned FunctionNum);
MachineFunction(const MachineFunction &) = delete;
Expand Down Expand Up @@ -707,7 +707,7 @@ class LLVM_ABI MachineFunction {
void assignBeginEndSections();

/// getTarget - Return the target machine this machine code is compiled with
const LLVMTargetMachine &getTarget() const { return Target; }
const TargetMachine &getTarget() const { return Target; }

/// getSubtarget - Return the subtarget for which this machine code is being
/// compiled.
Expand Down
6 changes: 3 additions & 3 deletions llvm/include/llvm/CodeGen/MachineFunctionAnalysis.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
namespace llvm {

class MachineFunction;
class LLVMTargetMachine;
class TargetMachine;

/// This analysis create MachineFunction for given Function.
/// To release the MachineFunction, users should invalidate it explicitly.
Expand All @@ -28,7 +28,7 @@ class MachineFunctionAnalysis

static AnalysisKey Key;

const LLVMTargetMachine *TM;
const TargetMachine *TM;

public:
class Result {
Expand All @@ -41,7 +41,7 @@ class MachineFunctionAnalysis
FunctionAnalysisManager::Invalidator &);
};

MachineFunctionAnalysis(const LLVMTargetMachine *TM) : TM(TM){};
MachineFunctionAnalysis(const TargetMachine *TM) : TM(TM) {};
Result run(Function &F, FunctionAnalysisManager &FAM);
};

Expand Down
15 changes: 7 additions & 8 deletions llvm/include/llvm/CodeGen/MachineModuleInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
namespace llvm {

class Function;
class LLVMTargetMachine;
class TargetMachine;
class MachineFunction;
class Module;

Expand Down Expand Up @@ -83,7 +83,7 @@ class MachineModuleInfo {
friend class MachineModuleInfoWrapperPass;
friend class MachineModuleAnalysis;

const LLVMTargetMachine &TM;
const TargetMachine &TM;

/// This is the MCContext used for the entire code generator.
MCContext Context;
Expand All @@ -109,10 +109,9 @@ class MachineModuleInfo {
MachineModuleInfo &operator=(MachineModuleInfo &&MMII) = delete;

public:
explicit MachineModuleInfo(const LLVMTargetMachine *TM = nullptr);
explicit MachineModuleInfo(const TargetMachine *TM = nullptr);

explicit MachineModuleInfo(const LLVMTargetMachine *TM,
MCContext *ExtContext);
explicit MachineModuleInfo(const TargetMachine *TM, MCContext *ExtContext);

MachineModuleInfo(MachineModuleInfo &&MMII);

Expand All @@ -121,7 +120,7 @@ class MachineModuleInfo {
void initialize();
void finalize();

const LLVMTargetMachine &getTarget() const { return TM; }
const TargetMachine &getTarget() const { return TM; }

const MCContext &getContext() const {
return ExternalContext ? *ExternalContext : Context;
Expand Down Expand Up @@ -173,9 +172,9 @@ class MachineModuleInfoWrapperPass : public ImmutablePass {

public:
static char ID; // Pass identification, replacement for typeid
explicit MachineModuleInfoWrapperPass(const LLVMTargetMachine *TM = nullptr);
explicit MachineModuleInfoWrapperPass(const TargetMachine *TM = nullptr);

explicit MachineModuleInfoWrapperPass(const LLVMTargetMachine *TM,
explicit MachineModuleInfoWrapperPass(const TargetMachine *TM,
MCContext *ExtContext);

// Initialization and Finalization
Expand Down
6 changes: 3 additions & 3 deletions llvm/include/llvm/CodeGen/RegisterUsageInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
namespace llvm {

class Function;
class LLVMTargetMachine;
class TargetMachine;

class PhysicalRegisterUsageInfo : public ImmutablePass {
public:
Expand All @@ -41,7 +41,7 @@ class PhysicalRegisterUsageInfo : public ImmutablePass {
}

/// Set TargetMachine which is used to print analysis.
void setTargetMachine(const LLVMTargetMachine &TM);
void setTargetMachine(const TargetMachine &TM);

bool doInitialization(Module &M) override;

Expand All @@ -63,7 +63,7 @@ class PhysicalRegisterUsageInfo : public ImmutablePass {
/// and 1 means content of register will be preserved around function call.
DenseMap<const Function *, std::vector<uint32_t>> RegMasks;

const LLVMTargetMachine *TM = nullptr;
const TargetMachine *TM = nullptr;
};

} // end namespace llvm
Expand Down
4 changes: 2 additions & 2 deletions llvm/include/llvm/CodeGen/ScheduleDAG.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ namespace llvm {

template <class GraphType> struct GraphTraits;
template<class Graph> class GraphWriter;
class LLVMTargetMachine;
class TargetMachine;
class MachineFunction;
class MachineRegisterInfo;
class MCInstrDesc;
Expand Down Expand Up @@ -571,7 +571,7 @@ class TargetRegisterInfo;

class ScheduleDAG {
public:
const LLVMTargetMachine &TM; ///< Target processor
const TargetMachine &TM; ///< Target processor
const TargetInstrInfo *TII; ///< Target instruction information
const TargetRegisterInfo *TRI; ///< Target processor register info
MachineFunction &MF; ///< Machine function
Expand Down
10 changes: 5 additions & 5 deletions llvm/include/llvm/CodeGen/TargetPassConfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

namespace llvm {

class LLVMTargetMachine;
class TargetMachine;
struct MachineSchedContext;
class PassConfigImpl;
class ScheduleDAGInstrs;
Expand Down Expand Up @@ -120,7 +120,7 @@ class TargetPassConfig : public ImmutablePass {
void setStartStopPasses();

protected:
LLVMTargetMachine *TM;
TargetMachine *TM;
PassConfigImpl *Impl = nullptr; // Internal data structures
bool Initialized = false; // Flagged after all passes are configured.

Expand Down Expand Up @@ -148,7 +148,7 @@ class TargetPassConfig : public ImmutablePass {
bool addCoreISelPasses();

public:
TargetPassConfig(LLVMTargetMachine &TM, PassManagerBase &pm);
TargetPassConfig(TargetMachine &TM, PassManagerBase &PM);
// Dummy constructor.
TargetPassConfig();

Expand Down Expand Up @@ -413,7 +413,7 @@ class TargetPassConfig : public ImmutablePass {
virtual void addFastRegAlloc();

/// addOptimizedRegAlloc - Add passes related to register allocation.
/// LLVMTargetMachine provides standard regalloc passes for most targets.
/// CodeGenCommonTMImpl provides standard regalloc passes for most targets.
virtual void addOptimizedRegAlloc();

/// addPreRewrite - Add passes to the optimized register allocation pipeline
Expand Down Expand Up @@ -497,7 +497,7 @@ class TargetPassConfig : public ImmutablePass {
};

void registerCodeGenCallback(PassInstrumentationCallbacks &PIC,
LLVMTargetMachine &);
TargetMachine &);

} // end namespace llvm

Expand Down
2 changes: 1 addition & 1 deletion llvm/include/llvm/Passes/CodeGenPassBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -438,7 +438,7 @@ template <typename DerivedT, typename TargetMachineT> class CodeGenPassBuilder {
Error addFastRegAlloc(AddMachinePass &) const;

/// addOptimizedRegAlloc - Add passes related to register allocation.
/// LLVMTargetMachine provides standard regalloc passes for most targets.
/// CodeGenCommonTMImpl provides standard regalloc passes for most targets.
void addOptimizedRegAlloc(AddMachinePass &) const;

/// Add passes that optimize machine instructions after register allocation.
Expand Down
Loading
Loading