Skip to content

Commit

Permalink
MIR: Allow targets to serialize MachineFunctionInfo
Browse files Browse the repository at this point in the history
This has been a very painful missing feature that has made producing
reduced testcases difficult. In particular the various registers
determined for stack access during function lowering were necessary to
avoid undefined register errors in a large percentage of
cases. Implement a subset of the important fields that need to be
preserved for AMDGPU.

Most of the changes are to support targets parsing register fields and
properly reporting errors. The biggest sort-of bug remaining is for
fields that can be initialized from the IR section will be overwritten
by a default initialized machineFunctionInfo section. Another
remaining bug is the machineFunctionInfo section is still printed even
if empty.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@356215 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
arsenm committed Mar 14, 2019
1 parent 4a50374 commit d8706fc
Show file tree
Hide file tree
Showing 31 changed files with 665 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -164,8 +164,8 @@ struct PerFunctionMIParsingState {
PerTargetMIParsingState &Target;

DenseMap<unsigned, MachineBasicBlock *> MBBSlots;
DenseMap<unsigned, VRegInfo*> VRegInfos;
StringMap<VRegInfo*> VRegInfosNamed;
DenseMap<unsigned, VRegInfo *> VRegInfos;
StringMap<VRegInfo *> VRegInfosNamed;
DenseMap<unsigned, int> FixedStackObjectSlots;
DenseMap<unsigned, int> StackObjectSlots;
DenseMap<unsigned, unsigned> ConstantPoolSlots;
Expand Down
17 changes: 17 additions & 0 deletions include/llvm/CodeGen/MIRYamlMapping.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ struct StringValue {

StringValue() = default;
StringValue(std::string Value) : Value(std::move(Value)) {}
StringValue(const char Val[]) : Value(Val) {}

bool operator==(const StringValue &Other) const {
return Value == Other.Value;
Expand Down Expand Up @@ -482,6 +483,20 @@ template <> struct MappingTraits<MachineFrameInfo> {
}
};

/// Targets should override this in a way that mirrors the implementation of
/// llvm::MachineFunctionInfo.
struct MachineFunctionInfo {
virtual ~MachineFunctionInfo() {}
virtual void mappingImpl(IO &YamlIO) {}
};

template <> struct MappingTraits<std::unique_ptr<MachineFunctionInfo>> {
static void mapping(IO &YamlIO, std::unique_ptr<MachineFunctionInfo> &MFI) {
if (MFI)
MFI->mappingImpl(YamlIO);
}
};

struct MachineFunction {
StringRef Name;
unsigned Alignment = 0;
Expand All @@ -503,6 +518,7 @@ struct MachineFunction {
std::vector<FixedMachineStackObject> FixedStackObjects;
std::vector<MachineStackObject> StackObjects;
std::vector<MachineConstantPoolValue> Constants; /// Constant pool.
std::unique_ptr<MachineFunctionInfo> MachineFuncInfo;
MachineJumpTable JumpTableInfo;
BlockStringValue Body;
};
Expand Down Expand Up @@ -531,6 +547,7 @@ template <> struct MappingTraits<MachineFunction> {
std::vector<MachineStackObject>());
YamlIO.mapOptional("constants", MF.Constants,
std::vector<MachineConstantPoolValue>());
YamlIO.mapOptional("machineFunctionInfo", MF.MachineFuncInfo);
if (!YamlIO.outputting() || !MF.JumpTableInfo.Entries.empty())
YamlIO.mapOptional("jumpTable", MF.JumpTableInfo, MachineJumpTable());
YamlIO.mapOptional("body", MF.Body, BlockStringValue());
Expand Down
2 changes: 2 additions & 0 deletions include/llvm/CodeGen/MachineModuleInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,8 @@ class MachineModuleInfo : public ImmutablePass {
bool doInitialization(Module &) override;
bool doFinalization(Module &) override;

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

const MCContext &getContext() const { return Context; }
MCContext &getContext() { return Context; }

Expand Down
28 changes: 28 additions & 0 deletions include/llvm/Target/TargetMachine.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ class MCSubtargetInfo;
class MCSymbol;
class raw_pwrite_stream;
class PassManagerBuilder;
struct PerFunctionMIParsingState;
class SMDiagnostic;
class SMRange;
class Target;
class TargetIntrinsicInfo;
class TargetIRAnalysis;
Expand All @@ -49,6 +52,10 @@ class PassManagerBase;
}
using legacy::PassManagerBase;

namespace yaml {
struct MachineFunctionInfo;
}

//===----------------------------------------------------------------------===//
///
/// Primary interface to the complete machine description for the target
Expand Down Expand Up @@ -114,6 +121,27 @@ class TargetMachine {
return nullptr;
}

/// Allocate and return a default initialized instance of the YAML
/// representation for the MachineFunctionInfo.
virtual yaml::MachineFunctionInfo *createDefaultFuncInfoYAML() const {
return nullptr;
}

/// Allocate and initialize an instance of the YAML representation of the
/// MachineFunctionInfo.
virtual yaml::MachineFunctionInfo *
convertFuncInfoToYAML(const MachineFunction &MF) const {
return nullptr;
}

/// Parse out the target's MachineFunctionInfo from the YAML reprsentation.
virtual bool parseMachineFunctionInfo(const yaml::MachineFunctionInfo &,
PerFunctionMIParsingState &PFS,
SMDiagnostic &Error,
SMRange &SourceRange) const {
return false;
}

/// This method returns a pointer to the specified type of
/// TargetSubtargetInfo. In debug builds, it verifies that the object being
/// returned is of the correct type.
Expand Down
2 changes: 1 addition & 1 deletion lib/CodeGen/MIRParser/MIParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
//
//===----------------------------------------------------------------------===//

#include "MIParser.h"
#include "llvm/CodeGen/MIRParser/MIParser.h"
#include "MILexer.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/APSInt.h"
Expand Down
21 changes: 20 additions & 1 deletion lib/CodeGen/MIRParser/MIRParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
//===----------------------------------------------------------------------===//

#include "llvm/CodeGen/MIRParser/MIRParser.h"
#include "MIParser.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringMap.h"
Expand All @@ -21,6 +20,7 @@
#include "llvm/AsmParser/SlotMapping.h"
#include "llvm/CodeGen/GlobalISel/RegisterBank.h"
#include "llvm/CodeGen/GlobalISel/RegisterBankInfo.h"
#include "llvm/CodeGen/MIRParser/MIParser.h"
#include "llvm/CodeGen/MIRYamlMapping.h"
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
Expand All @@ -39,6 +39,7 @@
#include "llvm/Support/SMLoc.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/YAMLTraits.h"
#include "llvm/Target/TargetMachine.h"
#include <memory>

using namespace llvm;
Expand Down Expand Up @@ -266,6 +267,11 @@ bool MIRParserImpl::parseMachineFunction(Module &M, MachineModuleInfo &MMI) {
// Parse the yaml.
yaml::MachineFunction YamlMF;
yaml::EmptyContext Ctx;

const LLVMTargetMachine &TM = MMI.getTarget();
YamlMF.MachineFuncInfo = std::unique_ptr<yaml::MachineFunctionInfo>(
TM.createDefaultFuncInfoYAML());

yaml::yamlize(In, YamlMF, false, Ctx);
if (In.error())
return true;
Expand Down Expand Up @@ -407,6 +413,19 @@ MIRParserImpl::initializeMachineFunction(const yaml::MachineFunction &YamlMF,
if (setupRegisterInfo(PFS, YamlMF))
return true;

if (YamlMF.MachineFuncInfo) {
const LLVMTargetMachine &TM = MF.getTarget();
// Note this is called after the initial constructor of the
// MachineFunctionInfo based on the MachineFunction, which may depend on the
// IR.

SMRange SrcRange;
if (TM.parseMachineFunctionInfo(*YamlMF.MachineFuncInfo, PFS, Error,
SrcRange)) {
return error(Error, SrcRange);
}
}

computeFunctionProperties(MF);

MF.getSubtarget().mirFileLoaded(MF);
Expand Down
5 changes: 5 additions & 0 deletions lib/CodeGen/MIRPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,11 @@ void MIRPrinter::print(const MachineFunction &MF) {
convert(YamlMF, *ConstantPool);
if (const auto *JumpTableInfo = MF.getJumpTableInfo())
convert(MST, YamlMF.JumpTableInfo, *JumpTableInfo);

const TargetMachine &TM = MF.getTarget();
YamlMF.MachineFuncInfo =
std::unique_ptr<yaml::MachineFunctionInfo>(TM.convertFuncInfoToYAML(MF));

raw_string_ostream StrOS(YamlMF.Body.Value.Value);
bool IsNewlineNeeded = false;
for (const auto &MBB : MF) {
Expand Down
73 changes: 73 additions & 0 deletions lib/Target/AMDGPU/AMDGPUTargetMachine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,13 @@
#include "GCNIterativeScheduler.h"
#include "GCNSchedStrategy.h"
#include "R600MachineScheduler.h"
#include "SIMachineFunctionInfo.h"
#include "SIMachineScheduler.h"
#include "llvm/CodeGen/GlobalISel/IRTranslator.h"
#include "llvm/CodeGen/GlobalISel/InstructionSelect.h"
#include "llvm/CodeGen/GlobalISel/Legalizer.h"
#include "llvm/CodeGen/GlobalISel/RegBankSelect.h"
#include "llvm/CodeGen/MIRParser/MIParser.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/TargetPassConfig.h"
#include "llvm/IR/Attributes.h"
Expand Down Expand Up @@ -930,3 +932,74 @@ void GCNPassConfig::addPreEmitPass() {
TargetPassConfig *GCNTargetMachine::createPassConfig(PassManagerBase &PM) {
return new GCNPassConfig(*this, PM);
}

yaml::MachineFunctionInfo *GCNTargetMachine::createDefaultFuncInfoYAML() const {
return new yaml::SIMachineFunctionInfo();
}

yaml::MachineFunctionInfo *
GCNTargetMachine::convertFuncInfoToYAML(const MachineFunction &MF) const {
const SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();
return new yaml::SIMachineFunctionInfo(*MFI,
*MF.getSubtarget().getRegisterInfo());
}

bool GCNTargetMachine::parseMachineFunctionInfo(
const yaml::MachineFunctionInfo &MFI_, PerFunctionMIParsingState &PFS,
SMDiagnostic &Error, SMRange &SourceRange) const {
const yaml::SIMachineFunctionInfo &YamlMFI =
reinterpret_cast<const yaml::SIMachineFunctionInfo &>(MFI_);
MachineFunction &MF = PFS.MF;
SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();

MFI->initializeBaseYamlFields(YamlMFI);

auto parseRegister = [&](const yaml::StringValue &RegName, unsigned &RegVal) {
if (parseNamedRegisterReference(PFS, RegVal, RegName.Value, Error)) {
SourceRange = RegName.SourceRange;
return true;
}

return false;
};

auto diagnoseRegisterClass = [&](const yaml::StringValue &RegName) {
// Create a diagnostic for a the register string literal.
const MemoryBuffer &Buffer =
*PFS.SM->getMemoryBuffer(PFS.SM->getMainFileID());
Error = SMDiagnostic(*PFS.SM, SMLoc(), Buffer.getBufferIdentifier(), 1,
RegName.Value.size(), SourceMgr::DK_Error,
"incorrect register class for field", RegName.Value,
None, None);
SourceRange = RegName.SourceRange;
return true;
};

if (parseRegister(YamlMFI.ScratchRSrcReg, MFI->ScratchRSrcReg) ||
parseRegister(YamlMFI.ScratchWaveOffsetReg, MFI->ScratchWaveOffsetReg) ||
parseRegister(YamlMFI.FrameOffsetReg, MFI->FrameOffsetReg) ||
parseRegister(YamlMFI.StackPtrOffsetReg, MFI->StackPtrOffsetReg))
return true;

if (MFI->ScratchRSrcReg != AMDGPU::PRIVATE_RSRC_REG &&
!AMDGPU::SReg_128RegClass.contains(MFI->ScratchRSrcReg)) {
return diagnoseRegisterClass(YamlMFI.ScratchRSrcReg);
}

if (MFI->ScratchWaveOffsetReg != AMDGPU::SCRATCH_WAVE_OFFSET_REG &&
!AMDGPU::SGPR_32RegClass.contains(MFI->ScratchWaveOffsetReg)) {
return diagnoseRegisterClass(YamlMFI.ScratchWaveOffsetReg);
}

if (MFI->FrameOffsetReg != AMDGPU::FP_REG &&
!AMDGPU::SGPR_32RegClass.contains(MFI->FrameOffsetReg)) {
return diagnoseRegisterClass(YamlMFI.FrameOffsetReg);
}

if (MFI->StackPtrOffsetReg != AMDGPU::SP_REG &&
!AMDGPU::SGPR_32RegClass.contains(MFI->StackPtrOffsetReg)) {
return diagnoseRegisterClass(YamlMFI.StackPtrOffsetReg);
}

return false;
}
8 changes: 8 additions & 0 deletions lib/Target/AMDGPU/AMDGPUTargetMachine.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,14 @@ class GCNTargetMachine final : public AMDGPUTargetMachine {
bool useIPRA() const override {
return true;
}

yaml::MachineFunctionInfo *createDefaultFuncInfoYAML() const override;
yaml::MachineFunctionInfo *
convertFuncInfoToYAML(const MachineFunction &MF) const override;
bool parseMachineFunctionInfo(const yaml::MachineFunctionInfo &,
PerFunctionMIParsingState &PFS,
SMDiagnostic &Error,
SMRange &SourceRange) const override;
};

} // end namespace llvm
Expand Down
2 changes: 1 addition & 1 deletion lib/Target/AMDGPU/LLVMBuild.txt
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,5 @@ has_disassembler = 1
type = Library
name = AMDGPUCodeGen
parent = AMDGPU
required_libraries = Analysis AsmPrinter CodeGen Core IPO MC AMDGPUAsmPrinter AMDGPUDesc AMDGPUInfo AMDGPUUtils Scalar SelectionDAG Support Target TransformUtils Vectorize GlobalISel BinaryFormat
required_libraries = Analysis AsmPrinter CodeGen Core IPO MC AMDGPUAsmPrinter AMDGPUDesc AMDGPUInfo AMDGPUUtils Scalar SelectionDAG Support Target TransformUtils Vectorize GlobalISel BinaryFormat MIRParser
add_to_library_groups = AMDGPU
19 changes: 14 additions & 5 deletions lib/Target/AMDGPU/SIISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9607,13 +9607,22 @@ void SITargetLowering::finalizeLowering(MachineFunction &MF) const {
assert(Info->getStackPtrOffsetReg() != Info->getFrameOffsetReg());
assert(!TRI->isSubRegister(Info->getScratchRSrcReg(),
Info->getStackPtrOffsetReg()));
MRI.replaceRegWith(AMDGPU::SP_REG, Info->getStackPtrOffsetReg());
if (Info->getStackPtrOffsetReg() != AMDGPU::SP_REG)
MRI.replaceRegWith(AMDGPU::SP_REG, Info->getStackPtrOffsetReg());
}

MRI.replaceRegWith(AMDGPU::PRIVATE_RSRC_REG, Info->getScratchRSrcReg());
MRI.replaceRegWith(AMDGPU::FP_REG, Info->getFrameOffsetReg());
MRI.replaceRegWith(AMDGPU::SCRATCH_WAVE_OFFSET_REG,
Info->getScratchWaveOffsetReg());
// We need to worry about replacing the default register with itself in case
// of MIR testcases missing the MFI.
if (Info->getScratchRSrcReg() != AMDGPU::PRIVATE_RSRC_REG)
MRI.replaceRegWith(AMDGPU::PRIVATE_RSRC_REG, Info->getScratchRSrcReg());

if (Info->getFrameOffsetReg() != AMDGPU::FP_REG)
MRI.replaceRegWith(AMDGPU::FP_REG, Info->getFrameOffsetReg());

if (Info->getScratchWaveOffsetReg() != AMDGPU::SCRATCH_WAVE_OFFSET_REG) {
MRI.replaceRegWith(AMDGPU::SCRATCH_WAVE_OFFSET_REG,
Info->getScratchWaveOffsetReg());
}

Info->limitOccupancy(MF);

Expand Down
39 changes: 39 additions & 0 deletions lib/Target/AMDGPU/SIMachineFunctionInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -319,3 +319,42 @@ MCPhysReg SIMachineFunctionInfo::getNextUserSGPR() const {
MCPhysReg SIMachineFunctionInfo::getNextSystemSGPR() const {
return AMDGPU::SGPR0 + NumUserSGPRs + NumSystemSGPRs;
}

static yaml::StringValue regToString(unsigned Reg,
const TargetRegisterInfo &TRI) {
yaml::StringValue Dest;
raw_string_ostream OS(Dest.Value);
OS << printReg(Reg, &TRI);
return Dest;
}

yaml::SIMachineFunctionInfo::SIMachineFunctionInfo(
const llvm::SIMachineFunctionInfo& MFI,
const TargetRegisterInfo &TRI)
: ExplicitKernArgSize(MFI.getExplicitKernArgSize()),
MaxKernArgAlign(MFI.getMaxKernArgAlign()),
LDSSize(MFI.getLDSSize()),
IsEntryFunction(MFI.isEntryFunction()),
NoSignedZerosFPMath(MFI.hasNoSignedZerosFPMath()),
MemoryBound(MFI.isMemoryBound()),
WaveLimiter(MFI.needsWaveLimiter()),
ScratchRSrcReg(regToString(MFI.getScratchRSrcReg(), TRI)),
ScratchWaveOffsetReg(regToString(MFI.getScratchWaveOffsetReg(), TRI)),
FrameOffsetReg(regToString(MFI.getFrameOffsetReg(), TRI)),
StackPtrOffsetReg(regToString(MFI.getStackPtrOffsetReg(), TRI)) {}

void yaml::SIMachineFunctionInfo::mappingImpl(yaml::IO &YamlIO) {
MappingTraits<SIMachineFunctionInfo>::mapping(YamlIO, *this);
}

bool SIMachineFunctionInfo::initializeBaseYamlFields(
const yaml::SIMachineFunctionInfo &YamlMFI) {
ExplicitKernArgSize = YamlMFI.ExplicitKernArgSize;
MaxKernArgAlign = YamlMFI.MaxKernArgAlign;
LDSSize = YamlMFI.LDSSize;
IsEntryFunction = YamlMFI.IsEntryFunction;
NoSignedZerosFPMath = YamlMFI.NoSignedZerosFPMath;
MemoryBound = YamlMFI.MemoryBound;
WaveLimiter = YamlMFI.WaveLimiter;
return false;
}
Loading

0 comments on commit d8706fc

Please sign in to comment.