[clang] [NFC] [Clang] [CodeGen] Reduce code duplication when emitting trap calls (PR #221022)
Ambrose Leeb via cfe-commits
cfe-commits at lists.llvm.org
Thu Sep 3 12:00:36 PDT 2026
https://github.com/Sirraide created https://github.com/llvm/llvm-project/pull/221022
There are a number of places in codegen where we do this:
```c++
llvm::CallInst *TrapCall = EmitTrapCall(llvm::Intrinsic::trap);
TrapCall->setDoesNotReturn();
TrapCall->setDoesNotThrow();
Builder.CreateUnreachable();
Builder.ClearInsertionPoint();
```
This patch adds a helper that does this and updates `EmitTrapCall()` to no longer create a new block after emitting the trap call.
One test had to be updated because an unnecessary block was dropped. Before, we were generating this:
```llvm
dtor.call_delete_after_array_destroy: ; preds = %dtor.vector.cont
call void @llvm.trap() #7
unreachable
6: ; No predecessors!
unreachable
```
The second block here is now no longer present, which caused some instruction renumbering.
>From ab9b5b1a55fd4203a42d8e0309f4c71b81fe818b Mon Sep 17 00:00:00 2001
From: Ambrose Leeb <aleeb at nvidia.com>
Date: Thu, 3 Sep 2026 20:55:37 +0200
Subject: [PATCH] [Clang] [NFC] Reduce code duplication when emitting trap
calls
---
clang/lib/CodeGen/CGClass.cpp | 12 ++----------
clang/lib/CodeGen/CGExpr.cpp | 19 +++++++++++++++++--
clang/lib/CodeGen/CodeGenFunction.cpp | 18 +++---------------
clang/lib/CodeGen/CodeGenFunction.h | 10 +++++++---
.../microsoft-vector-deleting-dtors2.cpp | 6 +++---
5 files changed, 32 insertions(+), 33 deletions(-)
diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp
index b1c4b0db65c2b..579af2c558833 100644
--- a/clang/lib/CodeGen/CGClass.cpp
+++ b/clang/lib/CodeGen/CGClass.cpp
@@ -1509,11 +1509,7 @@ static void EmitConditionalArrayDtorCall(const CXXDestructorDecl *DD,
}
} else {
// No operators delete[] were found, so emit a trap.
- llvm::CallInst *TrapCall = CGF.EmitTrapCall(llvm::Intrinsic::trap);
- TrapCall->setDoesNotReturn();
- TrapCall->setDoesNotThrow();
- CGF.Builder.CreateUnreachable();
- CGF.Builder.ClearInsertionPoint();
+ CGF.EmitTrapCallAndMakeUnreachable();
}
CGF.EmitBranchThroughCleanup(CGF.ReturnBlock);
@@ -1531,11 +1527,7 @@ void CodeGenFunction::EmitDestructorBody(FunctionArgList &Args) {
// in fact emit references to them from other compilations, so emit them
// as functions containing a trap instruction.
if (DtorType != Dtor_Base && Dtor->getParent()->isAbstract()) {
- llvm::CallInst *TrapCall = EmitTrapCall(llvm::Intrinsic::trap);
- TrapCall->setDoesNotReturn();
- TrapCall->setDoesNotThrow();
- Builder.CreateUnreachable();
- Builder.ClearInsertionPoint();
+ EmitTrapCallAndMakeUnreachable();
return;
}
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index cba81de9d10dd..13cdded928d89 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -4625,7 +4625,8 @@ void CodeGenFunction::EmitTrapCheck(llvm::Value *Checked,
EmitBlock(Cont);
}
-llvm::CallInst *CodeGenFunction::EmitTrapCall(llvm::Intrinsic::ID IntrID) {
+llvm::CallInst *CodeGenFunction::EmitTrapCall(llvm::Intrinsic::ID IntrID,
+ bool EnsureInsertPoint) {
llvm::Function *TrapIntrinsic = CGM.getIntrinsic(IntrID);
llvm::CallInst *TrapCall = Builder.CreateCall(TrapIntrinsic);
@@ -4642,11 +4643,25 @@ llvm::CallInst *CodeGenFunction::EmitTrapCall(llvm::Intrinsic::ID IntrID) {
if (TrapIntrinsic->doesNotReturn()) {
TrapCall->setDoesNotReturn();
Builder.CreateUnreachable();
- EmitBlock(createBasicBlock());
+ if (EnsureInsertPoint)
+ EmitBlock(createBasicBlock());
+ else
+ Builder.ClearInsertionPoint();
}
return TrapCall;
}
+void CodeGenFunction::EmitTrapCallAndMakeUnreachable() {
+ llvm::CallInst *TrapCall =
+ EmitTrapCall(llvm::Intrinsic::trap, /*EnsureInsertPoint=*/false);
+ TrapCall->setDoesNotReturn();
+ TrapCall->setDoesNotThrow();
+ if (HaveInsertPoint()) {
+ Builder.CreateUnreachable();
+ Builder.ClearInsertionPoint();
+ }
+}
+
Address CodeGenFunction::EmitArrayToPointerDecay(const Expr *E,
LValueBaseInfo *BaseInfo,
TBAAAccessInfo *TBAAInfo) {
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index 119aebb673789..7e7f9a072f765 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -3267,11 +3267,7 @@ void CodeGenFunction::EmitRISCVMultiVersionResolver(
// If no generic/default, emit an unreachable.
Builder.SetInsertPoint(CurBlock);
- llvm::CallInst *TrapCall = EmitTrapCall(llvm::Intrinsic::trap);
- TrapCall->setDoesNotReturn();
- TrapCall->setDoesNotThrow();
- Builder.CreateUnreachable();
- Builder.ClearInsertionPoint();
+ EmitTrapCallAndMakeUnreachable();
}
void CodeGenFunction::EmitAArch64MultiVersionResolver(
@@ -3316,11 +3312,7 @@ void CodeGenFunction::EmitAArch64MultiVersionResolver(
// If no default, emit an unreachable.
Builder.SetInsertPoint(CurBlock);
- llvm::CallInst *TrapCall = EmitTrapCall(llvm::Intrinsic::trap);
- TrapCall->setDoesNotReturn();
- TrapCall->setDoesNotThrow();
- Builder.CreateUnreachable();
- Builder.ClearInsertionPoint();
+ EmitTrapCallAndMakeUnreachable();
}
void CodeGenFunction::EmitX86MultiVersionResolver(
@@ -3356,11 +3348,7 @@ void CodeGenFunction::EmitX86MultiVersionResolver(
// If no generic/default, emit an unreachable.
Builder.SetInsertPoint(CurBlock);
- llvm::CallInst *TrapCall = EmitTrapCall(llvm::Intrinsic::trap);
- TrapCall->setDoesNotReturn();
- TrapCall->setDoesNotThrow();
- Builder.CreateUnreachable();
- Builder.ClearInsertionPoint();
+ EmitTrapCallAndMakeUnreachable();
}
// Loc - where the diagnostic will point, where in the source code this
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index 7bdc79d86ea0a..3c8188c4cefdd 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -5441,9 +5441,13 @@ class CodeGenFunction : public CodeGenTypeCache {
void EmitTrapCheck(llvm::Value *Checked, SanitizerHandler CheckHandlerID,
bool NoMerge = false, const TrapReason *TR = nullptr);
- /// Emit a call to trap or debugtrap and attach function attribute
- /// "trap-func-name" if specified.
- llvm::CallInst *EmitTrapCall(llvm::Intrinsic::ID IntrID);
+ /// Emit a call to trap or debugtrap. If 'EnsureInsertPoint' is false, the
+ /// IR builder need not have a valid insert point after this returns.
+ llvm::CallInst *EmitTrapCall(llvm::Intrinsic::ID IntrID,
+ bool EnsureInsertPoint = true);
+
+ /// Emit a call to '\@llvm.trap()' and clear the current insert point.
+ void EmitTrapCallAndMakeUnreachable();
/// Emit a stub for the cross-DSO CFI check function.
void EmitCfiCheckStub();
diff --git a/clang/test/CodeGenCXX/microsoft-vector-deleting-dtors2.cpp b/clang/test/CodeGenCXX/microsoft-vector-deleting-dtors2.cpp
index 465010ef752cb..fc6ce1763c86c 100644
--- a/clang/test/CodeGenCXX/microsoft-vector-deleting-dtors2.cpp
+++ b/clang/test/CodeGenCXX/microsoft-vector-deleting-dtors2.cpp
@@ -83,9 +83,9 @@ void TesttheTest() {
// CHECK: dtor.scalar:
// X64-NEXT: call void @"??1Test@@UEAA at XZ"(ptr noundef nonnull align 8 dead_on_return(8) dereferenceable(8) %this1)
// X86-NEXT: call x86_thiscallcc void @"??1Test@@UAE at XZ"(ptr noundef nonnull align 4 dead_on_return(4) dereferenceable(4) %this1)
-// CHECK-NEXT: %7 = and i32 %should_call_delete2, 1
-// CHECK-NEXT: %8 = icmp eq i32 %7, 0
-// CHECK-NEXT: br i1 %8, label %dtor.continue, label %dtor.call_delete
+// CHECK-NEXT: %[[AND:[0-9]+]] = and i32 %should_call_delete2, 1
+// CHECK-NEXT: %[[ICMP:[0-9]+]] = icmp eq i32 %[[AND]], 0
+// CHECK-NEXT: br i1 %[[ICMP]], label %dtor.continue, label %dtor.call_delete
// CHECK: dtor.call_delete:
// X64-NEXT: call void @"??3Test@@SAXPEAX at Z"(ptr noundef %this1)
// X86-NEXT: call void @"??3Test@@SAXPAX at Z"(ptr noundef %this1)
More information about the cfe-commits
mailing list