1//===----------------------------------------------------------------------===//
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/// \file
9/// This file contains the RISC-V CodeGen pipeline builder.
10//===----------------------------------------------------------------------===//
11
12#include "RISCV.h"
13#include "RISCVAsmPrinter.h"
14#include "RISCVTargetMachine.h"
15#include "llvm/CodeGen/AtomicExpand.h"
16#include "llvm/CodeGen/BranchRelaxation.h"
17#include "llvm/CodeGen/CFIInstrInserter.h"
18#include "llvm/CodeGen/InterleavedAccess.h"
19#include "llvm/CodeGen/KCFI.h"
20#include "llvm/CodeGen/MachineCopyPropagation.h"
21#include "llvm/CodeGen/MachineInstrBundle.h"
22#include "llvm/CodeGen/MachineLICM.h"
23#include "llvm/CodeGen/TypePromotion.h"
24#include "llvm/IR/PassInstrumentation.h"
25#include "llvm/MC/MCStreamer.h"
26#include "llvm/Passes/CodeGenPassBuilder.h"
27#include "llvm/Passes/PassBuilder.h"
28#include "llvm/Support/CodeGen.h"
29#include "llvm/Target/CGPassBuilderOption.h"
30#include "llvm/Transforms/Scalar/LoopDataPrefetch.h"
31#include "llvm/Transforms/Vectorize/LoopIdiomVectorize.h"
32
33using namespace llvm;
34
35namespace {
36
37class RISCVCodeGenPassBuilder : public CodeGenPassBuilder {
38 using Base = CodeGenPassBuilder;
39
40 RISCVTargetMachine &getTM() const {
41 return static_cast<RISCVTargetMachine &>(TM);
42 }
43
44public:
45 explicit RISCVCodeGenPassBuilder(RISCVTargetMachine &TM,
46 const CGPassBuilderOption &Opts,
47 PassInstrumentationCallbacks *PIC)
48 : CodeGenPassBuilder(TM, Opts, PIC) {
49 // TODO: See the FIXME on RISCVPassConfig::setEnableSinkAndFold in the
50 // legacy pass manager pipeline. There is currently no way to plumb
51 // -riscv-enable-sink-fold through to CGPassBuilderOption::EnableSinkAndFold
52 // from a target-local CodeGenPassBuilder, so this NewPM pipeline always
53 // uses the base class default (disabled).
54 }
55
56 void addIRPasses(PassManagerWrapper &PMW) override;
57 void addCodeGenPrepare(PassManagerWrapper &PMW) override;
58 Error addInstSelector(PassManagerWrapper &PMW) override;
59 void addMachineSSAOptimization(PassManagerWrapper &PMW) override;
60 void addPreRegAlloc(PassManagerWrapper &PMW) override;
61 void addPostRegAlloc(PassManagerWrapper &PMW) override;
62 void addPreSched2(PassManagerWrapper &PMW) override;
63 void addPreEmitPass(PassManagerWrapper &PMW) override;
64 void addPreEmitPass2(PassManagerWrapper &PMW) override;
65 void addAsmPrinterBegin(PassManagerWrapper &PMW) override;
66 void addAsmPrinter(PassManagerWrapper &PMW) override;
67 void addAsmPrinterEnd(PassManagerWrapper &PMW) override;
68};
69
70void RISCVCodeGenPassBuilder::addIRPasses(PassManagerWrapper &PMW) {
71 addFunctionPass(Pass: AtomicExpandPass(TM), PMW);
72 addFunctionPass(Pass: RISCVZacasABIFixPass(&getTM()), PMW);
73
74 if (getOptLevel() != CodeGenOptLevel::None) {
75 addFunctionPass(Pass: LoopDataPrefetchPass(), PMW);
76
77 addFunctionPass(Pass: RISCVGatherScatterLoweringPass(&getTM()), PMW);
78 addFunctionPass(Pass: InterleavedAccessPass(TM), PMW);
79 addFunctionPass(Pass: RISCVCodeGenPreparePass(&getTM()), PMW);
80 }
81
82 Base::addIRPasses(PMW);
83
84 // TODO: SelectOptimizePass is already added by the base class when
85 // !Opt.DisableSelectOptimize. The legacy pipeline additionally gates this
86 // on -riscv-select-opt and only runs it at -O3; that extra gating is not
87 // yet replicated here.
88}
89
90void RISCVCodeGenPassBuilder::addCodeGenPrepare(PassManagerWrapper &PMW) {
91 if (getOptLevel() != CodeGenOptLevel::None)
92 addFunctionPass(Pass: TypePromotionPass(TM), PMW);
93 Base::addCodeGenPrepare(PMW);
94}
95
96Error RISCVCodeGenPassBuilder::addInstSelector(PassManagerWrapper &PMW) {
97 addMachineFunctionPass(Pass: RISCVISelDAGToDAGPass(getTM(), getOptLevel()), PMW);
98 return Error::success();
99}
100
101void RISCVCodeGenPassBuilder::addMachineSSAOptimization(
102 PassManagerWrapper &PMW) {
103 // It's beneficial to reduce the VL to enable more
104 // Machine SSA optimizations.
105 if (getOptLevel() != CodeGenOptLevel::None) {
106 // RISCVVLOptimizer can make loop invariant instructions like vmv.v.i
107 // loop variant by propagating a VL defined inside the loop. Run LICM and
108 // hoist them early. Don't do this at -O0 to avoid the compile-time
109 // overhead. Not reducing the VL of loop invariant pseudos results in more
110 // vsetvli toggles, and still requires the MachineLoopInfo analysis to be
111 // run.
112 addMachineFunctionPass(Pass: EarlyMachineLICMPass(), PMW);
113 addMachineFunctionPass(Pass: RISCVVLOptimizerPass(), PMW);
114 }
115
116 addMachineFunctionPass(Pass: RISCVVectorPeepholePass(), PMW);
117 addMachineFunctionPass(Pass: RISCVFoldMemOffsetPass(), PMW);
118
119 Base::addMachineSSAOptimization(PMW);
120
121 if (TM.getTargetTriple().isRISCV64())
122 addMachineFunctionPass(Pass: RISCVOptWInstrsPass(), PMW);
123}
124
125void RISCVCodeGenPassBuilder::addPreRegAlloc(PassManagerWrapper &PMW) {
126 addMachineFunctionPass(Pass: RISCVExpandPseudoPreRAPass(), PMW);
127 if (getOptLevel() != CodeGenOptLevel::None) {
128 // TODO: RISCVMergeBaseOffsetOptPass
129 // TODO: RISCVPreAllocZilsdOptPass
130 }
131
132 // TODO: RISCVInsertReadWriteCSRPass
133 // TODO: RISCVInsertWriteVXRMPass
134 // TODO: RISCVLandingPadSetupPass
135
136 // TODO: MachinePipelinerPass (no new pass manager port exists yet)
137
138 // TODO: RISCVVMV0EliminationPass
139}
140
141void RISCVCodeGenPassBuilder::addPostRegAlloc(PassManagerWrapper &PMW) {
142 if (getOptLevel() != CodeGenOptLevel::None) {
143 // TODO: RISCVRedundantCopyEliminationPass
144 }
145}
146
147void RISCVCodeGenPassBuilder::addPreSched2(PassManagerWrapper &PMW) {
148 addMachineFunctionPass(Pass: RISCVExpandPseudoPostRAPass(), PMW);
149
150 addMachineFunctionPass(Pass: MachineKCFIPass(), PMW);
151 if (getOptLevel() != CodeGenOptLevel::None) {
152 // TODO: RISCVLoadStoreOptPass
153 }
154}
155
156void RISCVCodeGenPassBuilder::addPreEmitPass(PassManagerWrapper &PMW) {
157 // TODO: It would potentially be better to schedule copy propagation after
158 // expanding pseudos (in addPreEmitPass2). However, performing copy
159 // propagation after the machine outliner (which runs after addPreEmitPass)
160 // currently leads to incorrect code-gen, where copies to registers within
161 // outlined functions are removed erroneously.
162 if (getOptLevel() >= CodeGenOptLevel::Default) {
163 addMachineFunctionPass(Pass: MachineCopyPropagationPass(true), PMW);
164 // TODO: RISCVLateBranchOptPass
165 }
166 // The IndirectBranchTrackingPass inserts lpad and could have changed the
167 // basic block alignment. It must be done before Branch Relaxation to
168 // prevent the adjusted offset exceeding the branch range.
169 // TODO: RISCVIndirectBranchTrackingPass
170 addMachineFunctionPass(Pass: BranchRelaxationPass(), PMW);
171 // TODO: RISCVMakeCompressibleOptPass
172}
173
174void RISCVCodeGenPassBuilder::addPreEmitPass2(PassManagerWrapper &PMW) {
175 if (getOptLevel() != CodeGenOptLevel::None) {
176 // TODO: RISCVMoveMergePass
177 // TODO: RISCVPushPopOptimizationPass
178 }
179 addMachineFunctionPass(Pass: RISCVExpandPseudoPreEmitPass(), PMW);
180
181 // Add QC Relaxation Markers as late as possible, and only for RV32
182 if (getOptLevel() != CodeGenOptLevel::None &&
183 TM.getTargetTriple().isRISCV32()) {
184 // TODO: RISCVQCRelaxMarkingPass
185 }
186
187 addMachineFunctionPass(Pass: RISCVExpandPseudoAtomicsPass(), PMW);
188
189 // KCFI indirect call checks are lowered to a bundle.
190 addMachineFunctionPass(
191 Pass: UnpackMachineBundlesPass([&](const MachineFunction &MF) {
192 return MF.getFunction().getParent()->getModuleFlag(Key: "kcfi");
193 }),
194 PMW);
195
196 // RISCVTargetMachine's constructor sets Options.EnableCFIFixup to the
197 // inverse of -riscv-enable-cfi-instr-inserter (a flag private to
198 // RISCVTargetMachine.cpp), so checking it here is equivalent to checking
199 // that flag directly -- the two passes solve overlapping problems and
200 // this target picks exactly one.
201 if (!TM.Options.EnableCFIFixup)
202 addMachineFunctionPass(Pass: CFIInstrInserterPass(), PMW);
203}
204
205void RISCVCodeGenPassBuilder::addAsmPrinterBegin(PassManagerWrapper &PMW) {
206 addModulePass(Pass: RISCVAsmPrinterBeginPass(), PMW, /*Force=*/true);
207}
208
209void RISCVCodeGenPassBuilder::addAsmPrinter(PassManagerWrapper &PMW) {
210 addMachineFunctionPass(Pass: RISCVAsmPrinterPass(), PMW);
211}
212
213void RISCVCodeGenPassBuilder::addAsmPrinterEnd(PassManagerWrapper &PMW) {
214 addModulePass(Pass: RISCVAsmPrinterEndPass(), PMW, /*Force=*/true);
215}
216
217} // namespace
218
219void RISCVTargetMachine::registerPassBuilderCallbacks(PassBuilder &PB) {
220#define GET_PASS_REGISTRY "RISCVPassRegistry.def"
221#include "llvm/Passes/TargetPassRegistry.inc"
222
223 PB.registerLateLoopOptimizationsEPCallback(C: [=](LoopPassManager &LPM,
224 OptimizationLevel Level) {
225 if (Level != OptimizationLevel::O0)
226 LPM.addPass(Pass: LoopIdiomVectorizePass(LoopIdiomVectorizeStyle::Predicated));
227 });
228}
229
230Error RISCVTargetMachine::buildCodeGenPipeline(
231 ModulePassManager &MPM, ModuleAnalysisManager &MAM, raw_pwrite_stream &Out,
232 raw_pwrite_stream *DwoOut, CodeGenFileType FileType,
233 const CGPassBuilderOption &Opt, MCContext &Ctx,
234 PassInstrumentationCallbacks *PIC) {
235 auto CGPB = RISCVCodeGenPassBuilder(*this, Opt, PIC);
236 return CGPB.buildPipeline(MPM, MAM, Out, DwoOut, FileType, Ctx);
237}
238