LLVM: lib/Target/RISCV/RISCVCodeGenPrepare.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
29
30using namespace llvm;
31
32#define DEBUG_TYPE "riscv-codegenprepare"
33#define PASS_NAME "RISC-V CodeGenPrepare"
34
35namespace {
36class RISCVCodeGenPrepare : public InstVisitor<RISCVCodeGenPrepare, bool> {
41
42public:
45 : F(F), DL(&F.getDataLayout()), DT(DT), ST(ST) {}
46 bool run();
47 bool visitInstruction(Instruction &I) { return false; }
52};
53}
54
55namespace {
56class RISCVCodeGenPrepareLegacyPass : public FunctionPass {
57public:
58 static char ID;
59
60 RISCVCodeGenPrepareLegacyPass() : FunctionPass(ID) {}
61
63 StringRef getPassName() const override { return PASS_NAME; }
64
65 void getAnalysisUsage(AnalysisUsage &AU) const override {
67 AU.addRequired();
69 }
70};
71}
72
73
74
75
76bool RISCVCodeGenPrepare::visitAnd(BinaryOperator &BO) {
78 return false;
79
81 return false;
82
83 using namespace PatternMatch;
84
85
88 return false;
89
91 return false;
92
93
95
97 if (!CI)
98 return false;
99 uint64_t C = CI->getZExtValue();
100
101
102
103
105 return false;
106
107
110
111 return true;
112}
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143bool RISCVCodeGenPrepare::widenVPMerge(IntrinsicInst &II) {
144 if (.getType()->getScalarType()->isIntegerTy(1))
145 return false;
146
148 using namespace PatternMatch;
152 return false;
153
155 if (!Phi || ->hasOneUse() || Phi->getNumIncomingValues() != 2 ||
157 Phi->getIncomingValue(1) != &II)
158 return false;
159
160 Type *WideTy =
161 VectorType::get(IntegerType::getInt8Ty(II.getContext()),
163
165 PHINode *WidePhi = Builder.CreatePHI(WideTy, 2);
167 Phi->getIncomingBlock(0));
168 Builder.SetInsertPoint(&II);
169 Value *WideTrue = Builder.CreateZExt(True, WideTy);
170 Value *WideMerge = Builder.CreateIntrinsic(Intrinsic::vp_merge, {WideTy},
171 {Mask, WideTrue, WidePhi, EVL});
172 WidePhi->addIncoming(WideMerge, Phi->getIncomingBlock(1));
173 Value *Trunc = Builder.CreateTrunc(WideMerge, II.getType());
174
175 II.replaceAllUsesWith(Trunc);
176
177
178 Phi->setIncomingValue(1, Phi->getIncomingValue(0));
180
181 return true;
182}
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215bool RISCVCodeGenPrepare::visitIntrinsicInst(IntrinsicInst &I) {
216 if (expandVPStrideLoad(I))
217 return true;
218
219 if (widenVPMerge(I))
220 return true;
221
222 if (I.getIntrinsicID() != Intrinsic::vector_reduce_fadd &&
224 return false;
225
227 if ( ||
->hasOneUse() ||
229 return false;
230
231 Type *VecTy = I.getOperand(1)->getType();
233 auto *VecPHI = Builder.CreatePHI(VecTy, PHI->getNumIncomingValues());
234
235 for (auto *BB : PHI->blocks()) {
236 Builder.SetInsertPoint(BB->getTerminator());
237 Value *InsertElt = Builder.CreateInsertElement(
238 VecTy, PHI->getIncomingValueForBlock(BB), (uint64_t)0);
239 VecPHI->addIncoming(InsertElt, BB);
240 }
241
242 Builder.SetInsertPoint(&I);
243 I.setOperand(0, Builder.CreateExtractElement(VecPHI, (uint64_t)0));
244
245 PHI->eraseFromParent();
246
247 return true;
248}
249
250
251
252
253bool RISCVCodeGenPrepare::expandVPStrideLoad(IntrinsicInst &II) {
255
256 using namespace PatternMatch;
259 return false;
260
261
262
263 if (II.getType()->getScalarSizeInBits() > ST->getXLen())
264 return false;
265
267 return false;
268
270
272 Type *STy = VTy->getElementType();
273 Value *Val = Builder.CreateLoad(STy, BasePtr);
274 Value *Res = Builder.CreateIntrinsic(
275 Intrinsic::vp_merge, VTy,
276 {II.getOperand(2), Builder.CreateVectorSplat(VTy->getElementCount(), Val),
278
279 II.replaceAllUsesWith(Res);
280 II.eraseFromParent();
281 return true;
282}
283
284bool RISCVCodeGenPrepare::run() {
285 bool MadeChange = false;
286 for (auto &BB : F)
289
290 return MadeChange;
291}
292
293bool RISCVCodeGenPrepareLegacyPass::runOnFunction(Function &F) {
294 if (skipFunction(F))
295 return false;
296
297 auto &TPC = getAnalysis();
298 auto &TM = TPC.getTM();
299 auto ST = &TM.getSubtarget(F);
300 auto DT = &getAnalysis().getDomTree();
301
302 RISCVCodeGenPrepare RVCGP(F, DT, ST);
303 return RVCGP.run();
304}
305
307 false, false)
311
312char RISCVCodeGenPrepareLegacyPass::ID = 0;
313
315 return new RISCVCodeGenPrepareLegacyPass();
316}
317
322 bool Changed = RISCVCodeGenPrepare(F, DT, ST).run();
325
328 return PA;
329}
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static bool runOnFunction(Function &F, bool PostInlining)
uint64_t IntrinsicInst * II
FunctionAnalysisManager FAM
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
#define PASS_NAME
Definition RISCVCodeGenPrepare.cpp:33
void visit(MachineFunction &MF, MachineBasicBlock &Start, std::function< void(MachineBasicBlock *)> op)
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
Target-Independent Code Generator Pass Configuration Options pass.
AnalysisUsage & addRequired()
LLVM_ABI void setPreservesCFG()
This function should be called by the pass, iff they do not:
Represents analyses that only rely on functions' control flow.
static LLVM_ABI ConstantAggregateZero * get(Type *Ty)
A parsed version of the target data layout string in and methods for querying it.
Analysis pass which computes a DominatorTree.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
FunctionPass class - This class is used to implement most global optimizations.
Base class for instruction visitors.
A wrapper class for inspecting calls to intrinsic functions.
void addIncoming(Value *V, BasicBlock *BB)
Add an incoming value to the end of the PHI list.
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses & preserveSet()
Mark an analysis set as preserved.
PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM)
Definition RISCVCodeGenPrepare.cpp:318
Target-Independent Code Generator Pass Configuration Options.
bool isIntegerTy() const
True if this is an instance of IntegerType.
void setOperand(unsigned i, Value *Val)
Value * getOperand(unsigned i) const
Type * getType() const
All values are typed, get the type of this value.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ C
The default llvm calling convention, compatible with C.
cst_pred_ty< is_all_ones > m_AllOnes()
Match an integer or vector with all bits set.
bool match(Val *V, const Pattern &P)
IntrinsicID_match m_Intrinsic()
Match intrinsic calls like this: m_IntrinsicIntrinsic::fabs(m_Value(X))
NNegZExt_match< OpTy > m_NNegZExt(const OpTy &Op)
class_match< Value > m_Value()
Match an arbitrary value and ignore it.
is_zero m_Zero()
Match any null constant or a vector with all elements equal to 0.
NodeAddr< PhiNode * > Phi
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
LLVM_ABI bool RecursivelyDeleteTriviallyDeadInstructions(Value *V, const TargetLibraryInfo *TLI=nullptr, MemorySSAUpdater *MSSAU=nullptr, std::function< void(Value *)> AboutToDeleteCallback=std::function< void(Value *)>())
If the specified value is a trivially dead instruction, delete it.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
FunctionPass * createRISCVCodeGenPrepareLegacyPass()
Definition RISCVCodeGenPrepare.cpp:314
decltype(auto) dyn_cast(const From &Val)
dyn_cast - Return the argument parameter cast to the specified type.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
bool isa(const From &Val)
isa - Return true if the parameter to the template is an instance of one of the template type argu...
LLVM_ABI bool isKnownNonZero(const Value *V, const SimplifyQuery &Q, unsigned Depth=0)
Return true if the given value is known to be non-zero when defined.
IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >
decltype(auto) cast(const From &Val)
cast - Return the argument parameter cast to the specified type.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
constexpr int64_t SignExtend64(uint64_t x)
Sign-extend the number in the bottom B bits of X to a 64-bit integer.
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.