[llvm] r342653 - [IR] add shuffle query for vector concatenation

Sanjay Patel via llvm-commits llvm-commits at lists.llvm.org
Thu Sep 20 08:21:52 PDT 2018


Author: spatel
Date: Thu Sep 20 08:21:52 2018
New Revision: 342653

URL: http://llvm.org/viewvc/llvm-project?rev=342653&view=rev
Log:
[IR] add shuffle query for vector concatenation

This can be used for combining and in the vectorizers/cost models.

Modified:
    llvm/trunk/include/llvm/IR/Instructions.h
    llvm/trunk/lib/IR/Instructions.cpp
    llvm/trunk/unittests/IR/InstructionsTest.cpp

Modified: llvm/trunk/include/llvm/IR/Instructions.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/Instructions.h?rev=342653&r1=342652&r2=342653&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/Instructions.h (original)
+++ llvm/trunk/include/llvm/IR/Instructions.h Thu Sep 20 08:21:52 2018
@@ -2513,6 +2513,11 @@ public:
   /// source vector.
   bool isIdentityWithExtract() const;
 
+  /// Return true if this shuffle concatenates its 2 source vectors. This
+  /// returns false if either input is undefined. In that case, the shuffle is
+  /// is better classified as an identity with padding operation.
+  bool isConcat() const;
+
   /// Return true if this shuffle mask chooses elements from its source vectors
   /// without lane crossings. A shuffle using this mask would be
   /// equivalent to a vector select with a constant condition operand.

Modified: llvm/trunk/lib/IR/Instructions.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Instructions.cpp?rev=342653&r1=342652&r2=342653&view=diff
==============================================================================
--- llvm/trunk/lib/IR/Instructions.cpp (original)
+++ llvm/trunk/lib/IR/Instructions.cpp Thu Sep 20 08:21:52 2018
@@ -1801,6 +1801,23 @@ bool ShuffleVectorInst::isIdentityWithEx
   return isIdentityMaskImpl(getShuffleMask(), NumOpElts);
 }
 
+bool ShuffleVectorInst::isConcat() const {
+  // Vector concatenation is differentiated from identity with padding.
+  if (isa<UndefValue>(Op<0>()) || isa<UndefValue>(Op<1>()))
+    return false;
+
+  int NumOpElts = Op<0>()->getType()->getVectorNumElements();
+  int NumMaskElts = getType()->getVectorNumElements();
+  if (NumMaskElts != NumOpElts * 2)
+    return false;
+
+  // Use the mask length rather than the operands' vector lengths here. We
+  // already know that the shuffle returns a vector twice as long as the inputs,
+  // and neither of the inputs are undef vectors. If the mask picks consecutive
+  // elements from both inputs, then this is a concatenation of the inputs.
+  return isIdentityMaskImpl(getShuffleMask(), NumMaskElts);
+}
+
 //===----------------------------------------------------------------------===//
 //                             InsertValueInst Class
 //===----------------------------------------------------------------------===//

Modified: llvm/trunk/unittests/IR/InstructionsTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/IR/InstructionsTest.cpp?rev=342653&r1=342652&r2=342653&view=diff
==============================================================================
--- llvm/trunk/unittests/IR/InstructionsTest.cpp (original)
+++ llvm/trunk/unittests/IR/InstructionsTest.cpp Thu Sep 20 08:21:52 2018
@@ -848,6 +848,7 @@ TEST(InstructionsTest, ShuffleMaskQuerie
   EXPECT_TRUE(Id1->isIdentity());
   EXPECT_FALSE(Id1->isIdentityWithPadding());
   EXPECT_FALSE(Id1->isIdentityWithExtract());
+  EXPECT_FALSE(Id1->isConcat());
   delete Id1;
 
   // Result has less elements than operands.
@@ -856,6 +857,7 @@ TEST(InstructionsTest, ShuffleMaskQuerie
   EXPECT_FALSE(Id2->isIdentity());
   EXPECT_FALSE(Id2->isIdentityWithPadding());
   EXPECT_TRUE(Id2->isIdentityWithExtract());
+  EXPECT_FALSE(Id2->isConcat());
   delete Id2;
 
   // Result has less elements than operands; choose from Op1.
@@ -864,6 +866,7 @@ TEST(InstructionsTest, ShuffleMaskQuerie
   EXPECT_FALSE(Id3->isIdentity());
   EXPECT_FALSE(Id3->isIdentityWithPadding());
   EXPECT_TRUE(Id3->isIdentityWithExtract());
+  EXPECT_FALSE(Id3->isConcat());
   delete Id3;
 
   // Result has less elements than operands; choose from Op0 and Op1 is not identity.
@@ -872,6 +875,7 @@ TEST(InstructionsTest, ShuffleMaskQuerie
   EXPECT_FALSE(Id4->isIdentity());
   EXPECT_FALSE(Id4->isIdentityWithPadding());
   EXPECT_FALSE(Id4->isIdentityWithExtract());
+  EXPECT_FALSE(Id4->isConcat());
   delete Id4;
 
   // Result has more elements than operands, and extra elements are undef.
@@ -880,6 +884,7 @@ TEST(InstructionsTest, ShuffleMaskQuerie
   EXPECT_FALSE(Id5->isIdentity());
   EXPECT_TRUE(Id5->isIdentityWithPadding());
   EXPECT_FALSE(Id5->isIdentityWithExtract());
+  EXPECT_FALSE(Id5->isConcat());
   delete Id5;
 
   // Result has more elements than operands, and extra elements are undef; choose from Op1.
@@ -888,6 +893,7 @@ TEST(InstructionsTest, ShuffleMaskQuerie
   EXPECT_FALSE(Id6->isIdentity());
   EXPECT_TRUE(Id6->isIdentityWithPadding());
   EXPECT_FALSE(Id6->isIdentityWithExtract());
+  EXPECT_FALSE(Id6->isConcat());
   delete Id6;
   
   // Result has more elements than operands, but extra elements are not undef.
@@ -896,6 +902,7 @@ TEST(InstructionsTest, ShuffleMaskQuerie
   EXPECT_FALSE(Id7->isIdentity());
   EXPECT_FALSE(Id7->isIdentityWithPadding());
   EXPECT_FALSE(Id7->isIdentityWithExtract());
+  EXPECT_FALSE(Id7->isConcat());
   delete Id7;
   
   // Result has more elements than operands; choose from Op0 and Op1 is not identity.
@@ -904,7 +911,45 @@ TEST(InstructionsTest, ShuffleMaskQuerie
   EXPECT_FALSE(Id8->isIdentity());
   EXPECT_FALSE(Id8->isIdentityWithPadding());
   EXPECT_FALSE(Id8->isIdentityWithExtract());
+  EXPECT_FALSE(Id8->isConcat());
   delete Id8;
+
+  // Result has twice as many elements as operands; choose consecutively from Op0 and Op1 is concat.
+  ShuffleVectorInst *Id9 = new ShuffleVectorInst(V0, V1,
+                                                 ConstantVector::get({C0, CU, C2, C3, CU, CU, C6, C7}));
+  EXPECT_FALSE(Id9->isIdentity());
+  EXPECT_FALSE(Id9->isIdentityWithPadding());
+  EXPECT_FALSE(Id9->isIdentityWithExtract());
+  EXPECT_TRUE(Id9->isConcat());
+  delete Id9;
+
+  // Result has less than twice as many elements as operands, so not a concat.
+  ShuffleVectorInst *Id10 = new ShuffleVectorInst(V0, V1,
+                                                  ConstantVector::get({C0, CU, C2, C3, CU, CU, C6}));
+  EXPECT_FALSE(Id10->isIdentity());
+  EXPECT_FALSE(Id10->isIdentityWithPadding());
+  EXPECT_FALSE(Id10->isIdentityWithExtract());
+  EXPECT_FALSE(Id10->isConcat());
+  delete Id10;
+
+  // Result has more than twice as many elements as operands, so not a concat.
+  ShuffleVectorInst *Id11 = new ShuffleVectorInst(V0, V1,
+                                                  ConstantVector::get({C0, CU, C2, C3, CU, CU, C6, C7, CU}));
+  EXPECT_FALSE(Id11->isIdentity());
+  EXPECT_FALSE(Id11->isIdentityWithPadding());
+  EXPECT_FALSE(Id11->isIdentityWithExtract());
+  EXPECT_FALSE(Id11->isConcat());
+  delete Id11;
+
+  // If an input is undef, it's not a concat.
+  // TODO: IdentityWithPadding should be true here even though the high mask values are not undef.
+  ShuffleVectorInst *Id12 = new ShuffleVectorInst(V0, ConstantVector::get({CU, CU, CU, CU}),
+                                                  ConstantVector::get({C0, CU, C2, C3, CU, CU, C6, C7}));
+  EXPECT_FALSE(Id12->isIdentity());
+  EXPECT_FALSE(Id12->isIdentityWithPadding());
+  EXPECT_FALSE(Id12->isIdentityWithExtract());
+  EXPECT_FALSE(Id12->isConcat());
+  delete Id12;
 }
 
 TEST(InstructionsTest, SkipDebug) {




More information about the llvm-commits mailing list