Skip to content

[SLP] Fix PoisonValue in the argument VL of setOperand. #118949

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Dec 11, 2024

Conversation

HanKuanChen
Copy link
Contributor

In addition, Scalars is already in the struct, we don't need to pass VL here.

reference: #113880

In addition, Scalars is already in the struct, we don't need to pass VL here.
@llvmbot
Copy link
Member

llvmbot commented Dec 6, 2024

@llvm/pr-subscribers-llvm-transforms

Author: Han-Kuan Chen (HanKuanChen)

Changes

In addition, Scalars is already in the struct, we don't need to pass VL here.

reference: #113880


Full diff: https://github.com/llvm/llvm-project/pull/118949.diff

2 Files Affected:

  • (modified) llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp (+12-13)
  • (added) llvm/test/Transforms/SLPVectorizer/fix-113880.ll (+19)
diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
index 7ea039e04ca728..180238f4832293 100644
--- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
+++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
@@ -3338,14 +3338,13 @@ class BoUpSLP {
       copy(OpVL, Operands[OpIdx].begin());
     }
 
-    /// Set this bundle's operand from \p VL.
-    void setOperand(ArrayRef<Value *> VL, const BoUpSLP &R,
-                    bool RequireReorder = false) {
-      VLOperands Ops(VL, R);
+    /// Set this bundle's operand from Scalars.
+    void setOperand(const BoUpSLP &R, bool RequireReorder = false) {
+      VLOperands Ops(Scalars, R);
       if (RequireReorder)
         Ops.reorder();
-      for (unsigned I :
-           seq<unsigned>(cast<Instruction>(VL[0])->getNumOperands()))
+      auto *I0 = cast<Instruction>(*find_if(Scalars, IsaPred<Instruction>));
+      for (unsigned I : seq<unsigned>(I0->getNumOperands()))
         setOperand(I, Ops.getVL(I));
     }
 
@@ -8446,7 +8445,7 @@ void BoUpSLP::buildTree_rec(ArrayRef<Value *> VL, unsigned Depth,
                                    {}, CurrentOrder);
       LLVM_DEBUG(dbgs() << "SLP: added inserts bundle.\n");
 
-      TE->setOperand(VL, *this);
+      TE->setOperand(*this);
       buildTree_rec(TE->getOperand(1), Depth + 1, {TE, 1});
       return;
     }
@@ -8484,7 +8483,7 @@ void BoUpSLP::buildTree_rec(ArrayRef<Value *> VL, unsigned Depth,
       case TreeEntry::NeedToGather:
         llvm_unreachable("Unexpected loads state.");
       }
-      TE->setOperand(VL, *this);
+      TE->setOperand(*this);
       if (State == TreeEntry::ScatterVectorize)
         buildTree_rec(PointerOps, Depth + 1, {TE, 0});
       return;
@@ -8524,7 +8523,7 @@ void BoUpSLP::buildTree_rec(ArrayRef<Value *> VL, unsigned Depth,
                                    ReuseShuffleIndices);
       LLVM_DEBUG(dbgs() << "SLP: added a vector of casts.\n");
 
-      TE->setOperand(VL, *this);
+      TE->setOperand(*this);
       for (unsigned I : seq<unsigned>(VL0->getNumOperands()))
         buildTree_rec(TE->getOperand(I), Depth + 1, {TE, I});
       if (ShuffleOrOp == Instruction::Trunc) {
@@ -8621,7 +8620,7 @@ void BoUpSLP::buildTree_rec(ArrayRef<Value *> VL, unsigned Depth,
                                    ReuseShuffleIndices);
       LLVM_DEBUG(dbgs() << "SLP: added a vector of un/bin op.\n");
 
-      TE->setOperand(VL, *this, isa<BinaryOperator>(VL0) && isCommutative(VL0));
+      TE->setOperand(*this, isa<BinaryOperator>(VL0) && isCommutative(VL0));
       for (unsigned I : seq<unsigned>(VL0->getNumOperands()))
         buildTree_rec(TE->getOperand(I), Depth + 1, {TE, I});
       return;
@@ -8687,7 +8686,7 @@ void BoUpSLP::buildTree_rec(ArrayRef<Value *> VL, unsigned Depth,
         fixupOrderingIndices(CurrentOrder);
       TreeEntry *TE = newTreeEntry(VL, Bundle /*vectorized*/, S, UserTreeIdx,
                                    ReuseShuffleIndices, CurrentOrder);
-      TE->setOperand(VL, *this);
+      TE->setOperand(*this);
       buildTree_rec(TE->getOperand(0), Depth + 1, {TE, 0});
       if (Consecutive)
         LLVM_DEBUG(dbgs() << "SLP: added a vector of stores.\n");
@@ -8703,7 +8702,7 @@ void BoUpSLP::buildTree_rec(ArrayRef<Value *> VL, unsigned Depth,
 
       TreeEntry *TE = newTreeEntry(VL, Bundle /*vectorized*/, S, UserTreeIdx,
                                    ReuseShuffleIndices);
-      TE->setOperand(VL, *this, isCommutative(VL0));
+      TE->setOperand(*this, isCommutative(VL0));
       for (unsigned I : seq<unsigned>(CI->arg_size())) {
         // For scalar operands no need to create an entry since no need to
         // vectorize it.
@@ -8759,7 +8758,7 @@ void BoUpSLP::buildTree_rec(ArrayRef<Value *> VL, unsigned Depth,
         return;
       }
 
-      TE->setOperand(VL, *this, isa<BinaryOperator>(VL0) || CI);
+      TE->setOperand(*this, isa<BinaryOperator>(VL0) || CI);
       for (unsigned I : seq<unsigned>(VL0->getNumOperands()))
         buildTree_rec(TE->getOperand(I), Depth + 1, {TE, I});
       return;
diff --git a/llvm/test/Transforms/SLPVectorizer/fix-113880.ll b/llvm/test/Transforms/SLPVectorizer/fix-113880.ll
new file mode 100644
index 00000000000000..6c3c95b0d9359f
--- /dev/null
+++ b/llvm/test/Transforms/SLPVectorizer/fix-113880.ll
@@ -0,0 +1,19 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -passes=slp-vectorizer -S -slp-max-reg-size=1024 %s | FileCheck %s
+
+define ptr @test() {
+; CHECK-LABEL: @test(
+; CHECK-NEXT:    store <4 x double> <double poison, double 0.000000e+00, double 0.000000e+00, double 0.000000e+00>, ptr null, align 8
+; CHECK-NEXT:    ret ptr null
+;
+  store double poison, ptr null, align 8
+  %1 = getelementptr i8, ptr null, i64 8
+  %2 = fmul double 0.000000e+00, 0.000000e+00
+  store double %2, ptr %1, align 8
+  %3 = getelementptr i8, ptr null, i64 16
+  %4 = fmul double 0.000000e+00, 0.000000e+00
+  store double %4, ptr %3, align 8
+  %5 = getelementptr i8, ptr null, i64 24
+  store double %2, ptr %5, align 8
+  ret ptr null
+}

@llvmbot
Copy link
Member

llvmbot commented Dec 6, 2024

@llvm/pr-subscribers-vectorizers

Author: Han-Kuan Chen (HanKuanChen)

Changes

In addition, Scalars is already in the struct, we don't need to pass VL here.

reference: #113880


Full diff: https://github.com/llvm/llvm-project/pull/118949.diff

2 Files Affected:

  • (modified) llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp (+12-13)
  • (added) llvm/test/Transforms/SLPVectorizer/fix-113880.ll (+19)
diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
index 7ea039e04ca728..180238f4832293 100644
--- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
+++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
@@ -3338,14 +3338,13 @@ class BoUpSLP {
       copy(OpVL, Operands[OpIdx].begin());
     }
 
-    /// Set this bundle's operand from \p VL.
-    void setOperand(ArrayRef<Value *> VL, const BoUpSLP &R,
-                    bool RequireReorder = false) {
-      VLOperands Ops(VL, R);
+    /// Set this bundle's operand from Scalars.
+    void setOperand(const BoUpSLP &R, bool RequireReorder = false) {
+      VLOperands Ops(Scalars, R);
       if (RequireReorder)
         Ops.reorder();
-      for (unsigned I :
-           seq<unsigned>(cast<Instruction>(VL[0])->getNumOperands()))
+      auto *I0 = cast<Instruction>(*find_if(Scalars, IsaPred<Instruction>));
+      for (unsigned I : seq<unsigned>(I0->getNumOperands()))
         setOperand(I, Ops.getVL(I));
     }
 
@@ -8446,7 +8445,7 @@ void BoUpSLP::buildTree_rec(ArrayRef<Value *> VL, unsigned Depth,
                                    {}, CurrentOrder);
       LLVM_DEBUG(dbgs() << "SLP: added inserts bundle.\n");
 
-      TE->setOperand(VL, *this);
+      TE->setOperand(*this);
       buildTree_rec(TE->getOperand(1), Depth + 1, {TE, 1});
       return;
     }
@@ -8484,7 +8483,7 @@ void BoUpSLP::buildTree_rec(ArrayRef<Value *> VL, unsigned Depth,
       case TreeEntry::NeedToGather:
         llvm_unreachable("Unexpected loads state.");
       }
-      TE->setOperand(VL, *this);
+      TE->setOperand(*this);
       if (State == TreeEntry::ScatterVectorize)
         buildTree_rec(PointerOps, Depth + 1, {TE, 0});
       return;
@@ -8524,7 +8523,7 @@ void BoUpSLP::buildTree_rec(ArrayRef<Value *> VL, unsigned Depth,
                                    ReuseShuffleIndices);
       LLVM_DEBUG(dbgs() << "SLP: added a vector of casts.\n");
 
-      TE->setOperand(VL, *this);
+      TE->setOperand(*this);
       for (unsigned I : seq<unsigned>(VL0->getNumOperands()))
         buildTree_rec(TE->getOperand(I), Depth + 1, {TE, I});
       if (ShuffleOrOp == Instruction::Trunc) {
@@ -8621,7 +8620,7 @@ void BoUpSLP::buildTree_rec(ArrayRef<Value *> VL, unsigned Depth,
                                    ReuseShuffleIndices);
       LLVM_DEBUG(dbgs() << "SLP: added a vector of un/bin op.\n");
 
-      TE->setOperand(VL, *this, isa<BinaryOperator>(VL0) && isCommutative(VL0));
+      TE->setOperand(*this, isa<BinaryOperator>(VL0) && isCommutative(VL0));
       for (unsigned I : seq<unsigned>(VL0->getNumOperands()))
         buildTree_rec(TE->getOperand(I), Depth + 1, {TE, I});
       return;
@@ -8687,7 +8686,7 @@ void BoUpSLP::buildTree_rec(ArrayRef<Value *> VL, unsigned Depth,
         fixupOrderingIndices(CurrentOrder);
       TreeEntry *TE = newTreeEntry(VL, Bundle /*vectorized*/, S, UserTreeIdx,
                                    ReuseShuffleIndices, CurrentOrder);
-      TE->setOperand(VL, *this);
+      TE->setOperand(*this);
       buildTree_rec(TE->getOperand(0), Depth + 1, {TE, 0});
       if (Consecutive)
         LLVM_DEBUG(dbgs() << "SLP: added a vector of stores.\n");
@@ -8703,7 +8702,7 @@ void BoUpSLP::buildTree_rec(ArrayRef<Value *> VL, unsigned Depth,
 
       TreeEntry *TE = newTreeEntry(VL, Bundle /*vectorized*/, S, UserTreeIdx,
                                    ReuseShuffleIndices);
-      TE->setOperand(VL, *this, isCommutative(VL0));
+      TE->setOperand(*this, isCommutative(VL0));
       for (unsigned I : seq<unsigned>(CI->arg_size())) {
         // For scalar operands no need to create an entry since no need to
         // vectorize it.
@@ -8759,7 +8758,7 @@ void BoUpSLP::buildTree_rec(ArrayRef<Value *> VL, unsigned Depth,
         return;
       }
 
-      TE->setOperand(VL, *this, isa<BinaryOperator>(VL0) || CI);
+      TE->setOperand(*this, isa<BinaryOperator>(VL0) || CI);
       for (unsigned I : seq<unsigned>(VL0->getNumOperands()))
         buildTree_rec(TE->getOperand(I), Depth + 1, {TE, I});
       return;
diff --git a/llvm/test/Transforms/SLPVectorizer/fix-113880.ll b/llvm/test/Transforms/SLPVectorizer/fix-113880.ll
new file mode 100644
index 00000000000000..6c3c95b0d9359f
--- /dev/null
+++ b/llvm/test/Transforms/SLPVectorizer/fix-113880.ll
@@ -0,0 +1,19 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -passes=slp-vectorizer -S -slp-max-reg-size=1024 %s | FileCheck %s
+
+define ptr @test() {
+; CHECK-LABEL: @test(
+; CHECK-NEXT:    store <4 x double> <double poison, double 0.000000e+00, double 0.000000e+00, double 0.000000e+00>, ptr null, align 8
+; CHECK-NEXT:    ret ptr null
+;
+  store double poison, ptr null, align 8
+  %1 = getelementptr i8, ptr null, i64 8
+  %2 = fmul double 0.000000e+00, 0.000000e+00
+  store double %2, ptr %1, align 8
+  %3 = getelementptr i8, ptr null, i64 16
+  %4 = fmul double 0.000000e+00, 0.000000e+00
+  store double %4, ptr %3, align 8
+  %5 = getelementptr i8, ptr null, i64 24
+  store double %2, ptr %5, align 8
+  ret ptr null
+}

bool RequireReorder = false) {
VLOperands Ops(VL, R);
/// Set this bundle's operand from Scalars.
void setOperand(const BoUpSLP &R, bool RequireReorder = false) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Better to pass first instruction as an argument rather than redo the search for it

@alexey-bataev
Copy link
Member

Your original patch was reverted, better to revive the previous review and incorporate this fix into the previous review

@HanKuanChen
Copy link
Contributor Author

Your original patch was reverted, better to revive the previous review and incorporate this fix into the previous review

I will cherry pick this patch once this patch is approved.

VLOperands Ops(VL, R);
/// Set this bundle's operand from Scalars.
void setOperand(const BoUpSLP &R, bool RequireReorder = false) {
auto *I0 = cast<Instruction>(*find_if(Scalars, IsaPred<Instruction>));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You still looking for the instruction here, better to pass it as an argument or make it part of VLOperands class, just like Scalars

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I0 is passed to VLOperands Ops(Scalars, R, I0); to reduce the search. Is this not good?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You still redo search here

@@ -2542,13 +2541,11 @@ class BoUpSLP {

public:
/// Initialize with all the operands of the instruction vector \p RootVL.
VLOperands(ArrayRef<Value *> RootVL, const BoUpSLP &R)
VLOperands(ArrayRef<Value *> RootVL, Instruction *VL0, const BoUpSLP &R)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make VL0 a member of the сlass, it is used in too many cases

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

VL0 is only used by the constructor of VLOperands. I think you mean "Make VL0 a member of TreeEntry"?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we need to put VL0 into TreeEntry, I suggest we open the original PR (#113880 (comment)) and review there.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, no, no, need it.

Comment on lines 3339 to 3341
void setOperand(Instruction *VL0, const BoUpSLP &R,
bool RequireReorder = false) {
VLOperands Ops(VL, R);
VLOperands Ops(Scalars, VL0, R);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of passing VL0 here, I think you can safely use MainOp member instruction

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need this one #118609.

…vm#113880)

To reduce repeated code, TreeEntry::setOperandsInOrder will be replaced
by VLOperands.
Arg_size will be provided to make sure other operands will not be
reorderd when VL[0] is IntrinsicInst (because APO is a boolean value).
In addition, BoUpSLP::reorderInputsAccordingToOpcode will also be
removed since it is simple.
@HanKuanChen HanKuanChen merged commit 51a0c1b into llvm:main Dec 11, 2024
8 checks passed
@HanKuanChen HanKuanChen deleted the slp-fix-113880 branch December 11, 2024 02:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants