summaryrefslogtreecommitdiffstats
path: root/llvm/unittests/Analysis
diff options
context:
space:
mode:
authorSanjay Patel <spatel@rotateright.com>2019-06-11 22:25:18 +0000
committerSanjay Patel <spatel@rotateright.com>2019-06-11 22:25:18 +0000
commit40e3bdf8764d4d6053305bd602832912da245cdf (patch)
treedf43473d4bde24babc7020232ac680b753a323b9 /llvm/unittests/Analysis
parent898d48117430eac158fb3b01741ac4a3c63b4a4e (diff)
downloadbcm5719-llvm-40e3bdf8764d4d6053305bd602832912da245cdf.tar.gz
bcm5719-llvm-40e3bdf8764d4d6053305bd602832912da245cdf.zip
[Analysis] add isSplatValue() for vectors in IR
We have the related getSplatValue() already in IR (see code just above the proposed addition). But sometimes we only need to know that the value is a splat rather than capture the splatted scalar value. Also, we have an isSplatValue() function already in SDAG. Motivation - recent bugs that would potentially benefit from improved splat analysis in IR: https://bugs.llvm.org/show_bug.cgi?id=37428 https://bugs.llvm.org/show_bug.cgi?id=42174 Differential Revision: https://reviews.llvm.org/D63138 llvm-svn: 363106
Diffstat (limited to 'llvm/unittests/Analysis')
-rw-r--r--llvm/unittests/Analysis/VectorUtilsTest.cpp190
1 files changed, 190 insertions, 0 deletions
diff --git a/llvm/unittests/Analysis/VectorUtilsTest.cpp b/llvm/unittests/Analysis/VectorUtilsTest.cpp
index 8ff6744bf78..a33fdb503bb 100644
--- a/llvm/unittests/Analysis/VectorUtilsTest.cpp
+++ b/llvm/unittests/Analysis/VectorUtilsTest.cpp
@@ -11,8 +11,10 @@
#include "llvm/AsmParser/Parser.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/InstIterator.h"
+#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
+#include "llvm/IR/NoFolder.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/KnownBits.h"
@@ -56,8 +58,196 @@ protected:
Instruction *A;
};
+struct BasicTest : public testing::Test {
+ LLVMContext Ctx;
+ std::unique_ptr<Module> M;
+ Function *F;
+ BasicBlock *BB;
+ IRBuilder<NoFolder> IRB;
+
+ BasicTest()
+ : M(new Module("VectorUtils", Ctx)),
+ F(Function::Create(
+ FunctionType::get(Type::getVoidTy(Ctx), /* IsVarArg */ false),
+ Function::ExternalLinkage, "f", M.get())),
+ BB(BasicBlock::Create(Ctx, "entry", F)), IRB(BB) {}
+};
+
+
} // namespace
+TEST_F(BasicTest, isSplat) {
+ Value *UndefVec = UndefValue::get(VectorType::get(IRB.getInt8Ty(), 4));
+ EXPECT_TRUE(isSplatValue(UndefVec));
+
+ Constant *UndefScalar = UndefValue::get(IRB.getInt8Ty());
+ EXPECT_FALSE(isSplatValue(UndefScalar));
+
+ Constant *ScalarC = IRB.getInt8(42);
+ EXPECT_FALSE(isSplatValue(ScalarC));
+
+ Constant *OtherScalarC = IRB.getInt8(-42);
+ Constant *NonSplatC = ConstantVector::get({ScalarC, OtherScalarC});
+ EXPECT_FALSE(isSplatValue(NonSplatC));
+
+ Value *SplatC = IRB.CreateVectorSplat(5, ScalarC);
+ EXPECT_TRUE(isSplatValue(SplatC));
+
+ // FIXME: Constant splat analysis does not allow undef elements.
+ Constant *SplatWithUndefC = ConstantVector::get({ScalarC, UndefScalar});
+ EXPECT_FALSE(isSplatValue(SplatWithUndefC));
+}
+
+TEST_F(VectorUtilsTest, isSplatValue_00) {
+ parseAssembly(
+ "define <2 x i8> @test(<2 x i8> %x) {\n"
+ " %A = shufflevector <2 x i8> %x, <2 x i8> undef, <2 x i32> zeroinitializer\n"
+ " ret <2 x i8> %A\n"
+ "}\n");
+ EXPECT_TRUE(isSplatValue(A));
+}
+
+TEST_F(VectorUtilsTest, isSplatValue_11) {
+ parseAssembly(
+ "define <2 x i8> @test(<2 x i8> %x) {\n"
+ " %A = shufflevector <2 x i8> %x, <2 x i8> undef, <2 x i32> <i32 1, i32 1>\n"
+ " ret <2 x i8> %A\n"
+ "}\n");
+ EXPECT_TRUE(isSplatValue(A));
+}
+
+TEST_F(VectorUtilsTest, isSplatValue_01) {
+ parseAssembly(
+ "define <2 x i8> @test(<2 x i8> %x) {\n"
+ " %A = shufflevector <2 x i8> %x, <2 x i8> undef, <2 x i32> <i32 0, i32 1>\n"
+ " ret <2 x i8> %A\n"
+ "}\n");
+ EXPECT_FALSE(isSplatValue(A));
+}
+
+// FIXME: Constant (mask) splat analysis does not allow undef elements.
+
+TEST_F(VectorUtilsTest, isSplatValue_0u) {
+ parseAssembly(
+ "define <2 x i8> @test(<2 x i8> %x) {\n"
+ " %A = shufflevector <2 x i8> %x, <2 x i8> undef, <2 x i32> <i32 0, i32 undef>\n"
+ " ret <2 x i8> %A\n"
+ "}\n");
+ EXPECT_FALSE(isSplatValue(A));
+}
+
+TEST_F(VectorUtilsTest, isSplatValue_Binop) {
+ parseAssembly(
+ "define <2 x i8> @test(<2 x i8> %x) {\n"
+ " %v0 = shufflevector <2 x i8> %x, <2 x i8> undef, <2 x i32> <i32 0, i32 0>\n"
+ " %v1 = shufflevector <2 x i8> %x, <2 x i8> undef, <2 x i32> <i32 1, i32 1>\n"
+ " %A = udiv <2 x i8> %v0, %v1\n"
+ " ret <2 x i8> %A\n"
+ "}\n");
+ EXPECT_TRUE(isSplatValue(A));
+}
+
+TEST_F(VectorUtilsTest, isSplatValue_Binop_ConstantOp0) {
+ parseAssembly(
+ "define <2 x i8> @test(<2 x i8> %x) {\n"
+ " %v1 = shufflevector <2 x i8> %x, <2 x i8> undef, <2 x i32> <i32 1, i32 1>\n"
+ " %A = ashr <2 x i8> <i8 42, i8 42>, %v1\n"
+ " ret <2 x i8> %A\n"
+ "}\n");
+ EXPECT_TRUE(isSplatValue(A));
+}
+
+TEST_F(VectorUtilsTest, isSplatValue_Binop_Not_Op0) {
+ parseAssembly(
+ "define <2 x i8> @test(<2 x i8> %x) {\n"
+ " %v0 = shufflevector <2 x i8> %x, <2 x i8> undef, <2 x i32> <i32 1, i32 0>\n"
+ " %v1 = shufflevector <2 x i8> %x, <2 x i8> undef, <2 x i32> <i32 1, i32 1>\n"
+ " %A = add <2 x i8> %v0, %v1\n"
+ " ret <2 x i8> %A\n"
+ "}\n");
+ EXPECT_FALSE(isSplatValue(A));
+}
+
+TEST_F(VectorUtilsTest, isSplatValue_Binop_Not_Op1) {
+ parseAssembly(
+ "define <2 x i8> @test(<2 x i8> %x) {\n"
+ " %v0 = shufflevector <2 x i8> %x, <2 x i8> undef, <2 x i32> <i32 1, i32 1>\n"
+ " %v1 = shufflevector <2 x i8> %x, <2 x i8> undef, <2 x i32> <i32 0, i32 1>\n"
+ " %A = shl <2 x i8> %v0, %v1\n"
+ " ret <2 x i8> %A\n"
+ "}\n");
+ EXPECT_FALSE(isSplatValue(A));
+}
+
+TEST_F(VectorUtilsTest, isSplatValue_Select) {
+ parseAssembly(
+ "define <2 x i8> @test(<2 x i1> %x, <2 x i8> %y, <2 x i8> %z) {\n"
+ " %v0 = shufflevector <2 x i1> %x, <2 x i1> undef, <2 x i32> <i32 1, i32 1>\n"
+ " %v1 = shufflevector <2 x i8> %y, <2 x i8> undef, <2 x i32> <i32 0, i32 0>\n"
+ " %v2 = shufflevector <2 x i8> %z, <2 x i8> undef, <2 x i32> <i32 1, i32 1>\n"
+ " %A = select <2 x i1> %v0, <2 x i8> %v1, <2 x i8> %v2\n"
+ " ret <2 x i8> %A\n"
+ "}\n");
+ EXPECT_TRUE(isSplatValue(A));
+}
+
+TEST_F(VectorUtilsTest, isSplatValue_Select_ConstantOp) {
+ parseAssembly(
+ "define <2 x i8> @test(<2 x i1> %x, <2 x i8> %y, <2 x i8> %z) {\n"
+ " %v0 = shufflevector <2 x i1> %x, <2 x i1> undef, <2 x i32> <i32 1, i32 1>\n"
+ " %v2 = shufflevector <2 x i8> %z, <2 x i8> undef, <2 x i32> <i32 1, i32 1>\n"
+ " %A = select <2 x i1> %v0, <2 x i8> <i8 42, i8 42>, <2 x i8> %v2\n"
+ " ret <2 x i8> %A\n"
+ "}\n");
+ EXPECT_TRUE(isSplatValue(A));
+}
+
+TEST_F(VectorUtilsTest, isSplatValue_Select_NotCond) {
+ parseAssembly(
+ "define <2 x i8> @test(<2 x i1> %x, <2 x i8> %y, <2 x i8> %z) {\n"
+ " %v1 = shufflevector <2 x i8> %y, <2 x i8> undef, <2 x i32> <i32 0, i32 0>\n"
+ " %v2 = shufflevector <2 x i8> %z, <2 x i8> undef, <2 x i32> <i32 1, i32 1>\n"
+ " %A = select <2 x i1> %x, <2 x i8> %v1, <2 x i8> %v2\n"
+ " ret <2 x i8> %A\n"
+ "}\n");
+ EXPECT_FALSE(isSplatValue(A));
+}
+
+TEST_F(VectorUtilsTest, isSplatValue_Select_NotOp1) {
+ parseAssembly(
+ "define <2 x i8> @test(<2 x i1> %x, <2 x i8> %y, <2 x i8> %z) {\n"
+ " %v0 = shufflevector <2 x i1> %x, <2 x i1> undef, <2 x i32> <i32 1, i32 1>\n"
+ " %v2 = shufflevector <2 x i8> %z, <2 x i8> undef, <2 x i32> <i32 1, i32 1>\n"
+ " %A = select <2 x i1> %v0, <2 x i8> %y, <2 x i8> %v2\n"
+ " ret <2 x i8> %A\n"
+ "}\n");
+ EXPECT_FALSE(isSplatValue(A));
+}
+
+TEST_F(VectorUtilsTest, isSplatValue_Select_NotOp2) {
+ parseAssembly(
+ "define <2 x i8> @test(<2 x i1> %x, <2 x i8> %y, <2 x i8> %z) {\n"
+ " %v0 = shufflevector <2 x i1> %x, <2 x i1> undef, <2 x i32> <i32 1, i32 1>\n"
+ " %v1 = shufflevector <2 x i8> %y, <2 x i8> undef, <2 x i32> <i32 0, i32 0>\n"
+ " %A = select <2 x i1> %v0, <2 x i8> %v1, <2 x i8> %z\n"
+ " ret <2 x i8> %A\n"
+ "}\n");
+ EXPECT_FALSE(isSplatValue(A));
+}
+
+TEST_F(VectorUtilsTest, isSplatValue_SelectBinop) {
+ parseAssembly(
+ "define <2 x i8> @test(<2 x i1> %x, <2 x i8> %y, <2 x i8> %z) {\n"
+ " %v0 = shufflevector <2 x i1> %x, <2 x i1> undef, <2 x i32> <i32 1, i32 1>\n"
+ " %v1 = shufflevector <2 x i8> %y, <2 x i8> undef, <2 x i32> <i32 0, i32 0>\n"
+ " %v2 = shufflevector <2 x i8> %z, <2 x i8> undef, <2 x i32> <i32 1, i32 1>\n"
+ " %bo = xor <2 x i8> %v1, %v2\n"
+ " %A = select <2 x i1> %v0, <2 x i8> %bo, <2 x i8> %v2\n"
+ " ret <2 x i8> %A\n"
+ "}\n");
+ EXPECT_TRUE(isSplatValue(A));
+}
+
TEST_F(VectorUtilsTest, getSplatValueElt0) {
parseAssembly(
"define <2 x i8> @test(i8 %x) {\n"
OpenPOWER on IntegriCloud