When inlining exception handling code into another function, ensure that
authorDuncan Sands <baldrick@free.fr>
Wed, 7 Sep 2011 16:44:14 +0000 (16:44 +0000)
committerDuncan Sands <baldrick@free.fr>
Wed, 7 Sep 2011 16:44:14 +0000 (16:44 +0000)
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

include/llvm/Intrinsics.td
test/Transforms/GVN/2011-09-07-TypeIdFor.ll [new file with mode: 0644]

index 7646eaaf67fa80dd7e8b0fbeab48f74ef5bfef91..b7b4e7cc06c7d4b297abb6b0a051d99b81a7a9f7 100644 (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]>;
diff --git a/test/Transforms/GVN/2011-09-07-TypeIdFor.ll b/test/Transforms/GVN/2011-09-07-TypeIdFor.ll
new file mode 100644 (file)
index 0000000..eeaf998
--- /dev/null
@@ -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
+}