Skip to content

Commit 8f309a1

Browse files
chenqiangerekon
authored andcommitted
[Test] rename and add more examples in RISCVCustomLICM Pass
1 parent 3fdfd75 commit 8f309a1

12 files changed

+4163
-200
lines changed

llvm/lib/Target/RISCV/RISCVCustomLICM.cpp

Lines changed: 1363 additions & 185 deletions
Large diffs are not rendered by default.
Lines changed: 247 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,285 @@
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

2327
namespace llvm {
28+
2429
extern cl::opt<bool> EnableRISCVCustomLICM;
2530
class 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.
2746
struct 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

Comments
 (0)