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
LLVMInitializeLoongArchTarget()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
computeDataLayout(const Triple & TT)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
getEffectiveRelocModel(const Triple & TT,std::optional<Reloc::Model> RM)44 static Reloc::Model getEffectiveRelocModel(const Triple &TT,
45 std::optional<Reloc::Model> RM) {
46 return RM.value_or(Reloc::Static);
47 }
48
LoongArchTargetMachine(const Target & T,const Triple & TT,StringRef CPU,StringRef FS,const TargetOptions & Options,std::optional<Reloc::Model> RM,std::optional<CodeModel::Model> CM,CodeGenOpt::Level OL,bool JIT)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 *
getSubtargetImpl(const Function & F) const63 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
createMachineFunctionInfo(BumpPtrAllocator & Allocator,const Function & F,const TargetSubtargetInfo * STI) const98 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:
LoongArchPassConfig(LoongArchTargetMachine & TM,PassManagerBase & PM)108 LoongArchPassConfig(LoongArchTargetMachine &TM, PassManagerBase &PM)
109 : TargetPassConfig(TM, PM) {}
110
getLoongArchTargetMachine() const111 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 *
createPassConfig(PassManagerBase & PM)124 LoongArchTargetMachine::createPassConfig(PassManagerBase &PM) {
125 return new LoongArchPassConfig(*this, PM);
126 }
127
addIRPasses()128 void LoongArchPassConfig::addIRPasses() {
129 addPass(createAtomicExpandPass());
130
131 TargetPassConfig::addIRPasses();
132 }
133
addInstSelector()134 bool LoongArchPassConfig::addInstSelector() {
135 addPass(createLoongArchISelDag(getLoongArchTargetMachine()));
136
137 return false;
138 }
139
addPreEmitPass()140 void LoongArchPassConfig::addPreEmitPass() { addPass(&BranchRelaxationPassID); }
141
addPreEmitPass2()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
addPreRegAlloc()149 void LoongArchPassConfig::addPreRegAlloc() {
150 addPass(createLoongArchPreRAExpandPseudoPass());
151 }
152