xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/AMDGPU/R600TargetMachine.cpp (revision 81ad626541db97eb356e2c1d4a20eb2a26a766ab)
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"
18349cc55cSDimitry Andric #include "R600MachineScheduler.h"
19349cc55cSDimitry Andric #include "R600TargetTransformInfo.h"
20349cc55cSDimitry Andric #include "llvm/Transforms/Scalar.h"
21349cc55cSDimitry Andric 
22349cc55cSDimitry Andric using namespace llvm;
23349cc55cSDimitry Andric 
24349cc55cSDimitry Andric static cl::opt<bool>
25349cc55cSDimitry Andric     EnableR600StructurizeCFG("r600-ir-structurize",
26349cc55cSDimitry Andric                              cl::desc("Use StructurizeCFG IR pass"),
27349cc55cSDimitry Andric                              cl::init(true));
28349cc55cSDimitry Andric 
29349cc55cSDimitry Andric static cl::opt<bool> EnableR600IfConvert("r600-if-convert",
30349cc55cSDimitry Andric                                          cl::desc("Use if conversion pass"),
31349cc55cSDimitry Andric                                          cl::ReallyHidden, cl::init(true));
32349cc55cSDimitry Andric 
33349cc55cSDimitry Andric static cl::opt<bool, true> EnableAMDGPUFunctionCallsOpt(
34349cc55cSDimitry Andric     "amdgpu-function-calls", cl::desc("Enable AMDGPU function call support"),
35349cc55cSDimitry Andric     cl::location(AMDGPUTargetMachine::EnableFunctionCalls), cl::init(true),
36349cc55cSDimitry Andric     cl::Hidden);
37349cc55cSDimitry Andric 
38349cc55cSDimitry Andric static ScheduleDAGInstrs *createR600MachineScheduler(MachineSchedContext *C) {
39349cc55cSDimitry Andric   return new ScheduleDAGMILive(C, std::make_unique<R600SchedStrategy>());
40349cc55cSDimitry Andric }
41349cc55cSDimitry Andric 
42349cc55cSDimitry Andric static MachineSchedRegistry R600SchedRegistry("r600",
43349cc55cSDimitry Andric                                               "Run R600's custom scheduler",
44349cc55cSDimitry Andric                                               createR600MachineScheduler);
45349cc55cSDimitry Andric 
46349cc55cSDimitry Andric //===----------------------------------------------------------------------===//
47349cc55cSDimitry Andric // R600 Target Machine (R600 -> Cayman)
48349cc55cSDimitry Andric //===----------------------------------------------------------------------===//
49349cc55cSDimitry Andric 
50349cc55cSDimitry Andric R600TargetMachine::R600TargetMachine(const Target &T, const Triple &TT,
51349cc55cSDimitry Andric                                      StringRef CPU, StringRef FS,
52349cc55cSDimitry Andric                                      TargetOptions Options,
53349cc55cSDimitry Andric                                      Optional<Reloc::Model> RM,
54349cc55cSDimitry Andric                                      Optional<CodeModel::Model> CM,
55349cc55cSDimitry Andric                                      CodeGenOpt::Level OL, bool JIT)
56349cc55cSDimitry Andric     : AMDGPUTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL) {
57349cc55cSDimitry Andric   setRequiresStructuredCFG(true);
58349cc55cSDimitry Andric 
59349cc55cSDimitry Andric   // Override the default since calls aren't supported for r600.
60349cc55cSDimitry Andric   if (EnableFunctionCalls &&
61349cc55cSDimitry Andric       EnableAMDGPUFunctionCallsOpt.getNumOccurrences() == 0)
62349cc55cSDimitry Andric     EnableFunctionCalls = false;
63349cc55cSDimitry Andric }
64349cc55cSDimitry Andric 
65349cc55cSDimitry Andric const TargetSubtargetInfo *
66349cc55cSDimitry Andric R600TargetMachine::getSubtargetImpl(const Function &F) const {
67349cc55cSDimitry Andric   StringRef GPU = getGPUName(F);
68349cc55cSDimitry Andric   StringRef FS = getFeatureString(F);
69349cc55cSDimitry Andric 
70349cc55cSDimitry Andric   SmallString<128> SubtargetKey(GPU);
71349cc55cSDimitry Andric   SubtargetKey.append(FS);
72349cc55cSDimitry Andric 
73349cc55cSDimitry Andric   auto &I = SubtargetMap[SubtargetKey];
74349cc55cSDimitry Andric   if (!I) {
75349cc55cSDimitry Andric     // This needs to be done before we create a new subtarget since any
76349cc55cSDimitry Andric     // creation will depend on the TM and the code generation flags on the
77349cc55cSDimitry Andric     // function that reside in TargetOptions.
78349cc55cSDimitry Andric     resetTargetOptions(F);
79349cc55cSDimitry Andric     I = std::make_unique<R600Subtarget>(TargetTriple, GPU, FS, *this);
80349cc55cSDimitry Andric   }
81349cc55cSDimitry Andric 
82349cc55cSDimitry Andric   return I.get();
83349cc55cSDimitry Andric }
84349cc55cSDimitry Andric 
85349cc55cSDimitry Andric TargetTransformInfo
86*81ad6265SDimitry Andric R600TargetMachine::getTargetTransformInfo(const Function &F) const {
87349cc55cSDimitry Andric   return TargetTransformInfo(R600TTIImpl(this, F));
88349cc55cSDimitry Andric }
89349cc55cSDimitry Andric 
90349cc55cSDimitry Andric class R600PassConfig final : public AMDGPUPassConfig {
91349cc55cSDimitry Andric public:
92349cc55cSDimitry Andric   R600PassConfig(LLVMTargetMachine &TM, PassManagerBase &PM)
93349cc55cSDimitry Andric       : AMDGPUPassConfig(TM, PM) {}
94349cc55cSDimitry Andric 
95349cc55cSDimitry Andric   ScheduleDAGInstrs *
96349cc55cSDimitry Andric   createMachineScheduler(MachineSchedContext *C) const override {
97349cc55cSDimitry Andric     return createR600MachineScheduler(C);
98349cc55cSDimitry Andric   }
99349cc55cSDimitry Andric 
100349cc55cSDimitry Andric   bool addPreISel() override;
101349cc55cSDimitry Andric   bool addInstSelector() override;
102349cc55cSDimitry Andric   void addPreRegAlloc() override;
103349cc55cSDimitry Andric   void addPreSched2() override;
104349cc55cSDimitry Andric   void addPreEmitPass() override;
105349cc55cSDimitry Andric };
106349cc55cSDimitry Andric 
107349cc55cSDimitry Andric //===----------------------------------------------------------------------===//
108349cc55cSDimitry Andric // R600 Pass Setup
109349cc55cSDimitry Andric //===----------------------------------------------------------------------===//
110349cc55cSDimitry Andric 
111349cc55cSDimitry Andric bool R600PassConfig::addPreISel() {
112349cc55cSDimitry Andric   AMDGPUPassConfig::addPreISel();
113349cc55cSDimitry Andric 
114349cc55cSDimitry Andric   if (EnableR600StructurizeCFG)
115349cc55cSDimitry Andric     addPass(createStructurizeCFGPass());
116349cc55cSDimitry Andric   return false;
117349cc55cSDimitry Andric }
118349cc55cSDimitry Andric 
119349cc55cSDimitry Andric bool R600PassConfig::addInstSelector() {
120349cc55cSDimitry Andric   addPass(createR600ISelDag(&getAMDGPUTargetMachine(), getOptLevel()));
121349cc55cSDimitry Andric   return false;
122349cc55cSDimitry Andric }
123349cc55cSDimitry Andric 
124349cc55cSDimitry Andric void R600PassConfig::addPreRegAlloc() { addPass(createR600VectorRegMerger()); }
125349cc55cSDimitry Andric 
126349cc55cSDimitry Andric void R600PassConfig::addPreSched2() {
127349cc55cSDimitry Andric   addPass(createR600EmitClauseMarkers());
128349cc55cSDimitry Andric   if (EnableR600IfConvert)
129349cc55cSDimitry Andric     addPass(&IfConverterID);
130349cc55cSDimitry Andric   addPass(createR600ClauseMergePass());
131349cc55cSDimitry Andric }
132349cc55cSDimitry Andric 
133349cc55cSDimitry Andric void R600PassConfig::addPreEmitPass() {
134*81ad6265SDimitry Andric   addPass(createR600MachineCFGStructurizerPass());
135349cc55cSDimitry Andric   addPass(createR600ExpandSpecialInstrsPass());
136349cc55cSDimitry Andric   addPass(&FinalizeMachineBundlesID);
137349cc55cSDimitry Andric   addPass(createR600Packetizer());
138349cc55cSDimitry Andric   addPass(createR600ControlFlowFinalizer());
139349cc55cSDimitry Andric }
140349cc55cSDimitry Andric 
141349cc55cSDimitry Andric TargetPassConfig *R600TargetMachine::createPassConfig(PassManagerBase &PM) {
142349cc55cSDimitry Andric   return new R600PassConfig(*this, PM);
143349cc55cSDimitry Andric }
144