diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp index b75c4d32cee2d2..cd044c78d90046 100644 --- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp +++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp @@ -4814,6 +4814,15 @@ void BoUpSLP::buildTree_rec(ArrayRef VL, unsigned Depth, return; } + // Don't go into catchswitch blocks, which can happen with PHIs. + // Such blocks can only have PHIs and the catchswitch. There is no + // place to insert a shuffle if we need to, so just avoid that issue. + if (isa(BB->getTerminator())) { + LLVM_DEBUG(dbgs() << "SLP: bundle in catchswitch block.\n"); + newTreeEntry(VL, None /*not vectorized*/, S, UserTreeIdx); + return; + } + // Check that every instruction appears once in this bundle. if (!TryToFindDuplicates(S)) return; diff --git a/llvm/test/Transforms/SLPVectorizer/X86/catchswitch.ll b/llvm/test/Transforms/SLPVectorizer/X86/catchswitch.ll new file mode 100644 index 00000000000000..29d3638c91e370 --- /dev/null +++ b/llvm/test/Transforms/SLPVectorizer/X86/catchswitch.ll @@ -0,0 +1,93 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -slp-vectorizer -S -mtriple=x86_64-pc-windows-msvc19.29.30145 < %s | FileCheck %s + +; This used to crash in SLP vectorization when attempting to set the +; IRBuilder's insertion point to the end of a catchswitch block, which +; is invalid. Only phis and the catchswitch may be present, so we must +; avoid trying to insert shuffles into such a block. + +%typeA = type { i8**, i8*, [20 x i8] } +@globalA = external global %typeA + +declare i32 @__CxxFrameHandler3(...) +declare void @funcA() + +define void @important_func() personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) { +; CHECK-LABEL: @important_func( +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[LABELB:%.*]] +; CHECK: labelB: +; CHECK-NEXT: invoke void @funcA() +; CHECK-NEXT: to label [[LABELC:%.*]] unwind label [[LABELD:%.*]] +; CHECK: labelC: +; CHECK-NEXT: invoke void @funcA() +; CHECK-NEXT: to label [[LABELE:%.*]] unwind label [[LABELF:%.*]] +; CHECK: labelD: +; CHECK-NEXT: [[TMP0:%.*]] = cleanuppad within none [] +; CHECK-NEXT: unreachable +; CHECK: labelE: +; CHECK-NEXT: [[TMP1:%.*]] = extractelement <4 x float> , i64 1 +; CHECK-NEXT: [[F:%.*]] = extractelement <4 x float> , i64 2 +; CHECK-NEXT: invoke void @funcA() +; CHECK-NEXT: to label [[LABELG:%.*]] unwind label [[CATCH_DISPATCH:%.*]] +; CHECK: labelF: +; CHECK-NEXT: [[TMP2:%.*]] = cleanuppad within none [] +; CHECK-NEXT: cleanupret from [[TMP2]] unwind to caller +; CHECK: labelG: +; CHECK-NEXT: [[G:%.*]] = extractelement <4 x float> , i64 0 +; CHECK-NEXT: [[H:%.*]] = extractelement <4 x float> , i64 3 +; CHECK-NEXT: invoke void @funcA() +; CHECK-NEXT: to label [[LABELH:%.*]] unwind label [[CATCH_DISPATCH]] +; CHECK: labelH: +; CHECK-NEXT: unreachable +; CHECK: catch.dispatch: +; CHECK-NEXT: [[TMP3:%.*]] = phi float [ [[G]], [[LABELG]] ], [ [[TMP1]], [[LABELE]] ] +; CHECK-NEXT: [[TMP4:%.*]] = phi float [ [[H]], [[LABELG]] ], [ [[F]], [[LABELE]] ] +; CHECK-NEXT: [[TMP5:%.*]] = catchswitch within none [label %catch] unwind to caller +; CHECK: catch: +; CHECK-NEXT: [[TMP6:%.*]] = catchpad within [[TMP5]] [%typeA* @globalA, i32 8, i8* null] +; CHECK-NEXT: unreachable +; +entry: + br label %labelB + +labelB: + invoke void @funcA() + to label %labelC unwind label %labelD + +labelC: + invoke void @funcA() + to label %labelE unwind label %labelF + +labelD: + %0 = cleanuppad within none [] + unreachable + +labelE: + %1 = extractelement <4 x float> , i64 1 + %f = extractelement <4 x float> , i64 2 + invoke void @funcA() + to label %labelG unwind label %catch.dispatch + +labelF: + %2 = cleanuppad within none [] + cleanupret from %2 unwind to caller + +labelG: + %g = extractelement <4 x float> , i64 0 + %h = extractelement <4 x float> , i64 3 + invoke void @funcA() + to label %labelH unwind label %catch.dispatch + +labelH: + unreachable + +catch.dispatch: + %3 = phi float [ %g, %labelG ], [ %1, %labelE ] + %4 = phi float [ %h, %labelG ], [ %f, %labelE ] + %5 = catchswitch within none [label %catch] unwind to caller + +catch: + %6 = catchpad within %5 [%typeA* @globalA, i32 8, i8* null] + unreachable +}