llvm/llvm/test/Transforms/InstCombine/LandingPadClauses.ll

; 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, ptr, ptr)
declare i32 @__gxx_personality_v0(i32, i64, ptr, ptr)
declare i32 @__objc_personality_v0(i32, i64, ptr, ptr)
declare i32 @__C_specific_handler(...)

declare void @bar()

define void @foo_generic() personality ptr @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 { ptr, i32 }
          catch ptr @T1
          catch ptr @T2
          catch ptr @T1
          catch ptr @T2
  unreachable
; CHECK: %a = landingpad
; CHECK-NEXT: @T1
; CHECK-NEXT: @T2
; CHECK-NEXT: unreachable

lpad.b:
  %b = landingpad { ptr, i32 }
          filter [0 x ptr] zeroinitializer
          catch ptr @T1
  unreachable
; CHECK: %b = landingpad
; CHECK-NEXT: filter
; CHECK-NEXT: unreachable

lpad.c:
  %c = landingpad { ptr, i32 }
          catch ptr @T1
          filter [1 x ptr] [ptr @T1]
          catch ptr @T2
  unreachable
; Caught types should not be removed from filters
; CHECK: %c = landingpad
; CHECK-NEXT: catch ptr @T1
; CHECK-NEXT: filter [1 x ptr] [ptr @T1]
; CHECK-NEXT: catch ptr @T2 
; CHECK-NEXT: unreachable

lpad.d:
  %d = landingpad { ptr, i32 }
          filter [3 x ptr] zeroinitializer
  unreachable
; CHECK: %d = landingpad
; CHECK-NEXT: filter [1 x ptr] zeroinitializer
; CHECK-NEXT: unreachable

lpad.e:
  %e = landingpad { ptr, i32 }
          catch ptr @T1
          filter [3 x ptr] [ptr @T1, ptr @T2, ptr @T2]
  unreachable
; Caught types should not be removed from filters
; CHECK: %e = landingpad
; CHECK-NEXT: catch ptr @T1
; CHECK-NEXT: filter [2 x ptr] [ptr @T1, ptr @T2]
; CHECK-NEXT: unreachable

lpad.f:
  %f = landingpad { ptr, i32 }
          filter [2 x ptr] [ptr @T2, ptr @T1]
          filter [1 x ptr] [ptr @T1]
  unreachable
; CHECK: %f = landingpad
; CHECK-NEXT: filter [1 x ptr] [ptr @T1]
; CHECK-NEXT: unreachable

lpad.g:
  %g = landingpad { ptr, i32 }
          filter [1 x ptr] [ptr @T1]
          catch ptr @T3
          filter [2 x ptr] [ptr @T2, ptr @T1]
  unreachable
; CHECK: %g = landingpad
; CHECK-NEXT: filter [1 x ptr] [ptr @T1]
; CHECK-NEXT: catch ptr @T3
; CHECK-NEXT: unreachable

lpad.h:
  %h = landingpad { ptr, i32 }
          filter [2 x ptr] [ptr @T1, ptr null]
          filter [1 x ptr] zeroinitializer
  unreachable
; CHECK: %h = landingpad
; CHECK-NEXT: filter [1 x ptr] zeroinitializer
; CHECK-NEXT: unreachable

lpad.i:
  %i = landingpad { ptr, i32 }
          cleanup
          filter [0 x ptr] zeroinitializer
  unreachable
; CHECK: %i = landingpad
; CHECK-NEXT: filter
; CHECK-NEXT: unreachable
}

define void @foo_cxx() personality ptr @__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 { ptr, i32 }
          catch ptr null
          catch ptr @T1
  unreachable
; CHECK: %a = landingpad
; CHECK-NEXT: null
; CHECK-NEXT: unreachable

lpad.b:
  %b = landingpad { ptr, i32 }
          filter [1 x ptr] zeroinitializer
  unreachable
; CHECK: %b = landingpad
; CHECK-NEXT: cleanup
; CHECK-NEXT: unreachable

lpad.c:
  %c = landingpad { ptr, i32 }
          filter [2 x ptr] [ptr @T1, ptr null]
  unreachable
; CHECK: %c = landingpad
; CHECK-NEXT: cleanup
; CHECK-NEXT: unreachable

lpad.d:
  %d = landingpad { ptr, i32 }
          cleanup
          catch ptr null
  unreachable
; CHECK: %d = landingpad
; CHECK-NEXT: null
; CHECK-NEXT: unreachable
}

define void @foo_objc() personality ptr @__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 { ptr, i32 }
          catch ptr null
          catch ptr @T1
  unreachable
; CHECK: %a = landingpad
; CHECK-NEXT: null
; CHECK-NEXT: unreachable

lpad.b:
  %b = landingpad { ptr, i32 }
          filter [1 x ptr] zeroinitializer
  unreachable
; CHECK: %b = landingpad
; CHECK-NEXT: cleanup
; CHECK-NEXT: unreachable

lpad.c:
  %c = landingpad { ptr, i32 }
          filter [2 x ptr] [ptr @T1, ptr null]
  unreachable
; CHECK: %c = landingpad
; CHECK-NEXT: cleanup
; CHECK-NEXT: unreachable

lpad.d:
  %d = landingpad { ptr, i32 }
          cleanup
          catch ptr null
  unreachable
; CHECK: %d = landingpad
; CHECK-NEXT: null
; CHECK-NEXT: unreachable
}

define void @foo_seh() personality ptr @__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 { ptr, i32 }
          catch ptr null
          catch ptr @T1
  unreachable
; CHECK: %a = landingpad
; CHECK-NEXT: null
; CHECK-NEXT: unreachable

lpad.b:
  %b = landingpad { ptr, i32 }
          filter [1 x ptr] zeroinitializer
  unreachable
; CHECK: %b = landingpad
; CHECK-NEXT: cleanup
; CHECK-NEXT: unreachable

lpad.c:
  %c = landingpad { ptr, i32 }
          filter [2 x ptr] [ptr @T1, ptr null]
  unreachable
; CHECK: %c = landingpad
; CHECK-NEXT: cleanup
; CHECK-NEXT: unreachable

lpad.d:
  %d = landingpad { ptr, i32 }
          cleanup
          catch ptr null
  unreachable
; CHECK: %d = landingpad
; CHECK-NEXT: null
; CHECK-NEXT: unreachable
}