1 //===-- RISCVTargetMachine.cpp - Define TargetMachine for RISCV -----------===//
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 RISCV target spec.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "RISCVTargetMachine.h"
14 #include "MCTargetDesc/RISCVBaseInfo.h"
15 #include "RISCV.h"
16 #include "RISCVMachineFunctionInfo.h"
17 #include "RISCVTargetObjectFile.h"
18 #include "RISCVTargetTransformInfo.h"
19 #include "TargetInfo/RISCVTargetInfo.h"
20 #include "llvm/ADT/STLExtras.h"
21 #include "llvm/Analysis/TargetTransformInfo.h"
22 #include "llvm/CodeGen/GlobalISel/IRTranslator.h"
23 #include "llvm/CodeGen/GlobalISel/InstructionSelect.h"
24 #include "llvm/CodeGen/GlobalISel/Legalizer.h"
25 #include "llvm/CodeGen/GlobalISel/RegBankSelect.h"
26 #include "llvm/CodeGen/MIRParser/MIParser.h"
27 #include "llvm/CodeGen/MIRYamlMapping.h"
28 #include "llvm/CodeGen/Passes.h"
29 #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
30 #include "llvm/CodeGen/TargetPassConfig.h"
31 #include "llvm/IR/LegacyPassManager.h"
32 #include "llvm/InitializePasses.h"
33 #include "llvm/MC/TargetRegistry.h"
34 #include "llvm/Support/FormattedStream.h"
35 #include "llvm/Target/TargetOptions.h"
36 #include "llvm/Transforms/IPO.h"
37 using namespace llvm;
38 
39 static cl::opt<bool> EnableRedundantCopyElimination(
40     "riscv-enable-copyelim",
41     cl::desc("Enable the redundant copy elimination pass"), cl::init(true),
42     cl::Hidden);
43 
44 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVTarget() {
45   RegisterTargetMachine<RISCVTargetMachine> X(getTheRISCV32Target());
46   RegisterTargetMachine<RISCVTargetMachine> Y(getTheRISCV64Target());
47   auto *PR = PassRegistry::getPassRegistry();
48   initializeGlobalISel(*PR);
49   initializeRISCVMakeCompressibleOptPass(*PR);
50   initializeRISCVGatherScatterLoweringPass(*PR);
51   initializeRISCVMergeBaseOffsetOptPass(*PR);
52   initializeRISCVSExtWRemovalPass(*PR);
53   initializeRISCVExpandPseudoPass(*PR);
54   initializeRISCVInsertVSETVLIPass(*PR);
55 }
56 
57 static StringRef computeDataLayout(const Triple &TT) {
58   if (TT.isArch64Bit())
59     return "e-m:e-p:64:64-i64:64-i128:128-n64-S128";
60   assert(TT.isArch32Bit() && "only RV32 and RV64 are currently supported");
61   return "e-m:e-p:32:32-i64:64-n32-S128";
62 }
63 
64 static Reloc::Model getEffectiveRelocModel(const Triple &TT,
65                                            Optional<Reloc::Model> RM) {
66   return RM.value_or(Reloc::Static);
67 }
68 
69 RISCVTargetMachine::RISCVTargetMachine(const Target &T, const Triple &TT,
70                                        StringRef CPU, StringRef FS,
71                                        const TargetOptions &Options,
72                                        Optional<Reloc::Model> RM,
73                                        Optional<CodeModel::Model> CM,
74                                        CodeGenOpt::Level OL, bool JIT)
75     : LLVMTargetMachine(T, computeDataLayout(TT), TT, CPU, FS, Options,
76                         getEffectiveRelocModel(TT, RM),
77                         getEffectiveCodeModel(CM, CodeModel::Small), OL),
78       TLOF(std::make_unique<RISCVELFTargetObjectFile>()) {
79   initAsmInfo();
80 
81   // RISC-V supports the MachineOutliner.
82   setMachineOutliner(true);
83   setSupportsDefaultOutlining(true);
84 }
85 
86 const RISCVSubtarget *
87 RISCVTargetMachine::getSubtargetImpl(const Function &F) const {
88   Attribute CPUAttr = F.getFnAttribute("target-cpu");
89   Attribute TuneAttr = F.getFnAttribute("tune-cpu");
90   Attribute FSAttr = F.getFnAttribute("target-features");
91 
92   std::string CPU =
93       CPUAttr.isValid() ? CPUAttr.getValueAsString().str() : TargetCPU;
94   std::string TuneCPU =
95       TuneAttr.isValid() ? TuneAttr.getValueAsString().str() : CPU;
96   std::string FS =
97       FSAttr.isValid() ? FSAttr.getValueAsString().str() : TargetFS;
98   std::string Key = CPU + TuneCPU + FS;
99   auto &I = SubtargetMap[Key];
100   if (!I) {
101     // This needs to be done before we create a new subtarget since any
102     // creation will depend on the TM and the code generation flags on the
103     // function that reside in TargetOptions.
104     resetTargetOptions(F);
105     auto ABIName = Options.MCOptions.getABIName();
106     if (const MDString *ModuleTargetABI = dyn_cast_or_null<MDString>(
107             F.getParent()->getModuleFlag("target-abi"))) {
108       auto TargetABI = RISCVABI::getTargetABI(ABIName);
109       if (TargetABI != RISCVABI::ABI_Unknown &&
110           ModuleTargetABI->getString() != ABIName) {
111         report_fatal_error("-target-abi option != target-abi module flag");
112       }
113       ABIName = ModuleTargetABI->getString();
114     }
115     I = std::make_unique<RISCVSubtarget>(TargetTriple, CPU, TuneCPU, FS, ABIName, *this);
116   }
117   return I.get();
118 }
119 
120 TargetTransformInfo
121 RISCVTargetMachine::getTargetTransformInfo(const Function &F) const {
122   return TargetTransformInfo(RISCVTTIImpl(this, F));
123 }
124 
125 // A RISC-V hart has a single byte-addressable address space of 2^XLEN bytes
126 // for all memory accesses, so it is reasonable to assume that an
127 // implementation has no-op address space casts. If an implementation makes a
128 // change to this, they can override it here.
129 bool RISCVTargetMachine::isNoopAddrSpaceCast(unsigned SrcAS,
130                                              unsigned DstAS) const {
131   return true;
132 }
133 
134 namespace {
135 class RISCVPassConfig : public TargetPassConfig {
136 public:
137   RISCVPassConfig(RISCVTargetMachine &TM, PassManagerBase &PM)
138       : TargetPassConfig(TM, PM) {}
139 
140   RISCVTargetMachine &getRISCVTargetMachine() const {
141     return getTM<RISCVTargetMachine>();
142   }
143 
144   void addIRPasses() override;
145   bool addPreISel() override;
146   bool addInstSelector() override;
147   bool addIRTranslator() override;
148   bool addLegalizeMachineIR() override;
149   bool addRegBankSelect() override;
150   bool addGlobalInstructionSelect() override;
151   void addPreEmitPass() override;
152   void addPreEmitPass2() override;
153   void addPreSched2() override;
154   void addMachineSSAOptimization() override;
155   void addPreRegAlloc() override;
156   void addPostRegAlloc() override;
157 };
158 } // namespace
159 
160 TargetPassConfig *RISCVTargetMachine::createPassConfig(PassManagerBase &PM) {
161   return new RISCVPassConfig(*this, PM);
162 }
163 
164 void RISCVPassConfig::addIRPasses() {
165   addPass(createAtomicExpandPass());
166 
167   addPass(createRISCVGatherScatterLoweringPass());
168 
169   TargetPassConfig::addIRPasses();
170 }
171 
172 bool RISCVPassConfig::addPreISel() {
173   if (TM->getOptLevel() != CodeGenOpt::None) {
174     // Add a barrier before instruction selection so that we will not get
175     // deleted block address after enabling default outlining. See D99707 for
176     // more details.
177     addPass(createBarrierNoopPass());
178   }
179   return false;
180 }
181 
182 bool RISCVPassConfig::addInstSelector() {
183   addPass(createRISCVISelDag(getRISCVTargetMachine(), getOptLevel()));
184 
185   return false;
186 }
187 
188 bool RISCVPassConfig::addIRTranslator() {
189   addPass(new IRTranslator(getOptLevel()));
190   return false;
191 }
192 
193 bool RISCVPassConfig::addLegalizeMachineIR() {
194   addPass(new Legalizer());
195   return false;
196 }
197 
198 bool RISCVPassConfig::addRegBankSelect() {
199   addPass(new RegBankSelect());
200   return false;
201 }
202 
203 bool RISCVPassConfig::addGlobalInstructionSelect() {
204   addPass(new InstructionSelect(getOptLevel()));
205   return false;
206 }
207 
208 void RISCVPassConfig::addPreSched2() {}
209 
210 void RISCVPassConfig::addPreEmitPass() {
211   addPass(&BranchRelaxationPassID);
212   addPass(createRISCVMakeCompressibleOptPass());
213 }
214 
215 void RISCVPassConfig::addPreEmitPass2() {
216   addPass(createRISCVExpandPseudoPass());
217   // Schedule the expansion of AMOs at the last possible moment, avoiding the
218   // possibility for other passes to break the requirements for forward
219   // progress in the LR/SC block.
220   addPass(createRISCVExpandAtomicPseudoPass());
221 }
222 
223 void RISCVPassConfig::addMachineSSAOptimization() {
224   TargetPassConfig::addMachineSSAOptimization();
225 
226   if (TM->getTargetTriple().getArch() == Triple::riscv64)
227     addPass(createRISCVSExtWRemovalPass());
228 }
229 
230 void RISCVPassConfig::addPreRegAlloc() {
231   if (TM->getOptLevel() != CodeGenOpt::None)
232     addPass(createRISCVMergeBaseOffsetOptPass());
233   addPass(createRISCVInsertVSETVLIPass());
234 }
235 
236 void RISCVPassConfig::addPostRegAlloc() {
237   if (TM->getOptLevel() != CodeGenOpt::None && EnableRedundantCopyElimination)
238     addPass(createRISCVRedundantCopyEliminationPass());
239 }
240 
241 yaml::MachineFunctionInfo *
242 RISCVTargetMachine::createDefaultFuncInfoYAML() const {
243   return new yaml::RISCVMachineFunctionInfo();
244 }
245 
246 yaml::MachineFunctionInfo *
247 RISCVTargetMachine::convertFuncInfoToYAML(const MachineFunction &MF) const {
248   const auto *MFI = MF.getInfo<RISCVMachineFunctionInfo>();
249   return new yaml::RISCVMachineFunctionInfo(*MFI);
250 }
251 
252 bool RISCVTargetMachine::parseMachineFunctionInfo(
253     const yaml::MachineFunctionInfo &MFI, PerFunctionMIParsingState &PFS,
254     SMDiagnostic &Error, SMRange &SourceRange) const {
255   const auto &YamlMFI =
256       static_cast<const yaml::RISCVMachineFunctionInfo &>(MFI);
257   PFS.MF.getInfo<RISCVMachineFunctionInfo>()->initializeBaseYamlFields(YamlMFI);
258   return false;
259 }
260