xref: /llvm-project/llvm/lib/Target/LoongArch/LoongArchTargetMachine.cpp (revision 0288d065eecb1208971dc4cdcc71731e34c6fca0)
1444c6d26SLu Weining //===-- LoongArchTargetMachine.cpp - Define TargetMachine for LoongArch ---===//
2444c6d26SLu Weining //
3444c6d26SLu Weining // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4444c6d26SLu Weining // See https://llvm.org/LICENSE.txt for license information.
5444c6d26SLu Weining // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6444c6d26SLu Weining //
7444c6d26SLu Weining //===----------------------------------------------------------------------===//
8444c6d26SLu Weining //
9444c6d26SLu Weining // Implements the info about LoongArch target spec.
10444c6d26SLu Weining //
11444c6d26SLu Weining //===----------------------------------------------------------------------===//
12444c6d26SLu Weining 
13444c6d26SLu Weining #include "LoongArchTargetMachine.h"
1433388ae8SLu Weining #include "LoongArch.h"
1508220df6Swanglei #include "LoongArchMachineFunctionInfo.h"
161918cf58SZhao Qi #include "LoongArchTargetTransformInfo.h"
1733388ae8SLu Weining #include "MCTargetDesc/LoongArchBaseInfo.h"
18444c6d26SLu Weining #include "TargetInfo/LoongArchTargetInfo.h"
191918cf58SZhao Qi #include "llvm/Analysis/TargetTransformInfo.h"
2033388ae8SLu Weining #include "llvm/CodeGen/Passes.h"
2133388ae8SLu Weining #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
2233388ae8SLu Weining #include "llvm/CodeGen/TargetPassConfig.h"
23444c6d26SLu Weining #include "llvm/MC/TargetRegistry.h"
2400786d3aSWANG Xuerui #include "llvm/Support/CodeGen.h"
2511674147SXiaodong Liu #include "llvm/Transforms/Scalar.h"
268c7c20f0SKrzysztof Parzyszek #include <optional>
27444c6d26SLu Weining 
28444c6d26SLu Weining using namespace llvm;
29444c6d26SLu Weining 
30444c6d26SLu Weining #define DEBUG_TYPE "loongarch"
31444c6d26SLu Weining 
32444c6d26SLu Weining extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeLoongArchTarget() {
33444c6d26SLu Weining   // Register the target.
34444c6d26SLu Weining   RegisterTargetMachine<LoongArchTargetMachine> X(getTheLoongArch32Target());
35444c6d26SLu Weining   RegisterTargetMachine<LoongArchTargetMachine> Y(getTheLoongArch64Target());
3675265c7fSwanglei   auto *PR = PassRegistry::getPassRegistry();
37240512c4Shev   initializeLoongArchDeadRegisterDefinitionsPass(*PR);
38b2e69f52Shev   initializeLoongArchMergeBaseOffsetOptPass(*PR);
39e9bcd2bfShev   initializeLoongArchOptWInstrsPass(*PR);
4075265c7fSwanglei   initializeLoongArchPreRAExpandPseudoPass(*PR);
41*0288d065SZhaoQi   initializeLoongArchExpandPseudoPass(*PR);
427652a594Spaperchalice   initializeLoongArchDAGToDAGISelLegacyPass(*PR);
43444c6d26SLu Weining }
44444c6d26SLu Weining 
45240512c4Shev static cl::opt<bool> EnableLoongArchDeadRegisterElimination(
46240512c4Shev     "loongarch-enable-dead-defs", cl::Hidden,
47240512c4Shev     cl::desc("Enable the pass that removes dead"
48240512c4Shev              " definitons and replaces stores to"
49240512c4Shev              " them with stores to r0"),
50240512c4Shev     cl::init(true));
51240512c4Shev 
5211674147SXiaodong Liu static cl::opt<bool>
5311674147SXiaodong Liu     EnableLoopDataPrefetch("loongarch-enable-loop-data-prefetch", cl::Hidden,
5411674147SXiaodong Liu                            cl::desc("Enable the loop data prefetch pass"),
5511674147SXiaodong Liu                            cl::init(false));
5611674147SXiaodong Liu 
57444c6d26SLu Weining static std::string computeDataLayout(const Triple &TT) {
58a1c67439Swanglei   if (TT.isArch64Bit())
5946edc02eShev     return "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128";
60a1c67439Swanglei   assert(TT.isArch32Bit() && "only LA32 and LA64 are currently supported");
61a1c67439Swanglei   return "e-m:e-p:32:32-i64:64-n32-S128";
62444c6d26SLu Weining }
63444c6d26SLu Weining 
64444c6d26SLu Weining static Reloc::Model getEffectiveRelocModel(const Triple &TT,
65bac97427SFangrui Song                                            std::optional<Reloc::Model> RM) {
663c849d0aSFangrui Song   return RM.value_or(Reloc::Static);
67444c6d26SLu Weining }
68444c6d26SLu Weining 
6900786d3aSWANG Xuerui static CodeModel::Model
7000786d3aSWANG Xuerui getEffectiveLoongArchCodeModel(const Triple &TT,
7100786d3aSWANG Xuerui                                std::optional<CodeModel::Model> CM) {
7200786d3aSWANG Xuerui   if (!CM)
7300786d3aSWANG Xuerui     return CodeModel::Small;
7400786d3aSWANG Xuerui 
7500786d3aSWANG Xuerui   switch (*CM) {
7600786d3aSWANG Xuerui   case CodeModel::Small:
7700786d3aSWANG Xuerui     return *CM;
782cf420d5Swanglei   case CodeModel::Medium:
7900786d3aSWANG Xuerui   case CodeModel::Large:
8000786d3aSWANG Xuerui     if (!TT.isArch64Bit())
812cf420d5Swanglei       report_fatal_error("Medium/Large code model requires LA64");
8200786d3aSWANG Xuerui     return *CM;
8300786d3aSWANG Xuerui   default:
8400786d3aSWANG Xuerui     report_fatal_error(
8500786d3aSWANG Xuerui         "Only small, medium and large code models are allowed on LoongArch");
8600786d3aSWANG Xuerui   }
8700786d3aSWANG Xuerui }
8800786d3aSWANG Xuerui 
89444c6d26SLu Weining LoongArchTargetMachine::LoongArchTargetMachine(
90444c6d26SLu Weining     const Target &T, const Triple &TT, StringRef CPU, StringRef FS,
91bac97427SFangrui Song     const TargetOptions &Options, std::optional<Reloc::Model> RM,
920a1aa6cdSArthur Eubanks     std::optional<CodeModel::Model> CM, CodeGenOptLevel OL, bool JIT)
93bb3f5e1fSMatin Raayai     : CodeGenTargetMachineImpl(T, computeDataLayout(TT), TT, CPU, FS, Options,
94444c6d26SLu Weining                                getEffectiveRelocModel(TT, RM),
9500786d3aSWANG Xuerui                                getEffectiveLoongArchCodeModel(TT, CM), OL),
9633388ae8SLu Weining       TLOF(std::make_unique<TargetLoweringObjectFileELF>()) {
97444c6d26SLu Weining   initAsmInfo();
98444c6d26SLu Weining }
99444c6d26SLu Weining 
100444c6d26SLu Weining LoongArchTargetMachine::~LoongArchTargetMachine() = default;
10133388ae8SLu Weining 
10233388ae8SLu Weining const LoongArchSubtarget *
10333388ae8SLu Weining LoongArchTargetMachine::getSubtargetImpl(const Function &F) const {
10433388ae8SLu Weining   Attribute CPUAttr = F.getFnAttribute("target-cpu");
10533388ae8SLu Weining   Attribute TuneAttr = F.getFnAttribute("tune-cpu");
10633388ae8SLu Weining   Attribute FSAttr = F.getFnAttribute("target-features");
10733388ae8SLu Weining 
10833388ae8SLu Weining   std::string CPU =
10933388ae8SLu Weining       CPUAttr.isValid() ? CPUAttr.getValueAsString().str() : TargetCPU;
11033388ae8SLu Weining   std::string TuneCPU =
11133388ae8SLu Weining       TuneAttr.isValid() ? TuneAttr.getValueAsString().str() : CPU;
11233388ae8SLu Weining   std::string FS =
11333388ae8SLu Weining       FSAttr.isValid() ? FSAttr.getValueAsString().str() : TargetFS;
11433388ae8SLu Weining 
11533388ae8SLu Weining   std::string Key = CPU + TuneCPU + FS;
11633388ae8SLu Weining   auto &I = SubtargetMap[Key];
11733388ae8SLu Weining   if (!I) {
11833388ae8SLu Weining     // This needs to be done before we create a new subtarget since any
11933388ae8SLu Weining     // creation will depend on the TM and the code generation flags on the
12033388ae8SLu Weining     // function that reside in TargetOptions.
12133388ae8SLu Weining     resetTargetOptions(F);
12233388ae8SLu Weining     auto ABIName = Options.MCOptions.getABIName();
12333388ae8SLu Weining     if (const MDString *ModuleTargetABI = dyn_cast_or_null<MDString>(
12433388ae8SLu Weining             F.getParent()->getModuleFlag("target-abi"))) {
12533388ae8SLu Weining       auto TargetABI = LoongArchABI::getTargetABI(ABIName);
12633388ae8SLu Weining       if (TargetABI != LoongArchABI::ABI_Unknown &&
12733388ae8SLu Weining           ModuleTargetABI->getString() != ABIName) {
12833388ae8SLu Weining         report_fatal_error("-target-abi option != target-abi module flag");
12933388ae8SLu Weining       }
13033388ae8SLu Weining       ABIName = ModuleTargetABI->getString();
13133388ae8SLu Weining     }
13233388ae8SLu Weining     I = std::make_unique<LoongArchSubtarget>(TargetTriple, CPU, TuneCPU, FS,
13333388ae8SLu Weining                                              ABIName, *this);
13433388ae8SLu Weining   }
13533388ae8SLu Weining   return I.get();
13633388ae8SLu Weining }
13733388ae8SLu Weining 
138c774fd55SMatt Arsenault MachineFunctionInfo *LoongArchTargetMachine::createMachineFunctionInfo(
139c774fd55SMatt Arsenault     BumpPtrAllocator &Allocator, const Function &F,
140c774fd55SMatt Arsenault     const TargetSubtargetInfo *STI) const {
141c774fd55SMatt Arsenault   return LoongArchMachineFunctionInfo::create<LoongArchMachineFunctionInfo>(
142c774fd55SMatt Arsenault       Allocator, F, STI);
143c774fd55SMatt Arsenault }
144c774fd55SMatt Arsenault 
14533388ae8SLu Weining namespace {
14633388ae8SLu Weining class LoongArchPassConfig : public TargetPassConfig {
14733388ae8SLu Weining public:
14833388ae8SLu Weining   LoongArchPassConfig(LoongArchTargetMachine &TM, PassManagerBase &PM)
14933388ae8SLu Weining       : TargetPassConfig(TM, PM) {}
15033388ae8SLu Weining 
15133388ae8SLu Weining   LoongArchTargetMachine &getLoongArchTargetMachine() const {
15233388ae8SLu Weining     return getTM<LoongArchTargetMachine>();
15333388ae8SLu Weining   }
15433388ae8SLu Weining 
15547f3dc6dSgonglingqin   void addIRPasses() override;
1563850912fShev   void addCodeGenPrepare() override;
15733388ae8SLu Weining   bool addInstSelector() override;
15857ad3f1dSXiaodong Liu   void addPreEmitPass() override;
159b60f8016Sgonglingqin   void addPreEmitPass2() override;
160e9bcd2bfShev   void addMachineSSAOptimization() override;
16175265c7fSwanglei   void addPreRegAlloc() override;
162240512c4Shev   bool addRegAssignAndRewriteFast() override;
163240512c4Shev   bool addRegAssignAndRewriteOptimized() override;
16433388ae8SLu Weining };
165904a87acSWeining Lu } // end namespace
16633388ae8SLu Weining 
16733388ae8SLu Weining TargetPassConfig *
16833388ae8SLu Weining LoongArchTargetMachine::createPassConfig(PassManagerBase &PM) {
16933388ae8SLu Weining   return new LoongArchPassConfig(*this, PM);
17033388ae8SLu Weining }
17133388ae8SLu Weining 
17247f3dc6dSgonglingqin void LoongArchPassConfig::addIRPasses() {
17311674147SXiaodong Liu   // Run LoopDataPrefetch
17411674147SXiaodong Liu   //
17511674147SXiaodong Liu   // Run this before LSR to remove the multiplies involved in computing the
17611674147SXiaodong Liu   // pointer values N iterations ahead.
1770a1aa6cdSArthur Eubanks   if (TM->getOptLevel() != CodeGenOptLevel::None && EnableLoopDataPrefetch)
17811674147SXiaodong Liu     addPass(createLoopDataPrefetchPass());
179fe42e72dSRishabh Bali   addPass(createAtomicExpandLegacyPass());
18047f3dc6dSgonglingqin 
18147f3dc6dSgonglingqin   TargetPassConfig::addIRPasses();
18247f3dc6dSgonglingqin }
18347f3dc6dSgonglingqin 
1843850912fShev void LoongArchPassConfig::addCodeGenPrepare() {
1853850912fShev   if (getOptLevel() != CodeGenOptLevel::None)
1863850912fShev     addPass(createTypePromotionLegacyPass());
1873850912fShev   TargetPassConfig::addCodeGenPrepare();
1883850912fShev }
1893850912fShev 
19033388ae8SLu Weining bool LoongArchPassConfig::addInstSelector() {
19133388ae8SLu Weining   addPass(createLoongArchISelDag(getLoongArchTargetMachine()));
19233388ae8SLu Weining 
19333388ae8SLu Weining   return false;
19433388ae8SLu Weining }
195b60f8016Sgonglingqin 
1961918cf58SZhao Qi TargetTransformInfo
1971918cf58SZhao Qi LoongArchTargetMachine::getTargetTransformInfo(const Function &F) const {
1981918cf58SZhao Qi   return TargetTransformInfo(LoongArchTTIImpl(this, F));
1991918cf58SZhao Qi }
2001918cf58SZhao Qi 
20157ad3f1dSXiaodong Liu void LoongArchPassConfig::addPreEmitPass() { addPass(&BranchRelaxationPassID); }
20257ad3f1dSXiaodong Liu 
203b60f8016Sgonglingqin void LoongArchPassConfig::addPreEmitPass2() {
204271087e3Swanglei   addPass(createLoongArchExpandPseudoPass());
205b60f8016Sgonglingqin   // Schedule the expansion of AtomicPseudos at the last possible moment,
206b60f8016Sgonglingqin   // avoiding the possibility for other passes to break the requirements for
207b60f8016Sgonglingqin   // forward progress in the LL/SC block.
208b60f8016Sgonglingqin   addPass(createLoongArchExpandAtomicPseudoPass());
209b60f8016Sgonglingqin }
21075265c7fSwanglei 
211e9bcd2bfShev void LoongArchPassConfig::addMachineSSAOptimization() {
212e9bcd2bfShev   TargetPassConfig::addMachineSSAOptimization();
213e9bcd2bfShev 
214e9bcd2bfShev   if (TM->getTargetTriple().isLoongArch64()) {
215e9bcd2bfShev     addPass(createLoongArchOptWInstrsPass());
216e9bcd2bfShev   }
217e9bcd2bfShev }
218e9bcd2bfShev 
21975265c7fSwanglei void LoongArchPassConfig::addPreRegAlloc() {
22075265c7fSwanglei   addPass(createLoongArchPreRAExpandPseudoPass());
221b2e69f52Shev   if (TM->getOptLevel() != CodeGenOptLevel::None)
222b2e69f52Shev     addPass(createLoongArchMergeBaseOffsetOptPass());
22375265c7fSwanglei }
224240512c4Shev 
225240512c4Shev bool LoongArchPassConfig::addRegAssignAndRewriteFast() {
226240512c4Shev   if (TM->getOptLevel() != CodeGenOptLevel::None &&
227240512c4Shev       EnableLoongArchDeadRegisterElimination)
228240512c4Shev     addPass(createLoongArchDeadRegisterDefinitionsPass());
229240512c4Shev   return TargetPassConfig::addRegAssignAndRewriteFast();
230240512c4Shev }
231240512c4Shev 
232240512c4Shev bool LoongArchPassConfig::addRegAssignAndRewriteOptimized() {
233240512c4Shev   if (TM->getOptLevel() != CodeGenOptLevel::None &&
234240512c4Shev       EnableLoongArchDeadRegisterElimination)
235240512c4Shev     addPass(createLoongArchDeadRegisterDefinitionsPass());
236240512c4Shev   return TargetPassConfig::addRegAssignAndRewriteOptimized();
237240512c4Shev }
238