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