1//===-- RISCVTargetMachine.cpp - Define TargetMachine for RISC-V ----------===//
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 RISC-V target spec.
10//
11//===----------------------------------------------------------------------===//
12
13#include "RISCVTargetMachine.h"
14#include "RISCV.h"
15#include "RISCVMachineFunctionInfo.h"
16#include "RISCVMachineScheduler.h"
17#include "RISCVTargetObjectFile.h"
18#include "RISCVTargetTransformInfo.h"
19#include "TargetInfo/RISCVTargetInfo.h"
20#include "llvm/Analysis/TargetTransformInfo.h"
21#include "llvm/CodeGen/GlobalISel/CSEInfo.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/MachineScheduler.h"
29#include "llvm/CodeGen/MacroFusion.h"
30#include "llvm/CodeGen/Passes.h"
31#include "llvm/CodeGen/RegAllocRegistry.h"
32#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
33#include "llvm/CodeGen/TargetPassConfig.h"
34#include "llvm/InitializePasses.h"
35#include "llvm/MC/TargetRegistry.h"
36#include "llvm/Option/LibraryOptions.h"
37#include "llvm/Support/Compiler.h"
38#include "llvm/Target/TargetOptions.h"
39#include "llvm/Transforms/IPO.h"
40#include "llvm/Transforms/Scalar.h"
41#include <optional>
42using namespace llvm;
43
44extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVTarget() {
45 RegisterTargetMachine<RISCVTargetMachine> X(getTheRISCV32Target());
46 RegisterTargetMachine<RISCVTargetMachine> Y(getTheRISCV64Target());
47 RegisterTargetMachine<RISCVTargetMachine> A(getTheRISCV32beTarget());
48 RegisterTargetMachine<RISCVTargetMachine> B(getTheRISCV64beTarget());
49 static opt::RegisterLibraryOptions<RISCVOptions> O;
50 auto *PR = PassRegistry::getPassRegistry();
51 initializeGlobalISel(*PR);
52 initializeRISCVO0PreLegalizerCombinerPass(*PR);
53 initializeRISCVPreLegalizerCombinerPass(*PR);
54 initializeRISCVPostLegalizerCombinerPass(*PR);
55 initializeMachineKCFILegacyPass(*PR);
56 initializeRISCVDeadRegisterDefinitionsPass(*PR);
57 initializeRISCVLateBranchOptPass(*PR);
58 initializeRISCVMakeCompressibleOptPass(*PR);
59 initializeRISCVQCRelaxMarkingPass(*PR);
60 initializeRISCVGatherScatterLoweringLegacyPass(*PR);
61 initializeRISCVCodeGenPrepareLegacyPass(*PR);
62 initializeRISCVZacasABIFixLegacyPass(*PR);
63 initializeRISCVExpandPseudoPostRALegacyPass(*PR);
64 initializeRISCVMergeBaseOffsetOptPass(*PR);
65 initializeRISCVOptWInstrsLegacyPass(*PR);
66 initializeRISCVFoldMemOffsetLegacyPass(*PR);
67 initializeRISCVExpandPseudoPreRALegacyPass(*PR);
68 initializeRISCVExpandPseudoPreEmitLegacyPass(*PR);
69 initializeRISCVVectorPeepholeLegacyPass(*PR);
70 initializeRISCVVLOptimizerLegacyPass(*PR);
71 initializeRISCVVMV0EliminationPass(*PR);
72 initializeRISCVInsertVSETVLIPass(*PR);
73 initializeRISCVInsertReadWriteCSRPass(*PR);
74 initializeRISCVInsertWriteVXRMPass(*PR);
75 initializeRISCVDAGToDAGISelLegacyPass(*PR);
76 initializeRISCVMoveMergePass(*PR);
77 initializeRISCVPushPopOptPass(*PR);
78 initializeRISCVIndirectBranchTrackingPass(*PR);
79 initializeRISCVLoadStoreOptPass(*PR);
80 initializeRISCVPreAllocZilsdOptPass(*PR);
81 initializeRISCVExpandPseudoAtomicsLegacyPass(*PR);
82 initializeRISCVRedundantCopyEliminationPass(*PR);
83 initializeRISCVAsmPrinterPass(*PR);
84 initializeRISCVPromoteConstantPass(*PR);
85}
86
87static Reloc::Model getEffectiveRelocModel(const Triple &TT,
88 std::optional<Reloc::Model> RM) {
89 if (TT.isOSBinFormatMachO())
90 return RM.value_or(u: Reloc::PIC_);
91
92 return RM.value_or(u: Reloc::Static);
93}
94
95static std::unique_ptr<TargetLoweringObjectFile> createTLOF(const Triple &TT) {
96 if (TT.isOSBinFormatMachO())
97 return std::make_unique<RISCVMachOTargetObjectFile>();
98 return std::make_unique<RISCVELFTargetObjectFile>();
99}
100
101RISCVTargetMachine::RISCVTargetMachine(const Target &T, const Triple &TT,
102 StringRef CPU, StringRef FS,
103 const TargetOptions &Options,
104 std::optional<Reloc::Model> RM,
105 std::optional<CodeModel::Model> CM,
106 CodeGenOptLevel OL, bool JIT)
107 : CodeGenTargetMachineImpl(T, TT, CPU, FS, Options,
108 getEffectiveRelocModel(TT, RM),
109 getEffectiveCodeModel(CM, Default: CodeModel::Small), OL),
110 CLOpts(RISCVOptions::Global), TLOF(createTLOF(TT)) {
111 initAsmInfo();
112
113 // RISC-V supports the MachineOutliner.
114 setMachineOutliner(true);
115 setSupportsDefaultOutlining(true);
116
117 // RISC-V supports the debug entry values.
118 setSupportsDebugEntryValues(true);
119
120 if (TT.isOSFuchsia() && !TT.isArch64Bit())
121 report_fatal_error(reason: "Fuchsia is only supported for 64-bit");
122
123 setCFIFixup(!CLOpts.enable_cfi_instr_inserter);
124}
125
126const RISCVSubtarget *
127RISCVTargetMachine::getSubtargetImpl(const Function &F) const {
128 Attribute CPUAttr = F.getFnAttribute(Kind: "target-cpu");
129 Attribute TuneAttr = F.getFnAttribute(Kind: "tune-cpu");
130 Attribute FSAttr = F.getFnAttribute(Kind: "target-features");
131
132 std::string CPU =
133 CPUAttr.isValid() ? CPUAttr.getValueAsString().str() : TargetCPU;
134 std::string TuneCPU =
135 TuneAttr.isValid() ? TuneAttr.getValueAsString().str() : CPU;
136 std::string FS =
137 FSAttr.isValid() ? FSAttr.getValueAsString().str() : TargetFS;
138
139 unsigned RVVBitsMin = CLOpts.v_vector_bits_min.value_or(u: -1);
140 unsigned RVVBitsMax = CLOpts.v_vector_bits_max.value_or(u: 0);
141
142 Attribute VScaleRangeAttr = F.getFnAttribute(Kind: Attribute::VScaleRange);
143 if (VScaleRangeAttr.isValid()) {
144 if (!CLOpts.v_vector_bits_min)
145 RVVBitsMin = VScaleRangeAttr.getVScaleRangeMin() * RISCV::RVVBitsPerBlock;
146 std::optional<unsigned> VScaleMax = VScaleRangeAttr.getVScaleRangeMax();
147 if (VScaleMax.has_value() && !CLOpts.v_vector_bits_max)
148 RVVBitsMax = *VScaleMax * RISCV::RVVBitsPerBlock;
149 }
150
151 if (RVVBitsMin != -1U) {
152 // FIXME: Change to >= 32 when VLEN = 32 is supported.
153 assert((RVVBitsMin == 0 || (RVVBitsMin >= 64 && RVVBitsMin <= 65536 &&
154 isPowerOf2_32(RVVBitsMin))) &&
155 "V or Zve* extension requires vector length to be in the range of "
156 "64 to 65536 and a power 2!");
157 assert((RVVBitsMax >= RVVBitsMin || RVVBitsMax == 0) &&
158 "Minimum V extension vector length should not be larger than its "
159 "maximum!");
160 }
161 assert((RVVBitsMax == 0 || (RVVBitsMax >= 64 && RVVBitsMax <= 65536 &&
162 isPowerOf2_32(RVVBitsMax))) &&
163 "V or Zve* extension requires vector length to be in the range of "
164 "64 to 65536 and a power 2!");
165
166 if (RVVBitsMin != -1U) {
167 if (RVVBitsMax != 0) {
168 RVVBitsMin = std::min(a: RVVBitsMin, b: RVVBitsMax);
169 RVVBitsMax = std::max(a: RVVBitsMin, b: RVVBitsMax);
170 }
171
172 RVVBitsMin = llvm::bit_floor(
173 Value: (RVVBitsMin < 64 || RVVBitsMin > 65536) ? 0 : RVVBitsMin);
174 }
175 RVVBitsMax =
176 llvm::bit_floor(Value: (RVVBitsMax < 64 || RVVBitsMax > 65536) ? 0 : RVVBitsMax);
177
178 SmallString<512> Key;
179 raw_svector_ostream(Key) << "RVVMin" << RVVBitsMin << "RVVMax" << RVVBitsMax
180 << CPU << TuneCPU << FS;
181 auto &I = SubtargetMap[Key];
182 if (!I) {
183 StringRef ABIName = getTargetABIName(M: *F.getParent());
184 I = std::make_unique<RISCVSubtarget>(
185 args: TargetTriple, args&: CPU, args&: TuneCPU, args&: FS, args&: ABIName, args&: RVVBitsMin, args&: RVVBitsMax, args: *this);
186 }
187 return I.get();
188}
189
190MachineFunctionInfo *RISCVTargetMachine::createMachineFunctionInfo(
191 BumpPtrAllocator &Allocator, const Function &F,
192 const TargetSubtargetInfo *STI) const {
193 return RISCVMachineFunctionInfo::create<RISCVMachineFunctionInfo>(
194 Allocator, F, STI: static_cast<const RISCVSubtarget *>(STI));
195}
196
197TargetTransformInfo
198RISCVTargetMachine::getTargetTransformInfo(const Function &F) const {
199 return TargetTransformInfo(std::make_unique<RISCVTTIImpl>(args: this, args: F));
200}
201
202// A RISC-V hart has a single byte-addressable address space of 2^XLEN bytes
203// for all memory accesses, so it is reasonable to assume that an
204// implementation has no-op address space casts. If an implementation makes a
205// change to this, they can override it here.
206bool RISCVTargetMachine::isNoopAddrSpaceCast(const DataLayout &DL,
207 unsigned SrcAS,
208 unsigned DstAS) const {
209 return true;
210}
211
212ScheduleDAGInstrs *
213RISCVTargetMachine::createMachineScheduler(MachineSchedContext *C) const {
214 const RISCVSubtarget &ST = C->MF->getSubtarget<RISCVSubtarget>();
215 ScheduleDAGMILive *DAG = createSchedLive<RISCVPreRAMachineSchedStrategy>(C);
216
217 // Add MacroFusion mutation first with a higher priority than later clustering
218 const auto &MacroFusions = ST.getMacroFusions();
219 if (!MacroFusions.empty())
220 DAG->addMutation(Mutation: createMacroFusionDAGMutation(Predicates: MacroFusions));
221
222 if (ST.enableMISchedLoadClustering())
223 DAG->addMutation(Mutation: createLoadClusterDAGMutation(
224 TII: DAG->TII, /*ReorderWhileClustering=*/true));
225
226 if (ST.enableMISchedStoreClustering())
227 DAG->addMutation(Mutation: createStoreClusterDAGMutation(
228 TII: DAG->TII, /*ReorderWhileClustering=*/true));
229
230 if (CLOpts.vector_mask_mutation && ST.hasVInstructions())
231 DAG->addMutation(Mutation: createRISCVVectorMaskDAGMutation(TRI: DAG->TRI));
232
233 return DAG;
234}
235
236ScheduleDAGInstrs *
237RISCVTargetMachine::createPostMachineScheduler(MachineSchedContext *C) const {
238 const RISCVSubtarget &ST = C->MF->getSubtarget<RISCVSubtarget>();
239 ScheduleDAGMI *DAG = createSchedPostRA(C);
240
241 // Add MacroFusion mutation first with a higher priority than later clustering
242 const auto &MacroFusions = ST.getMacroFusions();
243 if (!MacroFusions.empty())
244 DAG->addMutation(Mutation: createMacroFusionDAGMutation(Predicates: MacroFusions));
245
246 if (ST.enablePostMISchedLoadClustering())
247 DAG->addMutation(Mutation: createLoadClusterDAGMutation(
248 TII: DAG->TII, /*ReorderWhileClustering=*/true));
249
250 if (ST.enablePostMISchedStoreClustering())
251 DAG->addMutation(Mutation: createStoreClusterDAGMutation(
252 TII: DAG->TII, /*ReorderWhileClustering=*/true));
253
254 return DAG;
255}
256
257namespace {
258
259class RVVRegisterRegAlloc : public RegisterRegAllocBase<RVVRegisterRegAlloc> {
260public:
261 RVVRegisterRegAlloc(const char *N, const char *D, FunctionPassCtor C)
262 : RegisterRegAllocBase(N, D, C) {}
263};
264
265static bool onlyAllocateRVVReg(const TargetRegisterInfo &TRI,
266 const MachineRegisterInfo &MRI,
267 const Register Reg) {
268 const TargetRegisterClass *RC = MRI.getRegClass(Reg);
269 return RISCVRegisterInfo::isRVVRegClass(RC);
270}
271
272static FunctionPass *useDefaultRegisterAllocator() { return nullptr; }
273
274static llvm::once_flag InitializeDefaultRVVRegisterAllocatorFlag;
275
276/// -riscv-rvv-regalloc=<fast|basic|greedy> command line option.
277/// This option could designate the rvv register allocator only.
278/// For example: -riscv-rvv-regalloc=basic
279static cl::opt<RVVRegisterRegAlloc::FunctionPassCtor, false,
280 RegisterPassParser<RVVRegisterRegAlloc>>
281 RVVRegAlloc("riscv-rvv-regalloc", cl::Hidden,
282 cl::init(Val: &useDefaultRegisterAllocator),
283 cl::desc("Register allocator to use for RVV register."));
284
285static void initializeDefaultRVVRegisterAllocatorOnce() {
286 RegisterRegAlloc::FunctionPassCtor Ctor = RVVRegisterRegAlloc::getDefault();
287
288 if (!Ctor) {
289 Ctor = RVVRegAlloc;
290 RVVRegisterRegAlloc::setDefault(RVVRegAlloc);
291 }
292}
293
294static FunctionPass *createBasicRVVRegisterAllocator() {
295 return createBasicRegisterAllocator(F: onlyAllocateRVVReg);
296}
297
298static FunctionPass *createGreedyRVVRegisterAllocator() {
299 return createGreedyRegisterAllocator(F: onlyAllocateRVVReg);
300}
301
302static FunctionPass *createFastRVVRegisterAllocator() {
303 return createFastRegisterAllocator(F: onlyAllocateRVVReg, ClearVirtRegs: false);
304}
305
306static RVVRegisterRegAlloc basicRegAllocRVVReg("basic",
307 "basic register allocator",
308 createBasicRVVRegisterAllocator);
309static RVVRegisterRegAlloc
310 greedyRegAllocRVVReg("greedy", "greedy register allocator",
311 createGreedyRVVRegisterAllocator);
312
313static RVVRegisterRegAlloc fastRegAllocRVVReg("fast", "fast register allocator",
314 createFastRVVRegisterAllocator);
315
316class RISCVPassConfig : public TargetPassConfig {
317 const RISCVOptions &CLOpts;
318
319public:
320 RISCVPassConfig(RISCVTargetMachine &TM, PassManagerBase &PM)
321 : TargetPassConfig(TM, PM), CLOpts(TM.getCLOpts()) {
322 if (TM.getOptLevel() != CodeGenOptLevel::None)
323 substitutePass(StandardID: &PostRASchedulerID, TargetID: &PostMachineSchedulerID);
324 setEnableSinkAndFold(CLOpts.enable_sink_fold);
325 EnableLoopTermFold = true;
326 }
327
328 RISCVTargetMachine &getRISCVTargetMachine() const {
329 return getTM<RISCVTargetMachine>();
330 }
331
332 void addIRPasses() override;
333 bool addPreISel() override;
334 void addCodeGenPrepare() override;
335 bool addInstSelector() override;
336 bool addIRTranslator() override;
337 void addPreLegalizeMachineIR() override;
338 bool addLegalizeMachineIR() override;
339 void addPreRegBankSelect() override;
340 bool addRegBankSelect() override;
341 bool addGlobalInstructionSelect() override;
342 void addPreEmitPass() override;
343 void addPreEmitPass2() override;
344 void addPreSched2() override;
345 void addMachineSSAOptimization() override;
346 FunctionPass *createRVVRegAllocPass(bool Optimized);
347 bool addRegAssignAndRewriteFast() override;
348 bool addRegAssignAndRewriteOptimized() override;
349 void addPreRegAlloc() override;
350 void addPostRegAlloc() override;
351 void addFastRegAlloc() override;
352 bool addILPOpts() override;
353
354 std::unique_ptr<CSEConfigBase> getCSEConfig() const override;
355};
356} // namespace
357
358TargetPassConfig *RISCVTargetMachine::createPassConfig(PassManagerBase &PM) {
359 return new RISCVPassConfig(*this, PM);
360}
361
362std::unique_ptr<CSEConfigBase> RISCVPassConfig::getCSEConfig() const {
363 return getStandardCSEConfigForOpt(Level: TM->getOptLevel());
364}
365
366FunctionPass *RISCVPassConfig::createRVVRegAllocPass(bool Optimized) {
367 // Initialize the global default.
368 llvm::call_once(flag&: InitializeDefaultRVVRegisterAllocatorFlag,
369 F&: initializeDefaultRVVRegisterAllocatorOnce);
370
371 RegisterRegAlloc::FunctionPassCtor Ctor = RVVRegisterRegAlloc::getDefault();
372 if (Ctor != useDefaultRegisterAllocator)
373 return Ctor();
374
375 if (Optimized)
376 return createGreedyRVVRegisterAllocator();
377
378 return createFastRVVRegisterAllocator();
379}
380
381bool RISCVPassConfig::addRegAssignAndRewriteFast() {
382 addPass(P: createRVVRegAllocPass(Optimized: false));
383 addPass(P: createRISCVInsertVSETVLIPass());
384 if (TM->getOptLevel() != CodeGenOptLevel::None && CLOpts.enable_dead_defs)
385 addPass(P: createRISCVDeadRegisterDefinitionsPass());
386 return TargetPassConfig::addRegAssignAndRewriteFast();
387}
388
389bool RISCVPassConfig::addRegAssignAndRewriteOptimized() {
390 addPass(P: createRVVRegAllocPass(Optimized: true));
391 addPass(P: createVirtRegRewriter(ClearVirtRegs: false));
392 addPass(P: createRISCVInsertVSETVLIPass());
393 if (TM->getOptLevel() != CodeGenOptLevel::None && CLOpts.enable_dead_defs)
394 addPass(P: createRISCVDeadRegisterDefinitionsPass());
395 return TargetPassConfig::addRegAssignAndRewriteOptimized();
396}
397
398void RISCVPassConfig::addIRPasses() {
399 addPass(P: createAtomicExpandLegacyPass());
400 addPass(P: createRISCVZacasABIFixLegacyPass());
401
402 if (getOptLevel() != CodeGenOptLevel::None) {
403 if (CLOpts.enable_loop_data_prefetch)
404 addPass(P: createLoopDataPrefetchPass());
405
406 addPass(P: createRISCVGatherScatterLoweringLegacyPass());
407 addPass(P: createInterleavedAccessPass());
408 addPass(P: createRISCVCodeGenPrepareLegacyPass());
409 }
410
411 TargetPassConfig::addIRPasses();
412
413 if (getOptLevel() == CodeGenOptLevel::Aggressive && CLOpts.select_opt)
414 addPass(P: createSelectOptimizePass());
415}
416
417bool RISCVPassConfig::addPreISel() {
418 if (TM->getOptLevel() != CodeGenOptLevel::None)
419 addPass(P: createRISCVPromoteConstantPass());
420 if (TM->getOptLevel() != CodeGenOptLevel::None) {
421 // Add a barrier before instruction selection so that we will not get
422 // deleted block address after enabling default outlining. See D99707 for
423 // more details.
424 addPass(P: createBarrierNoopPass());
425 }
426
427 if (valueOr(X: CLOpts.enable_global_merge,
428 Default: TM->getOptLevel() != CodeGenOptLevel::None)) {
429 // FIXME: Like AArch64, we disable extern global merging by default due to
430 // concerns it might regress some workloads. Unlike AArch64, we don't
431 // currently support enabling the pass in an "OnlyOptimizeForSize" mode.
432 // Investigating and addressing both items are TODO.
433 addPass(P: createGlobalMergePass(TM, /* MaxOffset */ MaximalOffset: 2047,
434 /* OnlyOptimizeForSize */ false,
435 /* MergeExternalByDefault */ true));
436 }
437
438 return false;
439}
440
441void RISCVPassConfig::addCodeGenPrepare() {
442 if (getOptLevel() != CodeGenOptLevel::None)
443 addPass(P: createTypePromotionLegacyPass());
444 TargetPassConfig::addCodeGenPrepare();
445}
446
447bool RISCVPassConfig::addInstSelector() {
448 addPass(P: createRISCVISelDagLegacyPass(TM&: getRISCVTargetMachine(), OptLevel: getOptLevel()));
449
450 return false;
451}
452
453bool RISCVPassConfig::addIRTranslator() {
454 addPass(P: new IRTranslatorLegacy(getOptLevel()));
455 return false;
456}
457
458void RISCVPassConfig::addPreLegalizeMachineIR() {
459 if (getOptLevel() == CodeGenOptLevel::None) {
460 addPass(P: createRISCVO0PreLegalizerCombiner());
461 } else {
462 addPass(P: createRISCVPreLegalizerCombiner());
463 }
464}
465
466bool RISCVPassConfig::addLegalizeMachineIR() {
467 addPass(P: new LegalizerLegacy());
468 return false;
469}
470
471void RISCVPassConfig::addPreRegBankSelect() {
472 if (getOptLevel() != CodeGenOptLevel::None)
473 addPass(P: createRISCVPostLegalizerCombiner());
474}
475
476bool RISCVPassConfig::addRegBankSelect() {
477 addPass(P: new RegBankSelectLegacy());
478 return false;
479}
480
481bool RISCVPassConfig::addGlobalInstructionSelect() {
482 addPass(P: new InstructionSelectLegacy(getOptLevel()));
483 return false;
484}
485
486void RISCVPassConfig::addPreSched2() {
487 addPass(P: createRISCVExpandPseudoPostRALegacyPass());
488
489 // Emit KCFI checks for indirect calls.
490 addPass(P: createKCFIPass());
491 if (TM->getOptLevel() != CodeGenOptLevel::None)
492 addPass(P: createRISCVLoadStoreOptPass());
493}
494
495void RISCVPassConfig::addPreEmitPass() {
496 // TODO: It would potentially be better to schedule copy propagation after
497 // expanding pseudos (in addPreEmitPass2). However, performing copy
498 // propagation after the machine outliner (which runs after addPreEmitPass)
499 // currently leads to incorrect code-gen, where copies to registers within
500 // outlined functions are removed erroneously.
501 if (TM->getOptLevel() >= CodeGenOptLevel::Default &&
502 CLOpts.enable_copy_propagation)
503 addPass(P: createMachineCopyPropagationPass(UseCopyInstr: true));
504 if (TM->getOptLevel() >= CodeGenOptLevel::Default)
505 addPass(P: createRISCVLateBranchOptPass());
506 // The IndirectBranchTrackingPass inserts lpad and could have changed the
507 // basic block alignment. It must be done before Branch Relaxation to
508 // prevent the adjusted offset exceeding the branch range.
509 addPass(P: createRISCVIndirectBranchTrackingPass());
510 addPass(PassID: &BranchRelaxationPassID);
511 addPass(P: createRISCVMakeCompressibleOptPass());
512}
513
514void RISCVPassConfig::addPreEmitPass2() {
515 if (TM->getOptLevel() != CodeGenOptLevel::None) {
516 addPass(P: createRISCVMoveMergePass());
517 // Schedule PushPop Optimization before expansion of Pseudo instruction,
518 // ensuring return instruction is detected correctly.
519 addPass(P: createRISCVPushPopOptimizationPass());
520 }
521 addPass(P: createRISCVExpandPseudoPreEmitLegacyPass());
522
523 // Add QC Relaxation Markers as late as possible, and only for RV32
524 if (TM->getOptLevel() != CodeGenOptLevel::None &&
525 TM->getTargetTriple().isRISCV32())
526 addPass(P: createRISCVQCRelaxMarkingPass());
527
528 // Schedule the expansion of AMOs at the last possible moment, avoiding the
529 // possibility for other passes to break the requirements for forward
530 // progress in the LR/SC block.
531 addPass(P: createRISCVExpandPseudoAtomicsLegacyPass());
532
533 // KCFI indirect call checks are lowered to a bundle.
534 addPass(P: createUnpackMachineBundlesLegacy(Ftor: [&](const MachineFunction &MF) {
535 return MF.getFunction().getParent()->getModuleFlag(Key: "kcfi");
536 }));
537
538 if (CLOpts.enable_cfi_instr_inserter)
539 addPass(P: createCFIInstrInserterLegacy());
540}
541
542void RISCVPassConfig::addMachineSSAOptimization() {
543 // It's beneficial to reduce the VL to enable more
544 // Machine SSA optimizations.
545 if (TM->getOptLevel() != CodeGenOptLevel::None) {
546 // RISCVVLOptimizer can make loop invariant instructions like vmv.v.i
547 // loop variant by propagating a VL defined inside the loop. Run LICM and
548 // hoist them early. Don't do this at -O0 to avoid the compile-time
549 // overhead. Not reducing the VL of loop invariant pseudos results in more
550 // vsetvli toggles, and still requires the MachineLoopInfo analysis to be
551 // run.
552 addPass(PassID: &EarlyMachineLICMID);
553 addPass(P: createRISCVVLOptimizerLegacyPass());
554 }
555
556 addPass(P: createRISCVVectorPeepholeLegacyPass());
557 addPass(P: createRISCVFoldMemOffsetLegacyPass());
558
559 TargetPassConfig::addMachineSSAOptimization();
560
561 if (TM->getTargetTriple().isRISCV64()) {
562 addPass(P: createRISCVOptWInstrsLegacyPass());
563 }
564}
565
566void RISCVPassConfig::addPreRegAlloc() {
567 addPass(P: createRISCVExpandPseudoPreRALegacyPass());
568 if (TM->getOptLevel() != CodeGenOptLevel::None) {
569 addPass(P: createRISCVMergeBaseOffsetOptPass());
570 // Add Zilsd pre-allocation load/store optimization
571 addPass(P: createRISCVPreAllocZilsdOptPass());
572 }
573
574 addPass(P: createRISCVInsertReadWriteCSRPass());
575 addPass(P: createRISCVInsertWriteVXRMPass());
576 addPass(P: createRISCVLandingPadSetupPass());
577
578 if (TM->getOptLevel() != CodeGenOptLevel::None && CLOpts.enable_pipeliner)
579 addPass(PassID: &MachinePipelinerID);
580
581 addPass(P: createRISCVVMV0EliminationPass());
582}
583
584void RISCVPassConfig::addFastRegAlloc() {
585 addPass(PassID: &InitUndefID);
586 TargetPassConfig::addFastRegAlloc();
587}
588
589
590void RISCVPassConfig::addPostRegAlloc() {
591 if (TM->getOptLevel() != CodeGenOptLevel::None && CLOpts.enable_copyelim)
592 addPass(P: createRISCVRedundantCopyEliminationPass());
593}
594
595bool RISCVPassConfig::addILPOpts() {
596 if (CLOpts.enable_machine_combiner)
597 addPass(PassID: &MachineCombinerID);
598
599 return true;
600}
601
602yaml::MachineFunctionInfo *
603RISCVTargetMachine::createDefaultFuncInfoYAML() const {
604 return new yaml::RISCVMachineFunctionInfo();
605}
606
607yaml::MachineFunctionInfo *
608RISCVTargetMachine::convertFuncInfoToYAML(const MachineFunction &MF) const {
609 const auto *MFI = MF.getInfo<RISCVMachineFunctionInfo>();
610 return new yaml::RISCVMachineFunctionInfo(*MFI);
611}
612
613bool RISCVTargetMachine::parseMachineFunctionInfo(
614 const yaml::MachineFunctionInfo &MFI, PerFunctionMIParsingState &PFS,
615 SMDiagnostic &Error, SMRange &SourceRange) const {
616 const auto &YamlMFI =
617 static_cast<const yaml::RISCVMachineFunctionInfo &>(MFI);
618 PFS.MF.getInfo<RISCVMachineFunctionInfo>()->initializeBaseYamlFields(YamlMFI);
619 return false;
620}
621