Skip to content

Commit b88ac9f

Browse files
[clang][CodeGen][AA] Add !llvm.errno.tbaa listing int-compatible TBAA nodes
Model integer accesses through an ad-hoc TBAA module-level metadata, so as to disambiguate integer accesses from non-integer ones, at TBAA level. This is purposefully as part of handling `errno` accesses, which are guaranteed to be integer-compatible.
1 parent 25e79b1 commit b88ac9f

File tree

3 files changed

+59
-3
lines changed

3 files changed

+59
-3
lines changed

clang/lib/CodeGen/CodeGenModule.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ static llvm::cl::opt<bool> LimitedCoverage(
8383
llvm::cl::desc("Emit limited coverage mapping information (experimental)"));
8484

8585
static const char AnnotationSection[] = "llvm.metadata";
86+
static constexpr auto ErrnoTBAAMDName = "llvm.errno.tbaa";
8687

8788
static CGCXXABI *createCXXABI(CodeGenModule &CGM) {
8889
switch (CGM.getContext().getCXXABIKind()) {
@@ -1457,6 +1458,12 @@ void CodeGenModule::Release() {
14571458
}
14581459
}
14591460
}
1461+
1462+
if (TBAA) {
1463+
auto *ErrnoTBAAMD = TheModule.getOrInsertNamedMetadata(ErrnoTBAAMDName);
1464+
llvm::MDNode *IntegerNode = TBAA->getTypeInfo(Context.IntTy);
1465+
ErrnoTBAAMD->addOperand(IntegerNode);
1466+
}
14601467
}
14611468

14621469
void CodeGenModule::EmitOpenCLMetadata() {

llvm/test/Transforms/GVN/does-clobber-errno.ll

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
22
; RUN: opt -passes=gvn -S < %s | FileCheck %s
33

4-
; FIXME: This is a miscompilation.
54
define noundef i32 @test_malloc_clobbering_errno() {
65
; CHECK-LABEL: define noundef i32 @test_malloc_clobbering_errno() {
76
; CHECK-NEXT: [[TMP1:%.*]] = alloca ptr, align 8
87
; CHECK-NEXT: [[TMP2:%.*]] = call ptr @__errno_location()
98
; CHECK-NEXT: store i32 0, ptr [[TMP2]], align 4
109
; CHECK-NEXT: [[TMP3:%.*]] = call noalias ptr @malloc(i64 1844674407370955161)
1110
; CHECK-NEXT: store volatile ptr [[TMP3]], ptr [[TMP1]], align 8
12-
; CHECK-NEXT: ret i32 0
11+
; CHECK-NEXT: [[TMP4:%.*]] = load i32, ptr [[TMP2]], align 4
12+
; CHECK-NEXT: ret i32 [[TMP4]]
1313
;
1414
%1 = alloca ptr, align 8
1515
%2 = call ptr @__errno_location()
@@ -24,4 +24,4 @@ declare ptr @__errno_location() #1
2424
declare noalias ptr @malloc(i64) #2
2525

2626
attributes #1 = { mustprogress nofree nosync nounwind willreturn memory(none) }
27-
attributes #2 = { mustprogress nofree nounwind willreturn memory(inaccessiblemem: readwrite) }
27+
attributes #2 = { mustprogress nofree nounwind willreturn memory(inaccessiblemem: readwrite, errnomem: readwrite) }
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
2+
; RUN: opt -S -passes=instcombine < %s | FileCheck %s
3+
4+
; sinf clobbering errno, but %p cannot alias errno per C/C++ strict aliasing rules via TBAA.
5+
; Hence, can do constant store-to-load forwarding.
6+
define float @does_not_alias_errno(ptr noundef %p, float noundef %f) {
7+
; CHECK-LABEL: define float @does_not_alias_errno(
8+
; CHECK-SAME: ptr noundef [[P:%.*]], float noundef [[F:%.*]]) {
9+
; CHECK-NEXT: [[ENTRY:.*:]]
10+
; CHECK-NEXT: store float 0.000000e+00, ptr [[P]], align 4, !tbaa [[TBAA3:![0-9]+]]
11+
; CHECK-NEXT: [[CALL:%.*]] = call float @sinf(float noundef [[F]]), !tbaa [[TBAA5:![0-9]+]]
12+
; CHECK-NEXT: ret float 0.000000e+00
13+
;
14+
entry:
15+
store float 0.000000e+00, ptr %p, align 4, !tbaa !3
16+
%call = call float @sinf(float noundef %f), !tbaa !10
17+
%0 = load float, ptr %p, align 4, !tbaa !3
18+
ret float %0
19+
}
20+
21+
; sinf clobbering errno, unknown TBAA info, %p may alias errno
22+
define float @may_alias_errno(ptr noundef %p, float noundef %f) {
23+
; CHECK-LABEL: define float @may_alias_errno(
24+
; CHECK-SAME: ptr noundef [[P:%.*]], float noundef [[F:%.*]]) {
25+
; CHECK-NEXT: [[ENTRY:.*:]]
26+
; CHECK-NEXT: store float 0.000000e+00, ptr [[P]], align 4
27+
; CHECK-NEXT: [[CALL:%.*]] = call float @sinf(float noundef [[F]])
28+
; CHECK-NEXT: [[TMP0:%.*]] = load float, ptr [[P]], align 4
29+
; CHECK-NEXT: ret float [[TMP0]]
30+
;
31+
entry:
32+
store float 0.000000e+00, ptr %p, align 4
33+
%call = call float @sinf(float noundef %f)
34+
%0 = load float, ptr %p, align 4
35+
ret float %0
36+
}
37+
38+
declare float @sinf(float noundef) #1
39+
40+
attributes #1 = { mustprogress nofree nounwind willreturn memory(errnomem: write) }
41+
42+
!llvm.errno.tbaa = !{!0}
43+
44+
!0 = !{!"int", !1, i64 0}
45+
!1 = !{!"omnipotent char", !2, i64 0}
46+
!2 = !{!"Simple C/C++ TBAA"}
47+
!3 = !{!4, !4, i64 0}
48+
!4 = !{!"float", !1, i64 0}
49+
!10 = !{!0, !0, i64 0}

0 commit comments

Comments
 (0)