[PATCH] D83615: [WebAssembly] Custom combine splat build_vectors into swizzles

Thomas Lively via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Fri Jul 10 19:49:21 PDT 2020


tlively created this revision.
tlively added reviewers: aheejin, dschuff.
Herald added subscribers: llvm-commits, sunfish, hiraditya, jgravelle-google, sbc100.
Herald added a project: LLVM.

Some splat build_vectors can be lowered to swizzles, but only if all
of their lanes but one are undefined. This patch adds a custom combine
to turn these build_vectors into swizzles before their undefined lanes
are combined away by the combine introduced in D83606 <https://reviews.llvm.org/D83606>.

Depends on D83606 <https://reviews.llvm.org/D83606>.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D83615

Files:
  llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
  llvm/test/CodeGen/WebAssembly/simd-build-vector.ll


Index: llvm/test/CodeGen/WebAssembly/simd-build-vector.ll
===================================================================
--- llvm/test/CodeGen/WebAssembly/simd-build-vector.ll
+++ llvm/test/CodeGen/WebAssembly/simd-build-vector.ll
@@ -93,14 +93,10 @@
   ret <8 x i16> %v7
 }
 
-;; TODO: This should be a swizzle, but will need a custom combine to
-;; preempt the combine that removes undef lanes from splat
-;; build_vectors, since swizzle lowering depends on those lanes being
-;; undef.
-
 ; CHECK-LABEL: swizzle_one_i8x16:
 ; CHECK-NEXT:  .functype       swizzle_one_i8x16 (v128, v128) -> (v128)
-; CHECK-NOT:  v8x16.swizzle
+; CHECK-NEXT:  v8x16.swizzle   $push[[L0:[0-9]+]]=, $0, $1
+; CHECK-NEXT:  return          $pop[[L0]]
 define <16 x i8> @swizzle_one_i8x16(<16 x i8> %src, <16 x i8> %mask) {
   %m0 = extractelement <16 x i8> %mask, i32 0
   %s0 = extractelement <16 x i8> %src, i8 %m0
Index: llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
===================================================================
--- llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
+++ llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
@@ -1736,6 +1736,48 @@
   return DAG.getBitcast(DstType, NewShuffle);
 }
 
+static SDValue combineSwizzleSplat(BuildVectorSDNode *N, SelectionDAG &DAG,
+                                   const BitVector &UndefElts) {
+  // This splat can only be lowered to a swizzle if all lanes but one are undef.
+  //
+  // We are looking for the following pattern:
+  //   (insert undef,
+  //     (extract Vec1,
+  //       (sext (extract Vec2, Index))
+  //     ),
+  //     Index
+  //   )
+  //
+  // To combine to: (swizzle vec1, vec2)
+  if (N->getValueType(0) != MVT::v16i8)
+    return SDValue();
+  if (UndefElts.count() != 15)
+    return SDValue();
+  unsigned Index1 = UndefElts.find_first_unset();
+  auto Extract1 = N->getOperand(Index1);
+  if (Extract1.getOpcode() != ISD::EXTRACT_VECTOR_ELT)
+    return SDValue();
+  auto Vec1 = Extract1.getOperand(0);
+  if (Vec1.getValueType() != MVT::v16i8)
+    return SDValue();
+  auto SExt = Extract1.getOperand(1);
+  if (SExt.getOpcode() != ISD::SIGN_EXTEND)
+    return SDValue();
+  auto Extract2 = SExt.getOperand(0);
+  if (Extract2.getOpcode() != ISD::EXTRACT_VECTOR_ELT)
+    return SDValue();
+  auto Vec2 = Extract2.getOperand(0);
+  if (Vec2.getValueType() != MVT::v16i8)
+    return SDValue();
+  if (Extract2.getOperand(1).getOpcode() != ISD::Constant)
+    return SDValue();
+  unsigned Index2 = Extract2.getConstantOperandVal(1);
+  if (Index1 != Index2)
+    return SDValue();
+
+  return DAG.getNode(WebAssemblyISD::SWIZZLE, SDLoc(N), MVT::v16i8, Vec1, Vec2);
+}
+
 static SDValue
 performBUILD_VECTORCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI) {
   auto &DAG = DCI.DAG;
@@ -1744,9 +1786,16 @@
   // Remove undef lanes from splats. They don't allow us to make any extra
   // optimizations and they can inhibit splat scalarization combines.
   BitVector UndefElts;
-  if (SDValue SplatVal = Build->getSplatValue(&UndefElts))
-    if (UndefElts.any())
+  if (SDValue SplatVal = Build->getSplatValue(&UndefElts)) {
+    if (UndefElts.any()) {
+      // If this BUILD_VECTOR can be implemented as a swizzle, perform that
+      // transformation now because once we remove the undef lanes we will not
+      // be able to recover the swizzle.
+      if (auto Swizzle = combineSwizzleSplat(Build, DAG, UndefElts))
+        return Swizzle;
       return DAG.getSplatBuildVector(N->getValueType(0), SDLoc(N), SplatVal);
+    }
+  }
 
   return SDValue();
 }


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D83615.277210.patch
Type: text/x-patch
Size: 3583 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20200711/e26c5302/attachment.bin>


More information about the llvm-commits mailing list