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