1349cc55cSDimitry Andric //===-- R600TargetMachine.cpp - TargetMachine for hw codegen targets-------===// 2349cc55cSDimitry Andric // 3349cc55cSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4349cc55cSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5349cc55cSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6349cc55cSDimitry Andric // 7349cc55cSDimitry Andric //===----------------------------------------------------------------------===// 8349cc55cSDimitry Andric // 9349cc55cSDimitry Andric /// \file 10349cc55cSDimitry Andric /// The AMDGPU-R600 target machine contains all of the hardware specific 11349cc55cSDimitry Andric /// information needed to emit code for R600 GPUs. 12349cc55cSDimitry Andric // 13349cc55cSDimitry Andric //===----------------------------------------------------------------------===// 14349cc55cSDimitry Andric 15349cc55cSDimitry Andric #include "R600TargetMachine.h" 16349cc55cSDimitry Andric #include "AMDGPUTargetMachine.h" 17349cc55cSDimitry Andric #include "R600.h" 18*0fca6ea1SDimitry Andric #include "R600CodeGenPassBuilder.h" 19349cc55cSDimitry Andric #include "R600MachineScheduler.h" 20349cc55cSDimitry Andric #include "R600TargetTransformInfo.h" 21349cc55cSDimitry Andric #include "llvm/Transforms/Scalar.h" 22bdd1243dSDimitry Andric #include <optional> 23349cc55cSDimitry Andric 24349cc55cSDimitry Andric using namespace llvm; 25349cc55cSDimitry Andric 26349cc55cSDimitry Andric static cl::opt<bool> 27349cc55cSDimitry Andric EnableR600StructurizeCFG("r600-ir-structurize", 28349cc55cSDimitry Andric cl::desc("Use StructurizeCFG IR pass"), 29349cc55cSDimitry Andric cl::init(true)); 30349cc55cSDimitry Andric 31349cc55cSDimitry Andric static cl::opt<bool> EnableR600IfConvert("r600-if-convert", 32349cc55cSDimitry Andric cl::desc("Use if conversion pass"), 33349cc55cSDimitry Andric cl::ReallyHidden, cl::init(true)); 34349cc55cSDimitry Andric 35349cc55cSDimitry Andric static cl::opt<bool, true> EnableAMDGPUFunctionCallsOpt( 36349cc55cSDimitry Andric "amdgpu-function-calls", cl::desc("Enable AMDGPU function call support"), 37349cc55cSDimitry Andric cl::location(AMDGPUTargetMachine::EnableFunctionCalls), cl::init(true), 38349cc55cSDimitry Andric cl::Hidden); 39349cc55cSDimitry Andric 40349cc55cSDimitry Andric static ScheduleDAGInstrs *createR600MachineScheduler(MachineSchedContext *C) { 41349cc55cSDimitry Andric return new ScheduleDAGMILive(C, std::make_unique<R600SchedStrategy>()); 42349cc55cSDimitry Andric } 43349cc55cSDimitry Andric 44349cc55cSDimitry Andric static MachineSchedRegistry R600SchedRegistry("r600", 45349cc55cSDimitry Andric "Run R600's custom scheduler", 46349cc55cSDimitry Andric createR600MachineScheduler); 47349cc55cSDimitry Andric 48349cc55cSDimitry Andric //===----------------------------------------------------------------------===// 49349cc55cSDimitry Andric // R600 Target Machine (R600 -> Cayman) 50349cc55cSDimitry Andric //===----------------------------------------------------------------------===// 51349cc55cSDimitry Andric 52349cc55cSDimitry Andric R600TargetMachine::R600TargetMachine(const Target &T, const Triple &TT, 53349cc55cSDimitry Andric StringRef CPU, StringRef FS, 54*0fca6ea1SDimitry Andric const TargetOptions &Options, 55bdd1243dSDimitry Andric std::optional<Reloc::Model> RM, 56bdd1243dSDimitry Andric std::optional<CodeModel::Model> CM, 575f757f3fSDimitry Andric CodeGenOptLevel OL, bool JIT) 58349cc55cSDimitry Andric : AMDGPUTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL) { 59349cc55cSDimitry Andric setRequiresStructuredCFG(true); 60349cc55cSDimitry Andric 61349cc55cSDimitry Andric // Override the default since calls aren't supported for r600. 62349cc55cSDimitry Andric if (EnableFunctionCalls && 63349cc55cSDimitry Andric EnableAMDGPUFunctionCallsOpt.getNumOccurrences() == 0) 64349cc55cSDimitry Andric EnableFunctionCalls = false; 65349cc55cSDimitry Andric } 66349cc55cSDimitry Andric 67349cc55cSDimitry Andric const TargetSubtargetInfo * 68349cc55cSDimitry Andric R600TargetMachine::getSubtargetImpl(const Function &F) const { 69349cc55cSDimitry Andric StringRef GPU = getGPUName(F); 70349cc55cSDimitry Andric StringRef FS = getFeatureString(F); 71349cc55cSDimitry Andric 72349cc55cSDimitry Andric SmallString<128> SubtargetKey(GPU); 73349cc55cSDimitry Andric SubtargetKey.append(FS); 74349cc55cSDimitry Andric 75349cc55cSDimitry Andric auto &I = SubtargetMap[SubtargetKey]; 76349cc55cSDimitry Andric if (!I) { 77349cc55cSDimitry Andric // This needs to be done before we create a new subtarget since any 78349cc55cSDimitry Andric // creation will depend on the TM and the code generation flags on the 79349cc55cSDimitry Andric // function that reside in TargetOptions. 80349cc55cSDimitry Andric resetTargetOptions(F); 81349cc55cSDimitry Andric I = std::make_unique<R600Subtarget>(TargetTriple, GPU, FS, *this); 82349cc55cSDimitry Andric } 83349cc55cSDimitry Andric 84349cc55cSDimitry Andric return I.get(); 85349cc55cSDimitry Andric } 86349cc55cSDimitry Andric 87349cc55cSDimitry Andric TargetTransformInfo 8881ad6265SDimitry Andric R600TargetMachine::getTargetTransformInfo(const Function &F) const { 89349cc55cSDimitry Andric return TargetTransformInfo(R600TTIImpl(this, F)); 90349cc55cSDimitry Andric } 91349cc55cSDimitry Andric 92bdd1243dSDimitry Andric namespace { 93349cc55cSDimitry Andric class R600PassConfig final : public AMDGPUPassConfig { 94349cc55cSDimitry Andric public: 95349cc55cSDimitry Andric R600PassConfig(LLVMTargetMachine &TM, PassManagerBase &PM) 96349cc55cSDimitry Andric : AMDGPUPassConfig(TM, PM) {} 97349cc55cSDimitry Andric 98349cc55cSDimitry Andric ScheduleDAGInstrs * 99349cc55cSDimitry Andric createMachineScheduler(MachineSchedContext *C) const override { 100349cc55cSDimitry Andric return createR600MachineScheduler(C); 101349cc55cSDimitry Andric } 102349cc55cSDimitry Andric 103349cc55cSDimitry Andric bool addPreISel() override; 104349cc55cSDimitry Andric bool addInstSelector() override; 105349cc55cSDimitry Andric void addPreRegAlloc() override; 106349cc55cSDimitry Andric void addPreSched2() override; 107349cc55cSDimitry Andric void addPreEmitPass() override; 108349cc55cSDimitry Andric }; 109bdd1243dSDimitry Andric } // namespace 110349cc55cSDimitry Andric 111349cc55cSDimitry Andric //===----------------------------------------------------------------------===// 112349cc55cSDimitry Andric // R600 Pass Setup 113349cc55cSDimitry Andric //===----------------------------------------------------------------------===// 114349cc55cSDimitry Andric 115349cc55cSDimitry Andric bool R600PassConfig::addPreISel() { 116349cc55cSDimitry Andric AMDGPUPassConfig::addPreISel(); 117349cc55cSDimitry Andric 118349cc55cSDimitry Andric if (EnableR600StructurizeCFG) 119349cc55cSDimitry Andric addPass(createStructurizeCFGPass()); 120349cc55cSDimitry Andric return false; 121349cc55cSDimitry Andric } 122349cc55cSDimitry Andric 123349cc55cSDimitry Andric bool R600PassConfig::addInstSelector() { 124bdd1243dSDimitry Andric addPass(createR600ISelDag(getAMDGPUTargetMachine(), getOptLevel())); 125349cc55cSDimitry Andric return false; 126349cc55cSDimitry Andric } 127349cc55cSDimitry Andric 128349cc55cSDimitry Andric void R600PassConfig::addPreRegAlloc() { addPass(createR600VectorRegMerger()); } 129349cc55cSDimitry Andric 130349cc55cSDimitry Andric void R600PassConfig::addPreSched2() { 131349cc55cSDimitry Andric addPass(createR600EmitClauseMarkers()); 132349cc55cSDimitry Andric if (EnableR600IfConvert) 133349cc55cSDimitry Andric addPass(&IfConverterID); 134349cc55cSDimitry Andric addPass(createR600ClauseMergePass()); 135349cc55cSDimitry Andric } 136349cc55cSDimitry Andric 137349cc55cSDimitry Andric void R600PassConfig::addPreEmitPass() { 13881ad6265SDimitry Andric addPass(createR600MachineCFGStructurizerPass()); 139349cc55cSDimitry Andric addPass(createR600ExpandSpecialInstrsPass()); 140349cc55cSDimitry Andric addPass(&FinalizeMachineBundlesID); 141349cc55cSDimitry Andric addPass(createR600Packetizer()); 142349cc55cSDimitry Andric addPass(createR600ControlFlowFinalizer()); 143349cc55cSDimitry Andric } 144349cc55cSDimitry Andric 145349cc55cSDimitry Andric TargetPassConfig *R600TargetMachine::createPassConfig(PassManagerBase &PM) { 146349cc55cSDimitry Andric return new R600PassConfig(*this, PM); 147349cc55cSDimitry Andric } 148*0fca6ea1SDimitry Andric 149*0fca6ea1SDimitry Andric Error R600TargetMachine::buildCodeGenPipeline( 150*0fca6ea1SDimitry Andric ModulePassManager &MPM, raw_pwrite_stream &Out, raw_pwrite_stream *DwoOut, 151*0fca6ea1SDimitry Andric CodeGenFileType FileType, const CGPassBuilderOption &Opts, 152*0fca6ea1SDimitry Andric PassInstrumentationCallbacks *PIC) { 153*0fca6ea1SDimitry Andric R600CodeGenPassBuilder CGPB(*this, Opts, PIC); 154*0fca6ea1SDimitry Andric return CGPB.buildPipeline(MPM, Out, DwoOut, FileType); 155*0fca6ea1SDimitry Andric } 156