[llvm] [InstCombine][RISCV] Convert VPIntrinsics with splat operands to splats (PR #65706)

Michael Maitland via llvm-commits llvm-commits at lists.llvm.org
Thu Sep 7 20:50:51 PDT 2023


================
@@ -1399,6 +1399,110 @@ static Instruction *foldBitOrderCrossLogicOp(Value *V,
   return nullptr;
 }
 
+/// VP Intrinsics whose vector operands are both splat values may be simplified
+/// into the scalar version of the operation and the result is splatted. This
+/// can lead to scalarization down the line.
+Value *convertOpOfSplatsToSplatOfOp(VPIntrinsic *VPI,
+                                    InstCombiner::BuilderTy &Builder) {
+  Value *Op0 = VPI->getArgOperand(0);
+  Value *Op1 = VPI->getArgOperand(1);
+
+  if (!isSplatValue(Op0) || !isSplatValue(Op1))
+    return nullptr;
+
+  // For the binary VP intrinsics supported here, the result on disabled lanes
+  // is a poison value. For now, only do this simplification if all lanes
+  // are active.
+  // TODO: Relax the condition that all lanes are active by using insertelement
+  // on inactive lanes.
+  Value *Mask = VPI->getArgOperand(2);
+  if (!maskIsAllOneOrUndef(Mask))
+    return nullptr;
+
+  Value *EVL = VPI->getArgOperand(3);
+  auto SplatAndPoison = [&Builder, &Op0, &EVL](Value *V) {
+    ElementCount EC = cast<VectorType>(Op0->getType())->getElementCount();
+    return Builder.CreateVectorSplat(EC, V);
+    // FIXME: Do we need to Poison out all lanes past EVL since the semantics of
+    // all of these intrinsics are that non-active lanes are poison?
+  };
+  switch(VPI->getIntrinsicID()) {
+  case Intrinsic::vp_add:
+    return SplatAndPoison(
+      Builder.CreateAdd(Builder.CreateExtractElement(Op0, (uint64_t)0),
+      Builder.CreateExtractElement(Op1, (uint64_t)1)));
+  case Intrinsic::vp_sub:
+    return SplatAndPoison(
+      Builder.CreateSub(Builder.CreateExtractElement(Op0, (uint64_t)0),
+      Builder.CreateExtractElement(Op1, (uint64_t)1)));
+  case Intrinsic::vp_mul:
+    return SplatAndPoison(
+      Builder.CreateMul(Builder.CreateExtractElement(Op0, (uint64_t)0),
+      Builder.CreateExtractElement(Op1, (uint64_t)1)));
+  case Intrinsic::vp_sdiv:
+    return SplatAndPoison(
----------------
michaelmaitland wrote:

I've removed this conversion and left a TODO to improve it in the future. I will add this logic in this patch over the next few dats.

https://github.com/llvm/llvm-project/pull/65706


More information about the llvm-commits mailing list