; RUN: opt < %s -passes=instcombine -S | FileCheck %s @T1 = external constant i32 @T2 = external constant i32 @T3 = external constant i32 declare i32 @generic_personality(i32, i64, i8*, i8*) declare i32 @__gxx_personality_v0(i32, i64, i8*, i8*) declare i32 @__objc_personality_v0(i32, i64, i8*, i8*) declare i32 @__C_specific_handler(...) declare void @bar() define void @foo_generic() personality i32 (i32, i64, i8*, i8*)* @generic_personality { ; CHECK-LABEL: @foo_generic( invoke void @bar() to label %cont.a unwind label %lpad.a cont.a: invoke void @bar() to label %cont.b unwind label %lpad.b cont.b: invoke void @bar() to label %cont.c unwind label %lpad.c cont.c: invoke void @bar() to label %cont.d unwind label %lpad.d cont.d: invoke void @bar() to label %cont.e unwind label %lpad.e cont.e: invoke void @bar() to label %cont.f unwind label %lpad.f cont.f: invoke void @bar() to label %cont.g unwind label %lpad.g cont.g: invoke void @bar() to label %cont.h unwind label %lpad.h cont.h: invoke void @bar() to label %cont.i unwind label %lpad.i cont.i: ret void lpad.a: %a = landingpad { i8*, i32 } catch i32* @T1 catch i32* @T2 catch i32* @T1 catch i32* @T2 unreachable ; CHECK: %a = landingpad ; CHECK-NEXT: @T1 ; CHECK-NEXT: @T2 ; CHECK-NEXT: unreachable lpad.b: %b = landingpad { i8*, i32 } filter [0 x i32*] zeroinitializer catch i32* @T1 unreachable ; CHECK: %b = landingpad ; CHECK-NEXT: filter ; CHECK-NEXT: unreachable lpad.c: %c = landingpad { i8*, i32 } catch i32* @T1 filter [1 x i32*] [i32* @T1] catch i32* @T2 unreachable ; Caught types should not be removed from filters ; CHECK: %c = landingpad ; CHECK-NEXT: catch i32* @T1 ; CHECK-NEXT: filter [1 x i32*] [i32* @T1] ; CHECK-NEXT: catch i32* @T2 ; CHECK-NEXT: unreachable lpad.d: %d = landingpad { i8*, i32 } filter [3 x i32*] zeroinitializer unreachable ; CHECK: %d = landingpad ; CHECK-NEXT: filter [1 x i32*] zeroinitializer ; CHECK-NEXT: unreachable lpad.e: %e = landingpad { i8*, i32 } catch i32* @T1 filter [3 x i32*] [i32* @T1, i32* @T2, i32* @T2] unreachable ; Caught types should not be removed from filters ; CHECK: %e = landingpad ; CHECK-NEXT: catch i32* @T1 ; CHECK-NEXT: filter [2 x i32*] [i32* @T1, i32* @T2] ; CHECK-NEXT: unreachable lpad.f: %f = landingpad { i8*, i32 } filter [2 x i32*] [i32* @T2, i32* @T1] filter [1 x i32*] [i32* @T1] unreachable ; CHECK: %f = landingpad ; CHECK-NEXT: filter [1 x i32*] [i32* @T1] ; CHECK-NEXT: unreachable lpad.g: %g = landingpad { i8*, i32 } filter [1 x i32*] [i32* @T1] catch i32* @T3 filter [2 x i32*] [i32* @T2, i32* @T1] unreachable ; CHECK: %g = landingpad ; CHECK-NEXT: filter [1 x i32*] [i32* @T1] ; CHECK-NEXT: catch i32* @T3 ; CHECK-NEXT: unreachable lpad.h: %h = landingpad { i8*, i32 } filter [2 x i32*] [i32* @T1, i32* null] filter [1 x i32*] zeroinitializer unreachable ; CHECK: %h = landingpad ; CHECK-NEXT: filter [1 x i32*] zeroinitializer ; CHECK-NEXT: unreachable lpad.i: %i = landingpad { i8*, i32 } cleanup filter [0 x i32*] zeroinitializer unreachable ; CHECK: %i = landingpad ; CHECK-NEXT: filter ; CHECK-NEXT: unreachable } define void @foo_cxx() personality i32 (i32, i64, i8*, i8*)* @__gxx_personality_v0 { ; CHECK-LABEL: @foo_cxx( invoke void @bar() to label %cont.a unwind label %lpad.a cont.a: invoke void @bar() to label %cont.b unwind label %lpad.b cont.b: invoke void @bar() to label %cont.c unwind label %lpad.c cont.c: invoke void @bar() to label %cont.d unwind label %lpad.d cont.d: ret void lpad.a: %a = landingpad { i8*, i32 } catch i32* null catch i32* @T1 unreachable ; CHECK: %a = landingpad ; CHECK-NEXT: null ; CHECK-NEXT: unreachable lpad.b: %b = landingpad { i8*, i32 } filter [1 x i32*] zeroinitializer unreachable ; CHECK: %b = landingpad ; CHECK-NEXT: cleanup ; CHECK-NEXT: unreachable lpad.c: %c = landingpad { i8*, i32 } filter [2 x i32*] [i32* @T1, i32* null] unreachable ; CHECK: %c = landingpad ; CHECK-NEXT: cleanup ; CHECK-NEXT: unreachable lpad.d: %d = landingpad { i8*, i32 } cleanup catch i32* null unreachable ; CHECK: %d = landingpad ; CHECK-NEXT: null ; CHECK-NEXT: unreachable } define void @foo_objc() personality i32 (i32, i64, i8*, i8*)* @__objc_personality_v0 { ; CHECK-LABEL: @foo_objc( invoke void @bar() to label %cont.a unwind label %lpad.a cont.a: invoke void @bar() to label %cont.b unwind label %lpad.b cont.b: invoke void @bar() to label %cont.c unwind label %lpad.c cont.c: invoke void @bar() to label %cont.d unwind label %lpad.d cont.d: ret void lpad.a: %a = landingpad { i8*, i32 } catch i32* null catch i32* @T1 unreachable ; CHECK: %a = landingpad ; CHECK-NEXT: null ; CHECK-NEXT: unreachable lpad.b: %b = landingpad { i8*, i32 } filter [1 x i32*] zeroinitializer unreachable ; CHECK: %b = landingpad ; CHECK-NEXT: cleanup ; CHECK-NEXT: unreachable lpad.c: %c = landingpad { i8*, i32 } filter [2 x i32*] [i32* @T1, i32* null] unreachable ; CHECK: %c = landingpad ; CHECK-NEXT: cleanup ; CHECK-NEXT: unreachable lpad.d: %d = landingpad { i8*, i32 } cleanup catch i32* null unreachable ; CHECK: %d = landingpad ; CHECK-NEXT: null ; CHECK-NEXT: unreachable } define void @foo_seh() personality i32 (...)* @__C_specific_handler { ; CHECK-LABEL: @foo_seh( invoke void @bar() to label %cont.a unwind label %lpad.a cont.a: invoke void @bar() to label %cont.b unwind label %lpad.b cont.b: invoke void @bar() to label %cont.c unwind label %lpad.c cont.c: invoke void @bar() to label %cont.d unwind label %lpad.d cont.d: ret void lpad.a: %a = landingpad { i8*, i32 } catch i32* null catch i32* @T1 unreachable ; CHECK: %a = landingpad ; CHECK-NEXT: null ; CHECK-NEXT: unreachable lpad.b: %b = landingpad { i8*, i32 } filter [1 x i32*] zeroinitializer unreachable ; CHECK: %b = landingpad ; CHECK-NEXT: cleanup ; CHECK-NEXT: unreachable lpad.c: %c = landingpad { i8*, i32 } filter [2 x i32*] [i32* @T1, i32* null] unreachable ; CHECK: %c = landingpad ; CHECK-NEXT: cleanup ; CHECK-NEXT: unreachable lpad.d: %d = landingpad { i8*, i32 } cleanup catch i32* null unreachable ; CHECK: %d = landingpad ; CHECK-NEXT: null ; CHECK-NEXT: unreachable }