18
18
#include " llvm/ADT/Statistic.h"
19
19
#include " llvm/Analysis/ValueTracking.h"
20
20
#include " llvm/CodeGen/TargetPassConfig.h"
21
+ #include " llvm/IR/Dominators.h"
21
22
#include " llvm/IR/IRBuilder.h"
22
23
#include " llvm/IR/InstVisitor.h"
23
24
#include " llvm/IR/Intrinsics.h"
25
+ #include " llvm/IR/IntrinsicsRISCV.h"
24
26
#include " llvm/IR/PatternMatch.h"
25
27
#include " llvm/InitializePasses.h"
26
28
#include " llvm/Pass.h"
@@ -35,6 +37,7 @@ namespace {
35
37
class RISCVCodeGenPrepare : public FunctionPass ,
36
38
public InstVisitor<RISCVCodeGenPrepare, bool > {
37
39
const DataLayout *DL;
40
+ const DominatorTree *DT;
38
41
const RISCVSubtarget *ST;
39
42
40
43
public:
@@ -48,12 +51,14 @@ class RISCVCodeGenPrepare : public FunctionPass,
48
51
49
52
void getAnalysisUsage (AnalysisUsage &AU) const override {
50
53
AU.setPreservesCFG ();
54
+ AU.addRequired <DominatorTreeWrapperPass>();
51
55
AU.addRequired <TargetPassConfig>();
52
56
}
53
57
54
58
bool visitInstruction (Instruction &I) { return false ; }
55
59
bool visitAnd (BinaryOperator &BO);
56
60
bool visitIntrinsicInst (IntrinsicInst &I);
61
+ bool expandVPStrideLoad (IntrinsicInst &I);
57
62
};
58
63
59
64
} // end anonymous namespace
@@ -128,6 +133,9 @@ bool RISCVCodeGenPrepare::visitAnd(BinaryOperator &BO) {
128
133
// Which eliminates the scalar -> vector -> scalar crossing during instruction
129
134
// selection.
130
135
bool RISCVCodeGenPrepare::visitIntrinsicInst (IntrinsicInst &I) {
136
+ if (expandVPStrideLoad (I))
137
+ return true ;
138
+
131
139
if (I.getIntrinsicID () != Intrinsic::vector_reduce_fadd)
132
140
return false ;
133
141
@@ -155,6 +163,45 @@ bool RISCVCodeGenPrepare::visitIntrinsicInst(IntrinsicInst &I) {
155
163
return true ;
156
164
}
157
165
166
+ bool RISCVCodeGenPrepare::expandVPStrideLoad (IntrinsicInst &II) {
167
+ Value *BasePtr, *VL;
168
+
169
+ using namespace PatternMatch ;
170
+ if (!match (&II, m_Intrinsic<Intrinsic::experimental_vp_strided_load>(
171
+ m_Value (BasePtr), m_Zero (), m_AllOnes (), m_Value (VL))))
172
+ return false ;
173
+
174
+ if (!isKnownNonZero (VL, {*DL, DT, nullptr , &II}))
175
+ return false ;
176
+
177
+ auto *VTy = cast<VectorType>(II.getType ());
178
+
179
+ IRBuilder<> Builder (&II);
180
+
181
+ // Extend VL from i32 to XLen if needed.
182
+ if (ST->is64Bit ())
183
+ VL = Builder.CreateZExt (VL, Builder.getInt64Ty ());
184
+
185
+ Type *STy = VTy->getElementType ();
186
+ Value *Val = Builder.CreateLoad (STy, BasePtr);
187
+ const auto &TLI = *ST->getTargetLowering ();
188
+ Value *Res;
189
+
190
+ // TODO: Also support fixed/illegal vector types to splat with evl = vl.
191
+ if (isa<ScalableVectorType>(VTy) && TLI.isTypeLegal (EVT::getEVT (VTy))) {
192
+ unsigned VMVOp = STy->isFloatingPointTy () ? Intrinsic::riscv_vfmv_v_f
193
+ : Intrinsic::riscv_vmv_v_x;
194
+ Res = Builder.CreateIntrinsic (VMVOp, {VTy, VL->getType ()},
195
+ {PoisonValue::get (VTy), Val, VL});
196
+ } else {
197
+ Res = Builder.CreateVectorSplat (VTy->getElementCount (), Val);
198
+ }
199
+
200
+ II.replaceAllUsesWith (Res);
201
+ II.eraseFromParent ();
202
+ return true ;
203
+ }
204
+
158
205
bool RISCVCodeGenPrepare::runOnFunction (Function &F) {
159
206
if (skipFunction (F))
160
207
return false ;
@@ -164,6 +211,7 @@ bool RISCVCodeGenPrepare::runOnFunction(Function &F) {
164
211
ST = &TM.getSubtarget <RISCVSubtarget>(F);
165
212
166
213
DL = &F.getDataLayout ();
214
+ DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree ();
167
215
168
216
bool MadeChange = false ;
169
217
for (auto &BB : F)
0 commit comments