Skip to content

Commit 196aec3

Browse files
author
Vasileios Porpodas
committed
[SandboxVec][StructInitVec] Add support for constants
1 parent ca19fca commit 196aec3

File tree

2 files changed

+115
-33
lines changed

2 files changed

+115
-33
lines changed

llvm/lib/Transforms/Vectorize/SandboxVectorizer/Passes/StructInitVec.cpp

Lines changed: 61 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -93,46 +93,74 @@ bool StructInitVec::runOnRegion(Region &Rgn, const Analyses &A) {
9393
Operands.push_back(Op);
9494
}
9595
BasicBlock *BB = Bndl[0]->getParent();
96-
// TODO: For now we only support load operands.
97-
// TODO: For now we don't cross BBs.
98-
if (!all_of(Operands, [BB](Value *V) {
99-
auto *LI = dyn_cast<LoadInst>(V);
100-
if (LI == nullptr)
101-
return false;
102-
if (LI->getParent() != BB)
103-
return false;
104-
if (LI->hasNUsesOrMore(2))
105-
return false;
106-
return true;
107-
}))
108-
return false;
109-
// TODO: Try to avoid the extra copy to an instruction vector.
110-
SmallVector<Instruction *, 8> Loads;
111-
Loads.reserve(Operands.size());
112-
for (Value *Op : Operands)
113-
Loads.push_back(cast<Instruction>(Op));
114-
115-
bool Consecutive = VecUtils::areConsecutive<LoadInst, Instruction>(
116-
Loads, A.getScalarEvolution(), *DL);
117-
if (!Consecutive)
118-
return false;
119-
if (!canVectorize(Loads, Sched))
96+
bool AllLoads = all_of(Operands, [BB](Value *V) {
97+
auto *LI = dyn_cast<LoadInst>(V);
98+
if (LI == nullptr)
99+
return false;
100+
// TODO: For now we don't cross BBs.
101+
if (LI->getParent() != BB)
102+
return false;
103+
if (LI->hasNUsesOrMore(2))
104+
return false;
105+
return true;
106+
});
107+
bool AllConstants =
108+
all_of(Operands, [](Value *V) { return isa<Constant>(V); });
109+
if (!AllLoads && !AllConstants)
120110
return false;
121111

122-
// Generate vector store and vector load
123-
Type *Ty = VecUtils::getCombinedVectorTypeFor(Bndl, *DL);
124-
Value *LdPtr = cast<LoadInst>(Loads[0])->getPointerOperand();
125-
// TODO: Compute alignment.
126-
Align LdAlign(1);
127-
auto LdWhereIt = std::next(VecUtils::getLowest(Loads)->getIterator());
128-
auto *VecLd =
129-
LoadInst::create(Ty, LdPtr, LdAlign, LdWhereIt, Ctx, "VecIinitL");
112+
Value *VecOp = nullptr;
113+
SmallVector<Instruction *, 8> Loads;
114+
if (AllLoads) {
115+
// TODO: Try to avoid the extra copy to an instruction vector.
116+
Loads.reserve(Operands.size());
117+
for (Value *Op : Operands)
118+
Loads.push_back(cast<Instruction>(Op));
119+
120+
bool Consecutive = VecUtils::areConsecutive<LoadInst, Instruction>(
121+
Loads, A.getScalarEvolution(), *DL);
122+
if (!Consecutive)
123+
return false;
124+
if (!canVectorize(Loads, Sched))
125+
return false;
126+
127+
// Generate vector load.
128+
Type *Ty = VecUtils::getCombinedVectorTypeFor(Bndl, *DL);
129+
Value *LdPtr = cast<LoadInst>(Loads[0])->getPointerOperand();
130+
// TODO: Compute alignment.
131+
Align LdAlign(1);
132+
auto LdWhereIt = std::next(VecUtils::getLowest(Loads)->getIterator());
133+
VecOp = LoadInst::create(Ty, LdPtr, LdAlign, LdWhereIt, Ctx, "VecIinitL");
134+
} else if (AllConstants) {
135+
SmallVector<Constant *, 8> Constants;
136+
Constants.reserve(Operands.size());
137+
for (Value *Op : Operands) {
138+
auto *COp = cast<Constant>(Op);
139+
if (auto *AggrCOp = dyn_cast<ConstantAggregate>(COp)) {
140+
// If the operand is a constant aggregate, then append all its elements.
141+
for (Value *Elm : AggrCOp->operands())
142+
Constants.push_back(cast<Constant>(Elm));
143+
} else if (auto *SeqCOp = dyn_cast<ConstantDataSequential>(COp)) {
144+
for (auto ElmIdx : seq<unsigned>(SeqCOp->getNumElements()))
145+
Constants.push_back(SeqCOp->getElementAsConstant(ElmIdx));
146+
} else if (auto *Zero = dyn_cast<ConstantAggregateZero>(COp)) {
147+
auto *ZeroElm = Zero->getSequentialElement();
148+
for (auto ElmIdx :
149+
seq<unsigned>(Zero->getElementCount().getFixedValue()))
150+
Constants.push_back(ZeroElm);
151+
} else {
152+
Constants.push_back(COp);
153+
}
154+
}
155+
VecOp = ConstantVector::get(Constants);
156+
}
130157

158+
// Generate vector store.
131159
Value *StPtr = cast<StoreInst>(Bndl[0])->getPointerOperand();
132160
// TODO: Compute alignment.
133161
Align StAlign(1);
134162
auto StWhereIt = std::next(VecUtils::getLowest(Bndl)->getIterator());
135-
StoreInst::create(VecLd, StPtr, StAlign, StWhereIt, Ctx);
163+
StoreInst::create(VecOp, StPtr, StAlign, StWhereIt, Ctx);
136164

137165
tryEraseDeadInstrs(Bndl, Loads);
138166
return true;

llvm/test/Transforms/SandboxVectorizer/struct_init_vec.ll

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,57 @@ define void @struct_init_schedule_stores_and_loads(ptr noalias %ptrA, ptr noalia
272272
ret void
273273
}
274274

275+
; Store-constant pattern.
276+
define void @struct_init_constants(ptr %ptr) {
277+
; CHECK-LABEL: define void @struct_init_constants(
278+
; CHECK-SAME: ptr [[PTR:%.*]]) {
279+
; CHECK-NEXT: [[PTR0:%.*]] = getelementptr i8, ptr [[PTR]], i32 0
280+
; CHECK-NEXT: store <3 x i8> <i8 42, i8 43, i8 44>, ptr [[PTR0]], align 1, !sandboxvec [[META13:![0-9]+]]
281+
; CHECK-NEXT: ret void
282+
;
283+
%ptr0 = getelementptr i8, ptr %ptr, i32 0
284+
%ptr1 = getelementptr i8, ptr %ptr, i32 1
285+
%ptr2 = getelementptr i8, ptr %ptr, i32 3
286+
store i8 42, ptr %ptr0
287+
store i16 43, ptr %ptr1
288+
store i8 44, ptr %ptr2
289+
ret void
290+
}
291+
292+
; Same but with ConstantDataSequential.
293+
define void @struct_init_constants_CDS(ptr %ptr) {
294+
; CHECK-LABEL: define void @struct_init_constants_CDS(
295+
; CHECK-SAME: ptr [[PTR:%.*]]) {
296+
; CHECK-NEXT: [[PTR0:%.*]] = getelementptr i8, ptr [[PTR]], i32 0
297+
; CHECK-NEXT: store <4 x i8> <i8 0, i8 1, i8 2, i8 3>, ptr [[PTR0]], align 1, !sandboxvec [[META14:![0-9]+]]
298+
; CHECK-NEXT: ret void
299+
;
300+
%ptr0 = getelementptr i8, ptr %ptr, i32 0
301+
%ptr1 = getelementptr i8, ptr %ptr, i32 1
302+
%ptr2 = getelementptr i8, ptr %ptr, i32 3
303+
store i8 0, ptr %ptr0
304+
store <2 x i8> <i8 1, i8 2>, ptr %ptr1
305+
store i8 3, ptr %ptr2
306+
ret void
307+
}
308+
309+
; Same but with floats
310+
define void @struct_init_constants_CDS_float(ptr %ptr) {
311+
; CHECK-LABEL: define void @struct_init_constants_CDS_float(
312+
; CHECK-SAME: ptr [[PTR:%.*]]) {
313+
; CHECK-NEXT: [[PTR0:%.*]] = getelementptr float, ptr [[PTR]], i32 0
314+
; CHECK-NEXT: store <8 x float> <float 1.000000e+00, float 0.000000e+00, float 0.000000e+00, float 0.000000e+00, float 0.000000e+00, float 0.000000e+00, float 0.000000e+00, float 0.000000e+00>, ptr [[PTR0]], align 1, !sandboxvec [[META15:![0-9]+]]
315+
; CHECK-NEXT: ret void
316+
;
317+
%ptr0 = getelementptr float, ptr %ptr, i32 0
318+
%ptr1 = getelementptr float, ptr %ptr, i32 1
319+
%ptr2 = getelementptr float, ptr %ptr, i32 3
320+
store float 1.0, ptr %ptr0
321+
store <2 x float> zeroinitializer, ptr %ptr1
322+
store <5 x float> zeroinitializer, ptr %ptr2
323+
ret void
324+
}
325+
275326
;.
276327
; CHECK: [[META0]] = distinct !{!"sandboxregion"}
277328
; CHECK: [[META1]] = distinct !{!"sandboxregion"}
@@ -286,4 +337,7 @@ define void @struct_init_schedule_stores_and_loads(ptr noalias %ptrA, ptr noalia
286337
; CHECK: [[META10]] = distinct !{!"sandboxregion"}
287338
; CHECK: [[META11]] = distinct !{!"sandboxregion"}
288339
; CHECK: [[META12]] = distinct !{!"sandboxregion"}
340+
; CHECK: [[META13]] = distinct !{!"sandboxregion"}
341+
; CHECK: [[META14]] = distinct !{!"sandboxregion"}
342+
; CHECK: [[META15]] = distinct !{!"sandboxregion"}
289343
;.

0 commit comments

Comments
 (0)