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