1- // ===- RISCVcustomLICM .h - Function Entry/Exit Instrumentation ----- -===//
1+ // ===- RISCVCustomLICM .h - Custom Loop Invariant Code Motion ---*- C++ -* -===//
22//
33// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
44// See https://llvm.org/LICENSE.txt for license information.
55// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
66//
77// ===----------------------------------------------------------------------===//
88//
9- // RISCVCustomLICM pass - Custom Loop Invariant Code Motion
10- // This pass aims to optimize loops by moving invariant code out of loops
11- //
9+ // / \file
10+ // / This file declares the RISCVCustomLICM pass, which implements custom loop
11+ // / invariant code motion optimizations for RISC-V targets.
12+ // /
13+ // / The pass performs specialized optimizations for different types of DSP
14+ // / functions including biquad filters, FIR filters, convolution operations,
15+ // / FFT transforms, and window functions.
1216//
1317// ===----------------------------------------------------------------------===//
1418
15- #ifndef LLVM_TRANSFORMS_UTILS_RISCVCUSTOMLICM_H
16- #define LLVM_TRANSFORMS_UTILS_RISCVCUSTOMLICM_H
19+ #ifndef LLVM_LIB_TARGET_RISCV_RISCVCUSTOMLICM_H
20+ #define LLVM_LIB_TARGET_RISCV_RISCVCUSTOMLICM_H
1721
18- #include " llvm/Support/CommandLine .h"
22+ #include " RISCVESP32P4OptUtils .h"
1923#include " llvm/Analysis/LoopInfo.h"
2024#include " llvm/IR/Dominators.h"
2125#include " llvm/IR/PassManager.h"
2226
2327namespace llvm {
28+
2429extern cl::opt<bool > EnableRISCVCustomLICM;
2530class Function ;
2631
32+ // / Abstract base class for RISC-V custom LICM optimization strategies.
33+ // / Note: This class must be declared before RISCVCustomLICMPass
34+ class RISCVCustomLICMOptimizationStrategy {
35+ public:
36+ virtual ~RISCVCustomLICMOptimizationStrategy () = default ;
37+
38+ // / Check if this optimization can be applied to the given function.
39+ virtual bool isApplicable (Function &F, LoopInfo &LI) = 0;
40+
41+ // / Apply the optimization to the given function.
42+ virtual bool optimize (Function &F, DominatorTree &DT, LoopInfo &LI) = 0;
43+ };
44+
45+ // / Pass that performs custom loop invariant code motion for RISC-V targets.
2746struct RISCVCustomLICMPass : public PassInfoMixin <RISCVCustomLICMPass> {
2847 RISCVCustomLICMPass () {}
2948
3049 PreservedAnalyses run (Function &F, FunctionAnalysisManager &AM);
3150
3251 static bool isRequired () { return true ; }
33- // Implement logic to move fneg operations out of the loop
34- void moveFnegOutOfLoop (BasicBlock *Preheader, BasicBlock &BB,
35- LLVMContext &Ctx);
3652
37- // Implement logic to adjust phi nodes
53+ private:
54+ // / Create all optimization strategies.
55+ std::vector<std::unique_ptr<RISCVCustomLICMOptimizationStrategy>>
56+ createOptimizationStrategies ();
57+
58+ // / Apply optimization strategies to the function.
59+ bool applyOptimizationStrategies (
60+ const std::vector<std::unique_ptr<RISCVCustomLICMOptimizationStrategy>>
61+ &Strategies,
62+ Function &F, DominatorTree &DT, LoopInfo &LI);
63+
64+ // / Update statistics based on the applied strategy.
65+ void updateStatistics (size_t StrategyIndex);
66+
67+ // / Get strategy name by index.
68+ const char *getStrategyName (size_t Index);
69+ };
70+
71+ // / Optimizer for biquad filter functions.
72+ class BiquadCustomLICMOptimizer : public RISCVCustomLICMOptimizationStrategy {
73+ public:
74+ bool isApplicable (Function &F, LoopInfo &LI) override {
75+ return isSafeToOptimizeBiquadType (F, LI);
76+ }
77+
78+ bool optimize (Function &F, DominatorTree &DT, LoopInfo &LI) override {
79+ return processBiquadTypeAllLoops (F, DT, LI);
80+ }
81+
82+ // / Check if it's safe to optimize the given function as a biquad type.
83+ bool isSafeToOptimizeBiquadType (Function &F, LoopInfo &LI);
84+
85+ // / Check basic blocks and function parameters.
86+ bool checkBasicBlocksAndParameters (Function &F);
87+
88+ // / Check loop nesting structure.
89+ bool checkLoopNestingStructure (Function &F, LoopInfo &LI);
90+
91+ // / Check basic blocks and control flow.
92+ bool checkBasicBlocksAndControlFlow (Function &F);
93+
94+ // / Process a single biquad-type loop.
95+ bool processBiquadTypeLoop (Loop *L, DominatorTree &DT, LoopInfo &LI,
96+ Function &F);
97+
98+ // / Optimize a single loop by moving invariant code.
99+ bool optimizeLoop (Loop *L, BasicBlock *Preheader, Function &F);
100+
101+ // / Move fneg instructions out of the loop.
102+ void moveFNegOutOfLoop (BasicBlock *Preheader, BasicBlock &BB);
103+
104+ // / Adjust PHI nodes in the loop.
38105 void adjustPhiNodes (BasicBlock &BB);
39106
40- // Implement logic to create for.cond.cleanup basic block
107+ // / Create a cleanup block for the loop.
41108 void createCleanupBlock (Function &F, BasicBlock &LoopBB);
42109
43- // Implement logic to move store operations after the loop ends
110+ // / Move store instructions out of the loop.
44111 void moveStoreOutOfLoop (BasicBlock &BB);
45112
46- bool optimizeLoop (Loop *L, BasicBlock *Preheader, Function &F);
113+ // / Process all loops in the function.
114+ bool processBiquadTypeAllLoops (Function &F, DominatorTree &DT, LoopInfo &LI);
47115
116+ // / Check if an instruction is a must-tail call.
48117 bool isMustTailCall (Instruction *I);
49118};
50119
120+ // / Optimizer for FIRD (Finite Impulse Response Decimator) functions.
121+ class FIRDCustomLICMOptimizer : public RISCVCustomLICMOptimizationStrategy {
122+ public:
123+ bool isApplicable (Function &F, LoopInfo &LI) override {
124+ return checkInt16FIRDType (F, LI);
125+ }
126+
127+ bool optimize (Function &F, DominatorTree &DT, LoopInfo &LI) override {
128+ return transformFIRDTypeGEPLoad (F, DT, LI);
129+ }
130+
131+ // / Check if the function is an Int16 FIRD type.
132+ bool checkInt16FIRDType (Function &F, LoopInfo &LI);
133+
134+ // / Check FIRD unroll pattern.
135+ bool checkInt16FIRDUnrollPattern (Loop &L);
136+
137+ // / Check PHI nodes in FIRD function.
138+ bool checkInt16FIRDPhiNodes (BasicBlock *ForBody);
139+
140+ // / Transform GEP and load instructions for FIRD type.
141+ bool transformFIRDTypeGEPLoad (Function &F, DominatorTree &DT, LoopInfo &LI);
142+
143+ // / Modify GEP and load instructions.
144+ void modifyGEPAndLoadInstruction (GetElementPtrInst *GEP, ICmpInst *LastICmp);
145+
146+ // / Transform load instructions.
147+ bool transformLoadInstructions (SmallVector<GetElementPtrInst *> GEPs,
148+ ICmpInst *LastICmp);
149+
150+ // / Get GEP instructions from a basic block.
151+ SmallVector<GetElementPtrInst *> getGEPInstructions (BasicBlock *BB);
152+ };
153+
154+ // / Optimizer for convolution functions.
155+ class ConvCustomLICMOptimizer : public RISCVCustomLICMOptimizationStrategy {
156+ public:
157+ bool isApplicable (Function &F, LoopInfo &LI) override {
158+ return checkDSPIConvF32Type (F, LI);
159+ }
160+
161+ bool optimize (Function &F, DominatorTree &DT, LoopInfo &LI) override {
162+ return transformDSPIConvF32Type (F, LI);
163+ }
164+
165+ // / Check if the function is a DSPI convolution F32 type.
166+ bool checkDSPIConvF32Type (Function &F, LoopInfo &LI);
167+
168+ // / Transform DSPI convolution F32 type function.
169+ bool transformDSPIConvF32Type (Function &F, LoopInfo &LI);
170+
171+ // / Collect loop invariant instructions.
172+ void collectLoopInvariantInstructions (
173+ Loop *L, SmallVectorImpl<Instruction *> &InvariantInsts);
174+
175+ // / Hoist instructions from loops.
176+ bool hoistInstructionsFromLoops (LoopInfo &LI, BasicBlock &EntryBB,
177+ Function &F);
178+
179+ // / Hoist instructions from sub-loops.
180+ bool hoistInstructionsFromSubLoop (Loop *L, int Depth);
181+ };
182+
183+ // / Optimizer for DSP FFT2R FC32 functions.
184+ class DspsFft2rFc32CustomLICMOptimizer
185+ : public RISCVCustomLICMOptimizationStrategy {
186+ public:
187+ bool isApplicable (Function &F, LoopInfo &LI) override {
188+ return checkDspsFft2rFc32Type (F, LI);
189+ }
190+
191+ bool optimize (Function &F, DominatorTree &DT, LoopInfo &LI) override {
192+ return transformDspsFft2rFc32Type (F, DT, LI);
193+ }
194+
195+ // / Check if the function is a DSPS FFT2R FC32 type.
196+ bool checkDspsFft2rFc32Type (Function &F, LoopInfo &LI);
197+
198+ // / Transform DSPS FFT2R FC32 type function.
199+ bool transformDspsFft2rFc32Type (Function &F, DominatorTree &DT, LoopInfo &LI);
200+
201+ // / Group same instructions for DSPS FFT2R FC32.
202+ void groupSameInstructionDspsFft2rFc32 (BasicBlock *ForBody);
203+
204+ // / Find innermost loops.
205+ Loop *findInnermostLoops (Loop *L);
206+
207+ // / Check FFT computation pattern.
208+ bool checkFFTComputationPattern (Function &F, LoopInfo &LI);
209+
210+ // / Hoist loop invariant fneg.
211+ void hoistLoopInvariantFNeg (Loop *L, DominatorTree &DT, LoopInfo &LI);
212+
213+ private:
214+ // / FFT pattern analysis results.
215+ struct FFTPatternAnalysis {
216+ bool HasFMulAdd = false ;
217+ bool HasFNegFMulPattern = false ;
218+ bool HasComplexAccess = false ;
219+ unsigned FAddCount = 0 ;
220+ unsigned FSubCount = 0 ;
221+ };
222+
223+ // / Analyze FFT computation patterns in a basic block.
224+ FFTPatternAnalysis analyzeFFTPatterns (BasicBlock *Header);
225+
226+ // / Check if the analysis results indicate a valid FFT pattern.
227+ bool isValidFFTPattern (const FFTPatternAnalysis &Analysis);
228+ };
229+
230+ // / Template-based optimizer for DSP window functions.
231+ template <unsigned N>
232+ class DspsWindCustomLICMOptimizer : public RISCVCustomLICMOptimizationStrategy {
233+ public:
234+ bool isApplicable (Function &F, LoopInfo &LI) override {
235+ return checkDspsWindCommonF32Type (F, N);
236+ }
237+
238+ bool optimize (Function &F, DominatorTree &DT, LoopInfo &LI) override {
239+ return transformDspsWindCommonF32Type (F, N);
240+ }
241+
242+ // / Check if the function is a DSPS window function F32 type.
243+ bool checkDspsWindCommonF32Type (Function &F, unsigned NumCosf);
244+
245+ // / Transform DSPS window function F32 type.
246+ bool transformDspsWindCommonF32Type (Function &F, unsigned NumCosf);
247+
248+ private:
249+ // / Extract basic blocks for window function transformation.
250+ struct WindowFunctionBlocks {
251+ BasicBlock *EntryBB = nullptr ;
252+ BasicBlock *ForBodyLrPh = nullptr ;
253+ BasicBlock *ForBody = nullptr ;
254+ };
255+
256+ // / Get basic blocks needed for transformation.
257+ WindowFunctionBlocks getWindowFunctionBlocks (Function &F);
258+
259+ // / Find floating point multiplication instruction and constant.
260+ std::pair<BinaryOperator *, Value *>
261+ findFMulInstructionAndConstant (BasicBlock *ForBody);
262+
263+ // / Create multiplication instructions in preheader.
264+ SmallVector<Value *, 4 > createMultiplicationInstructions (IRBuilder<> &Builder,
265+ Instruction *Conv1,
266+ Value *FMulConst,
267+ Function &F,
268+ unsigned NumCosf);
269+
270+ // / Update cosine function calls with new parameters.
271+ bool updateCosineFunctionCalls (BasicBlock *ForBody,
272+ const SmallVector<Value *, 4 > &Muls,
273+ unsigned NumCosf);
274+ };
275+
276+ // / Type aliases for specific window function optimizers.
277+ using DspsWindCustomLICMHannOptimizer = DspsWindCustomLICMOptimizer<1 >;
278+ using DspsWindCustomLICMBlackmanOptimizer = DspsWindCustomLICMOptimizer<2 >;
279+ using DspsWindCustomLICMBlackmanHarrisOptimizer =
280+ DspsWindCustomLICMOptimizer<3 >;
281+ using DspsWindCustomLICMFlatTopOptimizer = DspsWindCustomLICMOptimizer<4 >;
282+
51283} // namespace llvm
52284
53- #endif // LLVM_TRANSFORMS_UTILS_RISCVCUSTOMLICM_H
285+ #endif // LLVM_LIB_TARGET_RISCV_RISCVCUSTOMLICM_H
0 commit comments