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