mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-15 20:29:48 +00:00
36ba7962a4
The previous implementation was extending the live range of SGPRs by modifying the live intervals directly. This was causing a lot of machine verification errors when the machine scheduler was enabled. The new implementation adds pseudo instructions with implicit uses to extend the live ranges of SGPRs, which works much better. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@218351 91177308-0d34-0410-b5e6-96231b3b80d8
193 lines
6.2 KiB
C++
193 lines
6.2 KiB
C++
//===-- AMDGPUTargetMachine.cpp - TargetMachine for hw codegen targets-----===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
/// \file
|
|
/// \brief The AMDGPU target machine contains all of the hardware specific
|
|
/// information needed to emit code for R600 and SI GPUs.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "AMDGPUTargetMachine.h"
|
|
#include "AMDGPU.h"
|
|
#include "R600ISelLowering.h"
|
|
#include "R600InstrInfo.h"
|
|
#include "R600MachineScheduler.h"
|
|
#include "SIISelLowering.h"
|
|
#include "SIInstrInfo.h"
|
|
#include "llvm/Analysis/Passes.h"
|
|
#include "llvm/CodeGen/MachineFunctionAnalysis.h"
|
|
#include "llvm/CodeGen/MachineModuleInfo.h"
|
|
#include "llvm/CodeGen/Passes.h"
|
|
#include "llvm/IR/Verifier.h"
|
|
#include "llvm/MC/MCAsmInfo.h"
|
|
#include "llvm/PassManager.h"
|
|
#include "llvm/Support/TargetRegistry.h"
|
|
#include "llvm/Support/raw_os_ostream.h"
|
|
#include "llvm/Transforms/IPO.h"
|
|
#include "llvm/Transforms/Scalar.h"
|
|
#include <llvm/CodeGen/Passes.h>
|
|
|
|
using namespace llvm;
|
|
|
|
extern "C" void LLVMInitializeR600Target() {
|
|
// Register the target
|
|
RegisterTargetMachine<AMDGPUTargetMachine> X(TheAMDGPUTarget);
|
|
}
|
|
|
|
static ScheduleDAGInstrs *createR600MachineScheduler(MachineSchedContext *C) {
|
|
return new ScheduleDAGMILive(C, make_unique<R600SchedStrategy>());
|
|
}
|
|
|
|
static MachineSchedRegistry
|
|
SchedCustomRegistry("r600", "Run R600's custom scheduler",
|
|
createR600MachineScheduler);
|
|
|
|
AMDGPUTargetMachine::AMDGPUTargetMachine(const Target &T, StringRef TT,
|
|
StringRef CPU, StringRef FS,
|
|
TargetOptions Options, Reloc::Model RM,
|
|
CodeModel::Model CM,
|
|
CodeGenOpt::Level OptLevel)
|
|
: LLVMTargetMachine(T, TT, CPU, FS, Options, RM, CM, OptLevel),
|
|
Subtarget(TT, CPU, FS, *this), IntrinsicInfo() {
|
|
setRequiresStructuredCFG(true);
|
|
initAsmInfo();
|
|
}
|
|
|
|
AMDGPUTargetMachine::~AMDGPUTargetMachine() {
|
|
}
|
|
|
|
namespace {
|
|
class AMDGPUPassConfig : public TargetPassConfig {
|
|
public:
|
|
AMDGPUPassConfig(AMDGPUTargetMachine *TM, PassManagerBase &PM)
|
|
: TargetPassConfig(TM, PM) {}
|
|
|
|
AMDGPUTargetMachine &getAMDGPUTargetMachine() const {
|
|
return getTM<AMDGPUTargetMachine>();
|
|
}
|
|
|
|
ScheduleDAGInstrs *
|
|
createMachineScheduler(MachineSchedContext *C) const override {
|
|
const AMDGPUSubtarget &ST = TM->getSubtarget<AMDGPUSubtarget>();
|
|
if (ST.getGeneration() <= AMDGPUSubtarget::NORTHERN_ISLANDS)
|
|
return createR600MachineScheduler(C);
|
|
return nullptr;
|
|
}
|
|
|
|
void addCodeGenPrepare() override;
|
|
bool addPreISel() override;
|
|
bool addInstSelector() override;
|
|
bool addPreRegAlloc() override;
|
|
bool addPostRegAlloc() override;
|
|
bool addPreSched2() override;
|
|
bool addPreEmitPass() override;
|
|
};
|
|
} // End of anonymous namespace
|
|
|
|
TargetPassConfig *AMDGPUTargetMachine::createPassConfig(PassManagerBase &PM) {
|
|
return new AMDGPUPassConfig(this, PM);
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// AMDGPU Analysis Pass Setup
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
void AMDGPUTargetMachine::addAnalysisPasses(PassManagerBase &PM) {
|
|
// Add first the target-independent BasicTTI pass, then our AMDGPU pass. This
|
|
// allows the AMDGPU pass to delegate to the target independent layer when
|
|
// appropriate.
|
|
PM.add(createBasicTargetTransformInfoPass(this));
|
|
PM.add(createAMDGPUTargetTransformInfoPass(this));
|
|
}
|
|
|
|
void AMDGPUPassConfig::addCodeGenPrepare() {
|
|
const AMDGPUSubtarget &ST = TM->getSubtarget<AMDGPUSubtarget>();
|
|
if (ST.isPromoteAllocaEnabled()) {
|
|
addPass(createAMDGPUPromoteAlloca(ST));
|
|
addPass(createSROAPass());
|
|
}
|
|
|
|
TargetPassConfig::addCodeGenPrepare();
|
|
}
|
|
|
|
bool
|
|
AMDGPUPassConfig::addPreISel() {
|
|
const AMDGPUSubtarget &ST = TM->getSubtarget<AMDGPUSubtarget>();
|
|
addPass(createFlattenCFGPass());
|
|
if (ST.IsIRStructurizerEnabled())
|
|
addPass(createStructurizeCFGPass());
|
|
if (ST.getGeneration() >= AMDGPUSubtarget::SOUTHERN_ISLANDS) {
|
|
addPass(createSinkingPass());
|
|
addPass(createSITypeRewriter());
|
|
addPass(createSIAnnotateControlFlowPass());
|
|
} else {
|
|
addPass(createR600TextureIntrinsicsReplacer());
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool AMDGPUPassConfig::addInstSelector() {
|
|
addPass(createAMDGPUISelDag(getAMDGPUTargetMachine()));
|
|
addPass(createSILowerI1CopiesPass());
|
|
return false;
|
|
}
|
|
|
|
bool AMDGPUPassConfig::addPreRegAlloc() {
|
|
const AMDGPUSubtarget &ST = TM->getSubtarget<AMDGPUSubtarget>();
|
|
|
|
if (ST.getGeneration() <= AMDGPUSubtarget::NORTHERN_ISLANDS) {
|
|
addPass(createR600VectorRegMerger(*TM));
|
|
} else {
|
|
addPass(createSIFixSGPRCopiesPass(*TM));
|
|
// SIFixSGPRCopies can generate a lot of duplicate instructions,
|
|
// so we need to run MachineCSE afterwards.
|
|
addPass(&MachineCSEID);
|
|
addPass(createSIShrinkInstructionsPass());
|
|
addPass(createSIFixSGPRLiveRangesPass());
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool AMDGPUPassConfig::addPostRegAlloc() {
|
|
const AMDGPUSubtarget &ST = TM->getSubtarget<AMDGPUSubtarget>();
|
|
|
|
addPass(createSIShrinkInstructionsPass());
|
|
if (ST.getGeneration() > AMDGPUSubtarget::NORTHERN_ISLANDS) {
|
|
addPass(createSIInsertWaits(*TM));
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool AMDGPUPassConfig::addPreSched2() {
|
|
const AMDGPUSubtarget &ST = TM->getSubtarget<AMDGPUSubtarget>();
|
|
|
|
if (ST.getGeneration() <= AMDGPUSubtarget::NORTHERN_ISLANDS)
|
|
addPass(createR600EmitClauseMarkers());
|
|
if (ST.isIfCvtEnabled())
|
|
addPass(&IfConverterID);
|
|
if (ST.getGeneration() <= AMDGPUSubtarget::NORTHERN_ISLANDS)
|
|
addPass(createR600ClauseMergePass(*TM));
|
|
return false;
|
|
}
|
|
|
|
bool AMDGPUPassConfig::addPreEmitPass() {
|
|
const AMDGPUSubtarget &ST = TM->getSubtarget<AMDGPUSubtarget>();
|
|
if (ST.getGeneration() <= AMDGPUSubtarget::NORTHERN_ISLANDS) {
|
|
addPass(createAMDGPUCFGStructurizerPass());
|
|
addPass(createR600ExpandSpecialInstrsPass(*TM));
|
|
addPass(&FinalizeMachineBundlesID);
|
|
addPass(createR600Packetizer(*TM));
|
|
addPass(createR600ControlFlowFinalizer(*TM));
|
|
} else {
|
|
addPass(createSILowerControlFlowPass(*TM));
|
|
}
|
|
|
|
return false;
|
|
}
|