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 "MCTargetDesc/LoongArchBaseInfo.h"
17 #include "TargetInfo/LoongArchTargetInfo.h"
18 #include "llvm/CodeGen/Passes.h"
19 #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
20 #include "llvm/CodeGen/TargetPassConfig.h"
21 #include "llvm/MC/TargetRegistry.h"
22 #include <optional>
23 
24 using namespace llvm;
25 
26 #define DEBUG_TYPE "loongarch"
27 
28 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeLoongArchTarget() {
29   // Register the target.
30   RegisterTargetMachine<LoongArchTargetMachine> X(getTheLoongArch32Target());
31   RegisterTargetMachine<LoongArchTargetMachine> Y(getTheLoongArch64Target());
32   auto *PR = PassRegistry::getPassRegistry();
33   initializeLoongArchPreRAExpandPseudoPass(*PR);
34   initializeLoongArchDAGToDAGISelPass(*PR);
35 }
36 
37 static std::string computeDataLayout(const Triple &TT) {
38   if (TT.isArch64Bit())
39     return "e-m:e-p:64:64-i64:64-i128:128-n64-S128";
40   assert(TT.isArch32Bit() && "only LA32 and LA64 are currently supported");
41   return "e-m:e-p:32:32-i64:64-n32-S128";
42 }
43 
44 static Reloc::Model getEffectiveRelocModel(const Triple &TT,
45                                            std::optional<Reloc::Model> RM) {
46   return RM.value_or(Reloc::Static);
47 }
48 
49 LoongArchTargetMachine::LoongArchTargetMachine(
50     const Target &T, const Triple &TT, StringRef CPU, StringRef FS,
51     const TargetOptions &Options, std::optional<Reloc::Model> RM,
52     std::optional<CodeModel::Model> CM, CodeGenOpt::Level OL, bool JIT)
53     : LLVMTargetMachine(T, computeDataLayout(TT), TT, CPU, FS, Options,
54                         getEffectiveRelocModel(TT, RM),
55                         getEffectiveCodeModel(CM, CodeModel::Small), OL),
56       TLOF(std::make_unique<TargetLoweringObjectFileELF>()) {
57   initAsmInfo();
58 }
59 
60 LoongArchTargetMachine::~LoongArchTargetMachine() = default;
61 
62 const LoongArchSubtarget *
63 LoongArchTargetMachine::getSubtargetImpl(const Function &F) const {
64   Attribute CPUAttr = F.getFnAttribute("target-cpu");
65   Attribute TuneAttr = F.getFnAttribute("tune-cpu");
66   Attribute FSAttr = F.getFnAttribute("target-features");
67 
68   std::string CPU =
69       CPUAttr.isValid() ? CPUAttr.getValueAsString().str() : TargetCPU;
70   std::string TuneCPU =
71       TuneAttr.isValid() ? TuneAttr.getValueAsString().str() : CPU;
72   std::string FS =
73       FSAttr.isValid() ? FSAttr.getValueAsString().str() : TargetFS;
74 
75   std::string Key = CPU + TuneCPU + FS;
76   auto &I = SubtargetMap[Key];
77   if (!I) {
78     // This needs to be done before we create a new subtarget since any
79     // creation will depend on the TM and the code generation flags on the
80     // function that reside in TargetOptions.
81     resetTargetOptions(F);
82     auto ABIName = Options.MCOptions.getABIName();
83     if (const MDString *ModuleTargetABI = dyn_cast_or_null<MDString>(
84             F.getParent()->getModuleFlag("target-abi"))) {
85       auto TargetABI = LoongArchABI::getTargetABI(ABIName);
86       if (TargetABI != LoongArchABI::ABI_Unknown &&
87           ModuleTargetABI->getString() != ABIName) {
88         report_fatal_error("-target-abi option != target-abi module flag");
89       }
90       ABIName = ModuleTargetABI->getString();
91     }
92     I = std::make_unique<LoongArchSubtarget>(TargetTriple, CPU, TuneCPU, FS,
93                                              ABIName, *this);
94   }
95   return I.get();
96 }
97 
98 MachineFunctionInfo *LoongArchTargetMachine::createMachineFunctionInfo(
99     BumpPtrAllocator &Allocator, const Function &F,
100     const TargetSubtargetInfo *STI) const {
101   return LoongArchMachineFunctionInfo::create<LoongArchMachineFunctionInfo>(
102       Allocator, F, STI);
103 }
104 
105 namespace {
106 class LoongArchPassConfig : public TargetPassConfig {
107 public:
108   LoongArchPassConfig(LoongArchTargetMachine &TM, PassManagerBase &PM)
109       : TargetPassConfig(TM, PM) {}
110 
111   LoongArchTargetMachine &getLoongArchTargetMachine() const {
112     return getTM<LoongArchTargetMachine>();
113   }
114 
115   void addIRPasses() override;
116   bool addInstSelector() override;
117   void addPreEmitPass() override;
118   void addPreEmitPass2() override;
119   void addPreRegAlloc() override;
120 };
121 } // end namespace
122 
123 TargetPassConfig *
124 LoongArchTargetMachine::createPassConfig(PassManagerBase &PM) {
125   return new LoongArchPassConfig(*this, PM);
126 }
127 
128 void LoongArchPassConfig::addIRPasses() {
129   addPass(createAtomicExpandPass());
130 
131   TargetPassConfig::addIRPasses();
132 }
133 
134 bool LoongArchPassConfig::addInstSelector() {
135   addPass(createLoongArchISelDag(getLoongArchTargetMachine()));
136 
137   return false;
138 }
139 
140 void LoongArchPassConfig::addPreEmitPass() { addPass(&BranchRelaxationPassID); }
141 
142 void LoongArchPassConfig::addPreEmitPass2() {
143   // Schedule the expansion of AtomicPseudos at the last possible moment,
144   // avoiding the possibility for other passes to break the requirements for
145   // forward progress in the LL/SC block.
146   addPass(createLoongArchExpandAtomicPseudoPass());
147 }
148 
149 void LoongArchPassConfig::addPreRegAlloc() {
150   addPass(createLoongArchPreRAExpandPseudoPass());
151 }
152