[clang] [llvm] [clang][CodeGen][AA] Add `!llvm.errno.tbaa` gathering int-compatible TBAA nodes (PR #125258)

Antonio Frighetto via cfe-commits cfe-commits at lists.llvm.org
Fri Feb 21 06:01:38 PST 2025


https://github.com/antoniofrighetto updated https://github.com/llvm/llvm-project/pull/125258

>From 25e79b19581d47924c4b1a56d954031a09600b8f Mon Sep 17 00:00:00 2001
From: Antonio Frighetto <me at antoniofrighetto.com>
Date: Tue, 18 Feb 2025 16:36:12 +0100
Subject: [PATCH 1/3] [GVN] Introduce test for PR125258 (NFC)

---
 .../test/Transforms/GVN/does-clobber-errno.ll | 27 +++++++++++++++++++
 1 file changed, 27 insertions(+)
 create mode 100644 llvm/test/Transforms/GVN/does-clobber-errno.ll

diff --git a/llvm/test/Transforms/GVN/does-clobber-errno.ll b/llvm/test/Transforms/GVN/does-clobber-errno.ll
new file mode 100644
index 0000000000000..4c68789a09dcd
--- /dev/null
+++ b/llvm/test/Transforms/GVN/does-clobber-errno.ll
@@ -0,0 +1,27 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; RUN: opt -passes=gvn -S < %s | FileCheck %s
+
+; FIXME: This is a miscompilation.
+define noundef i32 @test_malloc_clobbering_errno() {
+; CHECK-LABEL: define noundef i32 @test_malloc_clobbering_errno() {
+; CHECK-NEXT:    [[TMP1:%.*]] = alloca ptr, align 8
+; CHECK-NEXT:    [[TMP2:%.*]] = call ptr @__errno_location()
+; CHECK-NEXT:    store i32 0, ptr [[TMP2]], align 4
+; CHECK-NEXT:    [[TMP3:%.*]] = call noalias ptr @malloc(i64 1844674407370955161)
+; CHECK-NEXT:    store volatile ptr [[TMP3]], ptr [[TMP1]], align 8
+; CHECK-NEXT:    ret i32 0
+;
+  %1 = alloca ptr, align 8
+  %2 = call ptr @__errno_location()
+  store i32 0, ptr %2, align 4
+  %3 = call noalias ptr @malloc(i64 1844674407370955161)
+  store volatile ptr %3, ptr %1, align 8
+  %4 = load i32, ptr %2, align 4
+  ret i32 %4
+}
+
+declare ptr @__errno_location() #1
+declare noalias ptr @malloc(i64) #2
+
+attributes #1 = { mustprogress nofree nosync nounwind willreturn memory(none) }
+attributes #2 = { mustprogress nofree nounwind willreturn memory(inaccessiblemem: readwrite) }

>From b88ac9fb739ac495c31f09a57afcf240be84bab5 Mon Sep 17 00:00:00 2001
From: Antonio Frighetto <me at antoniofrighetto.com>
Date: Tue, 18 Feb 2025 15:32:09 +0100
Subject: [PATCH 2/3] [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.
---
 clang/lib/CodeGen/CodeGenModule.cpp           |  7 +++
 .../test/Transforms/GVN/does-clobber-errno.ll |  6 +--
 .../Transforms/InstCombine/may-alias-errno.ll | 49 +++++++++++++++++++
 3 files changed, 59 insertions(+), 3 deletions(-)
 create mode 100644 llvm/test/Transforms/InstCombine/may-alias-errno.ll

diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index 7924c32fcf633..3e8917a7b587d 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -83,6 +83,7 @@ static llvm::cl::opt<bool> LimitedCoverage(
     llvm::cl::desc("Emit limited coverage mapping information (experimental)"));
 
 static const char AnnotationSection[] = "llvm.metadata";
+static constexpr auto ErrnoTBAAMDName = "llvm.errno.tbaa";
 
 static CGCXXABI *createCXXABI(CodeGenModule &CGM) {
   switch (CGM.getContext().getCXXABIKind()) {
@@ -1457,6 +1458,12 @@ void CodeGenModule::Release() {
       }
     }
   }
+
+  if (TBAA) {
+    auto *ErrnoTBAAMD = TheModule.getOrInsertNamedMetadata(ErrnoTBAAMDName);
+    llvm::MDNode *IntegerNode = TBAA->getTypeInfo(Context.IntTy);
+    ErrnoTBAAMD->addOperand(IntegerNode);
+  }
 }
 
 void CodeGenModule::EmitOpenCLMetadata() {
diff --git a/llvm/test/Transforms/GVN/does-clobber-errno.ll b/llvm/test/Transforms/GVN/does-clobber-errno.ll
index 4c68789a09dcd..7c625b10eac7b 100644
--- a/llvm/test/Transforms/GVN/does-clobber-errno.ll
+++ b/llvm/test/Transforms/GVN/does-clobber-errno.ll
@@ -1,7 +1,6 @@
 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
 ; RUN: opt -passes=gvn -S < %s | FileCheck %s
 
-; FIXME: This is a miscompilation.
 define noundef i32 @test_malloc_clobbering_errno() {
 ; CHECK-LABEL: define noundef i32 @test_malloc_clobbering_errno() {
 ; CHECK-NEXT:    [[TMP1:%.*]] = alloca ptr, align 8
@@ -9,7 +8,8 @@ define noundef i32 @test_malloc_clobbering_errno() {
 ; CHECK-NEXT:    store i32 0, ptr [[TMP2]], align 4
 ; CHECK-NEXT:    [[TMP3:%.*]] = call noalias ptr @malloc(i64 1844674407370955161)
 ; CHECK-NEXT:    store volatile ptr [[TMP3]], ptr [[TMP1]], align 8
-; CHECK-NEXT:    ret i32 0
+; CHECK-NEXT:    [[TMP4:%.*]] = load i32, ptr [[TMP2]], align 4
+; CHECK-NEXT:    ret i32 [[TMP4]]
 ;
   %1 = alloca ptr, align 8
   %2 = call ptr @__errno_location()
@@ -24,4 +24,4 @@ declare ptr @__errno_location() #1
 declare noalias ptr @malloc(i64) #2
 
 attributes #1 = { mustprogress nofree nosync nounwind willreturn memory(none) }
-attributes #2 = { mustprogress nofree nounwind willreturn memory(inaccessiblemem: readwrite) }
+attributes #2 = { mustprogress nofree nounwind willreturn memory(inaccessiblemem: readwrite, errnomem: readwrite) }
diff --git a/llvm/test/Transforms/InstCombine/may-alias-errno.ll b/llvm/test/Transforms/InstCombine/may-alias-errno.ll
new file mode 100644
index 0000000000000..cd4a39815a904
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/may-alias-errno.ll
@@ -0,0 +1,49 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; RUN: opt -S -passes=instcombine < %s | FileCheck %s
+
+; sinf clobbering errno, but %p cannot alias errno per C/C++ strict aliasing rules via TBAA.
+; Hence, can do constant store-to-load forwarding.
+define float @does_not_alias_errno(ptr noundef %p, float noundef %f) {
+; CHECK-LABEL: define float @does_not_alias_errno(
+; CHECK-SAME: ptr noundef [[P:%.*]], float noundef [[F:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    store float 0.000000e+00, ptr [[P]], align 4, !tbaa [[TBAA3:![0-9]+]]
+; CHECK-NEXT:    [[CALL:%.*]] = call float @sinf(float noundef [[F]]), !tbaa [[TBAA5:![0-9]+]]
+; CHECK-NEXT:    ret float 0.000000e+00
+;
+entry:
+  store float 0.000000e+00, ptr %p, align 4, !tbaa !3
+  %call = call float @sinf(float noundef %f), !tbaa !10
+  %0 = load float, ptr %p, align 4, !tbaa !3
+  ret float %0
+}
+
+; sinf clobbering errno, unknown TBAA info, %p may alias errno
+define float @may_alias_errno(ptr noundef %p, float noundef %f) {
+; CHECK-LABEL: define float @may_alias_errno(
+; CHECK-SAME: ptr noundef [[P:%.*]], float noundef [[F:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    store float 0.000000e+00, ptr [[P]], align 4
+; CHECK-NEXT:    [[CALL:%.*]] = call float @sinf(float noundef [[F]])
+; CHECK-NEXT:    [[TMP0:%.*]] = load float, ptr [[P]], align 4
+; CHECK-NEXT:    ret float [[TMP0]]
+;
+entry:
+  store float 0.000000e+00, ptr %p, align 4
+  %call = call float @sinf(float noundef %f)
+  %0 = load float, ptr %p, align 4
+  ret float %0
+}
+
+declare float @sinf(float noundef) #1
+
+attributes #1 = { mustprogress nofree nounwind willreturn memory(errnomem: write) }
+
+!llvm.errno.tbaa = !{!0}
+
+!0 = !{!"int", !1, i64 0}
+!1 = !{!"omnipotent char", !2, i64 0}
+!2 = !{!"Simple C/C++ TBAA"}
+!3 = !{!4, !4, i64 0}
+!4 = !{!"float", !1, i64 0}
+!10 = !{!0, !0, i64 0}

>From 860a842b07fa2d3384b19bc182a617098b387cac Mon Sep 17 00:00:00 2001
From: Antonio Frighetto <me at antoniofrighetto.com>
Date: Fri, 21 Feb 2025 14:51:35 +0100
Subject: [PATCH 3/3] tmp

---
 llvm/include/llvm/Analysis/AliasAnalysis.h    | 14 +++++++++++++
 .../llvm/Analysis/TypeBasedAliasAnalysis.h    |  1 +
 llvm/lib/Analysis/AliasAnalysis.cpp           | 20 +++++++++++++++++++
 llvm/lib/Analysis/TypeBasedAliasAnalysis.cpp  | 15 ++++++++++++++
 4 files changed, 50 insertions(+)

diff --git a/llvm/include/llvm/Analysis/AliasAnalysis.h b/llvm/include/llvm/Analysis/AliasAnalysis.h
index b192a9f5e65e7..4ef461bc44f4c 100644
--- a/llvm/include/llvm/Analysis/AliasAnalysis.h
+++ b/llvm/include/llvm/Analysis/AliasAnalysis.h
@@ -572,6 +572,7 @@ class AAResults {
   // relationship holds through the entire function.
   AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB,
                     AAQueryInfo &AAQI, const Instruction *CtxI = nullptr);
+  AliasResult aliasErrno(const MemoryLocation &Loc, const Module *M);
 
   ModRefInfo getModRefInfoMask(const MemoryLocation &Loc, AAQueryInfo &AAQI,
                                bool IgnoreLocals = false);
@@ -718,6 +719,11 @@ class AAResults::Concept {
                             const MemoryLocation &LocB, AAQueryInfo &AAQI,
                             const Instruction *CtxI) = 0;
 
+  /// Returns an AliasResult indicating whether a specific memory location
+  /// aliases errno.
+  virtual AliasResult aliasErrno(const MemoryLocation &Loc,
+                                 const Module *M) = 0;
+
   /// @}
   //===--------------------------------------------------------------------===//
   /// \name Simple mod/ref information
@@ -779,6 +785,10 @@ template <typename AAResultT> class AAResults::Model final : public Concept {
     return Result.alias(LocA, LocB, AAQI, CtxI);
   }
 
+  AliasResult aliasErrno(const MemoryLocation &Loc, const Module *M) override {
+    return Result.aliasErrno(Loc, M);
+  }
+
   ModRefInfo getModRefInfoMask(const MemoryLocation &Loc, AAQueryInfo &AAQI,
                                bool IgnoreLocals) override {
     return Result.getModRefInfoMask(Loc, AAQI, IgnoreLocals);
@@ -834,6 +844,10 @@ class AAResultBase {
     return AliasResult::MayAlias;
   }
 
+  AliasResult aliasErrno(const MemoryLocation &Loc, const Module *M) {
+    return AliasResult::MayAlias;
+  }
+
   ModRefInfo getModRefInfoMask(const MemoryLocation &Loc, AAQueryInfo &AAQI,
                                bool IgnoreLocals) {
     return ModRefInfo::ModRef;
diff --git a/llvm/include/llvm/Analysis/TypeBasedAliasAnalysis.h b/llvm/include/llvm/Analysis/TypeBasedAliasAnalysis.h
index e70f35174e4ca..81ee271b245f8 100644
--- a/llvm/include/llvm/Analysis/TypeBasedAliasAnalysis.h
+++ b/llvm/include/llvm/Analysis/TypeBasedAliasAnalysis.h
@@ -48,6 +48,7 @@ class TypeBasedAAResult : public AAResultBase {
 
   AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB,
                     AAQueryInfo &AAQI, const Instruction *CtxI);
+  AliasResult aliasErrno(const MemoryLocation &Loc, const Module *M);
   ModRefInfo getModRefInfoMask(const MemoryLocation &Loc, AAQueryInfo &AAQI,
                                bool IgnoreLocals);
 
diff --git a/llvm/lib/Analysis/AliasAnalysis.cpp b/llvm/lib/Analysis/AliasAnalysis.cpp
index 1a9136e464d25..651b9e0d06757 100644
--- a/llvm/lib/Analysis/AliasAnalysis.cpp
+++ b/llvm/lib/Analysis/AliasAnalysis.cpp
@@ -146,6 +146,18 @@ AliasResult AAResults::alias(const MemoryLocation &LocA,
   return Result;
 }
 
+AliasResult AAResults::aliasErrno(const MemoryLocation &Loc, const Module *M) {
+  AliasResult Result = AliasResult::MayAlias;
+
+  for (const auto &AA : AAs) {
+    Result = AA->aliasErrno(Loc, M);
+    if (Result != AliasResult::MayAlias)
+      break;
+  }
+
+  return Result;
+}
+
 ModRefInfo AAResults::getModRefInfoMask(const MemoryLocation &Loc,
                                         bool IgnoreLocals) {
   SimpleAAQueryInfo AAQIP(*this);
@@ -253,6 +265,14 @@ ModRefInfo AAResults::getModRefInfo(const CallBase *Call,
 
   Result &= ArgMR | OtherMR;
 
+#if 0
+  // AA can mask out ErrnoMem, despite the call-site clobbering errno, if we can
+  // prove the location does not alias errno. Done only via TBAA, for now.
+  if (ME.getModRef(IRMemLocation::ErrnoMem) != ModRefInfo::NoModRef)
+    if (aliasErrno(Loc, Call->getModule()) == AliasResult::NoAlias)
+      Result &= ME.getWithoutLoc(IRMemLocation::ErrnoMem).getModRef();
+#endif
+
   // Apply the ModRef mask. This ensures that if Loc is a constant memory
   // location, we take into account the fact that the call definitely could not
   // modify the memory location.
diff --git a/llvm/lib/Analysis/TypeBasedAliasAnalysis.cpp b/llvm/lib/Analysis/TypeBasedAliasAnalysis.cpp
index 3f44f746eb173..704a6ef81def3 100644
--- a/llvm/lib/Analysis/TypeBasedAliasAnalysis.cpp
+++ b/llvm/lib/Analysis/TypeBasedAliasAnalysis.cpp
@@ -115,6 +115,7 @@
 #include "llvm/IR/InstrTypes.h"
 #include "llvm/IR/LLVMContext.h"
 #include "llvm/IR/Metadata.h"
+#include "llvm/IR/Module.h"
 #include "llvm/InitializePasses.h"
 #include "llvm/Pass.h"
 #include "llvm/Support/Casting.h"
@@ -385,6 +386,20 @@ AliasResult TypeBasedAAResult::alias(const MemoryLocation &LocA,
   return AliasResult::NoAlias;
 }
 
+AliasResult TypeBasedAAResult::aliasErrno(const MemoryLocation &Loc,
+                                          const Module *M) {
+  if (!shouldUseTBAA())
+    return AliasResult::MayAlias;
+
+  const auto *ErrnoTBAAMD = M->getNamedMetadata("llvm.errno.tbaa");
+  const auto *N = Loc.AATags.TBAA;
+  if (!ErrnoTBAAMD || !N ||
+      llvm::any_of(ErrnoTBAAMD->operands(),
+                   [&](const auto *Node) { return Aliases(N, Node); }))
+    return AliasResult::MayAlias;
+  return AliasResult::NoAlias;
+}
+
 ModRefInfo TypeBasedAAResult::getModRefInfoMask(const MemoryLocation &Loc,
                                                 AAQueryInfo &AAQI,
                                                 bool IgnoreLocals) {



More information about the cfe-commits mailing list