mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-09-03 02:30:00 +00:00
The SelectionDAGBuilder was promoting vector kernel arguments to legal types, but this won't work for R600 and SI since kernel arguments are stored in memory and can't be promoted. In order to handle vector arguments correctly we need to look at the original types from the LLVM IR function. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@193215 91177308-0d34-0410-b5e6-96231b3b80d8
192 lines
6.0 KiB
C++
192 lines
6.0 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/Analysis/Verifier.h"
|
|
#include "llvm/CodeGen/MachineFunctionAnalysis.h"
|
|
#include "llvm/CodeGen/MachineModuleInfo.h"
|
|
#include "llvm/CodeGen/Passes.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 ScheduleDAGMI(C, new 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),
|
|
Layout(Subtarget.getDataLayout()),
|
|
FrameLowering(TargetFrameLowering::StackGrowsUp,
|
|
64 * 16 // Maximum stack alignment (long16)
|
|
, 0),
|
|
IntrinsicInfo(this),
|
|
InstrItins(&Subtarget.getInstrItineraryData()) {
|
|
// TLInfo uses InstrInfo so it must be initialized after.
|
|
if (Subtarget.getGeneration() <= AMDGPUSubtarget::NORTHERN_ISLANDS) {
|
|
InstrInfo.reset(new R600InstrInfo(*this));
|
|
TLInfo.reset(new R600TargetLowering(*this));
|
|
} else {
|
|
InstrInfo.reset(new SIInstrInfo(*this));
|
|
TLInfo.reset(new SITargetLowering(*this));
|
|
}
|
|
initAsmInfo();
|
|
}
|
|
|
|
AMDGPUTargetMachine::~AMDGPUTargetMachine() {
|
|
}
|
|
|
|
namespace {
|
|
class AMDGPUPassConfig : public TargetPassConfig {
|
|
public:
|
|
AMDGPUPassConfig(AMDGPUTargetMachine *TM, PassManagerBase &PM)
|
|
: TargetPassConfig(TM, PM) {}
|
|
|
|
AMDGPUTargetMachine &getAMDGPUTargetMachine() const {
|
|
return getTM<AMDGPUTargetMachine>();
|
|
}
|
|
|
|
virtual ScheduleDAGInstrs *
|
|
createMachineScheduler(MachineSchedContext *C) const {
|
|
const AMDGPUSubtarget &ST = TM->getSubtarget<AMDGPUSubtarget>();
|
|
if (ST.getGeneration() <= AMDGPUSubtarget::NORTHERN_ISLANDS)
|
|
return createR600MachineScheduler(C);
|
|
return 0;
|
|
}
|
|
|
|
virtual bool addPreISel();
|
|
virtual bool addInstSelector();
|
|
virtual bool addPreRegAlloc();
|
|
virtual bool addPostRegAlloc();
|
|
virtual bool addPreSched2();
|
|
virtual bool addPreEmitPass();
|
|
};
|
|
} // 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));
|
|
}
|
|
|
|
bool
|
|
AMDGPUPassConfig::addPreISel() {
|
|
const AMDGPUSubtarget &ST = TM->getSubtarget<AMDGPUSubtarget>();
|
|
addPass(createFlattenCFGPass());
|
|
if (ST.IsIRStructurizerEnabled() ||
|
|
ST.getGeneration() > AMDGPUSubtarget::NORTHERN_ISLANDS)
|
|
addPass(createStructurizeCFGPass());
|
|
if (ST.getGeneration() > AMDGPUSubtarget::NORTHERN_ISLANDS) {
|
|
addPass(createSinkingPass());
|
|
addPass(createSITypeRewriter());
|
|
addPass(createSIAnnotateControlFlowPass());
|
|
} else {
|
|
addPass(createR600TextureIntrinsicsReplacer());
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool AMDGPUPassConfig::addInstSelector() {
|
|
addPass(createAMDGPUISelDag(getAMDGPUTargetMachine()));
|
|
return false;
|
|
}
|
|
|
|
bool AMDGPUPassConfig::addPreRegAlloc() {
|
|
addPass(createAMDGPUConvertToISAPass(*TM));
|
|
const AMDGPUSubtarget &ST = TM->getSubtarget<AMDGPUSubtarget>();
|
|
|
|
if (ST.getGeneration() <= AMDGPUSubtarget::NORTHERN_ISLANDS) {
|
|
addPass(createR600VectorRegMerger(*TM));
|
|
} else {
|
|
addPass(createSIFixSGPRCopiesPass(*TM));
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool AMDGPUPassConfig::addPostRegAlloc() {
|
|
const AMDGPUSubtarget &ST = TM->getSubtarget<AMDGPUSubtarget>();
|
|
|
|
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(*TM));
|
|
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(*TM));
|
|
addPass(createR600ExpandSpecialInstrsPass(*TM));
|
|
addPass(&FinalizeMachineBundlesID);
|
|
addPass(createR600Packetizer(*TM));
|
|
addPass(createR600ControlFlowFinalizer(*TM));
|
|
} else {
|
|
addPass(createSILowerControlFlowPass(*TM));
|
|
}
|
|
|
|
return false;
|
|
}
|