Index: llvm/lib/Transforms/InstCombine/InstCombinePHI.cpp =================================================================== --- llvm/lib/Transforms/InstCombine/InstCombinePHI.cpp +++ llvm/lib/Transforms/InstCombine/InstCombinePHI.cpp @@ -1316,9 +1316,12 @@ if (Instruction *Result = foldPHIArgOpIntoPHI(PN)) return Result; + // "catchswitch" blocks cannot have any other non-phis. + bool IsCatchSwitch = isa(PN.getParent()->getTerminator()); + // If the incoming values are pointer casts of the same original value, // replace the phi with a single cast. - if (PN.getType()->isPointerTy()) { + if (PN.getType()->isPointerTy() && !IsCatchSwitch) { Value *IV0 = PN.getIncomingValue(0); Value *IV0Stripped = IV0->stripPointerCasts(); // Set to keep track of values known to be equal to IV0Stripped after Index: llvm/test/Transforms/InstCombine/phi-catchswitch.ll =================================================================== --- /dev/null +++ llvm/test/Transforms/InstCombine/phi-catchswitch.ll @@ -0,0 +1,74 @@ +; RUN: opt -passes=instcombine -S %s | FileCheck %s + +; Catchswitch blocks may only contain phi and catchswitch. +; phi => bitcast transform must be suppressed in these blocks. + +; CHECK-LABEL: bb9: +; CHECK: phi i8* +; CHECK-NEXT: catchswitch +; CHECK-LABEL: bb12: + +source_filename = "memory_attributes-host-x86_64-pc-windows-msvc.ii" +target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-pc-windows-msvc19.16.27045" + +%struct.snork = type { i8**, i8*, [24 x i8] } +@global = external global %struct.snork + +; Function Attrs: argmemonly nofree nosync nounwind willreturn +declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture) #0 + +define dso_local void @main() local_unnamed_addr #1 personality i32 (...)* @__CxxFrameHandler3 { +bb: + %tmp = alloca i32, align 8 + invoke void @baz.3() + to label %bb1 unwind label %bb3 + +bb1: ; preds = %bb + invoke void @quux() + to label %bb2 unwind label %bb6 + +bb2: ; preds = %bb1 + unreachable + +bb3: ; preds = %bb + %tmp4 = cleanuppad within none [] + %tmp5 = bitcast i32* %tmp to i8* + cleanupret from %tmp4 unwind label %bb9 + +bb6: ; preds = %bb1 + %tmp7 = cleanuppad within none [] + %tmp8 = bitcast i32* %tmp to i8* + cleanupret from %tmp7 unwind label %bb9 + +bb9: ; preds = %bb6, %bb3 + %tmp10 = phi i8* [ %tmp8, %bb6 ], [ %tmp5, %bb3 ] + %tmp11 = catchswitch within none [label %bb12] unwind label %bb15 + +bb12: ; preds = %bb9 + %tmp13 = catchpad within %tmp11 [%struct.snork* @global, i32 8, i32** undef] + invoke void @baz() [ "funclet"(token %tmp13) ] + to label %bb14 unwind label %bb15 + +bb14: ; preds = %bb12 + unreachable + +bb15: ; preds = %bb12, %bb9 + %tmp16 = cleanuppad within none [] + call void @llvm.lifetime.end.p0i8(i64 40, i8* nonnull %tmp10) #3 + cleanupret from %tmp16 unwind to caller +} + +declare dso_local void @baz() local_unnamed_addr #1 + +; Function Attrs: nofree +declare dso_local i32 @__CxxFrameHandler3(...) #2 + +declare dllimport void @baz.3() unnamed_addr #1 + +declare dso_local void @quux() unnamed_addr #1 align 2 + +attributes #0 = { argmemonly nofree nosync nounwind willreturn } +attributes #1 = { "unsafe-fp-math"="true" } +attributes #2 = { nofree } +attributes #3 = { nounwind }