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
28using namespace llvm;
29
30#define DEBUG_TYPE "loongarch"
31
32extern "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
43static 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(Val: true));
49
50static cl::opt<bool>
51 EnableLoopDataPrefetch("loongarch-enable-loop-data-prefetch", cl::Hidden,
52 cl::desc("Enable the loop data prefetch pass"),
53 cl::init(Val: false));
54
55static 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
62static Reloc::Model getEffectiveRelocModel(const Triple &TT,
63 std::optional<Reloc::Model> RM) {
64 return RM.value_or(u: Reloc::Static);
65}
66
67static CodeModel::Model
68getEffectiveLoongArchCodeModel(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(reason: "Medium/Large code model requires LA64");
80 return *CM;
81 default:
82 report_fatal_error(
83 reason: "Only small, medium and large code models are allowed on LoongArch");
84 }
85}
86
87LoongArchTargetMachine::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
98LoongArchTargetMachine::~LoongArchTargetMachine() = default;
99
100const LoongArchSubtarget *
101LoongArchTargetMachine::getSubtargetImpl(const Function &F) const {
102 Attribute CPUAttr = F.getFnAttribute(Kind: "target-cpu");
103 Attribute TuneAttr = F.getFnAttribute(Kind: "tune-cpu");
104 Attribute FSAttr = F.getFnAttribute(Kind: "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 Val: F.getParent()->getModuleFlag(Key: "target-abi"))) {
123 auto TargetABI = LoongArchABI::getTargetABI(ABIName);
124 if (TargetABI != LoongArchABI::ABI_Unknown &&
125 ModuleTargetABI->getString() != ABIName) {
126 report_fatal_error(reason: "-target-abi option != target-abi module flag");
127 }
128 ABIName = ModuleTargetABI->getString();
129 }
130 I = std::make_unique<LoongArchSubtarget>(args: TargetTriple, args&: CPU, args&: TuneCPU, args&: FS,
131 args&: ABIName, args: *this);
132 }
133 return I.get();
134}
135
136MachineFunctionInfo *LoongArchTargetMachine::createMachineFunctionInfo(
137 BumpPtrAllocator &Allocator, const Function &F,
138 const TargetSubtargetInfo *STI) const {
139 return LoongArchMachineFunctionInfo::create<LoongArchMachineFunctionInfo>(
140 Allocator, F, STI);
141}
142
143namespace {
144class LoongArchPassConfig : public TargetPassConfig {
145public:
146 LoongArchPassConfig(LoongArchTargetMachine &TM, PassManagerBase &PM)
147 : TargetPassConfig(TM, PM) {}
148
149 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
165TargetPassConfig *
166LoongArchTargetMachine::createPassConfig(PassManagerBase &PM) {
167 return new LoongArchPassConfig(*this, PM);
168}
169
170void 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(P: createLoopDataPrefetchPass());
177 addPass(P: createAtomicExpandLegacyPass());
178
179 TargetPassConfig::addIRPasses();
180}
181
182void LoongArchPassConfig::addCodeGenPrepare() {
183 if (getOptLevel() != CodeGenOptLevel::None)
184 addPass(P: createTypePromotionLegacyPass());
185 TargetPassConfig::addCodeGenPrepare();
186}
187
188bool LoongArchPassConfig::addInstSelector() {
189 addPass(P: createLoongArchISelDag(TM&: getLoongArchTargetMachine()));
190
191 return false;
192}
193
194TargetTransformInfo
195LoongArchTargetMachine::getTargetTransformInfo(const Function &F) const {
196 return TargetTransformInfo(LoongArchTTIImpl(this, F));
197}
198
199void LoongArchPassConfig::addPreEmitPass() { addPass(PassID: &BranchRelaxationPassID); }
200
201void LoongArchPassConfig::addPreEmitPass2() {
202 addPass(P: 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(P: createLoongArchExpandAtomicPseudoPass());
207}
208
209void LoongArchPassConfig::addMachineSSAOptimization() {
210 TargetPassConfig::addMachineSSAOptimization();
211
212 if (TM->getTargetTriple().isLoongArch64()) {
213 addPass(P: createLoongArchOptWInstrsPass());
214 }
215}
216
217void LoongArchPassConfig::addPreRegAlloc() {
218 addPass(P: createLoongArchPreRAExpandPseudoPass());
219}
220
221bool LoongArchPassConfig::addRegAssignAndRewriteFast() {
222 if (TM->getOptLevel() != CodeGenOptLevel::None &&
223 EnableLoongArchDeadRegisterElimination)
224 addPass(P: createLoongArchDeadRegisterDefinitionsPass());
225 return TargetPassConfig::addRegAssignAndRewriteFast();
226}
227
228bool LoongArchPassConfig::addRegAssignAndRewriteOptimized() {
229 if (TM->getOptLevel() != CodeGenOptLevel::None &&
230 EnableLoongArchDeadRegisterElimination)
231 addPass(P: createLoongArchDeadRegisterDefinitionsPass());
232 return TargetPassConfig::addRegAssignAndRewriteOptimized();
233}
234