Bug type: crash
Component: SLPVectorizer
Bug location: llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp: BoUpSLP::getTreeCost
Issue title: [SLP vectorizer] Assertion fails with slp-revec
Labels: llvm:SLPVectorizer
crash
Reported by: JonPsson1

[tc_slp_revec.tar.gz](https://github.com/user-attachments/files/17118250/tc_slp_revec.tar.gz)

opt -mtriple=systemz-unknown -mcpu=z16 -O3 -o out.ll tc_crash22_aftercreduce.ll -slp-revec

Type.cpp:691: static llvm::FixedVectorType* llvm::FixedVectorType::get(llvm::Type*, unsigned int): Assertion `isValidElementType(
ElementType) && "Element type of a VectorType must " "be an integer, floating point, or " "pointer type."' failed.

#9 0x000002aa076e014e llvm::slpvectorizer::BoUpSLP::ShuffleCostEstimator::finalize



Comments: author: HanKuanChen
body: The fix is landing.
author: JonPsson1
body: Still failing, but this time I see another assertion:

[tc_slp_revec.tar.gz](https://github.com/user-attachments/files/17192435/tc_slp_revec.tar.gz)

opt -mtriple=s390x-unknown-linux -mcpu=z16 -O3 tc_crash38_aftercreduce.ll -o /dev/null -slp-revec

Assertion `!Dst->isVectorTy()' failed.
14 0x00000000030504c2 llvm::SLPVectorizerPass::vectorizeHorReduction


author: HanKuanChen
body: The fix is landing.

Fix patch:
commit cc01112660499a4db74bc3ee24b6f60b03d88dbd
Author: Han-Kuan Chen <hankuan.chen@sifive.com>
Date:   Tue Oct 1 19:15:58 2024 +0800

    [SLP][REVEC] getTypeSizeInBits should apply to scalar type instead of FixedVectorType. (#110610)
    
    reference: https://github.com/llvm/llvm-project/issues/109835

diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
index 68bf5c52814f..54a1b99606bc 100644
--- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
+++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
@@ -11786,7 +11786,7 @@ InstructionCost BoUpSLP::getTreeCost(ArrayRef<Value *> VectorizedVals) {
     auto BWIt = MinBWs.find(&Root);
     if (BWIt != MinBWs.end()) {
       Type *DstTy = Root.Scalars.front()->getType();
-      unsigned OriginalSz = DL->getTypeSizeInBits(DstTy);
+      unsigned OriginalSz = DL->getTypeSizeInBits(DstTy->getScalarType());
       unsigned SrcSz =
           ReductionBitWidth == 0 ? BWIt->second.first : ReductionBitWidth;
       if (OriginalSz != SrcSz) {
@@ -11794,6 +11794,10 @@ InstructionCost BoUpSLP::getTreeCost(ArrayRef<Value *> VectorizedVals) {
         if (OriginalSz > SrcSz)
           Opcode = BWIt->second.second ? Instruction::SExt : Instruction::ZExt;
         Type *SrcTy = IntegerType::get(DstTy->getContext(), SrcSz);
+        if (auto *VecTy = dyn_cast<FixedVectorType>(DstTy)) {
+          assert(SLPReVec && "Only supported by REVEC.");
+          SrcTy = getWidenedType(SrcTy, VecTy->getNumElements());
+        }
         Cost += TTI->getCastInstrCost(Opcode, DstTy, SrcTy,
                                       TTI::CastContextHint::None,
                                       TTI::TCK_RecipThroughput);


Regression tests:
file: llvm/test/Transforms/SLPVectorizer/SystemZ/revec-fix-109835.ll
commands: opt -mtriple=s390x-unknown-linux -mcpu=z16 -passes=slp-vectorizer -S -slp-revec %s
tests: test_name: func_1
test_body: @g_3_1_0 = external dso_local global i32, align 4
@g_7 = external dso_local global [5 x i32], align 4

define void @func_1() {
  %.pre = load i32, ptr @g_7, align 4
  %1 = load <4 x i32>, ptr getelementptr inbounds nuw (i8, ptr @g_7, i64 4), align 4
  br label %.loopexit

.loopexit:                                        ; preds = %.loopexit, %0
  %2 = phi i32 [ %op.rdx15, %.loopexit ], [ %.pre, %0 ]
  %3 = phi <4 x i32> [ %71, %.loopexit ], [ %1, %0 ]
  %4 = load volatile i32, ptr @g_3_1_0, align 4
  %5 = load volatile i32, ptr @g_3_1_0, align 4
  %6 = load volatile i32, ptr @g_3_1_0, align 4
  %7 = load volatile i32, ptr @g_3_1_0, align 4
  %8 = load volatile i32, ptr @g_3_1_0, align 4
  %9 = load volatile i32, ptr @g_3_1_0, align 4
  %10 = load volatile i32, ptr @g_3_1_0, align 4
  %11 = load volatile i32, ptr @g_3_1_0, align 4
  %12 = load volatile i32, ptr @g_3_1_0, align 4
  %13 = load volatile i32, ptr @g_3_1_0, align 4
  %14 = load volatile i32, ptr @g_3_1_0, align 4
  %15 = load volatile i32, ptr @g_3_1_0, align 4
  %16 = load volatile i32, ptr @g_3_1_0, align 4
  %17 = load volatile i32, ptr @g_3_1_0, align 4
  %18 = load volatile i32, ptr @g_3_1_0, align 4
  %19 = load volatile i32, ptr @g_3_1_0, align 4
  %20 = insertelement <4 x i32> poison, i32 %4, i32 0
  %21 = insertelement <4 x i32> %20, i32 %9, i32 1
  %22 = insertelement <4 x i32> %21, i32 %14, i32 2
  %23 = insertelement <4 x i32> %22, i32 %19, i32 3
  %24 = icmp eq <4 x i32> %23, zeroinitializer
  %25 = load volatile i32, ptr @g_3_1_0, align 4
  %26 = load volatile i32, ptr @g_3_1_0, align 4
  %27 = load volatile i32, ptr @g_3_1_0, align 4
  %28 = load volatile i32, ptr @g_3_1_0, align 4
  %29 = load volatile i32, ptr @g_3_1_0, align 4
  %.not2.410 = icmp eq i32 %29, 0
  %30 = zext i1 %.not2.410 to i32
  %31 = zext <4 x i1> %24 to <4 x i32>
  %32 = call i32 @llvm.vector.reduce.xor.v4i32(<4 x i32> %31)
  %op.rdx = xor i32 %32, %30
  %op.rdx15 = xor i32 %op.rdx, %2
  %33 = load volatile i32, ptr @g_3_1_0, align 4
  %34 = load volatile i32, ptr @g_3_1_0, align 4
  %35 = load volatile i32, ptr @g_3_1_0, align 4
  %36 = load volatile i32, ptr @g_3_1_0, align 4
  %37 = insertelement <4 x i32> poison, i32 %5, i32 0
  %38 = insertelement <4 x i32> %37, i32 %6, i32 1
  %39 = insertelement <4 x i32> %38, i32 %7, i32 2
  %40 = insertelement <4 x i32> %39, i32 %8, i32 3
  %41 = icmp eq <4 x i32> %40, zeroinitializer
  %42 = zext <4 x i1> %41 to <4 x i32>
  %43 = xor <4 x i32> %3, %42
  %44 = insertelement <4 x i32> poison, i32 %10, i32 0
  %45 = insertelement <4 x i32> %44, i32 %11, i32 1
  %46 = insertelement <4 x i32> %45, i32 %12, i32 2
  %47 = insertelement <4 x i32> %46, i32 %13, i32 3
  %48 = icmp eq <4 x i32> %47, zeroinitializer
  %49 = zext <4 x i1> %48 to <4 x i32>
  %50 = xor <4 x i32> %43, %49
  %51 = insertelement <4 x i32> poison, i32 %15, i32 0
  %52 = insertelement <4 x i32> %51, i32 %16, i32 1
  %53 = insertelement <4 x i32> %52, i32 %17, i32 2
  %54 = insertelement <4 x i32> %53, i32 %18, i32 3
  %55 = icmp eq <4 x i32> %54, zeroinitializer
  %56 = zext <4 x i1> %55 to <4 x i32>
  %57 = xor <4 x i32> %50, %56
  %58 = insertelement <4 x i32> poison, i32 %25, i32 0
  %59 = insertelement <4 x i32> %58, i32 %26, i32 1
  %60 = insertelement <4 x i32> %59, i32 %27, i32 2
  %61 = insertelement <4 x i32> %60, i32 %28, i32 3
  %62 = icmp eq <4 x i32> %61, zeroinitializer
  %63 = zext <4 x i1> %62 to <4 x i32>
  %64 = xor <4 x i32> %57, %63
  %65 = insertelement <4 x i32> poison, i32 %33, i32 0
  %66 = insertelement <4 x i32> %65, i32 %34, i32 1
  %67 = insertelement <4 x i32> %66, i32 %35, i32 2
  %68 = insertelement <4 x i32> %67, i32 %36, i32 3
  %69 = icmp eq <4 x i32> %68, zeroinitializer
  %70 = zext <4 x i1> %69 to <4 x i32>
  %71 = xor <4 x i32> %64, %70
  br label %.loopexit
}

; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare i32 @llvm.vector.reduce.xor.v4i32(<4 x i32>) #0

attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }