MaskRay created this revision. MaskRay added reviewers: ChuanqiXu, rjmccall. MaskRay requested review of this revision. Herald added a project: clang. Herald added a subscriber: cfe-commits.
See https://lists.llvm.org/pipermail/cfe-dev/2021-August/068740.html A catch clause calls __cxa_begin_catch/__cxa_end_catch. This allows a function with all non-nounwind callees surrounded by catch (...) can infer the nounwind attribute, e.g. `void test() { try { can_throw(); } catch (...) {}}` This can avoid unneeded call site records whose action record offset is 0 (cleanup). In addition, a `__clang_call_terminate` define may be avoided. Note: libcxxrt `__cxa_end_catch` doesn't call external functions. libsupc++/libc++abi `__cxa_end_catch` calls `_Unwind_DeleteException` for a foreign exception. We can except `_Unwind_DeleteException` does not throw (the behavior would be unclear if it throws). Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D108905 Files: clang/lib/CodeGen/ItaniumCXXABI.cpp clang/test/CodeGenCXX/exceptions.cpp clang/test/CodeGenCXX/stack-reuse-exceptions.cpp Index: clang/test/CodeGenCXX/stack-reuse-exceptions.cpp =================================================================== --- clang/test/CodeGenCXX/stack-reuse-exceptions.cpp +++ clang/test/CodeGenCXX/stack-reuse-exceptions.cpp @@ -86,8 +86,8 @@ // // CHECK: [[CATCH]]: // CHECK-NOT: call void @llvm.lifetime -// CHECK: invoke void -// CHECK-NEXT: to label %[[TRY_CONT]] unwind label %[[OUTER_LPAD:.+]] +// CHECK: call void @__cxa_end_catch +// CHECK-NEXT: br label %[[TRY_CONT]] // // CHECK: [[TRY_CONT]]: // CHECK: %[[T_OUTER:[^ ]+]] = bitcast %struct.Large* %{{[^ ]+}} to i8* @@ -100,15 +100,7 @@ // CHECK: call void @llvm.lifetime.end.p0i8({{[^,]+}}, i8* nonnull %[[CLEAN]]) // CHECK: ret void // -// CHECK: [[OUTER_LPAD]]: -// CHECK-NOT: call void @llvm.lifetime -// CHECK: br label %[[EHCLEANUP:.+]] -// -// CHECK: [[OUTER_LPAD2]]: -// CHECK: call void @llvm.lifetime.end.p0i8({{[^,]+}}, i8* nonnull %[[T_OUTER]]) -// CHECK: br label %[[EHCLEANUP]] -// -// CHECK: [[EHCLEANUP]]: +// CHECK: lpad[[#]]: // CHECK: call void @llvm.lifetime.end.p0i8({{[^,]+}}, i8* nonnull %[[CLEAN]]) NontrivialDtor clean; Index: clang/test/CodeGenCXX/exceptions.cpp =================================================================== --- clang/test/CodeGenCXX/exceptions.cpp +++ clang/test/CodeGenCXX/exceptions.cpp @@ -326,9 +326,12 @@ } } +// CHECK11-LABEL: declare{{.*}} i8* @__cxa_begin_catch(i8*) #[[#NOUNWIND:]] + // PR9303: invalid assert on this namespace test6 { bool cond(); + // CHECK11-LABEL: define{{.*}} void @_ZN5test64testEv() #[[#TEST6:]] void test() { try { lbl: @@ -634,3 +637,6 @@ } // CHECK98: attributes [[NI_NR_NUW]] = { noinline noreturn nounwind } + +// CHECK11: attributes #[[#NOUNWIND]] = { nounwind } +// CHECK11: attributes #[[#TEST6]] = {{.*}} nounwind Index: clang/lib/CodeGen/ItaniumCXXABI.cpp =================================================================== --- clang/lib/CodeGen/ItaniumCXXABI.cpp +++ clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -4393,7 +4393,12 @@ llvm::FunctionType *FTy = llvm::FunctionType::get( CGM.Int8PtrTy, CGM.Int8PtrTy, /*isVarArg=*/false); - return CGM.CreateRuntimeFunction(FTy, "__cxa_begin_catch"); + // Set nounwind so that a function with all non-nounwind callees surrounded by + // catch (...) can infer nounwind, which can avoid unneded call site records. + llvm::FunctionCallee Ret = + CGM.CreateRuntimeFunction(FTy, "__cxa_begin_catch"); + cast<llvm::Function>(Ret.getCallee())->addFnAttr(llvm::Attribute::NoUnwind); + return Ret; } static llvm::FunctionCallee getEndCatchFn(CodeGenModule &CGM) { @@ -4401,7 +4406,9 @@ llvm::FunctionType *FTy = llvm::FunctionType::get(CGM.VoidTy, /*isVarArg=*/false); - return CGM.CreateRuntimeFunction(FTy, "__cxa_end_catch"); + llvm::FunctionCallee Ret = CGM.CreateRuntimeFunction(FTy, "__cxa_end_catch"); + cast<llvm::Function>(Ret.getCallee())->addFnAttr(llvm::Attribute::NoUnwind); + return Ret; } static llvm::FunctionCallee getGetExceptionPtrFn(CodeGenModule &CGM) {
Index: clang/test/CodeGenCXX/stack-reuse-exceptions.cpp =================================================================== --- clang/test/CodeGenCXX/stack-reuse-exceptions.cpp +++ clang/test/CodeGenCXX/stack-reuse-exceptions.cpp @@ -86,8 +86,8 @@ // // CHECK: [[CATCH]]: // CHECK-NOT: call void @llvm.lifetime -// CHECK: invoke void -// CHECK-NEXT: to label %[[TRY_CONT]] unwind label %[[OUTER_LPAD:.+]] +// CHECK: call void @__cxa_end_catch +// CHECK-NEXT: br label %[[TRY_CONT]] // // CHECK: [[TRY_CONT]]: // CHECK: %[[T_OUTER:[^ ]+]] = bitcast %struct.Large* %{{[^ ]+}} to i8* @@ -100,15 +100,7 @@ // CHECK: call void @llvm.lifetime.end.p0i8({{[^,]+}}, i8* nonnull %[[CLEAN]]) // CHECK: ret void // -// CHECK: [[OUTER_LPAD]]: -// CHECK-NOT: call void @llvm.lifetime -// CHECK: br label %[[EHCLEANUP:.+]] -// -// CHECK: [[OUTER_LPAD2]]: -// CHECK: call void @llvm.lifetime.end.p0i8({{[^,]+}}, i8* nonnull %[[T_OUTER]]) -// CHECK: br label %[[EHCLEANUP]] -// -// CHECK: [[EHCLEANUP]]: +// CHECK: lpad[[#]]: // CHECK: call void @llvm.lifetime.end.p0i8({{[^,]+}}, i8* nonnull %[[CLEAN]]) NontrivialDtor clean; Index: clang/test/CodeGenCXX/exceptions.cpp =================================================================== --- clang/test/CodeGenCXX/exceptions.cpp +++ clang/test/CodeGenCXX/exceptions.cpp @@ -326,9 +326,12 @@ } } +// CHECK11-LABEL: declare{{.*}} i8* @__cxa_begin_catch(i8*) #[[#NOUNWIND:]] + // PR9303: invalid assert on this namespace test6 { bool cond(); + // CHECK11-LABEL: define{{.*}} void @_ZN5test64testEv() #[[#TEST6:]] void test() { try { lbl: @@ -634,3 +637,6 @@ } // CHECK98: attributes [[NI_NR_NUW]] = { noinline noreturn nounwind } + +// CHECK11: attributes #[[#NOUNWIND]] = { nounwind } +// CHECK11: attributes #[[#TEST6]] = {{.*}} nounwind Index: clang/lib/CodeGen/ItaniumCXXABI.cpp =================================================================== --- clang/lib/CodeGen/ItaniumCXXABI.cpp +++ clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -4393,7 +4393,12 @@ llvm::FunctionType *FTy = llvm::FunctionType::get( CGM.Int8PtrTy, CGM.Int8PtrTy, /*isVarArg=*/false); - return CGM.CreateRuntimeFunction(FTy, "__cxa_begin_catch"); + // Set nounwind so that a function with all non-nounwind callees surrounded by + // catch (...) can infer nounwind, which can avoid unneded call site records. + llvm::FunctionCallee Ret = + CGM.CreateRuntimeFunction(FTy, "__cxa_begin_catch"); + cast<llvm::Function>(Ret.getCallee())->addFnAttr(llvm::Attribute::NoUnwind); + return Ret; } static llvm::FunctionCallee getEndCatchFn(CodeGenModule &CGM) { @@ -4401,7 +4406,9 @@ llvm::FunctionType *FTy = llvm::FunctionType::get(CGM.VoidTy, /*isVarArg=*/false); - return CGM.CreateRuntimeFunction(FTy, "__cxa_end_catch"); + llvm::FunctionCallee Ret = CGM.CreateRuntimeFunction(FTy, "__cxa_end_catch"); + cast<llvm::Function>(Ret.getCallee())->addFnAttr(llvm::Attribute::NoUnwind); + return Ret; } static llvm::FunctionCallee getGetExceptionPtrFn(CodeGenModule &CGM) {
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits