Skip to content

Commit 96c7323

Browse files
committed
[BoundsSafety] Mark calls to soft trap runtime functions as NoMerge
In practice I haven't seen the optimizer merge calls to runtime trap functions. This is likely because the control flow continuing after the call makes optimization more difficult compared to hard traps where control flow does not resume. However, given that soft trap runtime requires that the traps be debuggable we should explicitly tell the optimizer to not merge the calls just in-case the optimizer gets smarter in the future. rdar://164341162 (cherry picked from commit 8797619) Conflicts: clang/test/BoundsSafety/CodeGen/soft-traps/call_with_str_with_ubsan.c
1 parent d1d7bec commit 96c7323

File tree

6 files changed

+29
-24
lines changed

6 files changed

+29
-24
lines changed

clang/lib/CodeGen/CGExpr.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4775,6 +4775,7 @@ void CodeGenFunction::EmitTrapCheck(llvm::Value *Checked,
47754775
// get different codegen at callsites.
47764776
TrapCall->setCallingConv(SoftTrapCC.value());
47774777
}
4778+
TrapCall->addFnAttr(llvm::Attribute::NoMerge);
47784779
Builder.CreateBr(Cont);
47794780
} else if (CGM.getCodeGenOpts().TrapFuncReturns) {
47804781
auto *TrapID = llvm::ConstantInt::get(CGM.Int8Ty, CheckHandlerID);

clang/test/BoundsSafety/CodeGen/soft-traps/call_minimal.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,10 +97,10 @@ int read(int* __bidi_indexable ptr, int idx) {
9797
//.
9898
// UNOPT: attributes #[[ATTR0]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
9999
// UNOPT: attributes #[[ATTR1:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }
100-
// UNOPT: attributes #[[ATTR2]] = { nounwind }
100+
// UNOPT: attributes #[[ATTR2]] = { nomerge nounwind }
101101
//.
102102
// OPT: attributes #[[ATTR0]] = { nounwind "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
103-
// OPT: attributes #[[ATTR1]] = { nounwind }
103+
// OPT: attributes #[[ATTR1]] = { nomerge nounwind }
104104
//.
105105
// UNOPT: [[META0:![0-9]+]] = !{i32 1, !"wchar_size", i32 4}
106106
// UNOPT: [[META1:![0-9]+]] = !{!"{{.*}}clang version {{.*}}"}

clang/test/BoundsSafety/CodeGen/soft-traps/call_minimal_with_ubsan.c

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -199,19 +199,19 @@
199199
// UNOPT-TFR-NEXT: [[TMP8:%.*]] = icmp ule ptr [[TMP7]], [[WIDE_PTR_UB]], !annotation [[META4]]
200200
// UNOPT-TFR-NEXT: br i1 [[TMP8]], label %[[CONT2:.*]], label %[[TRAP1:.*]], !prof [[PROF3]], !annotation [[META4]]
201201
// UNOPT-TFR: [[TRAP1]]:
202-
// UNOPT-TFR-NEXT: call preserve_allcc void @__bounds_safety_soft_trap() #[[ATTR3]], !annotation [[META4]]
202+
// UNOPT-TFR-NEXT: call preserve_allcc void @__bounds_safety_soft_trap() #[[ATTR4:[0-9]+]], !annotation [[META4]]
203203
// UNOPT-TFR-NEXT: br label %[[CONT2]], !annotation [[META4]]
204204
// UNOPT-TFR: [[CONT2]]:
205205
// UNOPT-TFR-NEXT: [[TMP9:%.*]] = icmp ule ptr [[ARRAYIDX]], [[TMP7]], !annotation [[META4]]
206206
// UNOPT-TFR-NEXT: br i1 [[TMP9]], label %[[CONT4:.*]], label %[[TRAP3:.*]], !prof [[PROF3]], !annotation [[META4]]
207207
// UNOPT-TFR: [[TRAP3]]:
208-
// UNOPT-TFR-NEXT: call preserve_allcc void @__bounds_safety_soft_trap() #[[ATTR3]], !annotation [[META4]]
208+
// UNOPT-TFR-NEXT: call preserve_allcc void @__bounds_safety_soft_trap() #[[ATTR4]], !annotation [[META4]]
209209
// UNOPT-TFR-NEXT: br label %[[CONT4]], !annotation [[META4]]
210210
// UNOPT-TFR: [[CONT4]]:
211211
// UNOPT-TFR-NEXT: [[TMP10:%.*]] = icmp uge ptr [[ARRAYIDX]], [[WIDE_PTR_LB]], !annotation [[META5:![0-9]+]]
212212
// UNOPT-TFR-NEXT: br i1 [[TMP10]], label %[[CONT6:.*]], label %[[TRAP5:.*]], !prof [[PROF3]], !annotation [[META5]]
213213
// UNOPT-TFR: [[TRAP5]]:
214-
// UNOPT-TFR-NEXT: call preserve_allcc void @__bounds_safety_soft_trap() #[[ATTR3]], !annotation [[META5]]
214+
// UNOPT-TFR-NEXT: call preserve_allcc void @__bounds_safety_soft_trap() #[[ATTR4]], !annotation [[META5]]
215215
// UNOPT-TFR-NEXT: br label %[[CONT6]], !annotation [[META5]]
216216
// UNOPT-TFR: [[CONT6]]:
217217
// UNOPT-TFR-NEXT: [[TMP11:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
@@ -268,25 +268,26 @@ int read(int* __bidi_indexable ptr, int idx, int other) {
268268
// UNOPT: attributes #[[ATTR2:[0-9]+]] = { cold noreturn nounwind }
269269
// UNOPT: attributes #[[ATTR3:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }
270270
// UNOPT: attributes #[[ATTR4]] = { nomerge noreturn nounwind }
271-
// UNOPT: attributes #[[ATTR5]] = { nounwind }
271+
// UNOPT: attributes #[[ATTR5]] = { nomerge nounwind }
272272
//.
273273
// UNOPT-TF: attributes #[[ATTR0]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
274274
// UNOPT-TF: attributes #[[ATTR1:[0-9]+]] = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
275275
// UNOPT-TF: attributes #[[ATTR2:[0-9]+]] = { cold noreturn nounwind }
276276
// UNOPT-TF: attributes #[[ATTR3:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }
277277
// UNOPT-TF: attributes #[[ATTR4]] = { nomerge noreturn nounwind "trap-func-name"="ubsan_handler" }
278-
// UNOPT-TF: attributes #[[ATTR5]] = { nounwind }
278+
// UNOPT-TF: attributes #[[ATTR5]] = { nomerge nounwind }
279279
//.
280280
// UNOPT-TFR: attributes #[[ATTR0]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
281281
// UNOPT-TFR: attributes #[[ATTR1:[0-9]+]] = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
282282
// UNOPT-TFR: attributes #[[ATTR2:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }
283283
// UNOPT-TFR: attributes #[[ATTR3]] = { nounwind }
284+
// UNOPT-TFR: attributes #[[ATTR4]] = { nomerge nounwind }
284285
//.
285286
// OPT: attributes #[[ATTR0]] = { nounwind "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
286287
// OPT: attributes #[[ATTR1:[0-9]+]] = { mustprogress nocallback nofree nosync nounwind speculatable willreturn memory(none) }
287288
// OPT: attributes #[[ATTR2:[0-9]+]] = { cold noreturn nounwind }
288289
// OPT: attributes #[[ATTR3]] = { nomerge noreturn nounwind }
289-
// OPT: attributes #[[ATTR4]] = { nounwind }
290+
// OPT: attributes #[[ATTR4]] = { nomerge nounwind }
290291
//.
291292
// UNOPT: [[META0:![0-9]+]] = !{i32 1, !"wchar_size", i32 4}
292293
// UNOPT: [[META1:![0-9]+]] = !{!"{{.*}}clang version {{.*}}"}

clang/test/BoundsSafety/CodeGen/soft-traps/call_with_str.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -396,7 +396,7 @@ void receive_cb(int*__counted_by(count) ptr, int count);
396396
// OPT-NEXT: tail call preserve_allcc void @__bounds_safety_soft_trap_s(ptr null) #[[ATTR2]], !annotation [[META12]]
397397
// OPT-NEXT: br label %[[CONT]], !annotation [[META12]]
398398
// OPT: [[CONT]]:
399-
// OPT-NEXT: tail call void @receive_cb(ptr noundef [[PTR]], i32 noundef [[COUNT]]) #[[ATTR2]]
399+
// OPT-NEXT: tail call void @receive_cb(ptr noundef [[PTR]], i32 noundef [[COUNT]]) #[[ATTR3:[0-9]+]]
400400
// OPT-NEXT: ret i32 0
401401
//
402402
int read_cb(int*__counted_by(count) ptr, int count) {
@@ -407,17 +407,18 @@ int read_cb(int*__counted_by(count) ptr, int count) {
407407
// UNOPT: attributes #[[ATTR0]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
408408
// UNOPT: attributes #[[ATTR1:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }
409409
// UNOPT: attributes #[[ATTR2:[0-9]+]] = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
410-
// UNOPT: attributes #[[ATTR3]] = { nounwind }
410+
// UNOPT: attributes #[[ATTR3]] = { nomerge nounwind }
411411
//.
412412
// UNOPT-TF: attributes #[[ATTR0]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
413413
// UNOPT-TF: attributes #[[ATTR1:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }
414414
// UNOPT-TF: attributes #[[ATTR2:[0-9]+]] = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
415-
// UNOPT-TF: attributes #[[ATTR3]] = { nounwind }
415+
// UNOPT-TF: attributes #[[ATTR3]] = { nomerge nounwind }
416416
// UNOPT-TF: attributes #[[ATTR4]] = { "trap-func-name"="not_used" }
417417
//.
418418
// OPT: attributes #[[ATTR0]] = { nounwind "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
419419
// OPT: attributes #[[ATTR1:[0-9]+]] = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
420-
// OPT: attributes #[[ATTR2]] = { nounwind }
420+
// OPT: attributes #[[ATTR2]] = { nomerge nounwind }
421+
// OPT: attributes #[[ATTR3]] = { nounwind }
421422
//.
422423
// UNOPT: [[META0:![0-9]+]] = !{i32 1, !"wchar_size", i32 4}
423424
// UNOPT: [[META1:![0-9]+]] = !{!"{{.*}}clang version {{.*}}"}

clang/test/BoundsSafety/CodeGen/soft-traps/call_with_str_custom_func.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,10 +98,10 @@ int read(int* __bidi_indexable ptr, int idx) {
9898
//.
9999
// UNOPT: attributes #[[ATTR0]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
100100
// UNOPT: attributes #[[ATTR1:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }
101-
// UNOPT: attributes #[[ATTR2]] = { nounwind }
101+
// UNOPT: attributes #[[ATTR2]] = { nomerge nounwind }
102102
//.
103103
// OPT: attributes #[[ATTR0]] = { nounwind "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
104-
// OPT: attributes #[[ATTR1]] = { nounwind }
104+
// OPT: attributes #[[ATTR1]] = { nomerge nounwind }
105105
//.
106106
// UNOPT: [[META0:![0-9]+]] = !{i32 1, !"wchar_size", i32 4}
107107
// UNOPT: [[META1:![0-9]+]] = !{!"{{.*}}clang version {{.*}}"}

clang/test/BoundsSafety/CodeGen/soft-traps/call_with_str_with_ubsan.c

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -212,19 +212,19 @@
212212
// UNOPT-TFR-NEXT: [[TMP8:%.*]] = icmp ule ptr [[TMP7]], [[WIDE_PTR_UB]], !annotation [[META4]]
213213
// UNOPT-TFR-NEXT: br i1 [[TMP8]], label %[[CONT2:.*]], label %[[TRAP1:.*]], !prof [[PROF3]], !annotation [[META4]]
214214
// UNOPT-TFR: [[TRAP1]]:
215-
// UNOPT-TFR-NEXT: call preserve_allcc void @__bounds_safety_soft_trap_s(ptr @trap.reason) #[[ATTR4]], !annotation [[META4]]
215+
// UNOPT-TFR-NEXT: call preserve_allcc void @__bounds_safety_soft_trap_s(ptr @trap.reason) #[[ATTR5:[0-9]+]], !annotation [[META4]]
216216
// UNOPT-TFR-NEXT: br label %[[CONT2]], !annotation [[META4]]
217217
// UNOPT-TFR: [[CONT2]]:
218218
// UNOPT-TFR-NEXT: [[TMP9:%.*]] = icmp ule ptr [[ARRAYIDX]], [[TMP7]], !annotation [[META4]]
219219
// UNOPT-TFR-NEXT: br i1 [[TMP9]], label %[[CONT4:.*]], label %[[TRAP3:.*]], !prof [[PROF3]], !annotation [[META4]]
220220
// UNOPT-TFR: [[TRAP3]]:
221-
// UNOPT-TFR-NEXT: call preserve_allcc void @__bounds_safety_soft_trap_s(ptr @trap.reason.1) #[[ATTR4]], !annotation [[META4]]
221+
// UNOPT-TFR-NEXT: call preserve_allcc void @__bounds_safety_soft_trap_s(ptr @trap.reason.1) #[[ATTR5]], !annotation [[META4]]
222222
// UNOPT-TFR-NEXT: br label %[[CONT4]], !annotation [[META4]]
223223
// UNOPT-TFR: [[CONT4]]:
224224
// UNOPT-TFR-NEXT: [[TMP10:%.*]] = icmp uge ptr [[ARRAYIDX]], [[WIDE_PTR_LB]], !annotation [[META5:![0-9]+]]
225225
// UNOPT-TFR-NEXT: br i1 [[TMP10]], label %[[CONT6:.*]], label %[[TRAP5:.*]], !prof [[PROF3]], !annotation [[META5]]
226226
// UNOPT-TFR: [[TRAP5]]:
227-
// UNOPT-TFR-NEXT: call preserve_allcc void @__bounds_safety_soft_trap_s(ptr @trap.reason.2) #[[ATTR4]], !annotation [[META5]]
227+
// UNOPT-TFR-NEXT: call preserve_allcc void @__bounds_safety_soft_trap_s(ptr @trap.reason.2) #[[ATTR5]], !annotation [[META5]]
228228
// UNOPT-TFR-NEXT: br label %[[CONT6]], !annotation [[META5]]
229229
// UNOPT-TFR: [[CONT6]]:
230230
// UNOPT-TFR-NEXT: [[TMP11:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
@@ -659,7 +659,7 @@ void receive_cb(int*__counted_by(count) ptr, int count);
659659
// UNOPT-TFR-NEXT: [[TMP16:%.*]] = phi i1 [ false, %[[LAND_LHS_TRUE]] ], [ false, %[[CONT]] ], [ [[TMP15]], %[[LAND_END]] ], !annotation [[META6]]
660660
// UNOPT-TFR-NEXT: br i1 [[TMP16]], label %[[CONT51:.*]], label %[[TRAP50:.*]], !prof [[PROF3]], !annotation [[META6]]
661661
// UNOPT-TFR: [[TRAP50]]:
662-
// UNOPT-TFR-NEXT: call preserve_allcc void @__bounds_safety_soft_trap_s(ptr null) #[[ATTR4]], !annotation [[META6]]
662+
// UNOPT-TFR-NEXT: call preserve_allcc void @__bounds_safety_soft_trap_s(ptr null) #[[ATTR5]], !annotation [[META6]]
663663
// UNOPT-TFR-NEXT: br label %[[CONT51]], !annotation [[META6]]
664664
// UNOPT-TFR: [[CONT51]]:
665665
// UNOPT-TFR-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TEMP52]], ptr align 8 [[AGG_TEMP]], i64 24, i1 false)
@@ -669,7 +669,7 @@ void receive_cb(int*__counted_by(count) ptr, int count);
669669
// UNOPT-TFR-NEXT: [[WIDE_PTR_UB56:%.*]] = load ptr, ptr [[WIDE_PTR_UB_ADDR55]], align 8
670670
// UNOPT-TFR-NEXT: [[WIDE_PTR_LB_ADDR57:%.*]] = getelementptr inbounds nuw %"__bounds_safety::wide_ptr.bidi_indexable", ptr [[AGG_TEMP52]], i32 0, i32 2
671671
// UNOPT-TFR-NEXT: [[WIDE_PTR_LB58:%.*]] = load ptr, ptr [[WIDE_PTR_LB_ADDR57]], align 8
672-
// UNOPT-TFR-NEXT: call void @receive_cb(ptr noundef [[WIDE_PTR_PTR54]], i32 noundef [[TMP11]]) #[[ATTR5:[0-9]+]]
672+
// UNOPT-TFR-NEXT: call void @receive_cb(ptr noundef [[WIDE_PTR_PTR54]], i32 noundef [[TMP11]]) #[[ATTR6:[0-9]+]]
673673
// UNOPT-TFR-NEXT: [[TMP17:%.*]] = load i32, ptr [[TMP]], align 4
674674
// UNOPT-TFR-NEXT: ret i32 [[TMP17]]
675675
//
@@ -690,7 +690,7 @@ void receive_cb(int*__counted_by(count) ptr, int count);
690690
// OPT-NEXT: br label %[[CONT51]], !annotation [[META13]]
691691
// OPT: [[CONT51]]:
692692
// OPT-NEXT: [[TMP2:%.*]] = extractvalue { i32, i1 } [[TMP0]], 0, !nosanitize [[META2]]
693-
// OPT-NEXT: tail call void @receive_cb(ptr noundef [[PTR]], i32 noundef [[COUNT]]) #[[ATTR5]]
693+
// OPT-NEXT: tail call void @receive_cb(ptr noundef [[PTR]], i32 noundef [[COUNT]]) #[[ATTR6:[0-9]+]]
694694
// OPT-NEXT: ret i32 [[TMP2]]
695695
//
696696
int read_cb(int*__counted_by(count) ptr, int count, int other) {
@@ -705,30 +705,32 @@ int read_cb(int*__counted_by(count) ptr, int count, int other) {
705705
// UNOPT: attributes #[[ATTR3:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }
706706
// UNOPT: attributes #[[ATTR4:[0-9]+]] = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
707707
// UNOPT: attributes #[[ATTR5]] = { nomerge noreturn nounwind }
708-
// UNOPT: attributes #[[ATTR6]] = { nounwind }
708+
// UNOPT: attributes #[[ATTR6]] = { nomerge nounwind }
709709
//.
710710
// UNOPT-TF: attributes #[[ATTR0]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
711711
// UNOPT-TF: attributes #[[ATTR1:[0-9]+]] = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
712712
// UNOPT-TF: attributes #[[ATTR2:[0-9]+]] = { cold noreturn nounwind }
713713
// UNOPT-TF: attributes #[[ATTR3:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }
714714
// UNOPT-TF: attributes #[[ATTR4:[0-9]+]] = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
715715
// UNOPT-TF: attributes #[[ATTR5]] = { nomerge noreturn nounwind "trap-func-name"="ubsan_handler" }
716-
// UNOPT-TF: attributes #[[ATTR6]] = { nounwind }
716+
// UNOPT-TF: attributes #[[ATTR6]] = { nomerge nounwind }
717717
// UNOPT-TF: attributes #[[ATTR7]] = { "trap-func-name"="ubsan_handler" }
718718
//.
719719
// UNOPT-TFR: attributes #[[ATTR0]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
720720
// UNOPT-TFR: attributes #[[ATTR1:[0-9]+]] = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
721721
// UNOPT-TFR: attributes #[[ATTR2:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }
722722
// UNOPT-TFR: attributes #[[ATTR3:[0-9]+]] = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
723723
// UNOPT-TFR: attributes #[[ATTR4]] = { nounwind }
724-
// UNOPT-TFR: attributes #[[ATTR5]] = { "trap-func-name"="ubsan_handler" }
724+
// UNOPT-TFR: attributes #[[ATTR5]] = { nomerge nounwind }
725+
// UNOPT-TFR: attributes #[[ATTR6]] = { "trap-func-name"="ubsan_handler" }
725726
//.
726727
// OPT: attributes #[[ATTR0]] = { nounwind "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
727728
// OPT: attributes #[[ATTR1:[0-9]+]] = { mustprogress nocallback nofree nosync nounwind speculatable willreturn memory(none) }
728729
// OPT: attributes #[[ATTR2:[0-9]+]] = { cold noreturn nounwind }
729730
// OPT: attributes #[[ATTR3:[0-9]+]] = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
730731
// OPT: attributes #[[ATTR4]] = { nomerge noreturn nounwind }
731-
// OPT: attributes #[[ATTR5]] = { nounwind }
732+
// OPT: attributes #[[ATTR5]] = { nomerge nounwind }
733+
// OPT: attributes #[[ATTR6]] = { nounwind }
732734
//.
733735
// UNOPT: [[META0:![0-9]+]] = !{i32 1, !"wchar_size", i32 4}
734736
// UNOPT: [[META1:![0-9]+]] = !{!"{{.*}}clang version {{.*}}"}

0 commit comments

Comments
 (0)