Compiler projects using llvm
; 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
}