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 initializeLoongArchPreRAExpandPseudoPass(*PR);
38 initializeLoongArchDAGToDAGISelPass(*PR);
39}
40
41static cl::opt<bool>
42 EnableLoopDataPrefetch("loongarch-enable-loop-data-prefetch", cl::Hidden,
43 cl::desc("Enable the loop data prefetch pass"),
44 cl::init(Val: false));
45
46static 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
53static Reloc::Model getEffectiveRelocModel(const Triple &TT,
54 std::optional<Reloc::Model> RM) {
55 return RM.value_or(u: Reloc::Static);
56}
57
58static CodeModel::Model
59getEffectiveLoongArchCodeModel(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(reason: "Medium/Large code model requires LA64");
71 return *CM;
72 default:
73 report_fatal_error(
74 reason: "Only small, medium and large code models are allowed on LoongArch");
75 }
76}
77
78LoongArchTargetMachine::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
89LoongArchTargetMachine::~LoongArchTargetMachine() = default;
90
91const LoongArchSubtarget *
92LoongArchTargetMachine::getSubtargetImpl(const Function &F) const {
93 Attribute CPUAttr = F.getFnAttribute(Kind: "target-cpu");
94 Attribute TuneAttr = F.getFnAttribute(Kind: "tune-cpu");
95 Attribute FSAttr = F.getFnAttribute(Kind: "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 Val: F.getParent()->getModuleFlag(Key: "target-abi"))) {
114 auto TargetABI = LoongArchABI::getTargetABI(ABIName);
115 if (TargetABI != LoongArchABI::ABI_Unknown &&
116 ModuleTargetABI->getString() != ABIName) {
117 report_fatal_error(reason: "-target-abi option != target-abi module flag");
118 }
119 ABIName = ModuleTargetABI->getString();
120 }
121 I = std::make_unique<LoongArchSubtarget>(args: TargetTriple, args&: CPU, args&: TuneCPU, args&: FS,
122 args&: ABIName, args: *this);
123 }
124 return I.get();
125}
126
127MachineFunctionInfo *LoongArchTargetMachine::createMachineFunctionInfo(
128 BumpPtrAllocator &Allocator, const Function &F,
129 const TargetSubtargetInfo *STI) const {
130 return LoongArchMachineFunctionInfo::create<LoongArchMachineFunctionInfo>(
131 Allocator, F, STI);
132}
133
134namespace {
135class LoongArchPassConfig : public TargetPassConfig {
136public:
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
152TargetPassConfig *
153LoongArchTargetMachine::createPassConfig(PassManagerBase &PM) {
154 return new LoongArchPassConfig(*this, PM);
155}
156
157void 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(P: createLoopDataPrefetchPass());
164 addPass(P: createAtomicExpandLegacyPass());
165
166 TargetPassConfig::addIRPasses();
167}
168
169bool LoongArchPassConfig::addInstSelector() {
170 addPass(P: createLoongArchISelDag(TM&: getLoongArchTargetMachine()));
171
172 return false;
173}
174
175TargetTransformInfo
176LoongArchTargetMachine::getTargetTransformInfo(const Function &F) const {
177 return TargetTransformInfo(LoongArchTTIImpl(this, F));
178}
179
180void LoongArchPassConfig::addPreEmitPass() { addPass(PassID: &BranchRelaxationPassID); }
181
182void LoongArchPassConfig::addPreEmitPass2() {
183 addPass(P: 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(P: createLoongArchExpandAtomicPseudoPass());
188}
189
190void LoongArchPassConfig::addPreRegAlloc() {
191 addPass(P: createLoongArchPreRAExpandPseudoPass());
192}
193

source code of llvm/lib/Target/LoongArch/LoongArchTargetMachine.cpp