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