xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/AMDGPU/R600TargetMachine.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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