| ; RUN: opt < %s -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 |
| } |