Home | History | Annotate | Download | only in X86
      1 ; RUN: opt -mtriple=x86_64-linux-gnu -dwarfehprepare < %s -S | FileCheck %s
      2 
      3 ; Check basic functionality of IR-to-IR DWARF EH preparation. This should
      4 ; eliminate resumes. This pass requires a TargetMachine, so we put it under X86
      5 ; and provide an x86 triple.
      6 
      7 @int_typeinfo = global i8 0
      8 
      9 declare void @might_throw()
     10 declare void @cleanup()
     11 
     12 define i32 @simple_cleanup_catch() personality i32 (...)* @__gxx_personality_v0 {
     13   invoke void @might_throw()
     14           to label %cont unwind label %lpad
     15 
     16 ; CHECK-LABEL: define i32 @simple_cleanup_catch()
     17 ; CHECK: invoke void @might_throw()
     18 
     19 cont:
     20   ret i32 0
     21 
     22 ; CHECK: ret i32 0
     23 
     24 lpad:
     25   %ehvals = landingpad { i8*, i32 }
     26       cleanup
     27       catch i8* @int_typeinfo
     28   %ehptr = extractvalue { i8*, i32 } %ehvals, 0
     29   %ehsel = extractvalue { i8*, i32 } %ehvals, 1
     30   call void @cleanup()
     31   %int_sel = call i32 @llvm.eh.typeid.for(i8* @int_typeinfo)
     32   %int_match = icmp eq i32 %ehsel, %int_sel
     33   br i1 %int_match, label %catch_int, label %eh.resume
     34 
     35 ; CHECK: lpad:
     36 ; CHECK: landingpad { i8*, i32 }
     37 ; CHECK: call void @cleanup()
     38 ; CHECK: call i32 @llvm.eh.typeid.for
     39 ; CHECK: br i1
     40 
     41 catch_int:
     42   ret i32 1
     43 
     44 ; CHECK: catch_int:
     45 ; CHECK: ret i32 1
     46 
     47 eh.resume:
     48   %tmp_ehvals = insertvalue { i8*, i32 } undef, i8* %ehptr, 0
     49   %new_ehvals = insertvalue { i8*, i32 } %tmp_ehvals, i32 %ehsel, 1
     50   resume { i8*, i32 } %new_ehvals
     51 
     52 ; CHECK: eh.resume:
     53 ; CHECK-NEXT: call void @_Unwind_Resume(i8* %ehptr)
     54 }
     55 
     56 
     57 define i32 @catch_no_resume() personality i32 (...)* @__gxx_personality_v0 {
     58   invoke void @might_throw()
     59           to label %cont unwind label %lpad
     60 
     61 cont:
     62   ret i32 0
     63 
     64 lpad:
     65   %ehvals = landingpad { i8*, i32 }
     66       catch i8* @int_typeinfo
     67   %ehptr = extractvalue { i8*, i32 } %ehvals, 0
     68   %ehsel = extractvalue { i8*, i32 } %ehvals, 1
     69   %int_sel = call i32 @llvm.eh.typeid.for(i8* @int_typeinfo)
     70   %int_match = icmp eq i32 %ehsel, %int_sel
     71   br i1 %int_match, label %catch_int, label %eh.resume
     72 
     73 catch_int:
     74   ret i32 1
     75 
     76 eh.resume:
     77   %tmp_ehvals = insertvalue { i8*, i32 } undef, i8* %ehptr, 0
     78   %new_ehvals = insertvalue { i8*, i32 } %tmp_ehvals, i32 %ehsel, 1
     79   resume { i8*, i32 } %new_ehvals
     80 }
     81 
     82 ; Check that we can prune the unreachable resume instruction.
     83 
     84 ; CHECK-LABEL: define i32 @catch_no_resume() personality i32 (...)* @__gxx_personality_v0 {
     85 ; CHECK: invoke void @might_throw()
     86 ; CHECK: ret i32 0
     87 ; CHECK: lpad:
     88 ; CHECK: landingpad { i8*, i32 }
     89 ; CHECK-NOT: br i1
     90 ; CHECK: ret i32 1
     91 ; CHECK-NOT: call void @_Unwind_Resume
     92 ; CHECK: {{^[}]}}
     93 
     94 
     95 define i32 @catch_cleanup_merge() personality i32 (...)* @__gxx_personality_v0 {
     96   invoke void @might_throw()
     97           to label %inner_invoke unwind label %outer_lpad
     98 inner_invoke:
     99   invoke void @might_throw()
    100           to label %cont unwind label %inner_lpad
    101 cont:
    102   ret i32 0
    103 
    104 outer_lpad:
    105   %ehvals1 = landingpad { i8*, i32 }
    106       catch i8* @int_typeinfo
    107   br label %catch.dispatch
    108 
    109 inner_lpad:
    110   %ehvals2 = landingpad { i8*, i32 }
    111       cleanup
    112       catch i8* @int_typeinfo
    113   call void @cleanup()
    114   br label %catch.dispatch
    115 
    116 catch.dispatch:
    117   %ehvals = phi { i8*, i32 } [ %ehvals1, %outer_lpad ], [ %ehvals2, %inner_lpad ]
    118   %ehptr = extractvalue { i8*, i32 } %ehvals, 0
    119   %ehsel = extractvalue { i8*, i32 } %ehvals, 1
    120   %int_sel = call i32 @llvm.eh.typeid.for(i8* @int_typeinfo)
    121   %int_match = icmp eq i32 %ehsel, %int_sel
    122   br i1 %int_match, label %catch_int, label %eh.resume
    123 
    124 catch_int:
    125   ret i32 1
    126 
    127 eh.resume:
    128   %tmp_ehvals = insertvalue { i8*, i32 } undef, i8* %ehptr, 0
    129   %new_ehvals = insertvalue { i8*, i32 } %tmp_ehvals, i32 %ehsel, 1
    130   resume { i8*, i32 } %new_ehvals
    131 }
    132 
    133 ; We can't prune this merge because one landingpad is a cleanup pad.
    134 
    135 ; CHECK-LABEL: define i32 @catch_cleanup_merge()
    136 ; CHECK: invoke void @might_throw()
    137 ; CHECK: invoke void @might_throw()
    138 ; CHECK: ret i32 0
    139 ;
    140 ; CHECK: outer_lpad:
    141 ; CHECK: landingpad { i8*, i32 }
    142 ; CHECK: br label %catch.dispatch
    143 ;
    144 ; CHECK: inner_lpad:
    145 ; CHECK: landingpad { i8*, i32 }
    146 ; CHECK: call void @cleanup()
    147 ; CHECK: br label %catch.dispatch
    148 ;
    149 ; CHECK: catch.dispatch:
    150 ; CHECK: call i32 @llvm.eh.typeid.for
    151 ; CHECK: br i1
    152 ; CHECK: catch_int:
    153 ; CHECK: ret i32 1
    154 ; CHECK: eh.resume:
    155 ; CHECK-NEXT: call void @_Unwind_Resume(i8* %ehptr)
    156 
    157 declare i32 @__gxx_personality_v0(...)
    158 declare i32 @llvm.eh.typeid.for(i8*)
    159