From 48908fb6d5387082018fb1d8b2f0ddb65e2e2baa Mon Sep 17 00:00:00 2001 From: Phoebe Wang Date: Sat, 27 Jan 2024 22:03:06 +0800 Subject: [PATCH 1/2] [SEH] Ignore EH pad check for internal intrinsics Intrinsics like @llvm.seh.scope.begin and @llvm.seh.scope.end which do not throw do not need funclets in catchpads or cleanuppads. Fixes #69428 Co-authored-by: Robert Cox --- llvm/lib/IR/Verifier.cpp | 5 +++ llvm/test/Verifier/pr69428.ll | 80 +++++++++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+) create mode 100644 llvm/test/Verifier/pr69428.ll diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp index 91cf91fbc788bd..0f1e9fa40c9b03 100644 --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -4280,6 +4280,11 @@ void Verifier::visitEHPadPredecessors(Instruction &I) { if (auto *II = dyn_cast(TI)) { Check(II->getUnwindDest() == BB && II->getNormalDest() != BB, "EH pad must be jumped to via an unwind edge", ToPad, II); + auto *CalledFn = + dyn_cast(II->getCalledOperand()->stripPointerCasts()); + if (CalledFn && CalledFn->isIntrinsic() && II->doesNotThrow() && + !IntrinsicInst::mayLowerToFunctionCall(CalledFn->getIntrinsicID())) + continue; if (auto Bundle = II->getOperandBundle(LLVMContext::OB_funclet)) FromPad = Bundle->Inputs[0]; else diff --git a/llvm/test/Verifier/pr69428.ll b/llvm/test/Verifier/pr69428.ll new file mode 100644 index 00000000000000..22d732076e3af7 --- /dev/null +++ b/llvm/test/Verifier/pr69428.ll @@ -0,0 +1,80 @@ +; RUN: llvm-as -disable-output %s + +%struct._List_node_emplace_op2 = type { i8 } + +$"??1?$_List_node_emplace_op2@H@@QEAA@XZ" = comdat any + +@"?_List@@3HA" = dso_local local_unnamed_addr global i32 0, align 4 + +; Function Attrs: mustprogress noreturn +define dso_local void @"?ExecutionEngineaddExecutableDependency@@YAXXZ"() local_unnamed_addr #0 personality ptr @__CxxFrameHandler3 { +entry: + %agg.tmp.ensured.i = alloca %struct._List_node_emplace_op2, align 1 + call void @llvm.lifetime.start.p0(i64 1, ptr nonnull %agg.tmp.ensured.i) + %0 = load i32, ptr @"?_List@@3HA", align 4 + %call.i = call noundef ptr @"??0?$_List_node_emplace_op2@H@@QEAA@H@Z"(ptr noundef nonnull align 1 dereferenceable(1) %agg.tmp.ensured.i, i32 noundef %0) + invoke void @llvm.seh.scope.begin() + to label %invoke.cont.i unwind label %ehcleanup.i + +invoke.cont.i: ; preds = %entry + invoke void @llvm.seh.scope.end() + to label %invoke.cont2.i unwind label %ehcleanup.i + +invoke.cont2.i: ; preds = %invoke.cont.i + call void @"??1?$_List_node_emplace_op2@H@@QEAA@XZ"(ptr noundef nonnull align 1 dereferenceable(1) %agg.tmp.ensured.i) #6 + unreachable + +ehcleanup.i: ; preds = %invoke.cont.i, %entry + %1 = cleanuppad within none [] + invoke void @llvm.seh.scope.begin() + to label %invoke.cont.i.i unwind label %ehcleanup.i.i + +invoke.cont.i.i: ; preds = %ehcleanup.i + invoke void @llvm.seh.scope.end() + to label %"??1?$_List_node_emplace_op2@H@@QEAA@XZ.exit.i" unwind label %ehcleanup.i.i + +ehcleanup.i.i: ; preds = %invoke.cont.i.i, %ehcleanup.i + %2 = cleanuppad within %1 [] + call void @"??1_Alloc_construct_ptr@@QEAA@XZ"(ptr noundef nonnull align 1 dereferenceable(1) %agg.tmp.ensured.i) #6 [ "funclet"(token %2) ] + cleanupret from %2 unwind to caller + +"??1?$_List_node_emplace_op2@H@@QEAA@XZ.exit.i": ; preds = %invoke.cont.i.i + call void @"??1_Alloc_construct_ptr@@QEAA@XZ"(ptr noundef nonnull align 1 dereferenceable(1) %agg.tmp.ensured.i) #6 [ "funclet"(token %1) ] + cleanupret from %1 unwind to caller +} + +declare dso_local noundef ptr @"??0?$_List_node_emplace_op2@H@@QEAA@H@Z"(ptr noundef nonnull returned align 1 dereferenceable(1), i32 noundef) unnamed_addr #1 + +declare dso_local i32 @__CxxFrameHandler3(...) + +; Function Attrs: nofree nosync nounwind memory(none) +declare dso_local void @llvm.seh.scope.begin() #2 + +; Function Attrs: nofree nosync nounwind memory(none) +declare dso_local void @llvm.seh.scope.end() #2 + +; Function Attrs: mustprogress nounwind +define linkonce_odr dso_local void @"??1?$_List_node_emplace_op2@H@@QEAA@XZ"(ptr noundef nonnull align 1 dereferenceable(1) %this) unnamed_addr #3 comdat align 2 personality ptr @__CxxFrameHandler3 { +entry: + invoke void @llvm.seh.scope.begin() + to label %invoke.cont unwind label %ehcleanup + +invoke.cont: ; preds = %entry + invoke void @llvm.seh.scope.end() + to label %invoke.cont2 unwind label %ehcleanup + +invoke.cont2: ; preds = %invoke.cont + tail call void @"??1_Alloc_construct_ptr@@QEAA@XZ"(ptr noundef nonnull align 1 dereferenceable(1) %this) #6 + ret void + +ehcleanup: ; preds = %invoke.cont, %entry + %0 = cleanuppad within none [] + call void @"??1_Alloc_construct_ptr@@QEAA@XZ"(ptr noundef nonnull align 1 dereferenceable(1) %this) #6 [ "funclet"(token %0) ] + cleanupret from %0 unwind to caller +} + +; Function Attrs: nounwind +declare dso_local void @"??1_Alloc_construct_ptr@@QEAA@XZ"(ptr noundef nonnull align 1 dereferenceable(1)) unnamed_addr #4 + +; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) +declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) #5 From a9ea5c30d2fe81ed8774812bf13700c6a81e4900 Mon Sep 17 00:00:00 2001 From: Phoebe Wang Date: Fri, 2 Feb 2024 20:19:50 +0800 Subject: [PATCH 2/2] Simplify test case --- llvm/test/Verifier/pr69428.ll | 56 ++++++++--------------------------- 1 file changed, 12 insertions(+), 44 deletions(-) diff --git a/llvm/test/Verifier/pr69428.ll b/llvm/test/Verifier/pr69428.ll index 22d732076e3af7..be8733bea1ab39 100644 --- a/llvm/test/Verifier/pr69428.ll +++ b/llvm/test/Verifier/pr69428.ll @@ -2,17 +2,13 @@ %struct._List_node_emplace_op2 = type { i8 } -$"??1?$_List_node_emplace_op2@H@@QEAA@XZ" = comdat any +@"?_List@@3HA" = global i32 0, align 4 -@"?_List@@3HA" = dso_local local_unnamed_addr global i32 0, align 4 - -; Function Attrs: mustprogress noreturn -define dso_local void @"?ExecutionEngineaddExecutableDependency@@YAXXZ"() local_unnamed_addr #0 personality ptr @__CxxFrameHandler3 { +define void @"?ExecutionEngineaddExecutableDependency@@YAXXZ"() personality ptr @__CxxFrameHandler3 { entry: %agg.tmp.ensured.i = alloca %struct._List_node_emplace_op2, align 1 - call void @llvm.lifetime.start.p0(i64 1, ptr nonnull %agg.tmp.ensured.i) %0 = load i32, ptr @"?_List@@3HA", align 4 - %call.i = call noundef ptr @"??0?$_List_node_emplace_op2@H@@QEAA@H@Z"(ptr noundef nonnull align 1 dereferenceable(1) %agg.tmp.ensured.i, i32 noundef %0) + %call.i = call noundef ptr @"??0?$_List_node_emplace_op2@H@@QEAA@H@Z"(ptr %agg.tmp.ensured.i, i32 %0) invoke void @llvm.seh.scope.begin() to label %invoke.cont.i unwind label %ehcleanup.i @@ -21,7 +17,7 @@ invoke.cont.i: ; preds = %entry to label %invoke.cont2.i unwind label %ehcleanup.i invoke.cont2.i: ; preds = %invoke.cont.i - call void @"??1?$_List_node_emplace_op2@H@@QEAA@XZ"(ptr noundef nonnull align 1 dereferenceable(1) %agg.tmp.ensured.i) #6 + call void @"??1?$_List_node_emplace_op2@H@@QEAA@XZ"(ptr %agg.tmp.ensured.i) #6 unreachable ehcleanup.i: ; preds = %invoke.cont.i, %entry @@ -35,46 +31,18 @@ invoke.cont.i.i: ; preds = %ehcleanup.i ehcleanup.i.i: ; preds = %invoke.cont.i.i, %ehcleanup.i %2 = cleanuppad within %1 [] - call void @"??1_Alloc_construct_ptr@@QEAA@XZ"(ptr noundef nonnull align 1 dereferenceable(1) %agg.tmp.ensured.i) #6 [ "funclet"(token %2) ] + call void @"??1_Alloc_construct_ptr@@QEAA@XZ"(ptr %agg.tmp.ensured.i) #6 [ "funclet"(token %2) ] cleanupret from %2 unwind to caller "??1?$_List_node_emplace_op2@H@@QEAA@XZ.exit.i": ; preds = %invoke.cont.i.i - call void @"??1_Alloc_construct_ptr@@QEAA@XZ"(ptr noundef nonnull align 1 dereferenceable(1) %agg.tmp.ensured.i) #6 [ "funclet"(token %1) ] + call void @"??1_Alloc_construct_ptr@@QEAA@XZ"(ptr %agg.tmp.ensured.i) #6 [ "funclet"(token %1) ] cleanupret from %1 unwind to caller } -declare dso_local noundef ptr @"??0?$_List_node_emplace_op2@H@@QEAA@H@Z"(ptr noundef nonnull returned align 1 dereferenceable(1), i32 noundef) unnamed_addr #1 - -declare dso_local i32 @__CxxFrameHandler3(...) - -; Function Attrs: nofree nosync nounwind memory(none) -declare dso_local void @llvm.seh.scope.begin() #2 - -; Function Attrs: nofree nosync nounwind memory(none) -declare dso_local void @llvm.seh.scope.end() #2 - -; Function Attrs: mustprogress nounwind -define linkonce_odr dso_local void @"??1?$_List_node_emplace_op2@H@@QEAA@XZ"(ptr noundef nonnull align 1 dereferenceable(1) %this) unnamed_addr #3 comdat align 2 personality ptr @__CxxFrameHandler3 { -entry: - invoke void @llvm.seh.scope.begin() - to label %invoke.cont unwind label %ehcleanup - -invoke.cont: ; preds = %entry - invoke void @llvm.seh.scope.end() - to label %invoke.cont2 unwind label %ehcleanup - -invoke.cont2: ; preds = %invoke.cont - tail call void @"??1_Alloc_construct_ptr@@QEAA@XZ"(ptr noundef nonnull align 1 dereferenceable(1) %this) #6 - ret void - -ehcleanup: ; preds = %invoke.cont, %entry - %0 = cleanuppad within none [] - call void @"??1_Alloc_construct_ptr@@QEAA@XZ"(ptr noundef nonnull align 1 dereferenceable(1) %this) #6 [ "funclet"(token %0) ] - cleanupret from %0 unwind to caller -} - -; Function Attrs: nounwind -declare dso_local void @"??1_Alloc_construct_ptr@@QEAA@XZ"(ptr noundef nonnull align 1 dereferenceable(1)) unnamed_addr #4 +declare i32 @__CxxFrameHandler3(...) +declare void @llvm.seh.scope.begin() +declare void @llvm.seh.scope.end() -; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) -declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) #5 +declare void @"??1?$_List_node_emplace_op2@H@@QEAA@XZ"(ptr) +declare void @"??1_Alloc_construct_ptr@@QEAA@XZ"(ptr) +declare ptr @"??0?$_List_node_emplace_op2@H@@QEAA@H@Z"(ptr, i32)