diff --git a/llvm/lib/Transforms/Vectorize/VectorCombine.cpp b/llvm/lib/Transforms/Vectorize/VectorCombine.cpp index bb4e1c0f67e79..2e8458e2cd03d 100644 --- a/llvm/lib/Transforms/Vectorize/VectorCombine.cpp +++ b/llvm/lib/Transforms/Vectorize/VectorCombine.cpp @@ -1579,6 +1579,11 @@ bool VectorCombine::scalarizeLoadExtract(Instruction &I) { if (!UI || UI->getParent() != LI->getParent()) return false; + // If any extract is waiting to be erased, then bail out as this will + // distort the cost calculation and possibly lead to infinite loops. + if (UI->use_empty()) + return false; + // Check if any instruction between the load and the extract may modify // memory. if (LastCheckedInst->comesBefore(UI)) { diff --git a/llvm/test/Transforms/VectorCombine/X86/load-extractelement-scalarization.ll b/llvm/test/Transforms/VectorCombine/X86/load-extractelement-scalarization.ll index 0acfeccb92ef7..d46c8c0de4037 100644 --- a/llvm/test/Transforms/VectorCombine/X86/load-extractelement-scalarization.ll +++ b/llvm/test/Transforms/VectorCombine/X86/load-extractelement-scalarization.ll @@ -24,3 +24,15 @@ define void @multiple_extract(ptr %p) { store i32 %e1, ptr %p1, align 4 ret void } + +; infinite loop if we fold an extract that is waiting to be erased +define void @unused_extract(ptr %p) { +; CHECK-LABEL: @unused_extract( +; CHECK-NEXT: ret void +; + %load = load <4 x float>, ptr %p, align 8 + %shuffle0 = shufflevector <4 x float> zeroinitializer, <4 x float> %load, <4 x i32> + %shuffle1 = shufflevector <4 x float> %shuffle0, <4 x float> zeroinitializer, <4 x i32> + %extract = extractelement <4 x float> %load, i64 1 + ret void +}