[llvm] [InstCombine] Scalarize `(vec_ops (insert ?, X, Idx))` when only one element is demanded (PR #84645)

via llvm-commits llvm-commits at lists.llvm.org
Sat Mar 9 09:50:46 PST 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-transforms

Author: None (goldsteinn)

<details>
<summary>Changes</summary>

- **[InstCombine] Add tests for scalarizing of blended vector inserts; NFC**
- **[InstCombine] Scalarize `(vec_ops (insert ?**


---

Patch is 49.87 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/84645.diff


11 Files Affected:

- (modified) llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp (+123-29) 
- (modified) llvm/test/Transforms/InstCombine/insert-extract-shuffle-inseltpoison.ll (+1-2) 
- (modified) llvm/test/Transforms/InstCombine/insert-extract-shuffle.ll (+1-2) 
- (modified) llvm/test/Transforms/InstCombine/shufflevector-div-rem-inseltpoison.ll (+6-6) 
- (modified) llvm/test/Transforms/InstCombine/shufflevector-div-rem.ll (+6-6) 
- (added) llvm/test/Transforms/InstCombine/shufflevector-inselt.ll (+258) 
- (modified) llvm/test/Transforms/LoopVectorize/invariant-store-vectorization-2.ll (+4-4) 
- (modified) llvm/test/Transforms/SLPVectorizer/X86/alternate-calls-inseltpoison.ll (+12-15) 
- (modified) llvm/test/Transforms/SLPVectorizer/X86/alternate-calls.ll (+12-15) 
- (modified) llvm/test/Transforms/SLPVectorizer/X86/alternate-int-inseltpoison.ll (+6-8) 
- (modified) llvm/test/Transforms/SLPVectorizer/X86/hadd-inseltpoison.ll (+8-10) 


``````````diff
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp b/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp
index 3c4c0f35eb6d48..bf46359accaaa0 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp
@@ -2579,6 +2579,97 @@ static Instruction *foldIdentityExtractShuffle(ShuffleVectorInst &Shuf) {
   return new ShuffleVectorInst(X, Y, NewMask);
 }
 
+// Extract `(scalar_ops... x)` from `(vector_ops... (insert ?, x, C)`
+static Value *
+getScalarizationOfInsertElement(Value *V, int ReqIndexC,
+                                InstCombiner::BuilderTy &Builder) {
+  Value *X, *Base;
+  ConstantInt *IndexC;
+  // Found a select.
+  if (match(V, m_InsertElt(m_Value(Base), m_Value(X), m_ConstantInt(IndexC)))) {
+    // See if matches the index we need.
+    if (match(IndexC, m_SpecificInt(ReqIndexC)))
+      return X;
+    // Otherwise continue searching. This is necessary for finding both elements
+    // in the common pattern:
+    // V0 = (insert poison x, 0)
+    // V1 = (insert V0, y, 1)
+    return getScalarizationOfInsertElement(Base, ReqIndexC, Builder);
+  }
+
+  // We can search through a splat of a single element for an insert.
+  int SplatIndex;
+  if (match(V, m_Shuffle(m_Value(Base), m_Value(X),
+                         m_SplatOrUndefMask(SplatIndex))) &&
+      SplatIndex >= 0) {
+    if (auto *VType = dyn_cast<FixedVectorType>(V->getType())) {
+      // Chase whichever vector (Base/X) we are splatting from.
+      if (static_cast<unsigned>(SplatIndex) >= VType->getNumElements())
+          return getScalarizationOfInsertElement(
+              X, SplatIndex - VType->getNumElements(), Builder);
+      // New index we need to find is the index we are splatting from.
+      return getScalarizationOfInsertElement(Base, SplatIndex, Builder);
+    }
+    return nullptr;
+  }
+
+  // We don't want to duplicate `vector_ops...` if they have multiple uses.
+  if (!V->hasOneUse())
+    return nullptr;
+
+  Value *R = nullptr;
+  // Scalarize any unary op.
+  if (match(V, m_UnOp(m_Value(X)))) {
+    if (auto *Scalar = getScalarizationOfInsertElement(X, ReqIndexC, Builder))
+      R = Builder.CreateUnOp(cast<UnaryOperator>(V)->getOpcode(), Scalar);
+  }
+
+  // Scalarize any cast but bitcast.
+  // TODO: We skip bitcasts, but they would be okay if they are elementwise.
+  if (isa<CastInst>(V) && !match(V, m_BitCast(m_Value()))) {
+    X = cast<CastInst>(V)->getOperand(0);
+    if (auto *Scalar = getScalarizationOfInsertElement(X, ReqIndexC, Builder))
+      R = Builder.CreateCast(cast<CastInst>(V)->getOpcode(), Scalar,
+                             V->getType()->getScalarType());
+  }
+
+  // Binop with a constant.
+  Constant *C;
+  if (match(V, m_c_BinOp(m_Value(X), m_ImmConstant(C)))) {
+    BinaryOperator *BO = cast<BinaryOperator>(V);
+    if (isSafeToSpeculativelyExecute(BO)) {
+      if (auto *Scalar =
+              getScalarizationOfInsertElement(X, ReqIndexC, Builder)) {
+          auto *ScalarC =
+              ConstantExpr::getExtractElement(C, Builder.getInt64(ReqIndexC));
+
+          BinaryOperator::BinaryOps Opc = BO->getOpcode();
+          if (match(V, m_c_BinOp(m_Value(X), m_ImmConstant(C))))
+            R = Builder.CreateBinOp(Opc, Scalar, ScalarC);
+          else
+            R = Builder.CreateBinOp(Opc, ScalarC, Scalar);
+      }
+    }
+  }
+
+  // Cmp with a constant.
+  CmpInst::Predicate Pred;
+  if (match(V, m_Cmp(Pred, m_Value(X), m_ImmConstant(C)))) {
+    if (auto *Scalar = getScalarizationOfInsertElement(X, ReqIndexC, Builder)) {
+      auto *ScalarC =
+          ConstantExpr::getExtractElement(C, Builder.getInt64(ReqIndexC));
+      R = Builder.CreateCmp(Pred, Scalar, ScalarC);
+    }
+  }
+  // TODO: Intrinsics
+
+  // If we created a new scalar instruction, copy flags from the vec version.
+  if (R != nullptr)
+    cast<Instruction>(R)->copyIRFlags(V);
+
+  return R;
+}
+
 /// Try to replace a shuffle with an insertelement or try to replace a shuffle
 /// operand with the operand of an insertelement.
 static Instruction *foldShuffleWithInsert(ShuffleVectorInst &Shuf,
@@ -2616,13 +2707,11 @@ static Instruction *foldShuffleWithInsert(ShuffleVectorInst &Shuf,
   if (NumElts != InpNumElts)
     return nullptr;
 
-  // shuffle (insert ?, Scalar, IndexC), V1, Mask --> insert V1, Scalar, IndexC'
-  auto isShufflingScalarIntoOp1 = [&](Value *&Scalar, ConstantInt *&IndexC) {
-    // We need an insertelement with a constant index.
-    if (!match(V0, m_InsertElt(m_Value(), m_Value(Scalar),
-                               m_ConstantInt(IndexC))))
-      return false;
 
+  // (shuffle (vec_ops... (insert ?, Scalar, IndexC)), V1, Mask)
+  //    --> insert V1, (scalar_ops... Scalar), IndexC'
+  auto GetScalarizationOfInsertEle =
+      [&Mask, &NumElts, &IC](Value *V) -> std::pair<Value *, int> {
     // Test the shuffle mask to see if it splices the inserted scalar into the
     // operand 1 vector of the shuffle.
     int NewInsIndex = -1;
@@ -2631,40 +2720,45 @@ static Instruction *foldShuffleWithInsert(ShuffleVectorInst &Shuf,
       if (Mask[i] == -1)
         continue;
 
-      // The shuffle takes elements of operand 1 without lane changes.
-      if (Mask[i] == NumElts + i)
+      // The shuffle takes elements of operand 1.
+      if (Mask[i] >= NumElts)
         continue;
 
       // The shuffle must choose the inserted scalar exactly once.
-      if (NewInsIndex != -1 || Mask[i] != IndexC->getSExtValue())
-        return false;
+      if (NewInsIndex != -1)
+        return {nullptr, -1};
 
-      // The shuffle is placing the inserted scalar into element i.
+      // The shuffle is placing the inserted scalar into element i from operand
+      // 0.
       NewInsIndex = i;
     }
 
-    assert(NewInsIndex != -1 && "Did not fold shuffle with unused operand?");
+    // Operand is unused.
+    if (NewInsIndex < 0)
+      return {nullptr, -1};
 
-    // Index is updated to the potentially translated insertion lane.
-    IndexC = ConstantInt::get(IndexC->getIntegerType(), NewInsIndex);
-    return true;
-  };
+    Value *Scalar =
+        getScalarizationOfInsertElement(V, Mask[NewInsIndex], IC.Builder);
 
-  // If the shuffle is unnecessary, insert the scalar operand directly into
-  // operand 1 of the shuffle. Example:
-  // shuffle (insert ?, S, 1), V1, <1, 5, 6, 7> --> insert V1, S, 0
-  Value *Scalar;
-  ConstantInt *IndexC;
-  if (isShufflingScalarIntoOp1(Scalar, IndexC))
-    return InsertElementInst::Create(V1, Scalar, IndexC);
+    return {Scalar, NewInsIndex};
+  };
 
-  // Try again after commuting shuffle. Example:
-  // shuffle V0, (insert ?, S, 0), <0, 1, 2, 4> -->
-  // shuffle (insert ?, S, 0), V0, <4, 5, 6, 0> --> insert V0, S, 3
-  std::swap(V0, V1);
+  auto [V0Scalar, V0NewInsertIdx] = GetScalarizationOfInsertEle(V0);
   ShuffleVectorInst::commuteShuffleMask(Mask, NumElts);
-  if (isShufflingScalarIntoOp1(Scalar, IndexC))
-    return InsertElementInst::Create(V1, Scalar, IndexC);
+  auto [V1Scalar, V1NewInsertIdx] = GetScalarizationOfInsertEle(V1);
+
+  if (V0Scalar != nullptr && V1Scalar != nullptr) {
+    Value *R = IC.Builder.CreateInsertElement(Shuf.getType(), V0Scalar,
+                                              V0NewInsertIdx);
+    return InsertElementInst::Create(R, V1Scalar,
+                                     IC.Builder.getInt64(V1NewInsertIdx));
+  } else if (V0Scalar != nullptr) {
+    return InsertElementInst::Create(V1, V0Scalar,
+                                     IC.Builder.getInt64(V0NewInsertIdx));
+  } else if (V1Scalar != nullptr) {
+    return InsertElementInst::Create(V0, V1Scalar,
+                                     IC.Builder.getInt64(V1NewInsertIdx));
+  }
 
   return nullptr;
 }
diff --git a/llvm/test/Transforms/InstCombine/insert-extract-shuffle-inseltpoison.ll b/llvm/test/Transforms/InstCombine/insert-extract-shuffle-inseltpoison.ll
index 6cbb2a246f5a4a..4bc3bd7bd9c203 100644
--- a/llvm/test/Transforms/InstCombine/insert-extract-shuffle-inseltpoison.ll
+++ b/llvm/test/Transforms/InstCombine/insert-extract-shuffle-inseltpoison.ll
@@ -547,8 +547,7 @@ define <4 x float> @insert_in_splat_variable_index(float %x, i32 %y) {
 
 define <4 x float> @insert_in_nonsplat(float %x, <4 x float> %y) {
 ; CHECK-LABEL: @insert_in_nonsplat(
-; CHECK-NEXT:    [[XV:%.*]] = insertelement <4 x float> poison, float [[X:%.*]], i64 0
-; CHECK-NEXT:    [[SPLAT:%.*]] = shufflevector <4 x float> [[XV]], <4 x float> [[Y:%.*]], <4 x i32> <i32 poison, i32 0, i32 4, i32 poison>
+; CHECK-NEXT:    [[SPLAT:%.*]] = insertelement <4 x float> [[Y:%.*]], float [[X:%.*]], i64 1
 ; CHECK-NEXT:    [[R:%.*]] = insertelement <4 x float> [[SPLAT]], float [[X]], i64 3
 ; CHECK-NEXT:    ret <4 x float> [[R]]
 ;
diff --git a/llvm/test/Transforms/InstCombine/insert-extract-shuffle.ll b/llvm/test/Transforms/InstCombine/insert-extract-shuffle.ll
index c87e2e8596c62d..97fcc7a4b43707 100644
--- a/llvm/test/Transforms/InstCombine/insert-extract-shuffle.ll
+++ b/llvm/test/Transforms/InstCombine/insert-extract-shuffle.ll
@@ -547,8 +547,7 @@ define <4 x float> @insert_in_splat_variable_index(float %x, i32 %y) {
 
 define <4 x float> @insert_in_nonsplat(float %x, <4 x float> %y) {
 ; CHECK-LABEL: @insert_in_nonsplat(
-; CHECK-NEXT:    [[XV:%.*]] = insertelement <4 x float> poison, float [[X:%.*]], i64 0
-; CHECK-NEXT:    [[SPLAT:%.*]] = shufflevector <4 x float> [[XV]], <4 x float> [[Y:%.*]], <4 x i32> <i32 poison, i32 0, i32 4, i32 poison>
+; CHECK-NEXT:    [[SPLAT:%.*]] = insertelement <4 x float> [[Y:%.*]], float [[X:%.*]], i64 1
 ; CHECK-NEXT:    [[R:%.*]] = insertelement <4 x float> [[SPLAT]], float [[X]], i64 3
 ; CHECK-NEXT:    ret <4 x float> [[R]]
 ;
diff --git a/llvm/test/Transforms/InstCombine/shufflevector-div-rem-inseltpoison.ll b/llvm/test/Transforms/InstCombine/shufflevector-div-rem-inseltpoison.ll
index cc1d23943b09c8..2392bcac6eb7ec 100644
--- a/llvm/test/Transforms/InstCombine/shufflevector-div-rem-inseltpoison.ll
+++ b/llvm/test/Transforms/InstCombine/shufflevector-div-rem-inseltpoison.ll
@@ -88,9 +88,9 @@ define <2 x i16> @test_udiv(i16 %a, i1 %cmp) {
 ; shufflevector is eliminated here.
 define <2 x float> @test_fdiv(float %a, float %b, i1 %cmp) {
 ; CHECK-LABEL: @test_fdiv(
-; CHECK-NEXT:    [[TMP1:%.*]] = insertelement <2 x float> poison, float [[A:%.*]], i64 1
-; CHECK-NEXT:    [[SPLAT_OP:%.*]] = fdiv <2 x float> [[TMP1]], <float undef, float 3.000000e+00>
-; CHECK-NEXT:    [[T2:%.*]] = select i1 [[CMP:%.*]], <2 x float> <float 7.700000e+01, float 9.900000e+01>, <2 x float> [[SPLAT_OP]]
+; CHECK-NEXT:    [[A:%.*]] = fdiv float [[A1:%.*]], 3.000000e+00
+; CHECK-NEXT:    [[TMP1:%.*]] = insertelement <2 x float> poison, float [[A]], i64 1
+; CHECK-NEXT:    [[T2:%.*]] = select i1 [[CMP:%.*]], <2 x float> <float 7.700000e+01, float 9.900000e+01>, <2 x float> [[TMP1]]
 ; CHECK-NEXT:    ret <2 x float> [[T2]]
 ;
   %splatinsert = insertelement <2 x float> poison, float %a, i32 0
@@ -105,9 +105,9 @@ define <2 x float> @test_fdiv(float %a, float %b, i1 %cmp) {
 ; shufflevector is eliminated here.
 define <2 x float> @test_frem(float %a, float %b, i1 %cmp) {
 ; CHECK-LABEL: @test_frem(
-; CHECK-NEXT:    [[TMP1:%.*]] = insertelement <2 x float> poison, float [[A:%.*]], i64 1
-; CHECK-NEXT:    [[SPLAT_OP:%.*]] = frem <2 x float> [[TMP1]], <float undef, float 3.000000e+00>
-; CHECK-NEXT:    [[T2:%.*]] = select i1 [[CMP:%.*]], <2 x float> <float 7.700000e+01, float 9.900000e+01>, <2 x float> [[SPLAT_OP]]
+; CHECK-NEXT:    [[A:%.*]] = frem float [[A1:%.*]], 3.000000e+00
+; CHECK-NEXT:    [[TMP1:%.*]] = insertelement <2 x float> poison, float [[A]], i64 1
+; CHECK-NEXT:    [[T2:%.*]] = select i1 [[CMP:%.*]], <2 x float> <float 7.700000e+01, float 9.900000e+01>, <2 x float> [[TMP1]]
 ; CHECK-NEXT:    ret <2 x float> [[T2]]
 ;
   %splatinsert = insertelement <2 x float> poison, float %a, i32 0
diff --git a/llvm/test/Transforms/InstCombine/shufflevector-div-rem.ll b/llvm/test/Transforms/InstCombine/shufflevector-div-rem.ll
index 1699418dcc28b3..f445a0134b3589 100644
--- a/llvm/test/Transforms/InstCombine/shufflevector-div-rem.ll
+++ b/llvm/test/Transforms/InstCombine/shufflevector-div-rem.ll
@@ -88,9 +88,9 @@ define <2 x i16> @test_udiv(i16 %a, i1 %cmp) {
 ; shufflevector is eliminated here.
 define <2 x float> @test_fdiv(float %a, float %b, i1 %cmp) {
 ; CHECK-LABEL: @test_fdiv(
-; CHECK-NEXT:    [[TMP1:%.*]] = insertelement <2 x float> poison, float [[A:%.*]], i64 1
-; CHECK-NEXT:    [[SPLAT_OP:%.*]] = fdiv <2 x float> [[TMP1]], <float undef, float 3.000000e+00>
-; CHECK-NEXT:    [[T2:%.*]] = select i1 [[CMP:%.*]], <2 x float> <float 7.700000e+01, float 9.900000e+01>, <2 x float> [[SPLAT_OP]]
+; CHECK-NEXT:    [[A:%.*]] = fdiv float [[A1:%.*]], 3.000000e+00
+; CHECK-NEXT:    [[TMP1:%.*]] = insertelement <2 x float> poison, float [[A]], i64 1
+; CHECK-NEXT:    [[T2:%.*]] = select i1 [[CMP:%.*]], <2 x float> <float 7.700000e+01, float 9.900000e+01>, <2 x float> [[TMP1]]
 ; CHECK-NEXT:    ret <2 x float> [[T2]]
 ;
   %splatinsert = insertelement <2 x float> undef, float %a, i32 0
@@ -105,9 +105,9 @@ define <2 x float> @test_fdiv(float %a, float %b, i1 %cmp) {
 ; shufflevector is eliminated here.
 define <2 x float> @test_frem(float %a, float %b, i1 %cmp) {
 ; CHECK-LABEL: @test_frem(
-; CHECK-NEXT:    [[TMP1:%.*]] = insertelement <2 x float> poison, float [[A:%.*]], i64 1
-; CHECK-NEXT:    [[SPLAT_OP:%.*]] = frem <2 x float> [[TMP1]], <float undef, float 3.000000e+00>
-; CHECK-NEXT:    [[T2:%.*]] = select i1 [[CMP:%.*]], <2 x float> <float 7.700000e+01, float 9.900000e+01>, <2 x float> [[SPLAT_OP]]
+; CHECK-NEXT:    [[A:%.*]] = frem float [[A1:%.*]], 3.000000e+00
+; CHECK-NEXT:    [[TMP1:%.*]] = insertelement <2 x float> poison, float [[A]], i64 1
+; CHECK-NEXT:    [[T2:%.*]] = select i1 [[CMP:%.*]], <2 x float> <float 7.700000e+01, float 9.900000e+01>, <2 x float> [[TMP1]]
 ; CHECK-NEXT:    ret <2 x float> [[T2]]
 ;
   %splatinsert = insertelement <2 x float> undef, float %a, i32 0
diff --git a/llvm/test/Transforms/InstCombine/shufflevector-inselt.ll b/llvm/test/Transforms/InstCombine/shufflevector-inselt.ll
new file mode 100644
index 00000000000000..dae4ca1d8eba79
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/shufflevector-inselt.ll
@@ -0,0 +1,258 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -passes='instcombine' -S %s | FileCheck %s
+
+declare void @use.v2.float(<2 x float>)
+define <2 x float> @replace_through_casts(i16 %inp) {
+; CHECK-LABEL: @replace_through_casts(
+; CHECK-NEXT:    [[ADD:%.*]] = add nsw i16 [[INP:%.*]], -10
+; CHECK-NEXT:    [[TMP1:%.*]] = uitofp i16 [[INP]] to float
+; CHECK-NEXT:    [[TMP2:%.*]] = sitofp i16 [[ADD]] to float
+; CHECK-NEXT:    [[TMP3:%.*]] = insertelement <2 x float> poison, float [[TMP1]], i64 0
+; CHECK-NEXT:    [[R:%.*]] = insertelement <2 x float> [[TMP3]], float [[TMP2]], i64 1
+; CHECK-NEXT:    ret <2 x float> [[R]]
+;
+  %add = add nsw i16 %inp, -10
+  %v0 = insertelement <2 x i16> poison, i16 %inp, i64 0
+  %v = insertelement <2 x i16> %v0, i16 %add, i64 1
+  %ui_v = uitofp <2 x i16> %v to <2 x float>
+  %si_v = sitofp <2 x i16> %v to <2 x float>
+  %r = shufflevector <2 x float> %ui_v, <2 x float> %si_v, <2 x i32> <i32 0, i32 3>
+  ret <2 x float> %r
+}
+
+define <2 x float> @replace_through_casts_and_binop(i16 %inp) {
+; CHECK-LABEL: @replace_through_casts_and_binop(
+; CHECK-NEXT:    [[ADD:%.*]] = add nsw i16 [[INP:%.*]], -10
+; CHECK-NEXT:    [[MUL:%.*]] = mul nsw i16 [[INP]], 5
+; CHECK-NEXT:    [[TMP1:%.*]] = uitofp i16 [[MUL]] to float
+; CHECK-NEXT:    [[TMP2:%.*]] = fadd float [[TMP1]], 2.000000e+00
+; CHECK-NEXT:    [[TMP3:%.*]] = sitofp i16 [[ADD]] to float
+; CHECK-NEXT:    [[TMP4:%.*]] = insertelement <2 x float> poison, float [[TMP2]], i64 0
+; CHECK-NEXT:    [[R:%.*]] = insertelement <2 x float> [[TMP4]], float [[TMP3]], i64 1
+; CHECK-NEXT:    ret <2 x float> [[R]]
+;
+  %add = add nsw i16 %inp, -10
+  %mul = mul nsw i16 %inp, 5
+  %v0 = insertelement <2 x i16> poison, i16 %mul, i64 0
+  %v = insertelement <2 x i16> %v0, i16 %add, i64 1
+  %ui_v = uitofp <2 x i16> %v to <2 x float>
+  %si_v = sitofp <2 x i16> %v to <2 x float>
+  %ui_v_add = fadd <2 x float> %ui_v, <float 2.0, float 3.0>
+  %r = shufflevector <2 x float> %ui_v_add, <2 x float> %si_v, <2 x i32> <i32 0, i32 3>
+  ret <2 x float> %r
+}
+
+define <2 x float> @replace_through_casts_and_binop_and_unop(i16 %inp) {
+; CHECK-LABEL: @replace_through_casts_and_binop_and_unop(
+; CHECK-NEXT:    [[ADD:%.*]] = add nsw i16 [[INP:%.*]], -10
+; CHECK-NEXT:    [[TMP1:%.*]] = uitofp i16 [[ADD]] to float
+; CHECK-NEXT:    [[TMP2:%.*]] = fadd float [[TMP1]], 2.000000e+00
+; CHECK-NEXT:    [[TMP3:%.*]] = sitofp i16 [[ADD]] to float
+; CHECK-NEXT:    [[TMP4:%.*]] = fneg float [[TMP3]]
+; CHECK-NEXT:    [[TMP5:%.*]] = insertelement <2 x float> poison, float [[TMP2]], i64 0
+; CHECK-NEXT:    [[R:%.*]] = insertelement <2 x float> [[TMP5]], float [[TMP4]], i64 1
+; CHECK-NEXT:    ret <2 x float> [[R]]
+;
+  %add = add nsw i16 %inp, -10
+  %v0 = insertelement <2 x i16> poison, i16 %add, i64 0
+  %v = insertelement <2 x i16> %v0, i16 %inp, i64 1
+  %ui_v = uitofp <2 x i16> %v to <2 x float>
+  %si_v = sitofp <2 x i16> %v to <2 x float>
+  %ui_v_add = fadd <2 x float> %ui_v, <float 2.0, float 3.0>
+  %si_v_fneg = fneg <2 x float> %si_v
+  %r = shufflevector <2 x float> %ui_v_add, <2 x float> %si_v_fneg, <2 x i32> <i32 0, i32 2>
+  ret <2 x float> %r
+}
+
+define <2 x float> @replace_through_casts_through_splat(i16 %inp) {
+; CHECK-LABEL: @replace_through_casts_through_splat(
+; CHECK-NEXT:    [[ADD:%.*]] = add nsw i16 [[INP:%.*]], -10
+; CHECK-NEXT:    [[TMP1:%.*]] = uitofp i16 [[ADD]] to float
+; CHECK-NEXT:    [[TMP2:%.*]] = fadd float [[TMP1]], 2.000000e+00
+; CHECK-NEXT:    [[TMP3:%.*]] = sitofp i16 [[ADD]] to float
+; CHECK-NEXT:    [[TMP4:%.*]] = fneg float [[TMP3]]
+; CHECK-NEXT:    [[TMP5:%.*]] = insertelement <2 x float> poison, float [[TMP2]], i64 0
+; CHECK-NEXT:    [[R:%.*]] = insertelement <2 x float> [[TMP5]], float [[TMP4]], i64 1
+; CHECK-NEXT:    ret <2 x float> [[R]]
+;
+  %add = add nsw i16 %inp, -10
+  %v0 = insertelement <2 x i16> poison, i16 %add, i64 0
+  %v = shufflevector <2 x i16> %v0, <2 x i16> poison, <2 x i32> zeroinitializer
+  %ui_v = uitofp <2 x i16> %v to <2 x float>
+  %si_v = sitofp <2 x i16> %v to <2 x float>
+  %ui_v_add = fadd <2 x float> %ui_v, <float 2.0, float 3.0>
+  %si_v_fneg = fneg <2 x float> %si_v
+  %r = shufflevector <2 x float> %ui_v_add, <2 x float> %si_v_fneg, <2 x i32> <i32 0, i32 3>
+  ret <2 x float> %r
+}
+
+define <2 x float> @replace_through_casts_through_splat2(i16 %inp, <2 x i16> %any) {
+; CHECK-LABEL: @replace_through_casts_through_splat2(
+; CHECK-NEXT:    ret <2 x float> poison
+;
+  %add = add nsw i16 %inp, -10
+  %v0 = insertelement <2 x i16> poison, i16 %add, i64 0
+  %v = shufflevector <2 x i16> %v0, <2 x i16> %any, <2 x i32> <i32 1, i32 1>
+  %ui_v = uitofp <2 x i16> %v to <2 x float>
+  %si_v = sitofp <2 x i16> %v to <2 x float>
+  %ui_v_add = fadd <2 x float> %ui_v, <float 2.0, float 3.0>
+  %si_v_fneg = fneg <2 x float> %si_v
+  %r = shufflevector <2 x float> %ui_v_add, <2 x float> %si_v_fneg, <2 x i32> <i32 0, i32 3>
+  ret <2 x float> %r
+}
+
+define <2 x float> @replace_through_casts_through_splat_fail(i16 %inp, <2 x i16> %any) {
+; CHECK-LABEL: @replace_through_casts_through_splat_fail(
+; CHECK-NEXT:    [[V:%.*]] = shufflevector <2 x i16> [[V0:%.*]], <2 x i16> poison, <2 x i32> zeroinitializer
+; CHECK-NEXT:    [[UI_V:%.*]] = uitofp <2 x i16> [[V]] to <2 x float>
+; CHECK-NEXT:    [[SI_V:%.*]] = sitofp <2 x i16> [[V]] to <2 x float>
+; CHECK-NEXT:    [[UI_V_ADD:%.*]] = fadd <2 x float> [[UI_V]], <float 2.000000e+00, float poison>
+; CHECK-NEXT:    [[SI_V_FNEG:%.*]] = fneg <2 x float> [[SI_V]]
+; CHECK-NEXT:    [[R:%.*]] = shufflevector <2 x float> [[UI_V_ADD]], <2 x float> [[SI_V_FNEG]], <2 x i32> <i32 0, i32 3>
+; CHECK-NEXT:    ret <2 x float> [[R]]
+;
+  %add = add nsw i16 %inp, -10
+  %v0 = insertelement <2 x i16> poison, i16 %add, i64 1
+  %v = shufflevector <2 x i16> %v0, <2 x i16> %any, <2 x i32> <i32 2, i32 2>
+  %ui_v = uitofp <2 x i16> %v to <2 x float>
+  %si_v = sitofp <2 x i16> %v to <2 x float>
+  %ui_v_add = fadd <2 x float> %ui_v, <float 2.0, float 3.0>
+  %si_v_fneg = fneg <2 x float> %si_v
+  %r = shufflevector <2 x...
[truncated]

``````````

</details>


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


More information about the llvm-commits mailing list