1b0f98d34SSanjay Patel //===- VectorUtilsTest.cpp - VectorUtils tests ------------------------===//
2b0f98d34SSanjay Patel //
3b0f98d34SSanjay Patel // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4b0f98d34SSanjay Patel // See https://llvm.org/LICENSE.txt for license information.
5b0f98d34SSanjay Patel // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6b0f98d34SSanjay Patel //
7b0f98d34SSanjay Patel //===----------------------------------------------------------------------===//
8b0f98d34SSanjay Patel 
9b0f98d34SSanjay Patel #include "llvm/Analysis/VectorUtils.h"
10b0f98d34SSanjay Patel #include "llvm/Analysis/ValueTracking.h"
11b0f98d34SSanjay Patel #include "llvm/AsmParser/Parser.h"
12b0f98d34SSanjay Patel #include "llvm/IR/Function.h"
13b0f98d34SSanjay Patel #include "llvm/IR/InstIterator.h"
1440e3bdf8SSanjay Patel #include "llvm/IR/IRBuilder.h"
15b0f98d34SSanjay Patel #include "llvm/IR/LLVMContext.h"
16b0f98d34SSanjay Patel #include "llvm/IR/Module.h"
1740e3bdf8SSanjay Patel #include "llvm/IR/NoFolder.h"
18b0f98d34SSanjay Patel #include "llvm/Support/ErrorHandling.h"
19b0f98d34SSanjay Patel #include "llvm/Support/SourceMgr.h"
20b0f98d34SSanjay Patel #include "llvm/Support/KnownBits.h"
21b0f98d34SSanjay Patel #include "gtest/gtest.h"
22b0f98d34SSanjay Patel 
23b0f98d34SSanjay Patel using namespace llvm;
24b0f98d34SSanjay Patel 
25b0f98d34SSanjay Patel namespace {
26b0f98d34SSanjay Patel 
27b0f98d34SSanjay Patel class VectorUtilsTest : public testing::Test {
28b0f98d34SSanjay Patel protected:
parseAssembly(const char * Assembly)29b0f98d34SSanjay Patel   void parseAssembly(const char *Assembly) {
30b0f98d34SSanjay Patel     SMDiagnostic Error;
31b0f98d34SSanjay Patel     M = parseAssemblyString(Assembly, Error, Context);
32b0f98d34SSanjay Patel 
33b0f98d34SSanjay Patel     std::string errMsg;
34b0f98d34SSanjay Patel     raw_string_ostream os(errMsg);
35b0f98d34SSanjay Patel     Error.print("", os);
36b0f98d34SSanjay Patel 
37b0f98d34SSanjay Patel     // A failure here means that the test itself is buggy.
38b0f98d34SSanjay Patel     if (!M)
39*2e5daac2SSimon Pilgrim       report_fatal_error(Twine(os.str()));
40b0f98d34SSanjay Patel 
41b0f98d34SSanjay Patel     Function *F = M->getFunction("test");
42b0f98d34SSanjay Patel     if (F == nullptr)
43b0f98d34SSanjay Patel       report_fatal_error("Test must have a function named @test");
44b0f98d34SSanjay Patel 
45b0f98d34SSanjay Patel     A = nullptr;
46b0f98d34SSanjay Patel     for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) {
47b0f98d34SSanjay Patel       if (I->hasName()) {
48b0f98d34SSanjay Patel         if (I->getName() == "A")
49b0f98d34SSanjay Patel           A = &*I;
50b0f98d34SSanjay Patel       }
51b0f98d34SSanjay Patel     }
52b0f98d34SSanjay Patel     if (A == nullptr)
53b0f98d34SSanjay Patel       report_fatal_error("@test must have an instruction %A");
54b0f98d34SSanjay Patel   }
55b0f98d34SSanjay Patel 
56b0f98d34SSanjay Patel   LLVMContext Context;
57b0f98d34SSanjay Patel   std::unique_ptr<Module> M;
58b0f98d34SSanjay Patel   Instruction *A;
59b0f98d34SSanjay Patel };
60b0f98d34SSanjay Patel 
6140e3bdf8SSanjay Patel struct BasicTest : public testing::Test {
6240e3bdf8SSanjay Patel   LLVMContext Ctx;
6340e3bdf8SSanjay Patel   std::unique_ptr<Module> M;
6440e3bdf8SSanjay Patel   Function *F;
6540e3bdf8SSanjay Patel   BasicBlock *BB;
6640e3bdf8SSanjay Patel   IRBuilder<NoFolder> IRB;
6740e3bdf8SSanjay Patel 
BasicTest__anon53dca8130111::BasicTest6840e3bdf8SSanjay Patel   BasicTest()
6940e3bdf8SSanjay Patel       : M(new Module("VectorUtils", Ctx)),
7040e3bdf8SSanjay Patel         F(Function::Create(
7140e3bdf8SSanjay Patel             FunctionType::get(Type::getVoidTy(Ctx), /* IsVarArg */ false),
7240e3bdf8SSanjay Patel             Function::ExternalLinkage, "f", M.get())),
7340e3bdf8SSanjay Patel         BB(BasicBlock::Create(Ctx, "entry", F)), IRB(BB) {}
7440e3bdf8SSanjay Patel };
7540e3bdf8SSanjay Patel 
7640e3bdf8SSanjay Patel 
77b0f98d34SSanjay Patel } // namespace
78b0f98d34SSanjay Patel 
TEST_F(BasicTest,isSplat)7940e3bdf8SSanjay Patel TEST_F(BasicTest, isSplat) {
80eb81c85aSChristopher Tetreault   Value *UndefVec = UndefValue::get(FixedVectorType::get(IRB.getInt8Ty(), 4));
8140e3bdf8SSanjay Patel   EXPECT_TRUE(isSplatValue(UndefVec));
8240e3bdf8SSanjay Patel 
8340e3bdf8SSanjay Patel   Constant *UndefScalar = UndefValue::get(IRB.getInt8Ty());
8440e3bdf8SSanjay Patel   EXPECT_FALSE(isSplatValue(UndefScalar));
8540e3bdf8SSanjay Patel 
8640e3bdf8SSanjay Patel   Constant *ScalarC = IRB.getInt8(42);
8740e3bdf8SSanjay Patel   EXPECT_FALSE(isSplatValue(ScalarC));
8840e3bdf8SSanjay Patel 
8940e3bdf8SSanjay Patel   Constant *OtherScalarC = IRB.getInt8(-42);
9040e3bdf8SSanjay Patel   Constant *NonSplatC = ConstantVector::get({ScalarC, OtherScalarC});
9140e3bdf8SSanjay Patel   EXPECT_FALSE(isSplatValue(NonSplatC));
9240e3bdf8SSanjay Patel 
9340e3bdf8SSanjay Patel   Value *SplatC = IRB.CreateVectorSplat(5, ScalarC);
9440e3bdf8SSanjay Patel   EXPECT_TRUE(isSplatValue(SplatC));
9540e3bdf8SSanjay Patel 
96a407ec9bSMehdi Amini   Value *SplatC_SVE =
97a407ec9bSMehdi Amini       IRB.CreateVectorSplat(ElementCount::getScalable(5), ScalarC);
98e2022367SSimon Pilgrim   EXPECT_TRUE(isSplatValue(SplatC_SVE));
99e2022367SSimon Pilgrim 
10040e3bdf8SSanjay Patel   // FIXME: Constant splat analysis does not allow undef elements.
10140e3bdf8SSanjay Patel   Constant *SplatWithUndefC = ConstantVector::get({ScalarC, UndefScalar});
10240e3bdf8SSanjay Patel   EXPECT_FALSE(isSplatValue(SplatWithUndefC));
10340e3bdf8SSanjay Patel }
10440e3bdf8SSanjay Patel 
TEST_F(BasicTest,narrowShuffleMaskElts)1051318ddbcSSanjay Patel TEST_F(BasicTest, narrowShuffleMaskElts) {
1060eeee83dSSanjay Patel   SmallVector<int, 16> ScaledMask;
1071318ddbcSSanjay Patel   narrowShuffleMaskElts(1, {3,2,0,-2}, ScaledMask);
108f92563f9SCraig Topper   EXPECT_EQ(makeArrayRef(ScaledMask), makeArrayRef({3,2,0,-2}));
1091318ddbcSSanjay Patel   narrowShuffleMaskElts(4, {3,2,0,-1}, ScaledMask);
110f92563f9SCraig Topper   EXPECT_EQ(makeArrayRef(ScaledMask), makeArrayRef({12,13,14,15,8,9,10,11,0,1,2,3,-1,-1,-1,-1}));
1110eeee83dSSanjay Patel }
1120eeee83dSSanjay Patel 
TEST_F(BasicTest,widenShuffleMaskElts)113c23cbefdSSanjay Patel TEST_F(BasicTest, widenShuffleMaskElts) {
114c23cbefdSSanjay Patel   SmallVector<int, 16> WideMask;
115c23cbefdSSanjay Patel   SmallVector<int, 16> NarrowMask;
116c23cbefdSSanjay Patel 
117c23cbefdSSanjay Patel   // scale == 1 is a copy
118c23cbefdSSanjay Patel   EXPECT_TRUE(widenShuffleMaskElts(1, {3,2,0,-1}, WideMask));
119c23cbefdSSanjay Patel   EXPECT_EQ(makeArrayRef(WideMask), makeArrayRef({3,2,0,-1}));
120c23cbefdSSanjay Patel 
121c23cbefdSSanjay Patel   // back to original mask
122c23cbefdSSanjay Patel   narrowShuffleMaskElts(1, makeArrayRef(WideMask), NarrowMask);
123c23cbefdSSanjay Patel   EXPECT_EQ(makeArrayRef(NarrowMask), makeArrayRef({3,2,0,-1}));
124c23cbefdSSanjay Patel 
125c23cbefdSSanjay Patel   // can't widen non-consecutive 3/2
126c23cbefdSSanjay Patel   EXPECT_FALSE(widenShuffleMaskElts(2, {3,2,0,-1}, WideMask));
127c23cbefdSSanjay Patel 
128c23cbefdSSanjay Patel   // can't widen if not evenly divisible
129c23cbefdSSanjay Patel   EXPECT_FALSE(widenShuffleMaskElts(2, {0,1,2}, WideMask));
130c23cbefdSSanjay Patel 
131c23cbefdSSanjay Patel   // can always widen identity to single element
132c23cbefdSSanjay Patel   EXPECT_TRUE(widenShuffleMaskElts(3, {0,1,2}, WideMask));
133c23cbefdSSanjay Patel   EXPECT_EQ(makeArrayRef(WideMask), makeArrayRef({0}));
134c23cbefdSSanjay Patel 
135c23cbefdSSanjay Patel   // back to original mask
136c23cbefdSSanjay Patel   narrowShuffleMaskElts(3, makeArrayRef(WideMask), NarrowMask);
137c23cbefdSSanjay Patel   EXPECT_EQ(makeArrayRef(NarrowMask), makeArrayRef({0,1,2}));
138c23cbefdSSanjay Patel 
139c23cbefdSSanjay Patel   // groups of 4 must be consecutive/undef
140c23cbefdSSanjay Patel   EXPECT_TRUE(widenShuffleMaskElts(4, {12,13,14,15,8,9,10,11,0,1,2,3,-1,-1,-1,-1}, WideMask));
141c23cbefdSSanjay Patel   EXPECT_EQ(makeArrayRef(WideMask), makeArrayRef({3,2,0,-1}));
142c23cbefdSSanjay Patel 
143c23cbefdSSanjay Patel   // back to original mask
144c23cbefdSSanjay Patel   narrowShuffleMaskElts(4, makeArrayRef(WideMask), NarrowMask);
145c23cbefdSSanjay Patel   EXPECT_EQ(makeArrayRef(NarrowMask), makeArrayRef({12,13,14,15,8,9,10,11,0,1,2,3,-1,-1,-1,-1}));
146c23cbefdSSanjay Patel 
147c23cbefdSSanjay Patel   // groups of 2 must be consecutive/undef
148c23cbefdSSanjay Patel   EXPECT_FALSE(widenShuffleMaskElts(2, {12,12,14,15,8,9,10,11,0,1,2,3,-1,-1,-1,-1}, WideMask));
149c23cbefdSSanjay Patel 
150c23cbefdSSanjay Patel   // groups of 3 must be consecutive/undef
151c23cbefdSSanjay Patel   EXPECT_TRUE(widenShuffleMaskElts(3, {6,7,8,0,1,2,-1,-1,-1}, WideMask));
152c23cbefdSSanjay Patel   EXPECT_EQ(makeArrayRef(WideMask), makeArrayRef({2,0,-1}));
153c23cbefdSSanjay Patel 
154c23cbefdSSanjay Patel   // back to original mask
155c23cbefdSSanjay Patel   narrowShuffleMaskElts(3, makeArrayRef(WideMask), NarrowMask);
156c23cbefdSSanjay Patel   EXPECT_EQ(makeArrayRef(NarrowMask), makeArrayRef({6,7,8,0,1,2,-1,-1,-1}));
157c23cbefdSSanjay Patel 
158c23cbefdSSanjay Patel   // groups of 3 must be consecutive/undef (partial undefs are not ok)
159c23cbefdSSanjay Patel   EXPECT_FALSE(widenShuffleMaskElts(3, {-1,7,8,0,-1,2,-1,-1,-1}, WideMask));
160c23cbefdSSanjay Patel 
161c23cbefdSSanjay Patel   // negative indexes must match across a wide element
162c23cbefdSSanjay Patel   EXPECT_FALSE(widenShuffleMaskElts(2, {-1,-2,-1,-1}, WideMask));
163c23cbefdSSanjay Patel 
164c23cbefdSSanjay Patel   // negative indexes must match across a wide element
165c23cbefdSSanjay Patel   EXPECT_TRUE(widenShuffleMaskElts(2, {-2,-2,-3,-3}, WideMask));
166c23cbefdSSanjay Patel   EXPECT_EQ(makeArrayRef(WideMask), makeArrayRef({-2,-3}));
167c23cbefdSSanjay Patel }
168c23cbefdSSanjay Patel 
TEST_F(BasicTest,getSplatIndex)169686a038eSSanjay Patel TEST_F(BasicTest, getSplatIndex) {
170686a038eSSanjay Patel   EXPECT_EQ(getSplatIndex({0,0,0}), 0);
171686a038eSSanjay Patel   EXPECT_EQ(getSplatIndex({1,0,0}), -1);     // no splat
172686a038eSSanjay Patel   EXPECT_EQ(getSplatIndex({0,1,1}), -1);     // no splat
173686a038eSSanjay Patel   EXPECT_EQ(getSplatIndex({42,42,42}), 42);  // array size is independent of splat index
174686a038eSSanjay Patel   EXPECT_EQ(getSplatIndex({42,42,-1}), 42);  // ignore negative
175686a038eSSanjay Patel   EXPECT_EQ(getSplatIndex({-1,42,-1}), 42);  // ignore negatives
176686a038eSSanjay Patel   EXPECT_EQ(getSplatIndex({-4,42,-42}), 42); // ignore all negatives
177686a038eSSanjay Patel   EXPECT_EQ(getSplatIndex({-4,-1,-42}), -1); // all negative values map to -1
178686a038eSSanjay Patel }
179686a038eSSanjay Patel 
TEST_F(VectorUtilsTest,isSplatValue_00)18040e3bdf8SSanjay Patel TEST_F(VectorUtilsTest, isSplatValue_00) {
18140e3bdf8SSanjay Patel   parseAssembly(
18240e3bdf8SSanjay Patel       "define <2 x i8> @test(<2 x i8> %x) {\n"
18340e3bdf8SSanjay Patel       "  %A = shufflevector <2 x i8> %x, <2 x i8> undef, <2 x i32> zeroinitializer\n"
18440e3bdf8SSanjay Patel       "  ret <2 x i8> %A\n"
18540e3bdf8SSanjay Patel       "}\n");
18640e3bdf8SSanjay Patel   EXPECT_TRUE(isSplatValue(A));
18740e3bdf8SSanjay Patel }
18840e3bdf8SSanjay Patel 
TEST_F(VectorUtilsTest,isSplatValue_00_index0)1899b9e2da0SSanjay Patel TEST_F(VectorUtilsTest, isSplatValue_00_index0) {
1909b9e2da0SSanjay Patel   parseAssembly(
1919b9e2da0SSanjay Patel       "define <2 x i8> @test(<2 x i8> %x) {\n"
1929b9e2da0SSanjay Patel       "  %A = shufflevector <2 x i8> %x, <2 x i8> undef, <2 x i32> zeroinitializer\n"
1939b9e2da0SSanjay Patel       "  ret <2 x i8> %A\n"
1949b9e2da0SSanjay Patel       "}\n");
1959b9e2da0SSanjay Patel   EXPECT_TRUE(isSplatValue(A, 0));
1969b9e2da0SSanjay Patel }
1979b9e2da0SSanjay Patel 
TEST_F(VectorUtilsTest,isSplatValue_00_index1)1989b9e2da0SSanjay Patel TEST_F(VectorUtilsTest, isSplatValue_00_index1) {
1999b9e2da0SSanjay Patel   parseAssembly(
2009b9e2da0SSanjay Patel       "define <2 x i8> @test(<2 x i8> %x) {\n"
2019b9e2da0SSanjay Patel       "  %A = shufflevector <2 x i8> %x, <2 x i8> undef, <2 x i32> zeroinitializer\n"
2029b9e2da0SSanjay Patel       "  ret <2 x i8> %A\n"
2039b9e2da0SSanjay Patel       "}\n");
2049b9e2da0SSanjay Patel   EXPECT_FALSE(isSplatValue(A, 1));
2059b9e2da0SSanjay Patel }
2069b9e2da0SSanjay Patel 
TEST_F(VectorUtilsTest,isSplatValue_11)20740e3bdf8SSanjay Patel TEST_F(VectorUtilsTest, isSplatValue_11) {
20840e3bdf8SSanjay Patel   parseAssembly(
20940e3bdf8SSanjay Patel       "define <2 x i8> @test(<2 x i8> %x) {\n"
21040e3bdf8SSanjay Patel       "  %A = shufflevector <2 x i8> %x, <2 x i8> undef, <2 x i32> <i32 1, i32 1>\n"
21140e3bdf8SSanjay Patel       "  ret <2 x i8> %A\n"
21240e3bdf8SSanjay Patel       "}\n");
21340e3bdf8SSanjay Patel   EXPECT_TRUE(isSplatValue(A));
21440e3bdf8SSanjay Patel }
21540e3bdf8SSanjay Patel 
TEST_F(VectorUtilsTest,isSplatValue_11_index0)2169b9e2da0SSanjay Patel TEST_F(VectorUtilsTest, isSplatValue_11_index0) {
2179b9e2da0SSanjay Patel   parseAssembly(
2189b9e2da0SSanjay Patel       "define <2 x i8> @test(<2 x i8> %x) {\n"
2199b9e2da0SSanjay Patel       "  %A = shufflevector <2 x i8> %x, <2 x i8> undef, <2 x i32> <i32 1, i32 1>\n"
2209b9e2da0SSanjay Patel       "  ret <2 x i8> %A\n"
2219b9e2da0SSanjay Patel       "}\n");
2229b9e2da0SSanjay Patel   EXPECT_FALSE(isSplatValue(A, 0));
2239b9e2da0SSanjay Patel }
2249b9e2da0SSanjay Patel 
TEST_F(VectorUtilsTest,isSplatValue_11_index1)2259b9e2da0SSanjay Patel TEST_F(VectorUtilsTest, isSplatValue_11_index1) {
2269b9e2da0SSanjay Patel   parseAssembly(
2279b9e2da0SSanjay Patel       "define <2 x i8> @test(<2 x i8> %x) {\n"
2289b9e2da0SSanjay Patel       "  %A = shufflevector <2 x i8> %x, <2 x i8> undef, <2 x i32> <i32 1, i32 1>\n"
2299b9e2da0SSanjay Patel       "  ret <2 x i8> %A\n"
2309b9e2da0SSanjay Patel       "}\n");
2319b9e2da0SSanjay Patel   EXPECT_TRUE(isSplatValue(A, 1));
2329b9e2da0SSanjay Patel }
2339b9e2da0SSanjay Patel 
TEST_F(VectorUtilsTest,isSplatValue_01)23440e3bdf8SSanjay Patel TEST_F(VectorUtilsTest, isSplatValue_01) {
23540e3bdf8SSanjay Patel   parseAssembly(
23640e3bdf8SSanjay Patel       "define <2 x i8> @test(<2 x i8> %x) {\n"
23740e3bdf8SSanjay Patel       "  %A = shufflevector <2 x i8> %x, <2 x i8> undef, <2 x i32> <i32 0, i32 1>\n"
23840e3bdf8SSanjay Patel       "  ret <2 x i8> %A\n"
23940e3bdf8SSanjay Patel       "}\n");
24040e3bdf8SSanjay Patel   EXPECT_FALSE(isSplatValue(A));
24140e3bdf8SSanjay Patel }
24240e3bdf8SSanjay Patel 
TEST_F(VectorUtilsTest,isSplatValue_01_index0)2439b9e2da0SSanjay Patel TEST_F(VectorUtilsTest, isSplatValue_01_index0) {
2449b9e2da0SSanjay Patel   parseAssembly(
2459b9e2da0SSanjay Patel       "define <2 x i8> @test(<2 x i8> %x) {\n"
2469b9e2da0SSanjay Patel       "  %A = shufflevector <2 x i8> %x, <2 x i8> undef, <2 x i32> <i32 0, i32 1>\n"
2479b9e2da0SSanjay Patel       "  ret <2 x i8> %A\n"
2489b9e2da0SSanjay Patel       "}\n");
2499b9e2da0SSanjay Patel   EXPECT_FALSE(isSplatValue(A, 0));
2509b9e2da0SSanjay Patel }
2519b9e2da0SSanjay Patel 
TEST_F(VectorUtilsTest,isSplatValue_01_index1)2529b9e2da0SSanjay Patel TEST_F(VectorUtilsTest, isSplatValue_01_index1) {
2539b9e2da0SSanjay Patel   parseAssembly(
2549b9e2da0SSanjay Patel       "define <2 x i8> @test(<2 x i8> %x) {\n"
2559b9e2da0SSanjay Patel       "  %A = shufflevector <2 x i8> %x, <2 x i8> undef, <2 x i32> <i32 0, i32 1>\n"
2569b9e2da0SSanjay Patel       "  ret <2 x i8> %A\n"
2579b9e2da0SSanjay Patel       "}\n");
2589b9e2da0SSanjay Patel   EXPECT_FALSE(isSplatValue(A, 1));
2599b9e2da0SSanjay Patel }
2609b9e2da0SSanjay Patel 
2619b9e2da0SSanjay Patel // FIXME: Allow undef matching with Constant (mask) splat analysis.
26240e3bdf8SSanjay Patel 
TEST_F(VectorUtilsTest,isSplatValue_0u)26340e3bdf8SSanjay Patel TEST_F(VectorUtilsTest, isSplatValue_0u) {
26440e3bdf8SSanjay Patel   parseAssembly(
26540e3bdf8SSanjay Patel       "define <2 x i8> @test(<2 x i8> %x) {\n"
26640e3bdf8SSanjay Patel       "  %A = shufflevector <2 x i8> %x, <2 x i8> undef, <2 x i32> <i32 0, i32 undef>\n"
26740e3bdf8SSanjay Patel       "  ret <2 x i8> %A\n"
26840e3bdf8SSanjay Patel       "}\n");
26940e3bdf8SSanjay Patel   EXPECT_FALSE(isSplatValue(A));
27040e3bdf8SSanjay Patel }
27140e3bdf8SSanjay Patel 
2729b9e2da0SSanjay Patel // FIXME: Allow undef matching with Constant (mask) splat analysis.
2739b9e2da0SSanjay Patel 
TEST_F(VectorUtilsTest,isSplatValue_0u_index0)2749b9e2da0SSanjay Patel TEST_F(VectorUtilsTest, isSplatValue_0u_index0) {
2759b9e2da0SSanjay Patel   parseAssembly(
2769b9e2da0SSanjay Patel       "define <2 x i8> @test(<2 x i8> %x) {\n"
2779b9e2da0SSanjay Patel       "  %A = shufflevector <2 x i8> %x, <2 x i8> undef, <2 x i32> <i32 0, i32 undef>\n"
2789b9e2da0SSanjay Patel       "  ret <2 x i8> %A\n"
2799b9e2da0SSanjay Patel       "}\n");
2809b9e2da0SSanjay Patel   EXPECT_FALSE(isSplatValue(A, 0));
2819b9e2da0SSanjay Patel }
2829b9e2da0SSanjay Patel 
TEST_F(VectorUtilsTest,isSplatValue_0u_index1)2839b9e2da0SSanjay Patel TEST_F(VectorUtilsTest, isSplatValue_0u_index1) {
2849b9e2da0SSanjay Patel   parseAssembly(
2859b9e2da0SSanjay Patel       "define <2 x i8> @test(<2 x i8> %x) {\n"
2869b9e2da0SSanjay Patel       "  %A = shufflevector <2 x i8> %x, <2 x i8> undef, <2 x i32> <i32 0, i32 undef>\n"
2879b9e2da0SSanjay Patel       "  ret <2 x i8> %A\n"
2889b9e2da0SSanjay Patel       "}\n");
2899b9e2da0SSanjay Patel   EXPECT_FALSE(isSplatValue(A, 1));
2909b9e2da0SSanjay Patel }
2919b9e2da0SSanjay Patel 
TEST_F(VectorUtilsTest,isSplatValue_Binop)29240e3bdf8SSanjay Patel TEST_F(VectorUtilsTest, isSplatValue_Binop) {
29340e3bdf8SSanjay Patel   parseAssembly(
29440e3bdf8SSanjay Patel       "define <2 x i8> @test(<2 x i8> %x) {\n"
29540e3bdf8SSanjay Patel       "  %v0 = shufflevector <2 x i8> %x, <2 x i8> undef, <2 x i32> <i32 0, i32 0>\n"
29640e3bdf8SSanjay Patel       "  %v1 = shufflevector <2 x i8> %x, <2 x i8> undef, <2 x i32> <i32 1, i32 1>\n"
29740e3bdf8SSanjay Patel       "  %A = udiv <2 x i8> %v0, %v1\n"
29840e3bdf8SSanjay Patel       "  ret <2 x i8> %A\n"
29940e3bdf8SSanjay Patel       "}\n");
30040e3bdf8SSanjay Patel   EXPECT_TRUE(isSplatValue(A));
30140e3bdf8SSanjay Patel }
30240e3bdf8SSanjay Patel 
TEST_F(VectorUtilsTest,isSplatValue_Binop_index0)3039b9e2da0SSanjay Patel TEST_F(VectorUtilsTest, isSplatValue_Binop_index0) {
3049b9e2da0SSanjay Patel   parseAssembly(
3059b9e2da0SSanjay Patel       "define <2 x i8> @test(<2 x i8> %x) {\n"
3069b9e2da0SSanjay Patel       "  %v0 = shufflevector <2 x i8> %x, <2 x i8> undef, <2 x i32> <i32 0, i32 0>\n"
3079b9e2da0SSanjay Patel       "  %v1 = shufflevector <2 x i8> %x, <2 x i8> undef, <2 x i32> <i32 1, i32 1>\n"
3089b9e2da0SSanjay Patel       "  %A = udiv <2 x i8> %v0, %v1\n"
3099b9e2da0SSanjay Patel       "  ret <2 x i8> %A\n"
3109b9e2da0SSanjay Patel       "}\n");
3119b9e2da0SSanjay Patel   EXPECT_FALSE(isSplatValue(A, 0));
3129b9e2da0SSanjay Patel }
3139b9e2da0SSanjay Patel 
TEST_F(VectorUtilsTest,isSplatValue_Binop_index1)3149b9e2da0SSanjay Patel TEST_F(VectorUtilsTest, isSplatValue_Binop_index1) {
3159b9e2da0SSanjay Patel   parseAssembly(
3169b9e2da0SSanjay Patel       "define <2 x i8> @test(<2 x i8> %x) {\n"
3179b9e2da0SSanjay Patel       "  %v0 = shufflevector <2 x i8> %x, <2 x i8> undef, <2 x i32> <i32 0, i32 0>\n"
3189b9e2da0SSanjay Patel       "  %v1 = shufflevector <2 x i8> %x, <2 x i8> undef, <2 x i32> <i32 1, i32 1>\n"
3199b9e2da0SSanjay Patel       "  %A = udiv <2 x i8> %v0, %v1\n"
3209b9e2da0SSanjay Patel       "  ret <2 x i8> %A\n"
3219b9e2da0SSanjay Patel       "}\n");
3229b9e2da0SSanjay Patel   EXPECT_FALSE(isSplatValue(A, 1));
3239b9e2da0SSanjay Patel }
3249b9e2da0SSanjay Patel 
TEST_F(VectorUtilsTest,isSplatValue_Binop_ConstantOp0)32540e3bdf8SSanjay Patel TEST_F(VectorUtilsTest, isSplatValue_Binop_ConstantOp0) {
32640e3bdf8SSanjay Patel   parseAssembly(
32740e3bdf8SSanjay Patel       "define <2 x i8> @test(<2 x i8> %x) {\n"
32840e3bdf8SSanjay Patel       "  %v1 = shufflevector <2 x i8> %x, <2 x i8> undef, <2 x i32> <i32 1, i32 1>\n"
32940e3bdf8SSanjay Patel       "  %A = ashr <2 x i8> <i8 42, i8 42>, %v1\n"
33040e3bdf8SSanjay Patel       "  ret <2 x i8> %A\n"
33140e3bdf8SSanjay Patel       "}\n");
33240e3bdf8SSanjay Patel   EXPECT_TRUE(isSplatValue(A));
33340e3bdf8SSanjay Patel }
33440e3bdf8SSanjay Patel 
TEST_F(VectorUtilsTest,isSplatValue_Binop_ConstantOp0_index0)3359b9e2da0SSanjay Patel TEST_F(VectorUtilsTest, isSplatValue_Binop_ConstantOp0_index0) {
3369b9e2da0SSanjay Patel   parseAssembly(
3379b9e2da0SSanjay Patel       "define <2 x i8> @test(<2 x i8> %x) {\n"
3389b9e2da0SSanjay Patel       "  %v1 = shufflevector <2 x i8> %x, <2 x i8> undef, <2 x i32> <i32 1, i32 1>\n"
3399b9e2da0SSanjay Patel       "  %A = ashr <2 x i8> <i8 42, i8 42>, %v1\n"
3409b9e2da0SSanjay Patel       "  ret <2 x i8> %A\n"
3419b9e2da0SSanjay Patel       "}\n");
3429b9e2da0SSanjay Patel   EXPECT_FALSE(isSplatValue(A, 0));
3439b9e2da0SSanjay Patel }
3449b9e2da0SSanjay Patel 
TEST_F(VectorUtilsTest,isSplatValue_Binop_ConstantOp0_index1)3459b9e2da0SSanjay Patel TEST_F(VectorUtilsTest, isSplatValue_Binop_ConstantOp0_index1) {
3469b9e2da0SSanjay Patel   parseAssembly(
3479b9e2da0SSanjay Patel       "define <2 x i8> @test(<2 x i8> %x) {\n"
3489b9e2da0SSanjay Patel       "  %v1 = shufflevector <2 x i8> %x, <2 x i8> undef, <2 x i32> <i32 1, i32 1>\n"
3499b9e2da0SSanjay Patel       "  %A = ashr <2 x i8> <i8 42, i8 42>, %v1\n"
3509b9e2da0SSanjay Patel       "  ret <2 x i8> %A\n"
3519b9e2da0SSanjay Patel       "}\n");
3529b9e2da0SSanjay Patel   EXPECT_TRUE(isSplatValue(A, 1));
3539b9e2da0SSanjay Patel }
3549b9e2da0SSanjay Patel 
TEST_F(VectorUtilsTest,isSplatValue_Binop_Not_Op0)35540e3bdf8SSanjay Patel TEST_F(VectorUtilsTest, isSplatValue_Binop_Not_Op0) {
35640e3bdf8SSanjay Patel   parseAssembly(
35740e3bdf8SSanjay Patel       "define <2 x i8> @test(<2 x i8> %x) {\n"
35840e3bdf8SSanjay Patel       "  %v0 = shufflevector <2 x i8> %x, <2 x i8> undef, <2 x i32> <i32 1, i32 0>\n"
35940e3bdf8SSanjay Patel       "  %v1 = shufflevector <2 x i8> %x, <2 x i8> undef, <2 x i32> <i32 1, i32 1>\n"
36040e3bdf8SSanjay Patel       "  %A = add <2 x i8> %v0, %v1\n"
36140e3bdf8SSanjay Patel       "  ret <2 x i8> %A\n"
36240e3bdf8SSanjay Patel       "}\n");
36340e3bdf8SSanjay Patel   EXPECT_FALSE(isSplatValue(A));
36440e3bdf8SSanjay Patel }
36540e3bdf8SSanjay Patel 
TEST_F(VectorUtilsTest,isSplatValue_Binop_Not_Op1)36640e3bdf8SSanjay Patel TEST_F(VectorUtilsTest, isSplatValue_Binop_Not_Op1) {
36740e3bdf8SSanjay Patel   parseAssembly(
36840e3bdf8SSanjay Patel       "define <2 x i8> @test(<2 x i8> %x) {\n"
36940e3bdf8SSanjay Patel       "  %v0 = shufflevector <2 x i8> %x, <2 x i8> undef, <2 x i32> <i32 1, i32 1>\n"
37040e3bdf8SSanjay Patel       "  %v1 = shufflevector <2 x i8> %x, <2 x i8> undef, <2 x i32> <i32 0, i32 1>\n"
37140e3bdf8SSanjay Patel       "  %A = shl <2 x i8> %v0, %v1\n"
37240e3bdf8SSanjay Patel       "  ret <2 x i8> %A\n"
37340e3bdf8SSanjay Patel       "}\n");
37440e3bdf8SSanjay Patel   EXPECT_FALSE(isSplatValue(A));
37540e3bdf8SSanjay Patel }
37640e3bdf8SSanjay Patel 
TEST_F(VectorUtilsTest,isSplatValue_Select)37740e3bdf8SSanjay Patel TEST_F(VectorUtilsTest, isSplatValue_Select) {
37840e3bdf8SSanjay Patel   parseAssembly(
37940e3bdf8SSanjay Patel       "define <2 x i8> @test(<2 x i1> %x, <2 x i8> %y, <2 x i8> %z) {\n"
38040e3bdf8SSanjay Patel       "  %v0 = shufflevector <2 x i1> %x, <2 x i1> undef, <2 x i32> <i32 1, i32 1>\n"
38140e3bdf8SSanjay Patel       "  %v1 = shufflevector <2 x i8> %y, <2 x i8> undef, <2 x i32> <i32 0, i32 0>\n"
38240e3bdf8SSanjay Patel       "  %v2 = shufflevector <2 x i8> %z, <2 x i8> undef, <2 x i32> <i32 1, i32 1>\n"
38340e3bdf8SSanjay Patel       "  %A = select <2 x i1> %v0, <2 x i8> %v1, <2 x i8> %v2\n"
38440e3bdf8SSanjay Patel       "  ret <2 x i8> %A\n"
38540e3bdf8SSanjay Patel       "}\n");
38640e3bdf8SSanjay Patel   EXPECT_TRUE(isSplatValue(A));
38740e3bdf8SSanjay Patel }
38840e3bdf8SSanjay Patel 
TEST_F(VectorUtilsTest,isSplatValue_Select_ConstantOp)38940e3bdf8SSanjay Patel TEST_F(VectorUtilsTest, isSplatValue_Select_ConstantOp) {
39040e3bdf8SSanjay Patel   parseAssembly(
39140e3bdf8SSanjay Patel       "define <2 x i8> @test(<2 x i1> %x, <2 x i8> %y, <2 x i8> %z) {\n"
39240e3bdf8SSanjay Patel       "  %v0 = shufflevector <2 x i1> %x, <2 x i1> undef, <2 x i32> <i32 1, i32 1>\n"
39340e3bdf8SSanjay Patel       "  %v2 = shufflevector <2 x i8> %z, <2 x i8> undef, <2 x i32> <i32 1, i32 1>\n"
39440e3bdf8SSanjay Patel       "  %A = select <2 x i1> %v0, <2 x i8> <i8 42, i8 42>, <2 x i8> %v2\n"
39540e3bdf8SSanjay Patel       "  ret <2 x i8> %A\n"
39640e3bdf8SSanjay Patel       "}\n");
39740e3bdf8SSanjay Patel   EXPECT_TRUE(isSplatValue(A));
39840e3bdf8SSanjay Patel }
39940e3bdf8SSanjay Patel 
TEST_F(VectorUtilsTest,isSplatValue_Select_NotCond)40040e3bdf8SSanjay Patel TEST_F(VectorUtilsTest, isSplatValue_Select_NotCond) {
40140e3bdf8SSanjay Patel   parseAssembly(
40240e3bdf8SSanjay Patel       "define <2 x i8> @test(<2 x i1> %x, <2 x i8> %y, <2 x i8> %z) {\n"
40340e3bdf8SSanjay Patel       "  %v1 = shufflevector <2 x i8> %y, <2 x i8> undef, <2 x i32> <i32 0, i32 0>\n"
40440e3bdf8SSanjay Patel       "  %v2 = shufflevector <2 x i8> %z, <2 x i8> undef, <2 x i32> <i32 1, i32 1>\n"
40540e3bdf8SSanjay Patel       "  %A = select <2 x i1> %x, <2 x i8> %v1, <2 x i8> %v2\n"
40640e3bdf8SSanjay Patel       "  ret <2 x i8> %A\n"
40740e3bdf8SSanjay Patel       "}\n");
40840e3bdf8SSanjay Patel   EXPECT_FALSE(isSplatValue(A));
40940e3bdf8SSanjay Patel }
41040e3bdf8SSanjay Patel 
TEST_F(VectorUtilsTest,isSplatValue_Select_NotOp1)41140e3bdf8SSanjay Patel TEST_F(VectorUtilsTest, isSplatValue_Select_NotOp1) {
41240e3bdf8SSanjay Patel   parseAssembly(
41340e3bdf8SSanjay Patel       "define <2 x i8> @test(<2 x i1> %x, <2 x i8> %y, <2 x i8> %z) {\n"
41440e3bdf8SSanjay Patel       "  %v0 = shufflevector <2 x i1> %x, <2 x i1> undef, <2 x i32> <i32 1, i32 1>\n"
41540e3bdf8SSanjay Patel       "  %v2 = shufflevector <2 x i8> %z, <2 x i8> undef, <2 x i32> <i32 1, i32 1>\n"
41640e3bdf8SSanjay Patel       "  %A = select <2 x i1> %v0, <2 x i8> %y, <2 x i8> %v2\n"
41740e3bdf8SSanjay Patel       "  ret <2 x i8> %A\n"
41840e3bdf8SSanjay Patel       "}\n");
41940e3bdf8SSanjay Patel   EXPECT_FALSE(isSplatValue(A));
42040e3bdf8SSanjay Patel }
42140e3bdf8SSanjay Patel 
TEST_F(VectorUtilsTest,isSplatValue_Select_NotOp2)42240e3bdf8SSanjay Patel TEST_F(VectorUtilsTest, isSplatValue_Select_NotOp2) {
42340e3bdf8SSanjay Patel   parseAssembly(
42440e3bdf8SSanjay Patel       "define <2 x i8> @test(<2 x i1> %x, <2 x i8> %y, <2 x i8> %z) {\n"
42540e3bdf8SSanjay Patel       "  %v0 = shufflevector <2 x i1> %x, <2 x i1> undef, <2 x i32> <i32 1, i32 1>\n"
42640e3bdf8SSanjay Patel       "  %v1 = shufflevector <2 x i8> %y, <2 x i8> undef, <2 x i32> <i32 0, i32 0>\n"
42740e3bdf8SSanjay Patel       "  %A = select <2 x i1> %v0, <2 x i8> %v1, <2 x i8> %z\n"
42840e3bdf8SSanjay Patel       "  ret <2 x i8> %A\n"
42940e3bdf8SSanjay Patel       "}\n");
43040e3bdf8SSanjay Patel   EXPECT_FALSE(isSplatValue(A));
43140e3bdf8SSanjay Patel }
43240e3bdf8SSanjay Patel 
TEST_F(VectorUtilsTest,isSplatValue_SelectBinop)43340e3bdf8SSanjay Patel TEST_F(VectorUtilsTest, isSplatValue_SelectBinop) {
43440e3bdf8SSanjay Patel   parseAssembly(
43540e3bdf8SSanjay Patel       "define <2 x i8> @test(<2 x i1> %x, <2 x i8> %y, <2 x i8> %z) {\n"
43640e3bdf8SSanjay Patel       "  %v0 = shufflevector <2 x i1> %x, <2 x i1> undef, <2 x i32> <i32 1, i32 1>\n"
43740e3bdf8SSanjay Patel       "  %v1 = shufflevector <2 x i8> %y, <2 x i8> undef, <2 x i32> <i32 0, i32 0>\n"
43840e3bdf8SSanjay Patel       "  %v2 = shufflevector <2 x i8> %z, <2 x i8> undef, <2 x i32> <i32 1, i32 1>\n"
43940e3bdf8SSanjay Patel       "  %bo = xor <2 x i8> %v1, %v2\n"
44040e3bdf8SSanjay Patel       "  %A = select <2 x i1> %v0, <2 x i8> %bo, <2 x i8> %v2\n"
44140e3bdf8SSanjay Patel       "  ret <2 x i8> %A\n"
44240e3bdf8SSanjay Patel       "}\n");
44340e3bdf8SSanjay Patel   EXPECT_TRUE(isSplatValue(A));
44440e3bdf8SSanjay Patel }
44540e3bdf8SSanjay Patel 
TEST_F(VectorUtilsTest,getSplatValueElt0)446b0f98d34SSanjay Patel TEST_F(VectorUtilsTest, getSplatValueElt0) {
447b0f98d34SSanjay Patel   parseAssembly(
448b0f98d34SSanjay Patel       "define <2 x i8> @test(i8 %x) {\n"
449b0f98d34SSanjay Patel       "  %ins = insertelement <2 x i8> undef, i8 %x, i32 0\n"
450b0f98d34SSanjay Patel       "  %A = shufflevector <2 x i8> %ins, <2 x i8> undef, <2 x i32> zeroinitializer\n"
451b0f98d34SSanjay Patel       "  ret <2 x i8> %A\n"
452b0f98d34SSanjay Patel       "}\n");
453b0f98d34SSanjay Patel   EXPECT_EQ(getSplatValue(A)->getName(), "x");
454b0f98d34SSanjay Patel }
455b0f98d34SSanjay Patel 
TEST_F(VectorUtilsTest,getSplatValueEltMismatch)456b0f98d34SSanjay Patel TEST_F(VectorUtilsTest, getSplatValueEltMismatch) {
457b0f98d34SSanjay Patel   parseAssembly(
458b0f98d34SSanjay Patel       "define <2 x i8> @test(i8 %x) {\n"
459b0f98d34SSanjay Patel       "  %ins = insertelement <2 x i8> undef, i8 %x, i32 1\n"
460b0f98d34SSanjay Patel       "  %A = shufflevector <2 x i8> %ins, <2 x i8> undef, <2 x i32> zeroinitializer\n"
461b0f98d34SSanjay Patel       "  ret <2 x i8> %A\n"
462b0f98d34SSanjay Patel       "}\n");
463b0f98d34SSanjay Patel   EXPECT_EQ(getSplatValue(A), nullptr);
464b0f98d34SSanjay Patel }
465b0f98d34SSanjay Patel 
466b0f98d34SSanjay Patel // TODO: This is a splat, but we don't recognize it.
467b0f98d34SSanjay Patel 
TEST_F(VectorUtilsTest,getSplatValueElt1)468b0f98d34SSanjay Patel TEST_F(VectorUtilsTest, getSplatValueElt1) {
469b0f98d34SSanjay Patel   parseAssembly(
470b0f98d34SSanjay Patel       "define <2 x i8> @test(i8 %x) {\n"
471b0f98d34SSanjay Patel       "  %ins = insertelement <2 x i8> undef, i8 %x, i32 1\n"
472b0f98d34SSanjay Patel       "  %A = shufflevector <2 x i8> %ins, <2 x i8> undef, <2 x i32> <i32 1, i32 1>\n"
473b0f98d34SSanjay Patel       "  ret <2 x i8> %A\n"
474b0f98d34SSanjay Patel       "}\n");
475b0f98d34SSanjay Patel   EXPECT_EQ(getSplatValue(A), nullptr);
476b0f98d34SSanjay Patel }
477eac93757SFrancesco Petrogalli 
478eac93757SFrancesco Petrogalli ////////////////////////////////////////////////////////////////////////////////
479eac93757SFrancesco Petrogalli // VFShape API tests.
480eac93757SFrancesco Petrogalli ////////////////////////////////////////////////////////////////////////////////
481eac93757SFrancesco Petrogalli 
482eac93757SFrancesco Petrogalli class VFShapeAPITest : public testing::Test {
483eac93757SFrancesco Petrogalli protected:
SetUp()484eac93757SFrancesco Petrogalli   void SetUp() override {
485eac93757SFrancesco Petrogalli     M = parseAssemblyString(IR, Err, Ctx);
486eac93757SFrancesco Petrogalli     // Get the only call instruction in the block, which is the first
487eac93757SFrancesco Petrogalli     // instruction.
488eac93757SFrancesco Petrogalli     CI = dyn_cast<CallInst>(&*(instructions(M->getFunction("f")).begin()));
489eac93757SFrancesco Petrogalli   }
490eac93757SFrancesco Petrogalli 
491eac93757SFrancesco Petrogalli   const char *IR = "define i32 @f(i32 %a, i64 %b, double %c) {\n"
492eac93757SFrancesco Petrogalli                    " %1 = call i32 @g(i32 %a, i64 %b, double %c)\n"
493eac93757SFrancesco Petrogalli                    "  ret i32 %1\n"
494eac93757SFrancesco Petrogalli                    "}\n"
495eac93757SFrancesco Petrogalli                    "declare i32 @g(i32, i64, double)\n";
496eac93757SFrancesco Petrogalli   LLVMContext Ctx;
497eac93757SFrancesco Petrogalli   SMDiagnostic Err;
498eac93757SFrancesco Petrogalli   std::unique_ptr<Module> M;
499eac93757SFrancesco Petrogalli   CallInst *CI;
500eac93757SFrancesco Petrogalli   // Dummy shape with no parameters, overwritten by buildShape when invoked.
5018a8d01d5SPaul Walker   VFShape Shape = {/*VF*/ ElementCount::getFixed(2), /*Parameters*/ {}};
502eac93757SFrancesco Petrogalli   VFShape Expected;
503eac93757SFrancesco Petrogalli   SmallVector<VFParameter, 8> &ExpectedParams = Expected.Parameters;
504eac93757SFrancesco Petrogalli 
buildShape(ElementCount VF,bool HasGlobalPred)5058a8d01d5SPaul Walker   void buildShape(ElementCount VF, bool HasGlobalPred) {
5068a8d01d5SPaul Walker     Shape = VFShape::get(*CI, VF, HasGlobalPred);
507eac93757SFrancesco Petrogalli   }
508eac93757SFrancesco Petrogalli 
validParams(ArrayRef<VFParameter> Parameters)509eac93757SFrancesco Petrogalli   bool validParams(ArrayRef<VFParameter> Parameters) {
510eac93757SFrancesco Petrogalli     Shape.Parameters =
511eac93757SFrancesco Petrogalli         SmallVector<VFParameter, 8>(Parameters.begin(), Parameters.end());
512eac93757SFrancesco Petrogalli     return Shape.hasValidParameterList();
513eac93757SFrancesco Petrogalli   }
514eac93757SFrancesco Petrogalli };
515eac93757SFrancesco Petrogalli 
TEST_F(VFShapeAPITest,API_buildVFShape)516eac93757SFrancesco Petrogalli TEST_F(VFShapeAPITest, API_buildVFShape) {
5178a8d01d5SPaul Walker   buildShape(/*VF*/ ElementCount::getFixed(2), /*HasGlobalPred*/ false);
5188a8d01d5SPaul Walker   Expected = {/*VF*/ ElementCount::getFixed(2), /*Parameters*/ {
519eac93757SFrancesco Petrogalli                   {0, VFParamKind::Vector},
520eac93757SFrancesco Petrogalli                   {1, VFParamKind::Vector},
521eac93757SFrancesco Petrogalli                   {2, VFParamKind::Vector},
522eac93757SFrancesco Petrogalli               }};
523eac93757SFrancesco Petrogalli   EXPECT_EQ(Shape, Expected);
524eac93757SFrancesco Petrogalli 
5258a8d01d5SPaul Walker   buildShape(/*VF*/ ElementCount::getFixed(4), /*HasGlobalPred*/ true);
5268a8d01d5SPaul Walker   Expected = {/*VF*/ ElementCount::getFixed(4), /*Parameters*/ {
527eac93757SFrancesco Petrogalli                   {0, VFParamKind::Vector},
528eac93757SFrancesco Petrogalli                   {1, VFParamKind::Vector},
529eac93757SFrancesco Petrogalli                   {2, VFParamKind::Vector},
530eac93757SFrancesco Petrogalli                   {3, VFParamKind::GlobalPredicate},
531eac93757SFrancesco Petrogalli               }};
532eac93757SFrancesco Petrogalli   EXPECT_EQ(Shape, Expected);
533eac93757SFrancesco Petrogalli 
5348a8d01d5SPaul Walker   buildShape(/*VF*/ ElementCount::getScalable(16), /*HasGlobalPred*/ false);
5358a8d01d5SPaul Walker   Expected = {/*VF*/ ElementCount::getScalable(16), /*Parameters*/ {
536eac93757SFrancesco Petrogalli                   {0, VFParamKind::Vector},
537eac93757SFrancesco Petrogalli                   {1, VFParamKind::Vector},
538eac93757SFrancesco Petrogalli                   {2, VFParamKind::Vector},
539eac93757SFrancesco Petrogalli               }};
540eac93757SFrancesco Petrogalli   EXPECT_EQ(Shape, Expected);
541eac93757SFrancesco Petrogalli }
542eac93757SFrancesco Petrogalli 
TEST_F(VFShapeAPITest,API_getScalarShape)543c7878ad2SAnh Tuyen Tran TEST_F(VFShapeAPITest, API_getScalarShape) {
5448a8d01d5SPaul Walker   buildShape(/*VF*/ ElementCount::getFixed(1), /*HasGlobalPred*/ false);
545c7878ad2SAnh Tuyen Tran   EXPECT_EQ(VFShape::getScalarShape(*CI), Shape);
546c7878ad2SAnh Tuyen Tran }
547c7878ad2SAnh Tuyen Tran 
TEST_F(VFShapeAPITest,API_getVectorizedFunction)548c7878ad2SAnh Tuyen Tran TEST_F(VFShapeAPITest, API_getVectorizedFunction) {
549c7878ad2SAnh Tuyen Tran   VFShape ScalarShape = VFShape::getScalarShape(*CI);
550c7878ad2SAnh Tuyen Tran   EXPECT_EQ(VFDatabase(*CI).getVectorizedFunction(ScalarShape),
551c7878ad2SAnh Tuyen Tran             M->getFunction("g"));
552c7878ad2SAnh Tuyen Tran 
5538a8d01d5SPaul Walker   buildShape(/*VF*/ ElementCount::getScalable(1), /*HasGlobalPred*/ false);
554c7878ad2SAnh Tuyen Tran   EXPECT_EQ(VFDatabase(*CI).getVectorizedFunction(Shape), nullptr);
5558a8d01d5SPaul Walker   buildShape(/*VF*/ ElementCount::getFixed(1), /*HasGlobalPred*/ true);
556c7878ad2SAnh Tuyen Tran   EXPECT_EQ(VFDatabase(*CI).getVectorizedFunction(Shape), nullptr);
5578a8d01d5SPaul Walker   buildShape(/*VF*/ ElementCount::getScalable(1), /*HasGlobalPred*/ true);
558c7878ad2SAnh Tuyen Tran   EXPECT_EQ(VFDatabase(*CI).getVectorizedFunction(Shape), nullptr);
559c7878ad2SAnh Tuyen Tran }
560c7878ad2SAnh Tuyen Tran 
TEST_F(VFShapeAPITest,API_updateVFShape)561eac93757SFrancesco Petrogalli TEST_F(VFShapeAPITest, API_updateVFShape) {
562eac93757SFrancesco Petrogalli 
5638a8d01d5SPaul Walker   buildShape(/*VF*/ ElementCount::getFixed(2), /*HasGlobalPred*/ false);
564eac93757SFrancesco Petrogalli   Shape.updateParam({0 /*Pos*/, VFParamKind::OMP_Linear, 1, Align(4)});
5658a8d01d5SPaul Walker   Expected = {/*VF*/ ElementCount::getFixed(2), /*Parameters*/ {
566eac93757SFrancesco Petrogalli                   {0, VFParamKind::OMP_Linear, 1, Align(4)},
567eac93757SFrancesco Petrogalli                   {1, VFParamKind::Vector},
568eac93757SFrancesco Petrogalli                   {2, VFParamKind::Vector},
569eac93757SFrancesco Petrogalli               }};
570eac93757SFrancesco Petrogalli   EXPECT_EQ(Shape, Expected);
571eac93757SFrancesco Petrogalli 
572eac93757SFrancesco Petrogalli   // From this point on, we update only the parameters of the VFShape,
573eac93757SFrancesco Petrogalli   // so we update only the reference of the expected Parameters.
574eac93757SFrancesco Petrogalli   Shape.updateParam({1 /*Pos*/, VFParamKind::OMP_Uniform});
575eac93757SFrancesco Petrogalli   ExpectedParams = {
576eac93757SFrancesco Petrogalli       {0, VFParamKind::OMP_Linear, 1, Align(4)},
577eac93757SFrancesco Petrogalli       {1, VFParamKind::OMP_Uniform},
578eac93757SFrancesco Petrogalli       {2, VFParamKind::Vector},
579eac93757SFrancesco Petrogalli   };
580eac93757SFrancesco Petrogalli   EXPECT_EQ(Shape, Expected);
581eac93757SFrancesco Petrogalli 
582eac93757SFrancesco Petrogalli   Shape.updateParam({2 /*Pos*/, VFParamKind::OMP_LinearRefPos, 1});
583eac93757SFrancesco Petrogalli   ExpectedParams = {
584eac93757SFrancesco Petrogalli       {0, VFParamKind::OMP_Linear, 1, Align(4)},
585eac93757SFrancesco Petrogalli       {1, VFParamKind::OMP_Uniform},
586eac93757SFrancesco Petrogalli       {2, VFParamKind::OMP_LinearRefPos, 1},
587eac93757SFrancesco Petrogalli   };
588eac93757SFrancesco Petrogalli   EXPECT_EQ(Shape, Expected);
589eac93757SFrancesco Petrogalli }
590eac93757SFrancesco Petrogalli 
TEST_F(VFShapeAPITest,API_updateVFShape_GlobalPredicate)591eac93757SFrancesco Petrogalli TEST_F(VFShapeAPITest, API_updateVFShape_GlobalPredicate) {
592eac93757SFrancesco Petrogalli 
5938a8d01d5SPaul Walker   buildShape(/*VF*/ ElementCount::getScalable(2), /*HasGlobalPred*/ true);
594eac93757SFrancesco Petrogalli   Shape.updateParam({1 /*Pos*/, VFParamKind::OMP_Uniform});
5958a8d01d5SPaul Walker   Expected = {/*VF*/ ElementCount::getScalable(2),
596eac93757SFrancesco Petrogalli               /*Parameters*/ {{0, VFParamKind::Vector},
597eac93757SFrancesco Petrogalli                               {1, VFParamKind::OMP_Uniform},
598eac93757SFrancesco Petrogalli                               {2, VFParamKind::Vector},
599eac93757SFrancesco Petrogalli                               {3, VFParamKind::GlobalPredicate}}};
600eac93757SFrancesco Petrogalli   EXPECT_EQ(Shape, Expected);
601eac93757SFrancesco Petrogalli }
602eac93757SFrancesco Petrogalli 
TEST_F(VFShapeAPITest,Parameters_Valid)603eac93757SFrancesco Petrogalli TEST_F(VFShapeAPITest, Parameters_Valid) {
604eac93757SFrancesco Petrogalli   // ParamPos in order.
605eac93757SFrancesco Petrogalli   EXPECT_TRUE(validParams({{0, VFParamKind::Vector}}));
606eac93757SFrancesco Petrogalli   EXPECT_TRUE(
607eac93757SFrancesco Petrogalli       validParams({{0, VFParamKind::Vector}, {1, VFParamKind::Vector}}));
608eac93757SFrancesco Petrogalli   EXPECT_TRUE(validParams({{0, VFParamKind::Vector},
609eac93757SFrancesco Petrogalli                            {1, VFParamKind::Vector},
610eac93757SFrancesco Petrogalli                            {2, VFParamKind::Vector}}));
611eac93757SFrancesco Petrogalli 
612eac93757SFrancesco Petrogalli   // GlocalPredicate is unique.
613eac93757SFrancesco Petrogalli   EXPECT_TRUE(validParams({{0, VFParamKind::Vector},
614eac93757SFrancesco Petrogalli                            {1, VFParamKind::Vector},
615eac93757SFrancesco Petrogalli                            {2, VFParamKind::Vector},
616eac93757SFrancesco Petrogalli                            {3, VFParamKind::GlobalPredicate}}));
617eac93757SFrancesco Petrogalli 
618eac93757SFrancesco Petrogalli   EXPECT_TRUE(validParams({{0, VFParamKind::Vector},
619eac93757SFrancesco Petrogalli                            {1, VFParamKind::GlobalPredicate},
620eac93757SFrancesco Petrogalli                            {2, VFParamKind::Vector}}));
621eac93757SFrancesco Petrogalli }
622eac93757SFrancesco Petrogalli 
TEST_F(VFShapeAPITest,Parameters_ValidOpenMPLinear)623eac93757SFrancesco Petrogalli TEST_F(VFShapeAPITest, Parameters_ValidOpenMPLinear) {
624eac93757SFrancesco Petrogalli // Valid linear constant step (>0).
625eac93757SFrancesco Petrogalli #define __BUILD_PARAMETERS(Kind, Val)                                          \
626eac93757SFrancesco Petrogalli   {                                                                            \
627eac93757SFrancesco Petrogalli     { 0, Kind, Val }                                                           \
628eac93757SFrancesco Petrogalli   }
629eac93757SFrancesco Petrogalli   EXPECT_TRUE(validParams(__BUILD_PARAMETERS(VFParamKind::OMP_Linear, 1)));
630eac93757SFrancesco Petrogalli   EXPECT_TRUE(validParams(__BUILD_PARAMETERS(VFParamKind::OMP_LinearRef, 2)));
631eac93757SFrancesco Petrogalli   EXPECT_TRUE(validParams(__BUILD_PARAMETERS(VFParamKind::OMP_LinearVal, 4)));
632eac93757SFrancesco Petrogalli   EXPECT_TRUE(validParams(__BUILD_PARAMETERS(VFParamKind::OMP_LinearUVal, 33)));
633eac93757SFrancesco Petrogalli #undef __BUILD_PARAMETERS
634eac93757SFrancesco Petrogalli 
635eac93757SFrancesco Petrogalli // Valid linear runtime step (the step parameter is marked uniform).
636eac93757SFrancesco Petrogalli #define __BUILD_PARAMETERS(Kind)                                               \
637eac93757SFrancesco Petrogalli   {                                                                            \
638eac93757SFrancesco Petrogalli     {0, VFParamKind::OMP_Uniform}, {1, VFParamKind::Vector}, { 2, Kind, 0 }    \
639eac93757SFrancesco Petrogalli   }
640eac93757SFrancesco Petrogalli   EXPECT_TRUE(validParams(__BUILD_PARAMETERS(VFParamKind::OMP_LinearPos)));
641eac93757SFrancesco Petrogalli   EXPECT_TRUE(validParams(__BUILD_PARAMETERS(VFParamKind::OMP_LinearRefPos)));
642eac93757SFrancesco Petrogalli   EXPECT_TRUE(validParams(__BUILD_PARAMETERS(VFParamKind::OMP_LinearValPos)));
643eac93757SFrancesco Petrogalli   EXPECT_TRUE(validParams(__BUILD_PARAMETERS(VFParamKind::OMP_LinearUValPos)));
644eac93757SFrancesco Petrogalli #undef __BUILD_PARAMETERS
645eac93757SFrancesco Petrogalli }
646eac93757SFrancesco Petrogalli 
TEST_F(VFShapeAPITest,Parameters_Invalid)647eac93757SFrancesco Petrogalli TEST_F(VFShapeAPITest, Parameters_Invalid) {
6481de214faSFrancesco Petrogalli #ifndef NDEBUG
649d68904f9SJames Henderson   // Wrong order is checked by an assertion: make sure that the
650eac93757SFrancesco Petrogalli   // assertion is not removed.
651eac93757SFrancesco Petrogalli   EXPECT_DEATH(validParams({{1, VFParamKind::Vector}}),
652eac93757SFrancesco Petrogalli                "Broken parameter list.");
653eac93757SFrancesco Petrogalli   EXPECT_DEATH(
654eac93757SFrancesco Petrogalli       validParams({{1, VFParamKind::Vector}, {0, VFParamKind::Vector}}),
655eac93757SFrancesco Petrogalli       "Broken parameter list.");
6561de214faSFrancesco Petrogalli #endif
657eac93757SFrancesco Petrogalli 
658eac93757SFrancesco Petrogalli   // GlobalPredicate is not unique
659eac93757SFrancesco Petrogalli   EXPECT_FALSE(validParams({{0, VFParamKind::Vector},
660eac93757SFrancesco Petrogalli                             {1, VFParamKind::GlobalPredicate},
661eac93757SFrancesco Petrogalli                             {2, VFParamKind::GlobalPredicate}}));
662eac93757SFrancesco Petrogalli   EXPECT_FALSE(validParams({{0, VFParamKind::GlobalPredicate},
663eac93757SFrancesco Petrogalli                             {1, VFParamKind::Vector},
664eac93757SFrancesco Petrogalli                             {2, VFParamKind::GlobalPredicate}}));
665eac93757SFrancesco Petrogalli }
666eac93757SFrancesco Petrogalli 
TEST_F(VFShapeAPITest,Parameters_InvalidOpenMPLinear)667eac93757SFrancesco Petrogalli TEST_F(VFShapeAPITest, Parameters_InvalidOpenMPLinear) {
668eac93757SFrancesco Petrogalli // Compile time linear steps must be non-zero (compile time invariant).
669eac93757SFrancesco Petrogalli #define __BUILD_PARAMETERS(Kind)                                               \
670eac93757SFrancesco Petrogalli   {                                                                            \
671eac93757SFrancesco Petrogalli     { 0, Kind, 0 }                                                             \
672eac93757SFrancesco Petrogalli   }
673eac93757SFrancesco Petrogalli   EXPECT_FALSE(validParams(__BUILD_PARAMETERS(VFParamKind::OMP_Linear)));
674eac93757SFrancesco Petrogalli   EXPECT_FALSE(validParams(__BUILD_PARAMETERS(VFParamKind::OMP_LinearRef)));
675eac93757SFrancesco Petrogalli   EXPECT_FALSE(validParams(__BUILD_PARAMETERS(VFParamKind::OMP_LinearVal)));
676eac93757SFrancesco Petrogalli   EXPECT_FALSE(validParams(__BUILD_PARAMETERS(VFParamKind::OMP_LinearUVal)));
677eac93757SFrancesco Petrogalli #undef __BUILD_PARAMETERS
678eac93757SFrancesco Petrogalli 
679eac93757SFrancesco Petrogalli // The step of a runtime linear parameter must be marked
680eac93757SFrancesco Petrogalli // as uniform (runtime invariant).
681eac93757SFrancesco Petrogalli #define __BUILD_PARAMETERS(Kind)                                               \
682eac93757SFrancesco Petrogalli   {                                                                            \
683eac93757SFrancesco Petrogalli     {0, VFParamKind::OMP_Uniform}, {1, VFParamKind::Vector}, { 2, Kind, 1 }    \
684eac93757SFrancesco Petrogalli   }
685eac93757SFrancesco Petrogalli   EXPECT_FALSE(validParams(__BUILD_PARAMETERS(VFParamKind::OMP_LinearPos)));
686eac93757SFrancesco Petrogalli   EXPECT_FALSE(validParams(__BUILD_PARAMETERS(VFParamKind::OMP_LinearRefPos)));
687eac93757SFrancesco Petrogalli   EXPECT_FALSE(validParams(__BUILD_PARAMETERS(VFParamKind::OMP_LinearValPos)));
688eac93757SFrancesco Petrogalli   EXPECT_FALSE(validParams(__BUILD_PARAMETERS(VFParamKind::OMP_LinearUValPos)));
689eac93757SFrancesco Petrogalli #undef __BUILD_PARAMETERS
690eac93757SFrancesco Petrogalli 
691eac93757SFrancesco Petrogalli // The linear step parameter can't point at itself.
692eac93757SFrancesco Petrogalli #define __BUILD_PARAMETERS(Kind)                                               \
693eac93757SFrancesco Petrogalli   {                                                                            \
694eac93757SFrancesco Petrogalli     {0, VFParamKind::Vector}, {1, VFParamKind::Vector}, { 2, Kind, 2 }         \
695eac93757SFrancesco Petrogalli   }
696eac93757SFrancesco Petrogalli   EXPECT_FALSE(validParams(__BUILD_PARAMETERS(VFParamKind::OMP_LinearPos)));
697eac93757SFrancesco Petrogalli   EXPECT_FALSE(validParams(__BUILD_PARAMETERS(VFParamKind::OMP_LinearRefPos)));
698eac93757SFrancesco Petrogalli   EXPECT_FALSE(validParams(__BUILD_PARAMETERS(VFParamKind::OMP_LinearValPos)));
699eac93757SFrancesco Petrogalli   EXPECT_FALSE(validParams(__BUILD_PARAMETERS(VFParamKind::OMP_LinearUValPos)));
700eac93757SFrancesco Petrogalli #undef __BUILD_PARAMETERS
701eac93757SFrancesco Petrogalli 
702eac93757SFrancesco Petrogalli // Linear parameter (runtime) is out of range.
703eac93757SFrancesco Petrogalli #define __BUILD_PARAMETERS(Kind)                                               \
704eac93757SFrancesco Petrogalli   {                                                                            \
705eac93757SFrancesco Petrogalli     {0, VFParamKind::Vector}, {1, VFParamKind::Vector}, { 2, Kind, 3 }         \
706eac93757SFrancesco Petrogalli   }
707eac93757SFrancesco Petrogalli   EXPECT_FALSE(validParams(__BUILD_PARAMETERS(VFParamKind::OMP_LinearPos)));
708eac93757SFrancesco Petrogalli   EXPECT_FALSE(validParams(__BUILD_PARAMETERS(VFParamKind::OMP_LinearRefPos)));
709eac93757SFrancesco Petrogalli   EXPECT_FALSE(validParams(__BUILD_PARAMETERS(VFParamKind::OMP_LinearValPos)));
710eac93757SFrancesco Petrogalli   EXPECT_FALSE(validParams(__BUILD_PARAMETERS(VFParamKind::OMP_LinearUValPos)));
711eac93757SFrancesco Petrogalli #undef __BUILD_PARAMETERS
712eac93757SFrancesco Petrogalli }
713