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 <m...@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 <m...@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 <m...@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) { _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits