diff options
author | Alexey Bataev <a.bataev@outlook.com> | 2022-11-17 16:46:51 -0800 |
---|---|---|
committer | Alexey Bataev <a.bataev@outlook.com> | 2022-11-17 17:23:48 -0800 |
commit | 07015e12f0a96e2c9484240b319c4d63b78be5e2 (patch) | |
tree | 619c7cc52566b491e7b85738c0f3e0ca7272ad61 | |
parent | 6b852ffa9973015fb5deb6d859d980692387dcc7 (diff) | |
download | llvm-07015e12f0a96e2c9484240b319c4d63b78be5e2.zip llvm-07015e12f0a96e2c9484240b319c4d63b78be5e2.tar.gz llvm-07015e12f0a96e2c9484240b319c4d63b78be5e2.tar.bz2 |
[SLP]Fix PR59053: trying to erase instruction with users.
Need to count the reduced values, vectorized in the tree but not in the top node. Such scalars still must be extracted out of the vector node instead of the original scalar.
-rw-r--r-- | llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp | 33 | ||||
-rw-r--r-- | llvm/test/Transforms/SLPVectorizer/X86/reduction-value-in-tree.ll | 58 |
2 files changed, 81 insertions, 10 deletions
diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp index ef63fbb..dc67c9e 100644 --- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp +++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp @@ -11873,23 +11873,36 @@ public: Value *V = Candidates[Cnt]; ++NumUses.try_emplace(V, 0).first->getSecond(); } + SmallPtrSet<Value *, 4> VLScalars(VL.begin(), VL.end()); // Gather externally used values. SmallPtrSet<Value *, 4> Visited; for (unsigned Cnt = 0; Cnt < Pos; ++Cnt) { - Value *V = Candidates[Cnt]; - if (!Visited.insert(V).second) + Value *RdxVal = Candidates[Cnt]; + if (!Visited.insert(RdxVal).second) + continue; + // Check if the scalar was vectorized as part of the vectorization + // tree but not the top node. + if (!VLScalars.contains(RdxVal) && V.isVectorized(RdxVal)) { + LocalExternallyUsedValues[RdxVal]; continue; - unsigned NumOps = VectorizedVals.lookup(V) + NumUses[V]; - if (NumOps != ReducedValsToOps.find(V)->second.size()) - LocalExternallyUsedValues[V]; + } + unsigned NumOps = VectorizedVals.lookup(RdxVal) + NumUses[RdxVal]; + if (NumOps != ReducedValsToOps.find(RdxVal)->second.size()) + LocalExternallyUsedValues[RdxVal]; } for (unsigned Cnt = Pos + ReduxWidth; Cnt < NumReducedVals; ++Cnt) { - Value *V = Candidates[Cnt]; - if (!Visited.insert(V).second) + Value *RdxVal = Candidates[Cnt]; + if (!Visited.insert(RdxVal).second) + continue; + // Check if the scalar was vectorized as part of the vectorization + // tree but not the top node. + if (!VLScalars.contains(RdxVal) && V.isVectorized(RdxVal)) { + LocalExternallyUsedValues[RdxVal]; continue; - unsigned NumOps = VectorizedVals.lookup(V) + NumUses[V]; - if (NumOps != ReducedValsToOps.find(V)->second.size()) - LocalExternallyUsedValues[V]; + } + unsigned NumOps = VectorizedVals.lookup(RdxVal) + NumUses[RdxVal]; + if (NumOps != ReducedValsToOps.find(RdxVal)->second.size()) + LocalExternallyUsedValues[RdxVal]; } for (Value *RdxVal : VL) if (RequiredExtract.contains(RdxVal)) diff --git a/llvm/test/Transforms/SLPVectorizer/X86/reduction-value-in-tree.ll b/llvm/test/Transforms/SLPVectorizer/X86/reduction-value-in-tree.ll new file mode 100644 index 0000000..b349c3a --- /dev/null +++ b/llvm/test/Transforms/SLPVectorizer/X86/reduction-value-in-tree.ll @@ -0,0 +1,58 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -S -passes=slp-vectorizer -mtriple=x86_64-unknown-linux < %s | FileCheck %s +define void @test() { +; CHECK-LABEL: @test( +; CHECK-NEXT: bb: +; CHECK-NEXT: br i1 false, label [[PH:%.*]], label [[EXIT:%.*]] +; CHECK: ph: +; CHECK-NEXT: [[TMP0:%.*]] = call i8 @llvm.vector.reduce.and.v8i8(<8 x i8> zeroinitializer) +; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.vector.reduce.and.v4i8(<4 x i8> zeroinitializer) +; CHECK-NEXT: [[OP_RDX:%.*]] = and i8 [[TMP0]], [[TMP1]] +; CHECK-NEXT: [[TMP2:%.*]] = call i8 @llvm.vector.reduce.and.v8i8(<8 x i8> zeroinitializer) +; CHECK-NEXT: [[OP_RDX1:%.*]] = and i8 [[OP_RDX]], [[TMP2]] +; CHECK-NEXT: [[OP_RDX2:%.*]] = and i8 [[OP_RDX1]], 0 +; CHECK-NEXT: br label [[EXIT]] +; CHECK: exit: +; CHECK-NEXT: [[PHI:%.*]] = phi i8 [ [[OP_RDX2]], [[PH]] ], [ 0, [[BB:%.*]] ] +; CHECK-NEXT: ret void +; +bb: + br i1 false, label %ph, label %exit + +ph: + %add1 = add i8 0, 0 + %add2 = add i8 %add1, 0 + %add3 = add i8 %add1, 0 + %add4 = add i8 %add1, 0 + %add5 = add i8 %add1, 0 + %add6 = add i8 %add1, 0 + %add7 = add i8 %add1, 0 + %add8 = add i8 %add1, 0 + %add9 = add i8 0, 0 + %add10 = add i8 0, %add9 + %0 = and i8 %add10, %add3 + %1 = and i8 %0, %add2 + %2 = and i8 %1, %add4 + %3 = and i8 %2, 0 + %4 = and i8 %3, %add5 + %5 = and i8 %4, %add6 + %6 = and i8 %5, 0 + %7 = and i8 %6, 0 + %8 = and i8 %7, 0 + %9 = and i8 %8, 0 + %10 = and i8 %9, 0 + %11 = and i8 %10, 0 + %12 = and i8 %11, 0 + %13 = and i8 %12, %add7 + %14 = and i8 %13, %add8 + %15 = and i8 %14, 0 + %16 = and i8 %15, 0 + %17 = and i8 %16, 0 + %18 = and i8 %17, 0 + %and = and i8 %18, %add1 + br label %exit + +exit: + %phi = phi i8 [ %and, %ph ], [ 0, %bb ] + ret void +} |