Skip to content

Commit 5e84646

Browse files
authored
[Clang] Fix nomerge attribute not working with __builtin_trap(), __debugbreak(), __builtin_verbose_trap() (#101549)
1. It fixes the problem that llvm.trap() not getting the nomerge attribute. 2. It sets nomerge flag for the node if the instruction has nomerge arrtibute. This is a copy of https://reviews.llvm.org/D146164. This only attempts to fix `nomerge` for `__builtin_trap()`, `__debugbreak()`, `__builtin_verbose_trap()`, not working for non-trap builtins. Fixes #53011
1 parent 451bba6 commit 5e84646

File tree

4 files changed

+104
-2
lines changed

4 files changed

+104
-2
lines changed

clang/lib/CodeGen/CGExpr.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3882,6 +3882,8 @@ llvm::CallInst *CodeGenFunction::EmitTrapCall(llvm::Intrinsic::ID IntrID) {
38823882
TrapCall->addFnAttr(A);
38833883
}
38843884

3885+
if (InNoMergeAttributedStmt)
3886+
TrapCall->addFnAttr(llvm::Attribute::NoMerge);
38853887
return TrapCall;
38863888
}
38873889

clang/test/CodeGen/attr-nomerge.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %clang_cc1 -emit-llvm %s -triple x86_64-unknown-linux-gnu -o - | FileCheck %s
1+
// RUN: %clang_cc1 -emit-llvm %s -fms-extensions -o - | FileCheck %s
22

33
class A {
44
public:
@@ -42,6 +42,9 @@ void foo(int i, A *ap, B *bp) {
4242

4343
A *newA = new B();
4444
delete newA;
45+
[[clang::nomerge]] __builtin_trap();
46+
[[clang::nomerge]] __debugbreak();
47+
[[clang::nomerge]] __builtin_verbose_trap("check null", "Argument must not be null.");
4548
}
4649

4750
int g(int i);
@@ -97,6 +100,9 @@ void something_else_again() {
97100
// CHECK: load ptr, ptr
98101
// CHECK: %[[AG:.*]] = load ptr, ptr
99102
// CHECK-NEXT: call void %[[AG]](ptr {{.*}}) #[[ATTR1]]
103+
// CHECK: call void @llvm.trap() #[[ATTR0]]
104+
// CHECK: call void @llvm.debugtrap() #[[ATTR0]]
105+
// CHECK: call void @llvm.trap() #[[ATTR0]]
100106
// CHECK: call void @_ZN1AD1Ev(ptr {{.*}}) #[[ATTR1]]
101107

102108
// CHECK-DAG: attributes #[[ATTR0]] = {{{.*}}nomerge{{.*}}}

llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7448,6 +7448,8 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I,
74487448
break;
74497449
default: llvm_unreachable("unknown trap intrinsic");
74507450
}
7451+
DAG.addNoMergeSiteInfo(DAG.getRoot().getNode(),
7452+
I.hasFnAttr(Attribute::NoMerge));
74517453
return;
74527454
}
74537455
TargetLowering::ArgListTy Args;
@@ -7464,7 +7466,7 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I,
74647466
DAG.getExternalSymbol(TrapFuncName.data(),
74657467
TLI.getPointerTy(DAG.getDataLayout())),
74667468
std::move(Args));
7467-
7469+
CLI.NoMerge = I.hasFnAttr(Attribute::NoMerge);
74687470
std::pair<SDValue, SDValue> Result = TLI.LowerCallTo(CLI);
74697471
DAG.setRoot(Result.second);
74707472
return;

llvm/test/CodeGen/X86/nomerge.ll

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,4 +62,96 @@ if.end:
6262

6363
declare dso_local void @bar()
6464

65+
define void @nomerge_trap(i32 %i) {
66+
; CHECK-LABEL: nomerge_trap:
67+
; CHECK: # %bb.0: # %entry
68+
; CHECK: # %bb.1: # %entry
69+
; CHECK: # %bb.2: # %if.then
70+
; CHECK-NEXT: ud2
71+
; CHECK-NEXT: LBB1_3: # %if.then2
72+
; CHECK-NEXT: ud2
73+
; CHECK-NEXT: .LBB1_4: # %if.end3
74+
; CHECK-NEXT: ud2
75+
entry:
76+
switch i32 %i, label %if.end3 [
77+
i32 5, label %if.then
78+
i32 7, label %if.then2
79+
]
80+
81+
if.then:
82+
tail call void @llvm.trap() #0
83+
unreachable
84+
85+
if.then2:
86+
tail call void @llvm.trap() #0
87+
unreachable
88+
89+
if.end3:
90+
tail call void @llvm.trap() #0
91+
unreachable
92+
}
93+
94+
declare dso_local void @llvm.trap()
95+
96+
define void @nomerge_debugtrap(i32 %i) {
97+
; CHECK-LABEL: nomerge_debugtrap:
98+
; CHECK: # %bb.0: # %entry
99+
; CHECK: # %bb.1: # %entry
100+
; CHECK: # %bb.2: # %if.then
101+
; CHECK-NEXT: int3
102+
; CHECK-NEXT: LBB2_3: # %if.then2
103+
; CHECK-NEXT: int3
104+
; CHECK-NEXT: .LBB2_4: # %if.end3
105+
; CHECK-NEXT: int3
106+
entry:
107+
switch i32 %i, label %if.end3 [
108+
i32 5, label %if.then
109+
i32 7, label %if.then2
110+
]
111+
112+
if.then:
113+
tail call void @llvm.debugtrap() #0
114+
unreachable
115+
116+
if.then2:
117+
tail call void @llvm.debugtrap() #0
118+
unreachable
119+
120+
if.end3:
121+
tail call void @llvm.debugtrap() #0
122+
unreachable
123+
}
124+
125+
define void @nomerge_named_debugtrap(i32 %i) {
126+
; CHECK-LABEL: nomerge_named_debugtrap:
127+
; CHECK: # %bb.0: # %entry
128+
; CHECK: # %bb.1: # %entry
129+
; CHECK: # %bb.2: # %if.then
130+
; CHECK-NEXT: callq trap_func@PLT
131+
; CHECK-NEXT: LBB3_3: # %if.then2
132+
; CHECK-NEXT: callq trap_func@PLT
133+
; CHECK-NEXT: .LBB3_4: # %if.end3
134+
; CHECK-NEXT: callq trap_func@PLT
135+
entry:
136+
switch i32 %i, label %if.end3 [
137+
i32 5, label %if.then
138+
i32 7, label %if.then2
139+
]
140+
141+
if.then:
142+
tail call void @llvm.debugtrap() #1
143+
unreachable
144+
145+
if.then2:
146+
tail call void @llvm.debugtrap() #1
147+
unreachable
148+
149+
if.end3:
150+
tail call void @llvm.debugtrap() #1
151+
unreachable
152+
}
153+
154+
declare dso_local void @llvm.debugtrap()
155+
65156
attributes #0 = { nomerge }
157+
attributes #1 = { nomerge "trap-func-name"="trap_func" }

0 commit comments

Comments
 (0)