1//===-- LoongArchTargetMachine.cpp - Define TargetMachine for LoongArch ---===//
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// Implements the info about LoongArch target spec.
10//
11//===----------------------------------------------------------------------===//
12
13#include "LoongArchTargetMachine.h"
14#include "LoongArch.h"
15#include "LoongArchMachineFunctionInfo.h"
16#include "LoongArchTargetObjectFile.h"
17#include "LoongArchTargetTransformInfo.h"
18#include "MCTargetDesc/LoongArchBaseInfo.h"
19#include "TargetInfo/LoongArchTargetInfo.h"
20#include "llvm/Analysis/TargetTransformInfo.h"
21#include "llvm/CodeGen/Passes.h"
22#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
23#include "llvm/CodeGen/TargetPassConfig.h"
24#include "llvm/MC/TargetRegistry.h"
25#include "llvm/Support/CodeGen.h"
26#include "llvm/Support/Compiler.h"
27#include "llvm/Transforms/Scalar.h"
28#include <optional>
29
30using namespace llvm;
31
32#define DEBUG_TYPE "loongarch"
33
34extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void
35LLVMInitializeLoongArchTarget() {
36 // Register the target.
37 RegisterTargetMachine<LoongArchTargetMachine> X(getTheLoongArch32Target());
38 RegisterTargetMachine<LoongArchTargetMachine> Y(getTheLoongArch64Target());
39 auto *PR = PassRegistry::getPassRegistry();
40 initializeLoongArchDeadRegisterDefinitionsPass(*PR);
41 initializeLoongArchMergeBaseOffsetOptPass(*PR);
42 initializeLoongArchOptWInstrsPass(*PR);
43 initializeLoongArchPreRAExpandPseudoPass(*PR);
44 initializeLoongArchExpandPseudoPass(*PR);
45 initializeLoongArchDAGToDAGISelLegacyPass(*PR);
46 initializeLoongArchExpandAtomicPseudoPass(*PR);
47}
48
49static cl::opt<bool> EnableLoongArchDeadRegisterElimination(
50 "loongarch-enable-dead-defs", cl::Hidden,
51 cl::desc("Enable the pass that removes dead"
52 " definitons and replaces stores to"
53 " them with stores to r0"),
54 cl::init(Val: true));
55
56static cl::opt<bool>
57 EnableLoopDataPrefetch("loongarch-enable-loop-data-prefetch", cl::Hidden,
58 cl::desc("Enable the loop data prefetch pass"),
59 cl::init(Val: false));
60
61static cl::opt<bool>
62 EnableMergeBaseOffset("loongarch-enable-merge-offset",
63 cl::desc("Enable the merge base offset pass"),
64 cl::init(Val: true), cl::Hidden);
65
66static cl::opt<bool>
67 EnableSinkFold("loongarch-enable-sink-fold",
68 cl::desc("Enable sinking and folding of instruction copies"),
69 cl::init(Val: true), cl::Hidden);
70
71static Reloc::Model getEffectiveRelocModel(std::optional<Reloc::Model> RM) {
72 return RM.value_or(u: Reloc::Static);
73}
74
75static CodeModel::Model
76getEffectiveLoongArchCodeModel(const Triple &TT,
77 std::optional<CodeModel::Model> CM) {
78 if (!CM)
79 return TT.isArch64Bit() ? CodeModel::Medium : CodeModel::Small;
80
81 switch (*CM) {
82 case CodeModel::Small:
83 case CodeModel::Medium:
84 return *CM;
85 case CodeModel::Large:
86 if (!TT.isArch64Bit())
87 report_fatal_error(reason: "Large code model requires LA64");
88 return *CM;
89 default:
90 report_fatal_error(
91 reason: "Only small, medium and large code models are allowed on LoongArch");
92 }
93}
94
95LoongArchTargetMachine::LoongArchTargetMachine(
96 const Target &T, const Triple &TT, StringRef CPU, StringRef FS,
97 const TargetOptions &Options, std::optional<Reloc::Model> RM,
98 std::optional<CodeModel::Model> CM, CodeGenOptLevel OL, bool JIT)
99 : CodeGenTargetMachineImpl(T, TT.computeDataLayout(), TT, CPU, FS, Options,
100 getEffectiveRelocModel(RM),
101 getEffectiveLoongArchCodeModel(TT, CM), OL),
102 TLOF(std::make_unique<LoongArchELFTargetObjectFile>()) {
103 initAsmInfo();
104}
105
106LoongArchTargetMachine::~LoongArchTargetMachine() = default;
107
108const LoongArchSubtarget *
109LoongArchTargetMachine::getSubtargetImpl(const Function &F) const {
110 Attribute CPUAttr = F.getFnAttribute(Kind: "target-cpu");
111 Attribute TuneAttr = F.getFnAttribute(Kind: "tune-cpu");
112 Attribute FSAttr = F.getFnAttribute(Kind: "target-features");
113
114 std::string CPU =
115 CPUAttr.isValid() ? CPUAttr.getValueAsString().str() : TargetCPU;
116 std::string TuneCPU =
117 TuneAttr.isValid() ? TuneAttr.getValueAsString().str() : CPU;
118 std::string FS =
119 FSAttr.isValid() ? FSAttr.getValueAsString().str() : TargetFS;
120
121 std::string Key = CPU + TuneCPU + FS;
122 auto &I = SubtargetMap[Key];
123 if (!I) {
124 StringRef ABIName = getTargetABIName(M: *F.getParent());
125 I = std::make_unique<LoongArchSubtarget>(args: TargetTriple, args&: CPU, args&: TuneCPU, args&: FS,
126 args&: ABIName, args: *this);
127 }
128 return I.get();
129}
130
131MachineFunctionInfo *LoongArchTargetMachine::createMachineFunctionInfo(
132 BumpPtrAllocator &Allocator, const Function &F,
133 const TargetSubtargetInfo *STI) const {
134 return LoongArchMachineFunctionInfo::create<LoongArchMachineFunctionInfo>(
135 Allocator, F, STI);
136}
137
138namespace {
139class LoongArchPassConfig : public TargetPassConfig {
140public:
141 LoongArchPassConfig(LoongArchTargetMachine &TM, PassManagerBase &PM)
142 : TargetPassConfig(TM, PM) {
143 setEnableSinkAndFold(EnableSinkFold);
144 }
145
146 LoongArchTargetMachine &getLoongArchTargetMachine() const {
147 return getTM<LoongArchTargetMachine>();
148 }
149
150 void addIRPasses() override;
151 void addCodeGenPrepare() override;
152 bool addInstSelector() override;
153 void addPreEmitPass() override;
154 void addPreEmitPass2() override;
155 void addMachineSSAOptimization() override;
156 void addPreRegAlloc() override;
157 bool addRegAssignAndRewriteFast() override;
158 bool addRegAssignAndRewriteOptimized() override;
159};
160} // end namespace
161
162TargetPassConfig *
163LoongArchTargetMachine::createPassConfig(PassManagerBase &PM) {
164 return new LoongArchPassConfig(*this, PM);
165}
166
167void LoongArchPassConfig::addIRPasses() {
168 // Run LoopDataPrefetch
169 //
170 // Run this before LSR to remove the multiplies involved in computing the
171 // pointer values N iterations ahead.
172 if (TM->getOptLevel() != CodeGenOptLevel::None && EnableLoopDataPrefetch)
173 addPass(P: createLoopDataPrefetchPass());
174 addPass(P: createAtomicExpandLegacyPass());
175
176 TargetPassConfig::addIRPasses();
177}
178
179void LoongArchPassConfig::addCodeGenPrepare() {
180 if (getOptLevel() != CodeGenOptLevel::None)
181 addPass(P: createTypePromotionLegacyPass());
182 TargetPassConfig::addCodeGenPrepare();
183}
184
185bool LoongArchPassConfig::addInstSelector() {
186 addPass(P: createLoongArchISelDag(TM&: getLoongArchTargetMachine(), OptLevel: getOptLevel()));
187
188 return false;
189}
190
191TargetTransformInfo
192LoongArchTargetMachine::getTargetTransformInfo(const Function &F) const {
193 return TargetTransformInfo(std::make_unique<LoongArchTTIImpl>(args: this, args: F));
194}
195
196void LoongArchPassConfig::addPreEmitPass() { addPass(PassID: &BranchRelaxationPassID); }
197
198void LoongArchPassConfig::addPreEmitPass2() {
199 addPass(P: createLoongArchExpandPseudoPass());
200 // Schedule the expansion of AtomicPseudos at the last possible moment,
201 // avoiding the possibility for other passes to break the requirements for
202 // forward progress in the LL/SC block.
203 addPass(P: createLoongArchExpandAtomicPseudoPass());
204}
205
206void LoongArchPassConfig::addMachineSSAOptimization() {
207 TargetPassConfig::addMachineSSAOptimization();
208
209 if (TM->getTargetTriple().isLoongArch64()) {
210 addPass(P: createLoongArchOptWInstrsPass());
211 }
212}
213
214void LoongArchPassConfig::addPreRegAlloc() {
215 addPass(P: createLoongArchPreRAExpandPseudoPass());
216 if (TM->getOptLevel() != CodeGenOptLevel::None && EnableMergeBaseOffset)
217 addPass(P: createLoongArchMergeBaseOffsetOptPass());
218}
219
220bool LoongArchPassConfig::addRegAssignAndRewriteFast() {
221 if (TM->getOptLevel() != CodeGenOptLevel::None &&
222 EnableLoongArchDeadRegisterElimination)
223 addPass(P: createLoongArchDeadRegisterDefinitionsPass());
224 return TargetPassConfig::addRegAssignAndRewriteFast();
225}
226
227bool LoongArchPassConfig::addRegAssignAndRewriteOptimized() {
228 if (TM->getOptLevel() != CodeGenOptLevel::None &&
229 EnableLoongArchDeadRegisterElimination)
230 addPass(P: createLoongArchDeadRegisterDefinitionsPass());
231 return TargetPassConfig::addRegAssignAndRewriteOptimized();
232}
233