Skip to content

Commit a85c3b8

Browse files
mshelegoigcbot
authored andcommitted
Split vectors containing dead elements
Use LiveElements analysis in GenXLegalization pass to see if there are any dead elements in a vector. If so, split instruction to isolate the dead parts, which will be removed by later passes
1 parent 7eae7ee commit a85c3b8

File tree

7 files changed

+245
-34
lines changed

7 files changed

+245
-34
lines changed

IGC/VectorCompiler/lib/GenXCodeGen/GenXLegalization.cpp

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ SPDX-License-Identifier: MIT
152152
#include "GenXAlignmentInfo.h"
153153
#include "GenXBaling.h"
154154
#include "GenXIntrinsics.h"
155+
#include "GenXLiveElements.h"
155156
#include "GenXSubtarget.h"
156157
#include "GenXTargetMachine.h"
157158
#include "GenXUtil.h"
@@ -213,6 +214,7 @@ struct LegalPredSize {
213214
class GenXLegalization : public FunctionPass {
214215
enum { DETERMINEWIDTH_UNBALE = 0, DETERMINEWIDTH_NO_SPLIT = 256 };
215216
GenXBaling *Baling = nullptr;
217+
GenXFuncLiveElements *LE = nullptr;
216218
const GenXSubtarget *ST = nullptr;
217219
DominatorTree *DT = nullptr;
218220
ScalarEvolution *SE = nullptr;
@@ -406,6 +408,7 @@ void initializeGenXLegalizationPass(PassRegistry &);
406408
INITIALIZE_PASS_BEGIN(GenXLegalization, "GenXLegalization", "GenXLegalization",
407409
false, false)
408410
INITIALIZE_PASS_DEPENDENCY(GenXFuncBaling)
411+
INITIALIZE_PASS_DEPENDENCY(GenXFuncLiveElements)
409412
INITIALIZE_PASS_DEPENDENCY(ScalarEvolutionWrapperPass)
410413
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
411414
INITIALIZE_PASS_END(GenXLegalization, "GenXLegalization", "GenXLegalization",
@@ -418,6 +421,7 @@ FunctionPass *llvm::createGenXLegalizationPass() {
418421

419422
void GenXLegalization::getAnalysisUsage(AnalysisUsage &AU) const {
420423
AU.addRequired<GenXFuncBaling>();
424+
AU.addRequired<GenXFuncLiveElements>();
421425
AU.addRequired<ScalarEvolutionWrapperPass>();
422426
AU.addRequired<TargetPassConfig>();
423427
AU.addRequired<DominatorTreeWrapperPass>();
@@ -430,6 +434,7 @@ void GenXLegalization::getAnalysisUsage(AnalysisUsage &AU) const {
430434
*/
431435
bool GenXLegalization::runOnFunction(Function &F) {
432436
Baling = &getAnalysis<GenXFuncBaling>();
437+
LE = &getAnalysis<GenXFuncLiveElements>();
433438
SE = &getAnalysis<ScalarEvolutionWrapperPass>().getSE();
434439
ST = &getAnalysis<TargetPassConfig>()
435440
.getTM<GenXTargetMachine>()
@@ -1423,6 +1428,50 @@ unsigned GenXLegalization::determineWidth(unsigned WholeWidth,
14231428
IGC_ASSERT(Width != 1);
14241429
Width >>= 1;
14251430
}
1431+
if (Width > 1) {
1432+
// Try to reduce width to isolate dead parts of the vector if there are any
1433+
Value *Dest = Head->Inst;
1434+
if (Head->Info.Type == BaleInfo::WRREGION ||
1435+
Head->Info.Type == BaleInfo::WRPREDREGION ||
1436+
Head->Info.Type == BaleInfo::WRPREDPREDREGION)
1437+
Dest = Head->Inst->getOperand(1);
1438+
const auto &LiveElems = LE->getLiveElements(Dest);
1439+
if (LiveElems.size() == 1 && !LiveElems.isAllDead() &&
1440+
LiveElems.isAnyDead()) {
1441+
// Value is not aggregate and vector contains both dead and live parts
1442+
IGC_ASSERT(LiveElems[0].size() == WholeWidth);
1443+
// Execution mask must be 4 aligned, which is important for predicates
1444+
unsigned FirstLive = LiveElems[0].find_first() & ~3U;
1445+
// Dead parts don't need to be aligned, because the will be removed anyway
1446+
unsigned LastLive = LiveElems[0].find_last();
1447+
if (StartIdx <= FirstLive && StartIdx + Width >= FirstLive ||
1448+
StartIdx <= LastLive && StartIdx + Width >= LastLive) {
1449+
// Instruction with current width crosses the boundary between live
1450+
// and dead parts
1451+
FirstLive = std::max(FirstLive, StartIdx);
1452+
LastLive = std::min(LastLive, StartIdx + Width);
1453+
unsigned LiveSize = LastLive - FirstLive + 1;
1454+
unsigned LiveWidth = 1;
1455+
while (LiveWidth < LiveSize)
1456+
LiveWidth <<= 1;
1457+
if (LiveWidth < Width) {
1458+
// Live part can fit in a single instruction with smaller width
1459+
unsigned NewWidth = LiveWidth;
1460+
if (StartIdx < FirstLive) {
1461+
// In this iteration we have to split preceding zeroes
1462+
// Determine the largest width not crossing the live part's boundary
1463+
unsigned DeadSize = FirstLive - StartIdx;
1464+
unsigned DeadWidth = Width;
1465+
while (DeadWidth > DeadSize)
1466+
DeadWidth >>= 1;
1467+
NewWidth = DeadWidth;
1468+
}
1469+
if (ExecSizeAllowedBits & NewWidth)
1470+
Width = NewWidth;
1471+
}
1472+
}
1473+
}
1474+
}
14261475
if (Width != WholeWidth && IsReadSameVector &&
14271476
CurSplitKind == SplitKind_Normal) {
14281477
// Splitting required, and the bale contains a rdregion from the same

IGC/VectorCompiler/lib/GenXCodeGen/GenXLiveElements.cpp

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ SPDX-License-Identifier: MIT
1515
#include "llvm/IR/Instructions.h"
1616
#include "llvm/IR/IntrinsicInst.h"
1717
#include "llvm/InitializePasses.h"
18+
#include "llvm/Support/Debug.h"
1819

1920
#include "Probe/Assertion.h"
2021
#include "vc/Utils/General/IndexFlattener.h"
@@ -57,7 +58,7 @@ LiveElements LiveElements::operator|=(const LiveElements &Rhs) {
5758
return *this;
5859
}
5960

60-
void LiveElements::dump(raw_ostream &OS) const {
61+
void LiveElements::print(raw_ostream &OS) const {
6162
SmallVector<std::string, 2> LiveElemsStr;
6263
LiveElemsStr.reserve(LiveElems.size());
6364

@@ -72,6 +73,13 @@ void LiveElements::dump(raw_ostream &OS) const {
7273
OS << '{' << join(LiveElemsStr, ", ") << '}';
7374
}
7475

76+
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
77+
void LiveElements::dump() const {
78+
print(dbgs());
79+
dbgs() << "\n";
80+
}
81+
#endif // if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
82+
7583
LiveElements LiveElementsAnalysis::getLiveElements(const Value *V) const {
7684
if (auto It = LiveMap.find(V); It != LiveMap.end())
7785
return It->second;
@@ -263,7 +271,7 @@ LiveElements LiveElementsAnalysis::getOperandLiveElements(
263271
auto OpTy = Inst->getOperand(OperandNo)->getType();
264272

265273
if (InstLiveElems.isAllDead() && !Inst->mayHaveSideEffects())
266-
return LiveElements(OpTy);
274+
return LiveElements(OpTy, false);
267275

268276
if (auto BCI = dyn_cast<BitCastInst>(Inst))
269277
return getBitCastLiveElements(BCI, InstLiveElems);
@@ -299,8 +307,17 @@ LiveElements LiveElementsAnalysis::getOperandLiveElements(
299307
if (ID == GenXIntrinsic::genx_addc || ID == GenXIntrinsic::genx_subb)
300308
return getTwoDstInstLiveElements(InstLiveElems);
301309

302-
if (isElementWise(Inst))
303-
return InstLiveElems;
310+
auto OpLiveElems = LiveElements(OpTy);
311+
if (isElementWise(Inst) && InstLiveElems.size() == OpLiveElems.size()) {
312+
bool EqualSize = true;
313+
for (unsigned Idx = 0; Idx < InstLiveElems.size(); Idx++)
314+
if (InstLiveElems[Idx].size() != OpLiveElems[Idx].size()) {
315+
EqualSize = false;
316+
break;
317+
}
318+
if (EqualSize)
319+
return InstLiveElems;
320+
}
304321

305322
return LiveElements(OpTy, true);
306323
}
@@ -361,14 +378,18 @@ void LiveElementsAnalysis::processFunction(const Function &F) {
361378
}
362379
}
363380

364-
if (PrintLiveElementsInfo)
365-
print(outs());
366-
}
367-
368-
void LiveElementsAnalysis::print(raw_ostream &OS) const {
369-
OS << "Live elements:\n";
370-
for (const auto &LiveElem : LiveMap)
371-
OS << *LiveElem.first << ": " << LiveElem.second << '\n';
381+
if (PrintLiveElementsInfo) {
382+
outs() << "Live elements for " << F.getName() << ":\n";
383+
for (auto &I : instructions(F)) {
384+
outs() << I << " ";
385+
auto It = LiveMap.find(&I);
386+
if (It != LiveMap.end())
387+
outs() << It->second;
388+
else
389+
outs() << LiveElements(I.getType());
390+
outs() << "\n";
391+
}
392+
}
372393
}
373394

374395
char GenXFuncLiveElements::ID = 0;

IGC/VectorCompiler/lib/GenXCodeGen/GenXLiveElements.h

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,10 @@ class LiveElements {
8888

8989
LiveElements operator|=(const LiveElements &Rhs);
9090

91-
void dump(raw_ostream &OS) const;
91+
void print(raw_ostream &OS) const;
92+
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
93+
void dump() const;
94+
#endif // if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
9295
};
9396

9497
inline LiveElements operator|(const LiveElements &Lhs,
@@ -99,7 +102,7 @@ inline LiveElements operator|(const LiveElements &Lhs,
99102
}
100103

101104
inline raw_ostream &operator<<(raw_ostream &OS, const LiveElements &LE) {
102-
LE.dump(OS);
105+
LE.print(OS);
103106
return OS;
104107
}
105108

@@ -118,8 +121,6 @@ class LiveElementsAnalysis {
118121
LiveElements getLiveElements(const Value *V) const;
119122
LiveElements getLiveElements(const Use *U) const;
120123

121-
void print(raw_ostream &OS) const;
122-
123124
private:
124125
ValueMap<const Value *, genx::LiveElements> LiveMap;
125126

@@ -166,10 +167,6 @@ class GenXFuncLiveElements : public FunctionPass,
166167
processFunction(F);
167168
return false;
168169
}
169-
170-
void print(raw_ostream &OS, const Module *M) const override {
171-
genx::LiveElementsAnalysis::print(OS);
172-
}
173170
};
174171

175172
void initializeGenXFuncLiveElementsPass(PassRegistry &);

IGC/VectorCompiler/test/GenXLegalization/debug_gstore.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ define void @test_transform(<128 x i8>* %a) !dbg !6 {
3131
entry:
3232
%0 = load <128 x i8>, <128 x i8>* %a, !dbg !12
3333
call void @llvm.dbg.value(metadata <128 x i8> %0, metadata !9, metadata !DIExpression()), !dbg !12
34-
%1 = call <128 x i8> @llvm.genx.rdregioni.v128i8.v128i8.i16(<128 x i8> %0, i32 1, i32 1, i32 0, i16 16, i32 0), !dbg !13
34+
%1 = call <128 x i8> @llvm.genx.rdregioni.v128i8.v128i8.i16(<128 x i8> %0, i32 1, i32 1, i32 0, i16 0, i32 0), !dbg !13
3535
call void @llvm.dbg.value(metadata <128 x i8> %1, metadata !9, metadata !DIExpression()), !dbg !13
3636
store <128 x i8> %1, <128 x i8>* @global_vec, !dbg !14
3737
ret void, !dbg !15

IGC/VectorCompiler/test/Legalization/debug-gstore.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ define void @test_transform(<128 x i8>* %a) !dbg !6 {
2929
entry:
3030
%0 = load <128 x i8>, <128 x i8>* %a, !dbg !12
3131
call void @llvm.dbg.value(metadata <128 x i8> %0, metadata !9, metadata !DIExpression()), !dbg !12
32-
%1 = call <128 x i8> @llvm.genx.rdregioni.v128i8.v128i8.i16(<128 x i8> %0, i32 1, i32 1, i32 0, i16 16, i32 0), !dbg !13
32+
%1 = call <128 x i8> @llvm.genx.rdregioni.v128i8.v128i8.i16(<128 x i8> %0, i32 1, i32 1, i32 0, i16 0, i32 0), !dbg !13
3333
call void @llvm.dbg.value(metadata <128 x i8> %1, metadata !11, metadata !DIExpression()), !dbg !13
3434
store <128 x i8> %1, <128 x i8>* @global_vec, !dbg !14
3535
ret void, !dbg !15
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
;=========================== begin_copyright_notice ============================
2+
;
3+
; Copyright (C) 2023 Intel Corporation
4+
;
5+
; SPDX-License-Identifier: MIT
6+
;
7+
;============================ end_copyright_notice =============================
8+
9+
; RUN: opt %use_old_pass_manager% -GenXLegalization -march=genx64 -mcpu=Gen9 -mtriple=spir64-unknown-unknown -S < %s | FileCheck %s
10+
11+
; NO SPLIT
12+
; CHECK-LABEL: @test1
13+
; CHECK: add <16 x i32>
14+
define <16 x i32> @test1(<16 x i32> %arg) {
15+
%add = add <16 x i32> %arg, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
16+
%and = and <16 x i32> %add, <i32 1, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 1>
17+
ret <16 x i32> %and
18+
}
19+
; CHECK-LABEL: @test2
20+
; CHECK: add <16 x i32>
21+
define <16 x i32> @test2(<16 x i32> %arg) {
22+
%add = add <16 x i32> %arg, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
23+
%and = and <16 x i32> %add, <i32 0, i32 0, i32 0, i32 0, i32 0, i32 1, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 1, i32 0>
24+
ret <16 x i32> %and
25+
}
26+
; CHECK-LABEL: @test3
27+
; CHECK: add <16 x i32>
28+
define <16 x i32> @test3(<16 x i32> %arg) {
29+
%add = add <16 x i32> %arg, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
30+
%and = and <16 x i32> %add, <i32 0, i32 0, i32 0, i32 1, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 1, i32 0, i32 0, i32 0, i32 0, i32 0>
31+
ret <16 x i32> %and
32+
}
33+
34+
; SPLIT 8
35+
; CHECK-LABEL: @test4
36+
; CHECK: add <8 x i32>
37+
; CHECK: add <8 x i32>
38+
define <16 x i32> @test4(<16 x i32> %arg) {
39+
%add = add <16 x i32> %arg, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
40+
%and = and <16 x i32> %add, <i32 1, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 1, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0>
41+
ret <16 x i32> %and
42+
}
43+
; CHECK-LABEL: @test5
44+
; CHECK: add <8 x i32>
45+
; CHECK: add <8 x i32>
46+
define <16 x i32> @test5(<16 x i32> %arg) {
47+
%add = add <16 x i32> %arg, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
48+
%and = and <16 x i32> %add, <i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 1, i32 0, i32 0, i32 0, i32 1, i32 0, i32 0>
49+
ret <16 x i32> %and
50+
}
51+
; CHECK-LABEL: @test6
52+
; CHECK: add <4 x i32>
53+
; CHECK: add <8 x i32>
54+
; CHECK: add <4 x i32>
55+
define <16 x i32> @test6(<16 x i32> %arg) {
56+
%add = add <16 x i32> %arg, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
57+
%and = and <16 x i32> %add, <i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 1, i32 0, i32 0, i32 1, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0>
58+
ret <16 x i32> %and
59+
}
60+
61+
; SPLIT 4
62+
; CHECK-LABEL: @test7
63+
; CHECK: add <4 x i32>
64+
; CHECK: add <8 x i32>
65+
; CHECK: add <4 x i32>
66+
define <16 x i32> @test7(<16 x i32> %arg) {
67+
%add = add <16 x i32> %arg, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
68+
%and = and <16 x i32> %add, <i32 1, i32 0, i32 0, i32 1, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0>
69+
ret <16 x i32> %and
70+
}
71+
; CHECK-LABEL: @test8
72+
; CHECK: add <8 x i32>
73+
; CHECK: add <4 x i32>
74+
; CHECK: add <4 x i32>
75+
define <16 x i32> @test8(<16 x i32> %arg) {
76+
%add = add <16 x i32> %arg, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
77+
%and = and <16 x i32> %add, <i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 1, i32 0, i32 1>
78+
ret <16 x i32> %and
79+
}
80+
; CHECK-LABEL: @test9
81+
; CHECK: add <4 x i32>
82+
; CHECK: add <4 x i32>
83+
; CHECK: add <8 x i32>
84+
define <16 x i32> @test9(<16 x i32> %arg) {
85+
%add = add <16 x i32> %arg, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
86+
%and = and <16 x i32> %add, <i32 0, i32 0, i32 0, i32 0, i32 0, i32 1, i32 1, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0>
87+
ret <16 x i32> %and
88+
}
89+
90+
; SPLIT 2
91+
; CHECK-LABEL: @test10
92+
; CHECK: add <2 x i32>
93+
; CHECK: add <8 x i32>
94+
; CHECK: add <4 x i32>
95+
; CHECK: add <2 x i32>
96+
define <16 x i32> @test10(<16 x i32> %arg) {
97+
%add = add <16 x i32> %arg, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
98+
%and = and <16 x i32> %add, <i32 1, i32 1, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0>
99+
ret <16 x i32> %and
100+
}
101+
; CHECK-LABEL: @test11
102+
; CHECK: add <8 x i32>
103+
; CHECK: add <2 x i32>
104+
; CHECK: add <4 x i32>
105+
; CHECK: add <2 x i32>
106+
define <16 x i32> @test11(<16 x i32> %arg) {
107+
%add = add <16 x i32> %arg, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
108+
%and = and <16 x i32> %add, <i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 1, i32 1, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0>
109+
ret <16 x i32> %and
110+
}
111+
; CHECK-LABEL: @test12
112+
; CHECK: add <4 x i32>
113+
; CHECK: add <2 x i32>
114+
; CHECK: add <8 x i32>
115+
; CHECK: add <2 x i32>
116+
define <16 x i32> @test12(<16 x i32> %arg) {
117+
%add = add <16 x i32> %arg, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
118+
%and = and <16 x i32> %add, <i32 0, i32 0, i32 0, i32 0, i32 0, i32 1, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0>
119+
ret <16 x i32> %and
120+
}
121+
122+
; SPLIT 1
123+
; CHECK-LABEL: @test13
124+
; CHECK: add <1 x i32>
125+
; CHECK: add <8 x i32>
126+
; CHECK: add <4 x i32>
127+
; CHECK: add <2 x i32>
128+
; CHECK: add <1 x i32>
129+
define <16 x i32> @test13(<16 x i32> %arg) {
130+
%add = add <16 x i32> %arg, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
131+
%and = and <16 x i32> %add, <i32 1, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0>
132+
ret <16 x i32> %and
133+
}
134+
; CHECK-LABEL: @test14
135+
; CHECK: add <4 x i32>
136+
; CHECK: add <1 x i32>
137+
; CHECK: add <8 x i32>
138+
; CHECK: add <2 x i32>
139+
; CHECK: add <1 x i32>
140+
define <16 x i32> @test14(<16 x i32> %arg) {
141+
%add = add <16 x i32> %arg, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
142+
%and = and <16 x i32> %add, <i32 0, i32 0, i32 0, i32 0, i32 1, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0>
143+
ret <16 x i32> %and
144+
}
145+

0 commit comments

Comments
 (0)