xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/AMDGPU/R600TargetMachine.cpp (revision 349cc55c9796c4596a5b9904cd3281af295f878f)
1*349cc55cSDimitry Andric //===-- R600TargetMachine.cpp - TargetMachine for hw codegen targets-------===//
2*349cc55cSDimitry Andric //
3*349cc55cSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*349cc55cSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*349cc55cSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*349cc55cSDimitry Andric //
7*349cc55cSDimitry Andric //===----------------------------------------------------------------------===//
8*349cc55cSDimitry Andric //
9*349cc55cSDimitry Andric /// \file
10*349cc55cSDimitry Andric /// The AMDGPU-R600 target machine contains all of the hardware specific
11*349cc55cSDimitry Andric /// information  needed to emit code for R600 GPUs.
12*349cc55cSDimitry Andric //
13*349cc55cSDimitry Andric //===----------------------------------------------------------------------===//
14*349cc55cSDimitry Andric 
15*349cc55cSDimitry Andric #include "R600TargetMachine.h"
16*349cc55cSDimitry Andric #include "AMDGPUTargetMachine.h"
17*349cc55cSDimitry Andric #include "R600.h"
18*349cc55cSDimitry Andric #include "R600MachineScheduler.h"
19*349cc55cSDimitry Andric #include "R600TargetTransformInfo.h"
20*349cc55cSDimitry Andric #include "llvm/Transforms/Scalar.h"
21*349cc55cSDimitry Andric 
22*349cc55cSDimitry Andric using namespace llvm;
23*349cc55cSDimitry Andric 
24*349cc55cSDimitry Andric static cl::opt<bool>
25*349cc55cSDimitry Andric     EnableR600StructurizeCFG("r600-ir-structurize",
26*349cc55cSDimitry Andric                              cl::desc("Use StructurizeCFG IR pass"),
27*349cc55cSDimitry Andric                              cl::init(true));
28*349cc55cSDimitry Andric 
29*349cc55cSDimitry Andric static cl::opt<bool> EnableR600IfConvert("r600-if-convert",
30*349cc55cSDimitry Andric                                          cl::desc("Use if conversion pass"),
31*349cc55cSDimitry Andric                                          cl::ReallyHidden, cl::init(true));
32*349cc55cSDimitry Andric 
33*349cc55cSDimitry Andric static cl::opt<bool, true> EnableAMDGPUFunctionCallsOpt(
34*349cc55cSDimitry Andric     "amdgpu-function-calls", cl::desc("Enable AMDGPU function call support"),
35*349cc55cSDimitry Andric     cl::location(AMDGPUTargetMachine::EnableFunctionCalls), cl::init(true),
36*349cc55cSDimitry Andric     cl::Hidden);
37*349cc55cSDimitry Andric 
38*349cc55cSDimitry Andric static ScheduleDAGInstrs *createR600MachineScheduler(MachineSchedContext *C) {
39*349cc55cSDimitry Andric   return new ScheduleDAGMILive(C, std::make_unique<R600SchedStrategy>());
40*349cc55cSDimitry Andric }
41*349cc55cSDimitry Andric 
42*349cc55cSDimitry Andric static MachineSchedRegistry R600SchedRegistry("r600",
43*349cc55cSDimitry Andric                                               "Run R600's custom scheduler",
44*349cc55cSDimitry Andric                                               createR600MachineScheduler);
45*349cc55cSDimitry Andric 
46*349cc55cSDimitry Andric //===----------------------------------------------------------------------===//
47*349cc55cSDimitry Andric // R600 Target Machine (R600 -> Cayman)
48*349cc55cSDimitry Andric //===----------------------------------------------------------------------===//
49*349cc55cSDimitry Andric 
50*349cc55cSDimitry Andric R600TargetMachine::R600TargetMachine(const Target &T, const Triple &TT,
51*349cc55cSDimitry Andric                                      StringRef CPU, StringRef FS,
52*349cc55cSDimitry Andric                                      TargetOptions Options,
53*349cc55cSDimitry Andric                                      Optional<Reloc::Model> RM,
54*349cc55cSDimitry Andric                                      Optional<CodeModel::Model> CM,
55*349cc55cSDimitry Andric                                      CodeGenOpt::Level OL, bool JIT)
56*349cc55cSDimitry Andric     : AMDGPUTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL) {
57*349cc55cSDimitry Andric   setRequiresStructuredCFG(true);
58*349cc55cSDimitry Andric 
59*349cc55cSDimitry Andric   // Override the default since calls aren't supported for r600.
60*349cc55cSDimitry Andric   if (EnableFunctionCalls &&
61*349cc55cSDimitry Andric       EnableAMDGPUFunctionCallsOpt.getNumOccurrences() == 0)
62*349cc55cSDimitry Andric     EnableFunctionCalls = false;
63*349cc55cSDimitry Andric }
64*349cc55cSDimitry Andric 
65*349cc55cSDimitry Andric const TargetSubtargetInfo *
66*349cc55cSDimitry Andric R600TargetMachine::getSubtargetImpl(const Function &F) const {
67*349cc55cSDimitry Andric   StringRef GPU = getGPUName(F);
68*349cc55cSDimitry Andric   StringRef FS = getFeatureString(F);
69*349cc55cSDimitry Andric 
70*349cc55cSDimitry Andric   SmallString<128> SubtargetKey(GPU);
71*349cc55cSDimitry Andric   SubtargetKey.append(FS);
72*349cc55cSDimitry Andric 
73*349cc55cSDimitry Andric   auto &I = SubtargetMap[SubtargetKey];
74*349cc55cSDimitry Andric   if (!I) {
75*349cc55cSDimitry Andric     // This needs to be done before we create a new subtarget since any
76*349cc55cSDimitry Andric     // creation will depend on the TM and the code generation flags on the
77*349cc55cSDimitry Andric     // function that reside in TargetOptions.
78*349cc55cSDimitry Andric     resetTargetOptions(F);
79*349cc55cSDimitry Andric     I = std::make_unique<R600Subtarget>(TargetTriple, GPU, FS, *this);
80*349cc55cSDimitry Andric   }
81*349cc55cSDimitry Andric 
82*349cc55cSDimitry Andric   return I.get();
83*349cc55cSDimitry Andric }
84*349cc55cSDimitry Andric 
85*349cc55cSDimitry Andric TargetTransformInfo
86*349cc55cSDimitry Andric R600TargetMachine::getTargetTransformInfo(const Function &F) {
87*349cc55cSDimitry Andric   return TargetTransformInfo(R600TTIImpl(this, F));
88*349cc55cSDimitry Andric }
89*349cc55cSDimitry Andric 
90*349cc55cSDimitry Andric class R600PassConfig final : public AMDGPUPassConfig {
91*349cc55cSDimitry Andric public:
92*349cc55cSDimitry Andric   R600PassConfig(LLVMTargetMachine &TM, PassManagerBase &PM)
93*349cc55cSDimitry Andric       : AMDGPUPassConfig(TM, PM) {}
94*349cc55cSDimitry Andric 
95*349cc55cSDimitry Andric   ScheduleDAGInstrs *
96*349cc55cSDimitry Andric   createMachineScheduler(MachineSchedContext *C) const override {
97*349cc55cSDimitry Andric     return createR600MachineScheduler(C);
98*349cc55cSDimitry Andric   }
99*349cc55cSDimitry Andric 
100*349cc55cSDimitry Andric   bool addPreISel() override;
101*349cc55cSDimitry Andric   bool addInstSelector() override;
102*349cc55cSDimitry Andric   void addPreRegAlloc() override;
103*349cc55cSDimitry Andric   void addPreSched2() override;
104*349cc55cSDimitry Andric   void addPreEmitPass() override;
105*349cc55cSDimitry Andric };
106*349cc55cSDimitry Andric 
107*349cc55cSDimitry Andric //===----------------------------------------------------------------------===//
108*349cc55cSDimitry Andric // R600 Pass Setup
109*349cc55cSDimitry Andric //===----------------------------------------------------------------------===//
110*349cc55cSDimitry Andric 
111*349cc55cSDimitry Andric bool R600PassConfig::addPreISel() {
112*349cc55cSDimitry Andric   AMDGPUPassConfig::addPreISel();
113*349cc55cSDimitry Andric 
114*349cc55cSDimitry Andric   if (EnableR600StructurizeCFG)
115*349cc55cSDimitry Andric     addPass(createStructurizeCFGPass());
116*349cc55cSDimitry Andric   return false;
117*349cc55cSDimitry Andric }
118*349cc55cSDimitry Andric 
119*349cc55cSDimitry Andric bool R600PassConfig::addInstSelector() {
120*349cc55cSDimitry Andric   addPass(createR600ISelDag(&getAMDGPUTargetMachine(), getOptLevel()));
121*349cc55cSDimitry Andric   return false;
122*349cc55cSDimitry Andric }
123*349cc55cSDimitry Andric 
124*349cc55cSDimitry Andric void R600PassConfig::addPreRegAlloc() { addPass(createR600VectorRegMerger()); }
125*349cc55cSDimitry Andric 
126*349cc55cSDimitry Andric void R600PassConfig::addPreSched2() {
127*349cc55cSDimitry Andric   addPass(createR600EmitClauseMarkers());
128*349cc55cSDimitry Andric   if (EnableR600IfConvert)
129*349cc55cSDimitry Andric     addPass(&IfConverterID);
130*349cc55cSDimitry Andric   addPass(createR600ClauseMergePass());
131*349cc55cSDimitry Andric }
132*349cc55cSDimitry Andric 
133*349cc55cSDimitry Andric void R600PassConfig::addPreEmitPass() {
134*349cc55cSDimitry Andric   addPass(createAMDGPUCFGStructurizerPass());
135*349cc55cSDimitry Andric   addPass(createR600ExpandSpecialInstrsPass());
136*349cc55cSDimitry Andric   addPass(&FinalizeMachineBundlesID);
137*349cc55cSDimitry Andric   addPass(createR600Packetizer());
138*349cc55cSDimitry Andric   addPass(createR600ControlFlowFinalizer());
139*349cc55cSDimitry Andric }
140*349cc55cSDimitry Andric 
141*349cc55cSDimitry Andric TargetPassConfig *R600TargetMachine::createPassConfig(PassManagerBase &PM) {
142*349cc55cSDimitry Andric   return new R600PassConfig(*this, PM);
143*349cc55cSDimitry Andric }
144