diff options
-rw-r--r-- | llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp | 18 | ||||
-rw-r--r-- | llvm/test/Transforms/InstCombine/insert-extract-shuffle.ll | 30 |
2 files changed, 47 insertions, 1 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp b/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp index 5cde31a9162..bc4c0ebae79 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp @@ -380,6 +380,23 @@ static void replaceExtractElements(InsertElementInst *InsElt, ExtendMask.push_back(UndefValue::get(IntType)); Value *ExtVecOp = ExtElt->getVectorOperand(); + auto *ExtVecOpInst = dyn_cast<Instruction>(ExtVecOp); + BasicBlock *InsertionBlock = (ExtVecOpInst && !isa<PHINode>(ExtVecOpInst)) + ? ExtVecOpInst->getParent() + : ExtElt->getParent(); + + // TODO: This restriction matches the basic block check below when creating + // new extractelement instructions. If that limitation is removed, this one + // could also be removed. But for now, we just bail out to ensure that we + // will replace the extractelement instruction that is feeding our + // insertelement instruction. This allows the insertelement to then be + // replaced by a shufflevector. If the insertelement is not replaced, we can + // induce infinite looping because there's an optimization for extractelement + // that will delete our widening shuffle. This would trigger another attempt + // here to create that shuffle, and we spin forever. + if (InsertionBlock != InsElt->getParent()) + return; + auto *WideVec = new ShuffleVectorInst(ExtVecOp, UndefValue::get(ExtVecType), ConstantVector::get(ExtendMask)); @@ -387,7 +404,6 @@ static void replaceExtractElements(InsertElementInst *InsElt, // (as long as it's not a PHI) or at the start of the basic block of the // extract, so any subsequent extracts in the same basic block can use it. // TODO: Insert before the earliest ExtractElementInst that is replaced. - auto *ExtVecOpInst = dyn_cast<Instruction>(ExtVecOp); if (ExtVecOpInst && !isa<PHINode>(ExtVecOpInst)) WideVec->insertAfter(ExtVecOpInst); else diff --git a/llvm/test/Transforms/InstCombine/insert-extract-shuffle.ll b/llvm/test/Transforms/InstCombine/insert-extract-shuffle.ll index 47c2a139a47..8ed4db8bbbc 100644 --- a/llvm/test/Transforms/InstCombine/insert-extract-shuffle.ll +++ b/llvm/test/Transforms/InstCombine/insert-extract-shuffle.ll @@ -175,3 +175,33 @@ bb3: ret <4 x double> %tmp4 } +; PR26354: https://llvm.org/bugs/show_bug.cgi?id=26354 +; Don't create a shufflevector if we know that we're not going to replace the insertelement. + +define double @pr26354(<2 x double>* %tmp, i1 %B) { +; CHECK-LABEL: @pr26354( +; CHECK: %ld = load <2 x double>, <2 x double>* %tmp +; CHECK-NEXT: %e1 = extractelement <2 x double> %ld, i32 0 +; CHECK-NEXT: br i1 %B, label %if, label %end +; CHECK: if: +; CHECK-NEXT: %e2 = extractelement <2 x double> %ld, i32 1 +; CHECK-NEXT: %i1 = insertelement <4 x double> +; CHECK-NEXT: br label %end + +entry: + %ld = load <2 x double>, <2 x double>* %tmp + %e1 = extractelement <2 x double> %ld, i32 0 + %e2 = extractelement <2 x double> %ld, i32 1 + br i1 %B, label %if, label %end + +if: + %i1 = insertelement <4 x double> zeroinitializer, double %e2, i32 3 + br label %end + +end: + %ph = phi <4 x double> [ undef, %entry ], [ %i1, %if ] + %e3 = extractelement <4 x double> %ph, i32 1 + %mu = fmul double %e1, %e3 + ret double %mu +} + |