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