diff --git a/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp b/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp --- a/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp +++ b/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp @@ -3447,6 +3447,26 @@ // Don't bother if the instruction is in a BB which ends in an EHPad. if (UseBB->getTerminator()->isEHPad()) continue; + + // Check if a PHI node has reference-equal inputs which are terminated + // with non-splittable instructions + if (isa(UserInst)) { + const auto *PhiNode = cast(UserInst); + bool HasIncompatibleEHPTerminatedBlock = false; + llvm::Value *ExpectedValue = U; + for (unsigned int I = 0; I < PhiNode->getNumIncomingValues(); I++) { + if (PhiNode->getIncomingValue(I) == ExpectedValue) { + if (PhiNode->getIncomingBlock(I)->getTerminator()->isEHPad()) { + HasIncompatibleEHPTerminatedBlock = true; + break; + } + } + } + if (HasIncompatibleEHPTerminatedBlock) { + continue; + } + } + // Don't bother rewriting PHIs in catchswitch blocks. if (isa(UserInst->getParent()->getTerminator())) continue; diff --git a/llvm/test/Transforms/LoopStrengthReduce/X86/issue48708.ll b/llvm/test/Transforms/LoopStrengthReduce/X86/issue48708.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/LoopStrengthReduce/X86/issue48708.ll @@ -0,0 +1,72 @@ +; RUN: opt -loop-reduce -S %s +target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:6:2:64-S128" + +%"class.absl::Storage" = type {} +%"struct.absl::allocator_traits" = type {} +%"struct.absl::StorageView" = type { %"class.std::allocator"*, i32, i32 } +%"class.std::allocator" = type { i8 } +%"class.std::move_iterator" = type { i8 } + +define void @0(%"class.absl::Storage"* %0, %"struct.absl::allocator_traits" %1) personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) { + %3 = alloca %"struct.absl::StorageView", align 8 + %4 = alloca i8, align 1 + %5 = alloca %"class.std::move_iterator", align 8 + %6 = bitcast %"struct.absl::StorageView"* %3 to i8* + %7 = call i8 @"forward@V"(i8 undef) + %8 = call %"class.std::allocator"* @"forward@PEAV"(%"class.std::allocator"* null) + %9 = getelementptr i8, i8* %4 + %10 = getelementptr %"struct.absl::StorageView", %"struct.absl::StorageView"* %3, i64 0, i32 0 + %11 = load %"class.std::allocator"*, %"class.std::allocator"** %10, align 8 + %12 = invoke %"class.std::move_iterator"* @"move_iterator"(%"class.std::move_iterator"* %5, %"class.std::allocator"* %11) + to label %13 unwind label %33 + +13: ; preds = %2 + %14 = getelementptr %"class.std::move_iterator", %"class.std::move_iterator"* %5, i64 0, i32 0 + %15 = load i8, i8* %14, align 1 + %16 = invoke i8* @"IteratorValueAdapter"(i8* %4, i8 5) + to label %17 unwind label %33 + +17: ; preds = %13 + %18 = getelementptr %"struct.absl::StorageView", %"struct.absl::StorageView"* %3, i64 0, i32 2 + %19 = load i32, i32* %18, align 4 + %20 = icmp eq i32 9, 0 + %21 = select i1 %20, %"class.std::allocator"* %8, %"class.std::allocator"* null + br label %22 + +22: ; preds = %25, %17 + %23 = phi i64 [ %26, %25 ], [ 0, %17 ] + %24 = getelementptr %"class.std::allocator", %"class.std::allocator"* %21, i64 %23 + invoke void @"ConstructNext"(i8* %4, %"class.std::allocator"* null, %"class.std::allocator"* %24) + to label %25 unwind label %27 + +25: ; preds = %22 + %26 = add i64 %23, 1 + br label %22 + +27: ; preds = %22 + %28 = catchswitch within none [label %29] unwind label %33 + +29: ; preds = %27 + %30 = catchpad within %28 [] + catchret from %30 to label %31 + +31: ; preds = %29 + invoke void @"SetIsAllocated"(%"class.absl::Storage"* %0) + to label %32 unwind label %33 + +32: ; preds = %31 + unreachable + +33: ; preds = %31, %27, %13, %2 + %34 = phi %"class.std::allocator"* [ %21, %27 ], [ %21, %31 ], [ %8, %13 ], [ %8, %2 ] + %35 = cleanuppad within none [] + cleanupret from %35 unwind to caller +} + +declare %"class.std::move_iterator"* @"move_iterator"(%"class.std::move_iterator"*, %"class.std::allocator"*) +declare i32 @__CxxFrameHandler3(...) +declare i8* @"IteratorValueAdapter"(i8*, i8) +declare void @"SetIsAllocated"(%"class.absl::Storage"*) +declare i8 @"forward@V"(i8) +declare %"class.std::allocator"* @"forward@PEAV"(%"class.std::allocator"*) +declare void @"ConstructNext"(i8*, %"class.std::allocator"*, %"class.std::allocator"*)