148958d02SDaniil Fukalov //===-- R600TargetMachine.cpp - TargetMachine for hw codegen targets-------===//
248958d02SDaniil Fukalov //
348958d02SDaniil Fukalov // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
448958d02SDaniil Fukalov // See https://llvm.org/LICENSE.txt for license information.
548958d02SDaniil Fukalov // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
648958d02SDaniil Fukalov //
748958d02SDaniil Fukalov //===----------------------------------------------------------------------===//
848958d02SDaniil Fukalov //
948958d02SDaniil Fukalov /// \file
1048958d02SDaniil Fukalov /// The AMDGPU-R600 target machine contains all of the hardware specific
1148958d02SDaniil Fukalov /// information  needed to emit code for R600 GPUs.
1248958d02SDaniil Fukalov //
1348958d02SDaniil Fukalov //===----------------------------------------------------------------------===//
1448958d02SDaniil Fukalov 
1548958d02SDaniil Fukalov #include "R600TargetMachine.h"
1648958d02SDaniil Fukalov #include "AMDGPUTargetMachine.h"
1748958d02SDaniil Fukalov #include "R600.h"
1848958d02SDaniil Fukalov #include "R600MachineScheduler.h"
1948958d02SDaniil Fukalov #include "R600TargetTransformInfo.h"
2048958d02SDaniil Fukalov #include "llvm/Transforms/Scalar.h"
2148958d02SDaniil Fukalov 
2248958d02SDaniil Fukalov using namespace llvm;
2348958d02SDaniil Fukalov 
2448958d02SDaniil Fukalov static cl::opt<bool>
2548958d02SDaniil Fukalov     EnableR600StructurizeCFG("r600-ir-structurize",
2648958d02SDaniil Fukalov                              cl::desc("Use StructurizeCFG IR pass"),
2748958d02SDaniil Fukalov                              cl::init(true));
2848958d02SDaniil Fukalov 
2948958d02SDaniil Fukalov static cl::opt<bool> EnableR600IfConvert("r600-if-convert",
3048958d02SDaniil Fukalov                                          cl::desc("Use if conversion pass"),
3148958d02SDaniil Fukalov                                          cl::ReallyHidden, cl::init(true));
3248958d02SDaniil Fukalov 
3348958d02SDaniil Fukalov static cl::opt<bool, true> EnableAMDGPUFunctionCallsOpt(
3448958d02SDaniil Fukalov     "amdgpu-function-calls", cl::desc("Enable AMDGPU function call support"),
3548958d02SDaniil Fukalov     cl::location(AMDGPUTargetMachine::EnableFunctionCalls), cl::init(true),
3648958d02SDaniil Fukalov     cl::Hidden);
3748958d02SDaniil Fukalov 
createR600MachineScheduler(MachineSchedContext * C)3848958d02SDaniil Fukalov static ScheduleDAGInstrs *createR600MachineScheduler(MachineSchedContext *C) {
3948958d02SDaniil Fukalov   return new ScheduleDAGMILive(C, std::make_unique<R600SchedStrategy>());
4048958d02SDaniil Fukalov }
4148958d02SDaniil Fukalov 
4248958d02SDaniil Fukalov static MachineSchedRegistry R600SchedRegistry("r600",
4348958d02SDaniil Fukalov                                               "Run R600's custom scheduler",
4448958d02SDaniil Fukalov                                               createR600MachineScheduler);
4548958d02SDaniil Fukalov 
4648958d02SDaniil Fukalov //===----------------------------------------------------------------------===//
4748958d02SDaniil Fukalov // R600 Target Machine (R600 -> Cayman)
4848958d02SDaniil Fukalov //===----------------------------------------------------------------------===//
4948958d02SDaniil Fukalov 
R600TargetMachine(const Target & T,const Triple & TT,StringRef CPU,StringRef FS,TargetOptions Options,Optional<Reloc::Model> RM,Optional<CodeModel::Model> CM,CodeGenOpt::Level OL,bool JIT)5048958d02SDaniil Fukalov R600TargetMachine::R600TargetMachine(const Target &T, const Triple &TT,
5148958d02SDaniil Fukalov                                      StringRef CPU, StringRef FS,
5248958d02SDaniil Fukalov                                      TargetOptions Options,
5348958d02SDaniil Fukalov                                      Optional<Reloc::Model> RM,
5448958d02SDaniil Fukalov                                      Optional<CodeModel::Model> CM,
5548958d02SDaniil Fukalov                                      CodeGenOpt::Level OL, bool JIT)
5648958d02SDaniil Fukalov     : AMDGPUTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL) {
5748958d02SDaniil Fukalov   setRequiresStructuredCFG(true);
5848958d02SDaniil Fukalov 
5948958d02SDaniil Fukalov   // Override the default since calls aren't supported for r600.
6048958d02SDaniil Fukalov   if (EnableFunctionCalls &&
6148958d02SDaniil Fukalov       EnableAMDGPUFunctionCallsOpt.getNumOccurrences() == 0)
6248958d02SDaniil Fukalov     EnableFunctionCalls = false;
6348958d02SDaniil Fukalov }
6448958d02SDaniil Fukalov 
6548958d02SDaniil Fukalov const TargetSubtargetInfo *
getSubtargetImpl(const Function & F) const6648958d02SDaniil Fukalov R600TargetMachine::getSubtargetImpl(const Function &F) const {
6748958d02SDaniil Fukalov   StringRef GPU = getGPUName(F);
6848958d02SDaniil Fukalov   StringRef FS = getFeatureString(F);
6948958d02SDaniil Fukalov 
7048958d02SDaniil Fukalov   SmallString<128> SubtargetKey(GPU);
7148958d02SDaniil Fukalov   SubtargetKey.append(FS);
7248958d02SDaniil Fukalov 
7348958d02SDaniil Fukalov   auto &I = SubtargetMap[SubtargetKey];
7448958d02SDaniil Fukalov   if (!I) {
7548958d02SDaniil Fukalov     // This needs to be done before we create a new subtarget since any
7648958d02SDaniil Fukalov     // creation will depend on the TM and the code generation flags on the
7748958d02SDaniil Fukalov     // function that reside in TargetOptions.
7848958d02SDaniil Fukalov     resetTargetOptions(F);
7948958d02SDaniil Fukalov     I = std::make_unique<R600Subtarget>(TargetTriple, GPU, FS, *this);
8048958d02SDaniil Fukalov   }
8148958d02SDaniil Fukalov 
8248958d02SDaniil Fukalov   return I.get();
8348958d02SDaniil Fukalov }
8448958d02SDaniil Fukalov 
8548958d02SDaniil Fukalov TargetTransformInfo
getTargetTransformInfo(const Function & F) const86*c4b1a63aSJameson Nash R600TargetMachine::getTargetTransformInfo(const Function &F) const {
8748958d02SDaniil Fukalov   return TargetTransformInfo(R600TTIImpl(this, F));
8848958d02SDaniil Fukalov }
8948958d02SDaniil Fukalov 
9048958d02SDaniil Fukalov class R600PassConfig final : public AMDGPUPassConfig {
9148958d02SDaniil Fukalov public:
R600PassConfig(LLVMTargetMachine & TM,PassManagerBase & PM)9248958d02SDaniil Fukalov   R600PassConfig(LLVMTargetMachine &TM, PassManagerBase &PM)
9348958d02SDaniil Fukalov       : AMDGPUPassConfig(TM, PM) {}
9448958d02SDaniil Fukalov 
9548958d02SDaniil Fukalov   ScheduleDAGInstrs *
createMachineScheduler(MachineSchedContext * C) const9648958d02SDaniil Fukalov   createMachineScheduler(MachineSchedContext *C) const override {
9748958d02SDaniil Fukalov     return createR600MachineScheduler(C);
9848958d02SDaniil Fukalov   }
9948958d02SDaniil Fukalov 
10048958d02SDaniil Fukalov   bool addPreISel() override;
10148958d02SDaniil Fukalov   bool addInstSelector() override;
10248958d02SDaniil Fukalov   void addPreRegAlloc() override;
10348958d02SDaniil Fukalov   void addPreSched2() override;
10448958d02SDaniil Fukalov   void addPreEmitPass() override;
10548958d02SDaniil Fukalov };
10648958d02SDaniil Fukalov 
10748958d02SDaniil Fukalov //===----------------------------------------------------------------------===//
10848958d02SDaniil Fukalov // R600 Pass Setup
10948958d02SDaniil Fukalov //===----------------------------------------------------------------------===//
11048958d02SDaniil Fukalov 
addPreISel()11148958d02SDaniil Fukalov bool R600PassConfig::addPreISel() {
11248958d02SDaniil Fukalov   AMDGPUPassConfig::addPreISel();
11348958d02SDaniil Fukalov 
11448958d02SDaniil Fukalov   if (EnableR600StructurizeCFG)
11548958d02SDaniil Fukalov     addPass(createStructurizeCFGPass());
11648958d02SDaniil Fukalov   return false;
11748958d02SDaniil Fukalov }
11848958d02SDaniil Fukalov 
addInstSelector()11948958d02SDaniil Fukalov bool R600PassConfig::addInstSelector() {
12048958d02SDaniil Fukalov   addPass(createR600ISelDag(&getAMDGPUTargetMachine(), getOptLevel()));
12148958d02SDaniil Fukalov   return false;
12248958d02SDaniil Fukalov }
12348958d02SDaniil Fukalov 
addPreRegAlloc()12448958d02SDaniil Fukalov void R600PassConfig::addPreRegAlloc() { addPass(createR600VectorRegMerger()); }
12548958d02SDaniil Fukalov 
addPreSched2()12648958d02SDaniil Fukalov void R600PassConfig::addPreSched2() {
127012248b0SJay Foad   addPass(createR600EmitClauseMarkers());
12848958d02SDaniil Fukalov   if (EnableR600IfConvert)
129012248b0SJay Foad     addPass(&IfConverterID);
130012248b0SJay Foad   addPass(createR600ClauseMergePass());
13148958d02SDaniil Fukalov }
13248958d02SDaniil Fukalov 
addPreEmitPass()13348958d02SDaniil Fukalov void R600PassConfig::addPreEmitPass() {
13457baa14dSJay Foad   addPass(createR600MachineCFGStructurizerPass());
135012248b0SJay Foad   addPass(createR600ExpandSpecialInstrsPass());
136012248b0SJay Foad   addPass(&FinalizeMachineBundlesID);
137012248b0SJay Foad   addPass(createR600Packetizer());
138012248b0SJay Foad   addPass(createR600ControlFlowFinalizer());
13948958d02SDaniil Fukalov }
14048958d02SDaniil Fukalov 
createPassConfig(PassManagerBase & PM)14148958d02SDaniil Fukalov TargetPassConfig *R600TargetMachine::createPassConfig(PassManagerBase &PM) {
14248958d02SDaniil Fukalov   return new R600PassConfig(*this, PM);
14348958d02SDaniil Fukalov }
144