When inlining exception handling code into another function, ensure that

duplicate tests are eliminated (for example if the two functions both have
a catch clause catching the same type, ensure the redundant one is removed).
Note that it would probably be safe to say that eh.typeid.for is 'const',
but since two calls to it with the same argument can give different results
(but only if the calls are in different functions), it seems more correct to
mark it only 'pure'; this doesn't get in the way of the optimization.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@139236 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Duncan Sands 2011-09-07 16:44:14 +00:00
parent ffa5a76344
commit 758ba1f4ed
2 changed files with 79 additions and 1 deletions

View File

@ -309,7 +309,7 @@ def int_eh_selector : Intrinsic<[llvm_i32_ty],
[llvm_ptr_ty, llvm_ptr_ty, llvm_vararg_ty]>;
def int_eh_resume : Intrinsic<[], [llvm_ptr_ty, llvm_i32_ty], [Throws]>;
def int_eh_typeid_for : Intrinsic<[llvm_i32_ty], [llvm_ptr_ty]>;
def int_eh_typeid_for : Intrinsic<[llvm_i32_ty], [llvm_ptr_ty], [IntrReadMem]>;
def int_eh_return_i32 : Intrinsic<[], [llvm_i32_ty, llvm_ptr_ty]>;
def int_eh_return_i64 : Intrinsic<[], [llvm_i64_ty, llvm_ptr_ty]>;

View File

@ -0,0 +1,78 @@
; RUN: opt < %s -basicaa -gvn -S | FileCheck %s
%struct.__fundamental_type_info_pseudo = type { %struct.__type_info_pseudo }
%struct.__type_info_pseudo = type { i8*, i8* }
@_ZTIi = external constant %struct.__fundamental_type_info_pseudo
@_ZTIb = external constant %struct.__fundamental_type_info_pseudo
declare void @_Z4barv()
declare i32 @llvm.eh.typeid.for(i8*) nounwind readonly
declare i8* @__cxa_begin_catch(i8*) nounwind
declare void @__cxa_end_catch()
declare i32 @__gxx_personality_v0(i32, i64, i8*, i8*)
define void @_Z3foov() uwtable {
entry:
invoke void @_Z4barv()
to label %return unwind label %lpad
lpad: ; preds = %entry
%0 = landingpad { i8*, i32 } personality i32 (i32, i64, i8*, i8*)* @__gxx_personality_v0
catch %struct.__fundamental_type_info_pseudo* @_ZTIi
catch %struct.__fundamental_type_info_pseudo* @_ZTIb
catch %struct.__fundamental_type_info_pseudo* @_ZTIi
catch %struct.__fundamental_type_info_pseudo* @_ZTIb
%exc_ptr2.i = extractvalue { i8*, i32 } %0, 0
%filter3.i = extractvalue { i8*, i32 } %0, 1
%typeid.i = tail call i32 @llvm.eh.typeid.for(i8* bitcast (%struct.__fundamental_type_info_pseudo* @_ZTIi to i8*))
; CHECK: call i32 @llvm.eh.typeid.for
%1 = icmp eq i32 %filter3.i, %typeid.i
br i1 %1, label %ppad, label %next
next: ; preds = %lpad
%typeid1.i = tail call i32 @llvm.eh.typeid.for(i8* bitcast (%struct.__fundamental_type_info_pseudo* @_ZTIb to i8*))
; CHECK: call i32 @llvm.eh.typeid.for
%2 = icmp eq i32 %filter3.i, %typeid1.i
br i1 %2, label %ppad2, label %next2
ppad: ; preds = %lpad
%3 = tail call i8* @__cxa_begin_catch(i8* %exc_ptr2.i) nounwind
tail call void @__cxa_end_catch() nounwind
br label %return
ppad2: ; preds = %next
%D.2073_5.i = tail call i8* @__cxa_begin_catch(i8* %exc_ptr2.i) nounwind
tail call void @__cxa_end_catch() nounwind
br label %return
next2: ; preds = %next
%typeid = tail call i32 @llvm.eh.typeid.for(i8* bitcast (%struct.__fundamental_type_info_pseudo* @_ZTIi to i8*))
; CHECK-NOT: call i32 @llvm.eh.typeid.for
%4 = icmp eq i32 %filter3.i, %typeid
br i1 %4, label %ppad3, label %next3
next3: ; preds = %next2
%typeid1 = tail call i32 @llvm.eh.typeid.for(i8* bitcast (%struct.__fundamental_type_info_pseudo* @_ZTIb to i8*))
%5 = icmp eq i32 %filter3.i, %typeid1
br i1 %5, label %ppad4, label %unwind
unwind: ; preds = %next3
resume { i8*, i32 } %0
ppad3: ; preds = %next2
%6 = tail call i8* @__cxa_begin_catch(i8* %exc_ptr2.i) nounwind
tail call void @__cxa_end_catch() nounwind
br label %return
ppad4: ; preds = %next3
%D.2080_5 = tail call i8* @__cxa_begin_catch(i8* %exc_ptr2.i) nounwind
tail call void @__cxa_end_catch() nounwind
br label %return
return: ; preds = %ppad4, %ppad3, %ppad2, %ppad, %entry
ret void
}