Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions llvm/include/llvm/Analysis/AliasAnalysis.h
Original file line number Diff line number Diff line change
Expand Up @@ -585,6 +585,7 @@ class AAResults {
LLVM_ABI AliasResult alias(const MemoryLocation &LocA,
const MemoryLocation &LocB, AAQueryInfo &AAQI,
const Instruction *CtxI = nullptr);
LLVM_ABI AliasResult aliasErrno(const MemoryLocation &Loc, const Module *M);

LLVM_ABI ModRefInfo getModRefInfoMask(const MemoryLocation &Loc,
AAQueryInfo &AAQI,
Expand Down Expand Up @@ -744,6 +745,11 @@ class LLVM_ABI 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
Expand Down Expand Up @@ -805,6 +811,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);
Expand Down Expand Up @@ -860,6 +870,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;
Expand Down
2 changes: 2 additions & 0 deletions llvm/include/llvm/Analysis/BasicAliasAnalysis.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ class BasicAAResult : public AAResultBase {
const MemoryLocation &LocB, AAQueryInfo &AAQI,
const Instruction *CtxI);

LLVM_ABI AliasResult aliasErrno(const MemoryLocation &Loc, const Module *M);

LLVM_ABI ModRefInfo getModRefInfo(const CallBase *Call,
const MemoryLocation &Loc,
AAQueryInfo &AAQI);
Expand Down
1 change: 1 addition & 0 deletions llvm/include/llvm/Analysis/TypeBasedAliasAnalysis.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ class TypeBasedAAResult : public AAResultBase {
LLVM_ABI AliasResult alias(const MemoryLocation &LocA,
const MemoryLocation &LocB, AAQueryInfo &AAQI,
const Instruction *CtxI);
LLVM_ABI AliasResult aliasErrno(const MemoryLocation &Loc, const Module *M);
LLVM_ABI ModRefInfo getModRefInfoMask(const MemoryLocation &Loc,
AAQueryInfo &AAQI, bool IgnoreLocals);

Expand Down
12 changes: 12 additions & 0 deletions llvm/lib/Analysis/AliasAnalysis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,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);
Expand Down
25 changes: 24 additions & 1 deletion llvm/lib/Analysis/BasicAliasAnalysis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -951,7 +951,8 @@ ModRefInfo BasicAAResult::getModRefInfo(const CallBase *Call,
return ModRefInfo::NoModRef;

ModRefInfo ArgMR = ME.getModRef(IRMemLocation::ArgMem);
ModRefInfo OtherMR = ME.getWithoutLoc(IRMemLocation::ArgMem).getModRef();
ModRefInfo ErrnoMR = ME.getModRef(IRMemLocation::ErrnoMem);
ModRefInfo OtherMR = ME.getModRef(IRMemLocation::Other);

// An identified function-local object that does not escape can only be
// accessed via call arguments. Reduce OtherMR (which includes accesses to
Expand Down Expand Up @@ -997,6 +998,15 @@ ModRefInfo BasicAAResult::getModRefInfo(const CallBase *Call,
}

ModRefInfo Result = ArgMR | OtherMR;

// Refine accesses to errno memory.
if ((ErrnoMR | Result) != Result) {
if (AAQI.AAR.aliasErrno(Loc, Call->getModule()) != AliasResult::NoAlias) {
// Exclusion conditions do not hold, this memory location may alias errno.
Result |= ErrnoMR;
}
}

if (!isModAndRefSet(Result))
return Result;

Expand Down Expand Up @@ -1851,6 +1861,19 @@ AliasResult BasicAAResult::aliasCheckRecursive(
return AliasResult::MayAlias;
}

AliasResult BasicAAResult::aliasErrno(const MemoryLocation &Loc,
const Module *M) {
// There cannot be any alias with errno if the given memory location is an
// identified function-local object, or the size of the memory access is
// larger than the integer size.
if (Loc.Size.hasValue() && Loc.Size.getValue() * 8 > TLI.getIntSize())
return AliasResult::NoAlias;

if (isIdentifiedFunctionLocal(getUnderlyingObject(Loc.Ptr)))
return AliasResult::NoAlias;
return AliasResult::MayAlias;
}

/// Check whether two Values can be considered equivalent.
///
/// If the values may come from different cycle iterations, this will also
Expand Down
20 changes: 20 additions & 0 deletions llvm/lib/Analysis/TypeBasedAliasAnalysis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -385,6 +386,25 @@ 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 *N = Loc.AATags.TBAA;
if (!N)
return AliasResult::MayAlias;

// There cannot be any alias with errno if TBAA proves the given memory
// location does not alias errno.
const auto *ErrnoTBAAMD = M->getNamedMetadata("llvm.errno.tbaa");
if (!ErrnoTBAAMD || 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) {
Expand Down
133 changes: 133 additions & 0 deletions llvm/test/Transforms/InstCombine/may-alias-errno.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
; 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.
; Can do constant store-to-load forwarding.
define float @does_not_alias_errno(ptr %p, float %f) {
; CHECK-LABEL: define float @does_not_alias_errno(
; CHECK-SAME: ptr [[P:%.*]], float [[F:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: store float 0.000000e+00, ptr [[P]], align 4, !tbaa [[TBAA4:![0-9]+]]
; CHECK-NEXT: [[CALL:%.*]] = call float @sinf(float [[F]])
; CHECK-NEXT: ret float 0.000000e+00
;
entry:
store float 0.000000e+00, ptr %p, align 4, !tbaa !4
%call = call float @sinf(float %f)
%0 = load float, ptr %p, align 4, !tbaa !4
ret float %0
}

; sinf clobbering errno, but %p is alloca memory, wich can never aliases errno.
; Can do constant store-to-load forwarding.
define float @does_not_alias_errno_2(float %f) {
; CHECK-LABEL: define float @does_not_alias_errno_2(
; CHECK-SAME: float [[F:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[P:%.*]] = alloca float, align 4
; CHECK-NEXT: call void @escape(ptr nonnull [[P]])
; CHECK-NEXT: store float 0.000000e+00, ptr [[P]], align 4
; CHECK-NEXT: [[TMP1:%.*]] = call float @sinf(float [[F]])
; CHECK-NEXT: ret float 0.000000e+00
;
entry:
%p = alloca float
call void @escape(ptr %p)
store float 0.0, ptr %p
call float @sinf(float %f)
%v = load float, ptr %p
ret float %v
}

; sinf clobbering errno, but %p is memory accessed w/ size larger than errno.
; Can do constant store-to-load forwarding.
define double @does_not_alias_errno_3(ptr %p, float %f) {
; CHECK-LABEL: define double @does_not_alias_errno_3(
; CHECK-SAME: ptr [[P:%.*]], float [[F:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: call void @escape(ptr [[P]])
; CHECK-NEXT: store double 0.000000e+00, ptr [[P]], align 8
; CHECK-NEXT: [[TMP1:%.*]] = call float @sinf(float [[F]])
; CHECK-NEXT: ret double 0.000000e+00
;
entry:
call void @escape(ptr %p)
store double 0.0, ptr %p
call float @sinf(float %f)
%v = load double, ptr %p
ret double %v
}

; %p may alias errno, but read_errno does not clobber errno.
; Can do constant store-to-load forwarding.
define float @may_alias_errno_does_not_clobber(ptr %p, ptr byval(i8) %q) {
; CHECK-LABEL: define float @may_alias_errno_does_not_clobber(
; CHECK-SAME: ptr [[P:%.*]], ptr byval(i8) [[Q:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: store float 0.000000e+00, ptr [[P]], align 4
; CHECK-NEXT: [[CALL:%.*]] = call float @read_errno(ptr nonnull [[Q]])
; CHECK-NEXT: ret float 0.000000e+00
;
entry:
store float 0.000000e+00, ptr %p, align 4
%call = call float @read_errno(ptr %q)
%0 = load float, ptr %p, align 4
ret float %0
}

; sinf clobbering errno, unknown TBAA info, %p may alias errno.
; Cannot do constant store-to-load forwarding.
define float @may_alias_errno(ptr %p, float %f) {
; CHECK-LABEL: define float @may_alias_errno(
; CHECK-SAME: ptr [[P:%.*]], float [[F:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: store float 0.000000e+00, ptr [[P]], align 4
; CHECK-NEXT: [[CALL:%.*]] = call float @sinf(float [[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 %f)
%0 = load float, ptr %p, align 4
ret float %0
}

; sinf clobbering errno, %p, a integer pointer, may alias errno.
; Cannot do constant store-to-load forwarding.
define i32 @may_alias_errno_2(ptr %p, float %f) {
; CHECK-LABEL: define i32 @may_alias_errno_2(
; CHECK-SAME: ptr [[P:%.*]], float [[F:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: store i32 0, ptr [[P]], align 4, !tbaa [[TBAA0:![0-9]+]]
; CHECK-NEXT: [[CALL:%.*]] = call float @sinf(float [[F]])
; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[P]], align 4, !tbaa [[TBAA0]]
; CHECK-NEXT: ret i32 [[TMP0]]
;
entry:
store i32 0, ptr %p, align 4, !tbaa !0
%call = call float @sinf(float %f)
%0 = load i32, ptr %p, align 4, !tbaa !0
ret i32 %0
}

declare float @sinf(float) memory(errnomem: write)
declare float @read_errno(ptr) memory(argmem: write, errnomem: read)
declare void @escape(ptr %p)

!llvm.errno.tbaa = !{!0}

!0 = !{!1, !1, i64 0}
!1 = !{!"int", !2, i64 0}
!2 = !{!"omnipotent char", !3, i64 0}
!3 = !{!"Simple C/C++ TBAA"}
!4 = !{!5, !5, i64 0}
!5 = !{!"float", !2, i64 0}
;.
; CHECK: [[TBAA0]] = !{[[META1:![0-9]+]], [[META1]], i64 0}
; CHECK: [[META1]] = !{!"int", [[META2:![0-9]+]], i64 0}
; CHECK: [[META2]] = !{!"omnipotent char", [[META3:![0-9]+]], i64 0}
; CHECK: [[META3]] = !{!"Simple C/C++ TBAA"}
; CHECK: [[TBAA4]] = !{[[META5:![0-9]+]], [[META5]], i64 0}
; CHECK: [[META5]] = !{!"float", [[META2]], i64 0}
;.