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
22 using namespace llvm;
23
24 static cl::opt<bool>
25 EnableR600StructurizeCFG("r600-ir-structurize",
26 cl::desc("Use StructurizeCFG IR pass"),
27 cl::init(true));
28
29 static cl::opt<bool> EnableR600IfConvert("r600-if-convert",
30 cl::desc("Use if conversion pass"),
31 cl::ReallyHidden, cl::init(true));
32
33 static cl::opt<bool, true> EnableAMDGPUFunctionCallsOpt(
34 "amdgpu-function-calls", cl::desc("Enable AMDGPU function call support"),
35 cl::location(AMDGPUTargetMachine::EnableFunctionCalls), cl::init(true),
36 cl::Hidden);
37
createR600MachineScheduler(MachineSchedContext * C)38 static ScheduleDAGInstrs *createR600MachineScheduler(MachineSchedContext *C) {
39 return new ScheduleDAGMILive(C, std::make_unique<R600SchedStrategy>());
40 }
41
42 static MachineSchedRegistry R600SchedRegistry("r600",
43 "Run R600's custom scheduler",
44 createR600MachineScheduler);
45
46 //===----------------------------------------------------------------------===//
47 // R600 Target Machine (R600 -> Cayman)
48 //===----------------------------------------------------------------------===//
49
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)50 R600TargetMachine::R600TargetMachine(const Target &T, const Triple &TT,
51 StringRef CPU, StringRef FS,
52 TargetOptions Options,
53 Optional<Reloc::Model> RM,
54 Optional<CodeModel::Model> CM,
55 CodeGenOpt::Level OL, bool JIT)
56 : AMDGPUTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL) {
57 setRequiresStructuredCFG(true);
58
59 // Override the default since calls aren't supported for r600.
60 if (EnableFunctionCalls &&
61 EnableAMDGPUFunctionCallsOpt.getNumOccurrences() == 0)
62 EnableFunctionCalls = false;
63 }
64
65 const TargetSubtargetInfo *
getSubtargetImpl(const Function & F) const66 R600TargetMachine::getSubtargetImpl(const Function &F) const {
67 StringRef GPU = getGPUName(F);
68 StringRef FS = getFeatureString(F);
69
70 SmallString<128> SubtargetKey(GPU);
71 SubtargetKey.append(FS);
72
73 auto &I = SubtargetMap[SubtargetKey];
74 if (!I) {
75 // This needs to be done before we create a new subtarget since any
76 // creation will depend on the TM and the code generation flags on the
77 // function that reside in TargetOptions.
78 resetTargetOptions(F);
79 I = std::make_unique<R600Subtarget>(TargetTriple, GPU, FS, *this);
80 }
81
82 return I.get();
83 }
84
85 TargetTransformInfo
getTargetTransformInfo(const Function & F) const86 R600TargetMachine::getTargetTransformInfo(const Function &F) const {
87 return TargetTransformInfo(R600TTIImpl(this, F));
88 }
89
90 class R600PassConfig final : public AMDGPUPassConfig {
91 public:
R600PassConfig(LLVMTargetMachine & TM,PassManagerBase & PM)92 R600PassConfig(LLVMTargetMachine &TM, PassManagerBase &PM)
93 : AMDGPUPassConfig(TM, PM) {}
94
95 ScheduleDAGInstrs *
createMachineScheduler(MachineSchedContext * C) const96 createMachineScheduler(MachineSchedContext *C) const override {
97 return createR600MachineScheduler(C);
98 }
99
100 bool addPreISel() override;
101 bool addInstSelector() override;
102 void addPreRegAlloc() override;
103 void addPreSched2() override;
104 void addPreEmitPass() override;
105 };
106
107 //===----------------------------------------------------------------------===//
108 // R600 Pass Setup
109 //===----------------------------------------------------------------------===//
110
addPreISel()111 bool R600PassConfig::addPreISel() {
112 AMDGPUPassConfig::addPreISel();
113
114 if (EnableR600StructurizeCFG)
115 addPass(createStructurizeCFGPass());
116 return false;
117 }
118
addInstSelector()119 bool R600PassConfig::addInstSelector() {
120 addPass(createR600ISelDag(&getAMDGPUTargetMachine(), getOptLevel()));
121 return false;
122 }
123
addPreRegAlloc()124 void R600PassConfig::addPreRegAlloc() { addPass(createR600VectorRegMerger()); }
125
addPreSched2()126 void R600PassConfig::addPreSched2() {
127 addPass(createR600EmitClauseMarkers());
128 if (EnableR600IfConvert)
129 addPass(&IfConverterID);
130 addPass(createR600ClauseMergePass());
131 }
132
addPreEmitPass()133 void R600PassConfig::addPreEmitPass() {
134 addPass(createR600MachineCFGStructurizerPass());
135 addPass(createR600ExpandSpecialInstrsPass());
136 addPass(&FinalizeMachineBundlesID);
137 addPass(createR600Packetizer());
138 addPass(createR600ControlFlowFinalizer());
139 }
140
createPassConfig(PassManagerBase & PM)141 TargetPassConfig *R600TargetMachine::createPassConfig(PassManagerBase &PM) {
142 return new R600PassConfig(*this, PM);
143 }
144