93 changes: 58 additions & 35 deletions llvm/lib/Transforms/IPO/AttributorAttributes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -720,7 +720,7 @@ struct DenseMapInfo<AAPointerInfo::Access> : DenseMapInfo<Instruction *> {

/// Helper that allows OffsetAndSize as a key in a DenseMap.
template <>
struct DenseMapInfo<AAPointerInfo ::OffsetAndSize>
struct DenseMapInfo<AA::OffsetAndSize>
: DenseMapInfo<std::pair<int64_t, int64_t>> {};

/// Helper for AA::PointerInfo::Access DenseMap/Set usage ignoring everythign
Expand Down Expand Up @@ -847,7 +847,7 @@ struct AA::PointerInfo::State : public AbstractState {
};

/// We store all accesses in bins denoted by their offset and size.
using AccessBinsTy = DenseMap<AAPointerInfo::OffsetAndSize, Accesses *>;
using AccessBinsTy = DenseMap<AA::OffsetAndSize, Accesses *>;

AccessBinsTy::const_iterator begin() const { return AccessBins.begin(); }
AccessBinsTy::const_iterator end() const { return AccessBins.end(); }
Expand All @@ -865,7 +865,7 @@ struct AA::PointerInfo::State : public AbstractState {
AAPointerInfo::AccessKind Kind, Type *Ty,
Instruction *RemoteI = nullptr,
Accesses *BinPtr = nullptr) {
AAPointerInfo::OffsetAndSize Key{Offset, Size};
AA::OffsetAndSize Key{Offset, Size};
Accesses *&Bin = BinPtr ? BinPtr : AccessBins[Key];
if (!Bin)
Bin = new (A.Allocator) Accesses;
Expand All @@ -887,13 +887,13 @@ struct AA::PointerInfo::State : public AbstractState {

/// See AAPointerInfo::forallInterferingAccesses.
bool forallInterferingAccesses(
AAPointerInfo::OffsetAndSize OAS,
AA::OffsetAndSize OAS,
function_ref<bool(const AAPointerInfo::Access &, bool)> CB) const {
if (!isValidState())
return false;

for (const auto &It : AccessBins) {
AAPointerInfo::OffsetAndSize ItOAS = It.getFirst();
AA::OffsetAndSize ItOAS = It.getFirst();
if (!OAS.mayOverlap(ItOAS))
continue;
bool IsExact = OAS == ItOAS && !OAS.offsetOrSizeAreUnknown();
Expand All @@ -907,24 +907,29 @@ struct AA::PointerInfo::State : public AbstractState {
/// See AAPointerInfo::forallInterferingAccesses.
bool forallInterferingAccesses(
Instruction &I,
function_ref<bool(const AAPointerInfo::Access &, bool)> CB) const {
function_ref<bool(const AAPointerInfo::Access &, bool)> CB,
AA::OffsetAndSize *OASPtr) const {
if (!isValidState())
return false;

// First find the offset and size of I.
AAPointerInfo::OffsetAndSize OAS(-1, -1);
AA::OffsetAndSize OAS = AA::OffsetAndSize::getUnknown();
for (const auto &It : AccessBins) {
for (auto &Access : *It.getSecond()) {
if (Access.getRemoteInst() == &I) {
OAS = It.getFirst();
break;
}
}
if (OAS.getSize() != -1)
if (OAS.getSize() != AA::OffsetAndSize::Unknown)
break;
}

if (OASPtr)
*OASPtr = OAS;

// No access for I was found, we are done.
if (OAS.getSize() == -1)
if (OAS.getSize() == AA::OffsetAndSize::Unknown)
return true;

// Now that we have an offset and size, find all overlapping ones and use
Expand Down Expand Up @@ -957,17 +962,16 @@ struct AAPointerInfoImpl
}

bool forallInterferingAccesses(
OffsetAndSize OAS,
AA::OffsetAndSize OAS,
function_ref<bool(const AAPointerInfo::Access &, bool)> CB)
const override {
return State::forallInterferingAccesses(OAS, CB);
}

bool
forallInterferingAccesses(Attributor &A, const AbstractAttribute &QueryingAA,
Instruction &I,
function_ref<bool(const Access &, bool)> UserCB,
bool &HasBeenWrittenTo) const override {
bool forallInterferingAccesses(
Attributor &A, const AbstractAttribute &QueryingAA, Instruction &I,
function_ref<bool(const Access &, bool)> UserCB, bool &HasBeenWrittenTo,
AA::OffsetAndSize *OASPtr = nullptr) const override {
HasBeenWrittenTo = false;

SmallPtrSet<const Access *, 8> DominatingWrites;
Expand Down Expand Up @@ -1082,7 +1086,7 @@ struct AAPointerInfoImpl
InterferingAccesses.push_back({&Acc, Exact});
return true;
};
if (!State::forallInterferingAccesses(I, AccessCB))
if (!State::forallInterferingAccesses(I, AccessCB, OASPtr))
return false;

if (HasBeenWrittenTo) {
Expand Down Expand Up @@ -1150,9 +1154,10 @@ struct AAPointerInfoImpl
// Combine the accesses bin by bin.
ChangeStatus Changed = ChangeStatus::UNCHANGED;
for (const auto &It : OtherAAImpl.getState()) {
OffsetAndSize OAS = OffsetAndSize::getUnknown();
if (Offset != OffsetAndSize::Unknown)
OAS = OffsetAndSize(It.first.getOffset() + Offset, It.first.getSize());
AA::OffsetAndSize OAS = AA::OffsetAndSize::getUnknown();
if (Offset != AA::OffsetAndSize::Unknown)
OAS = AA::OffsetAndSize(It.first.getOffset() + Offset,
It.first.getSize());
Accesses *Bin = AccessBins.lookup(OAS);
for (const AAPointerInfo::Access &RAcc : *It.second) {
if (IsByval && !RAcc.isRead())
Expand Down Expand Up @@ -1210,11 +1215,10 @@ struct AAPointerInfoFloating : public AAPointerInfoImpl {
bool handleAccess(Attributor &A, Instruction &I, Value &Ptr,
Optional<Value *> Content, AccessKind Kind, int64_t Offset,
ChangeStatus &Changed, Type *Ty,
int64_t Size = OffsetAndSize::Unknown) {
int64_t Size = AA::OffsetAndSize::Unknown) {
using namespace AA::PointerInfo;
// No need to find a size if one is given or the offset is unknown.
if (Offset != OffsetAndSize::Unknown && Size == OffsetAndSize::Unknown &&
Ty) {
// No need to find a size if one is given.
if (Size == AA::OffsetAndSize::Unknown && Ty) {
const DataLayout &DL = A.getDataLayout();
TypeSize AccessSize = DL.getTypeStoreSize(Ty);
if (!AccessSize.isScalable())
Expand All @@ -1226,7 +1230,7 @@ struct AAPointerInfoFloating : public AAPointerInfoImpl {

/// Helper struct, will support ranges eventually.
struct OffsetInfo {
int64_t Offset = OffsetAndSize::Unknown;
int64_t Offset = AA::OffsetAndSize::Unknown;

bool operator==(const OffsetInfo &OI) const { return Offset == OI.Offset; }
};
Expand Down Expand Up @@ -1281,9 +1285,9 @@ struct AAPointerInfoFloating : public AAPointerInfoImpl {

// TODO: Use range information.
APInt GEPOffset(DL.getIndexTypeSizeInBits(GEP->getType()), 0);
if (PtrOI.Offset == OffsetAndSize::Unknown ||
if (PtrOI.Offset == AA::OffsetAndSize::Unknown ||
!GEP->accumulateConstantOffset(DL, GEPOffset)) {
UsrOI.Offset = OffsetAndSize::Unknown;
UsrOI.Offset = AA::OffsetAndSize::Unknown;
Follow = true;
return true;
}
Expand Down Expand Up @@ -1312,7 +1316,7 @@ struct AAPointerInfoFloating : public AAPointerInfoImpl {

// Check if the PHI operand has already an unknown offset as we can't
// improve on that anymore.
if (PtrOI.Offset == OffsetAndSize::Unknown) {
if (PtrOI.Offset == AA::OffsetAndSize::Unknown) {
UsrOI = PtrOI;
Follow = true;
return true;
Expand All @@ -1339,7 +1343,7 @@ struct AAPointerInfoFloating : public AAPointerInfoImpl {

// TODO: Approximate in case we know the direction of the recurrence.
UsrOI = PtrOI;
UsrOI.Offset = OffsetAndSize::Unknown;
UsrOI.Offset = AA::OffsetAndSize::Unknown;
Follow = true;
return true;
}
Expand Down Expand Up @@ -1482,7 +1486,7 @@ struct AAPointerInfoCallSiteArgument final : AAPointerInfoFloating {
// accessed.
if (auto *MI = dyn_cast_or_null<MemIntrinsic>(getCtxI())) {
ConstantInt *Length = dyn_cast<ConstantInt>(MI->getLength());
int64_t LengthVal = OffsetAndSize::Unknown;
int64_t LengthVal = AA::OffsetAndSize::Unknown;
if (Length)
LengthVal = Length->getSExtValue();
Value &Ptr = getAssociatedValue();
Expand Down Expand Up @@ -1513,13 +1517,32 @@ struct AAPointerInfoCallSiteArgument final : AAPointerInfoFloating {
// sense to specialize attributes for call sites arguments instead of
// redirecting requests to the callee argument.
Argument *Arg = getAssociatedArgument();
if (!Arg)
if (Arg) {
const IRPosition &ArgPos = IRPosition::argument(*Arg);
auto &ArgAA =
A.getAAFor<AAPointerInfo>(*this, ArgPos, DepClassTy::REQUIRED);
if (ArgAA.getState().isValidState())
return translateAndAddState(A, ArgAA, 0, *cast<CallBase>(getCtxI()),
/* FromCallee */ true);
}

const auto &NoCaptureAA =
A.getAAFor<AANoCapture>(*this, getIRPosition(), DepClassTy::OPTIONAL);

if (!NoCaptureAA.isAssumedNoCapture())
return indicatePessimisticFixpoint();
const IRPosition &ArgPos = IRPosition::argument(*Arg);
auto &ArgAA =
A.getAAFor<AAPointerInfo>(*this, ArgPos, DepClassTy::REQUIRED);
return translateAndAddState(A, ArgAA, 0, *cast<CallBase>(getCtxI()),
/* FromCallee */ true);

bool IsKnown = false;
if (AA::isAssumedReadNone(A, getIRPosition(), *this, IsKnown))
return ChangeStatus::UNCHANGED;
bool ReadOnly = AA::isAssumedReadOnly(A, getIRPosition(), *this, IsKnown);

ChangeStatus Changed = ChangeStatus::UNCHANGED;
handleAccess(A, *getCtxI(), getAssociatedValue(), nullptr,
ReadOnly ? AccessKind::AK_MAY_READ
: AccessKind::AK_MAY_READ_WRITE,
0, Changed, nullptr, AA::OffsetAndSize::Unknown);
return Changed;
}

/// See AbstractAttribute::trackStatistics()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes --check-globals
; RUN: opt -attributor -enable-new-pm=0 -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=5 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM
; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=5 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM
; RUN: opt -attributor -enable-new-pm=0 -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=2 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM
; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=2 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM
; RUN: opt -attributor-cgscc -enable-new-pm=0 -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM
; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_OPM,IS__CGSCC____,IS________NPM,IS__CGSCC_NPM

Expand All @@ -11,14 +11,11 @@
; CHECK: @[[G:[a-zA-Z0-9_$"\\.-]+]] = constant [[T:%.*]] { i32 0, i32 0, i32 17, i32 25 }
;.
define internal i32 @test(%T* %p) {
; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
; CHECK-LABEL: define {{[^@]+}}@test
; CHECK-SAME: () #[[ATTR0:[0-9]+]] {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[A:%.*]] = load i32, i32* getelementptr inbounds ([[T:%.*]], %T* @G, i64 0, i32 3), align 4
; CHECK-NEXT: [[B:%.*]] = load i32, i32* getelementptr inbounds ([[T]], %T* @G, i64 0, i32 2), align 8
; CHECK-NEXT: [[V:%.*]] = add i32 [[A]], [[B]]
; CHECK-NEXT: ret i32 [[V]]
; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
; IS__CGSCC____-LABEL: define {{[^@]+}}@test
; IS__CGSCC____-SAME: () #[[ATTR0:[0-9]+]] {
; IS__CGSCC____-NEXT: entry:
; IS__CGSCC____-NEXT: ret i32 42
;
entry:
%a.gep = getelementptr %T, %T* %p, i64 0, i32 3
Expand All @@ -32,16 +29,15 @@ entry:
define i32 @caller() {
; IS__TUNIT____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
; IS__TUNIT____-LABEL: define {{[^@]+}}@caller
; IS__TUNIT____-SAME: () #[[ATTR0]] {
; IS__TUNIT____-SAME: () #[[ATTR0:[0-9]+]] {
; IS__TUNIT____-NEXT: entry:
; IS__TUNIT____-NEXT: [[V:%.*]] = call i32 @test() #[[ATTR1:[0-9]+]]
; IS__TUNIT____-NEXT: ret i32 [[V]]
; IS__TUNIT____-NEXT: ret i32 42
;
; IS__CGSCC____: Function Attrs: nofree nosync nounwind readnone willreturn
; IS__CGSCC____-LABEL: define {{[^@]+}}@caller
; IS__CGSCC____-SAME: () #[[ATTR1:[0-9]+]] {
; IS__CGSCC____-NEXT: entry:
; IS__CGSCC____-NEXT: [[V:%.*]] = call i32 @test() #[[ATTR2:[0-9]+]]
; IS__CGSCC____-NEXT: [[V:%.*]] = call noundef i32 @test() #[[ATTR2:[0-9]+]]
; IS__CGSCC____-NEXT: ret i32 [[V]]
;
entry:
Expand All @@ -50,7 +46,6 @@ entry:
}
;.
; IS__TUNIT____: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind readnone willreturn }
; IS__TUNIT____: attributes #[[ATTR1]] = { nofree nosync nounwind readnone willreturn }
;.
; IS__CGSCC____: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind readnone willreturn }
; IS__CGSCC____: attributes #[[ATTR1]] = { nofree nosync nounwind readnone willreturn }
Expand Down
7 changes: 2 additions & 5 deletions llvm/test/Transforms/Attributor/ArgumentPromotion/fp80.ll
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,10 @@ define void @run() {
; NOT_CGSCC_NPM-NEXT: entry:
; NOT_CGSCC_NPM-NEXT: unreachable
;
; IS__CGSCC____: Function Attrs: nofree nosync nounwind readonly willreturn
; IS__CGSCC____: Function Attrs: nofree nosync nounwind readnone willreturn
; IS__CGSCC____-LABEL: define {{[^@]+}}@run
; IS__CGSCC____-SAME: () #[[ATTR0:[0-9]+]] {
; IS__CGSCC____-NEXT: entry:
; IS__CGSCC____-NEXT: [[TMP0:%.*]] = load i32, i32* getelementptr inbounds ([[STRUCT_FOO:%.*]], %struct.Foo* @a, i32 0, i32 0), align 8
; IS__CGSCC____-NEXT: [[A_0_1:%.*]] = getelementptr [[STRUCT_FOO]], %struct.Foo* @a, i64 0, i32 1
; IS__CGSCC____-NEXT: [[TMP1:%.*]] = load i64, i64* [[A_0_1]], align 8
; IS__CGSCC____-NEXT: unreachable
;
entry:
Expand Down Expand Up @@ -124,7 +121,7 @@ loop:
;.
; NOT_CGSCC_NPM: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind readnone willreturn }
;.
; IS__CGSCC____: attributes #[[ATTR0]] = { nofree nosync nounwind readonly willreturn }
; IS__CGSCC____: attributes #[[ATTR0]] = { nofree nosync nounwind readnone willreturn }
; IS__CGSCC____: attributes #[[ATTR1]] = { nofree norecurse nosync nounwind readnone willreturn }
; IS__CGSCC____: attributes #[[ATTR2]] = { nofree norecurse noreturn nosync nounwind readnone }
;.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes --check-globals
; RUN: opt -attributor -enable-new-pm=0 -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=15 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM
; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=15 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM
; RUN: opt -attributor -enable-new-pm=0 -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=16 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM
; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=16 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM
; RUN: opt -attributor-cgscc -enable-new-pm=0 -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM
; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_OPM,IS__CGSCC____,IS________NPM,IS__CGSCC_NPM
;
Expand Down Expand Up @@ -179,7 +179,7 @@ define internal void @.omp_outlined.(i32* noalias %.global_tid., i32* noalias %.
; IS__TUNIT_NPM: omp.inner.for.body:
; IS__TUNIT_NPM-NEXT: [[ADD10:%.*]] = add nsw i32 [[DOTOMP_IV_0]], 2
; IS__TUNIT_NPM-NEXT: [[TMP11:%.*]] = load double, double* [[CONV]], align 8
; IS__TUNIT_NPM-NEXT: call void @bar(i32 [[ADD10]], float 3.000000e+00, double [[TMP11]])
; IS__TUNIT_NPM-NEXT: call void @bar(i32 [[ADD10]], float 3.000000e+00, double noundef [[TMP11]])
; IS__TUNIT_NPM-NEXT: br label [[OMP_BODY_CONTINUE:%.*]]
; IS__TUNIT_NPM: omp.body.continue:
; IS__TUNIT_NPM-NEXT: br label [[OMP_INNER_FOR_INC]]
Expand Down Expand Up @@ -301,7 +301,7 @@ define internal void @.omp_outlined.(i32* noalias %.global_tid., i32* noalias %.
; IS__CGSCC_NPM-NEXT: [[ADD10:%.*]] = add nsw i32 [[DOTOMP_IV_0]], 2
; IS__CGSCC_NPM-NEXT: [[TMP10:%.*]] = load float, float* [[P]], align 4
; IS__CGSCC_NPM-NEXT: [[TMP11:%.*]] = load double, double* [[CONV]], align 8
; IS__CGSCC_NPM-NEXT: call void @bar(i32 [[ADD10]], float [[TMP10]], double [[TMP11]])
; IS__CGSCC_NPM-NEXT: call void @bar(i32 [[ADD10]], float [[TMP10]], double noundef [[TMP11]])
; IS__CGSCC_NPM-NEXT: br label [[OMP_BODY_CONTINUE:%.*]]
; IS__CGSCC_NPM: omp.body.continue:
; IS__CGSCC_NPM-NEXT: br label [[OMP_INNER_FOR_INC]]
Expand Down
14 changes: 6 additions & 8 deletions llvm/test/Transforms/Attributor/heap_to_stack_gpu.ll
Original file line number Diff line number Diff line change
Expand Up @@ -407,11 +407,10 @@ define i32 @irreducible_cfg(i32 %0) {
; IS________OPM-NEXT: [[TMP14]] = add nsw i32 [[DOT1]], 1
; IS________OPM-NEXT: br label [[TMP8]]
; IS________OPM: 15:
; IS________OPM-NEXT: [[TMP16:%.*]] = load i32, i32* [[TMP3]], align 4
; IS________OPM-NEXT: [[TMP17:%.*]] = bitcast i32* [[TMP3]] to i8*
; IS________OPM-NEXT: call void @free(i8* nocapture noundef [[TMP17]])
; IS________OPM-NEXT: [[TMP18:%.*]] = load i32, i32* [[TMP3]], align 4
; IS________OPM-NEXT: ret i32 [[TMP18]]
; IS________OPM-NEXT: [[TMP16:%.*]] = bitcast i32* [[TMP3]] to i8*
; IS________OPM-NEXT: call void @free(i8* nocapture noundef [[TMP16]])
; IS________OPM-NEXT: [[TMP17:%.*]] = load i32, i32* [[TMP3]], align 4
; IS________OPM-NEXT: ret i32 [[TMP17]]
;
; IS________NPM-LABEL: define {{[^@]+}}@irreducible_cfg
; IS________NPM-SAME: (i32 [[TMP0:%.*]]) {
Expand Down Expand Up @@ -439,10 +438,9 @@ define i32 @irreducible_cfg(i32 %0) {
; IS________NPM-NEXT: [[TMP14]] = add nsw i32 [[DOT1]], 1
; IS________NPM-NEXT: br label [[TMP8]]
; IS________NPM: 15:
; IS________NPM-NEXT: [[TMP16:%.*]] = load i32, i32* [[TMP3]], align 4
; IS________NPM-NEXT: call void @free(i8* nocapture noundef [[TMP2]])
; IS________NPM-NEXT: [[TMP17:%.*]] = load i32, i32* [[TMP3]], align 4
; IS________NPM-NEXT: ret i32 [[TMP17]]
; IS________NPM-NEXT: [[TMP16:%.*]] = load i32, i32* [[TMP3]], align 4
; IS________NPM-NEXT: ret i32 [[TMP16]]
;
%2 = call noalias i8* @malloc(i64 4)
%3 = bitcast i8* %2 to i32*
Expand Down
3 changes: 1 addition & 2 deletions llvm/test/Transforms/Attributor/pointer-info.ll
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,12 @@ define void @foo(i8* %ptr) {
;
; IS__CGSCC____: Function Attrs: nofree nosync nounwind readnone willreturn
; IS__CGSCC____-LABEL: define {{[^@]+}}@foo
; IS__CGSCC____-SAME: (i8* nocapture nofree writeonly [[PTR:%.*]]) #[[ATTR0:[0-9]+]] {
; IS__CGSCC____-SAME: (i8* nocapture nofree readnone [[PTR:%.*]]) #[[ATTR0:[0-9]+]] {
; IS__CGSCC____-NEXT: entry:
; IS__CGSCC____-NEXT: [[TMP0:%.*]] = alloca [[STRUCT_TEST_A:%.*]], align 8
; IS__CGSCC____-NEXT: br label [[CALL_BR:%.*]]
; IS__CGSCC____: call.br:
; IS__CGSCC____-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT_TEST_A]], %struct.test.a* [[TMP0]], i64 0, i32 2
; IS__CGSCC____-NEXT: store i8* [[PTR]], i8** [[TMP1]], align 8
; IS__CGSCC____-NEXT: tail call void @bar(%struct.test.a* noalias nocapture nofree noundef nonnull readnone byval([[STRUCT_TEST_A]]) align 8 dereferenceable(24) [[TMP0]]) #[[ATTR2:[0-9]+]]
; IS__CGSCC____-NEXT: ret void
;
Expand Down
225 changes: 225 additions & 0 deletions llvm/test/Transforms/Attributor/value-simplify-pointer-info-struct.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,225 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes --check-globals
; RUN: opt -attributor -enable-new-pm=0 -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=9 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM
; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=9 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM
; RUN: opt -attributor-cgscc -enable-new-pm=0 -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM
; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_OPM,IS__CGSCC____,IS________NPM,IS__CGSCC_NPM
;
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"

%struct.S = type { i32, double, ptr }

; struct S {
; int a;
; double b;
; struct S* c;
; };
;
; static const struct S GlobalS = {42, 3.14, 0};
;
; int testOneFieldGlobalS() {
; int r = 0;
; if (GlobalS.a != 42)
; r += 1;
; if (GlobalS.b == 3.14)
; r += 2;
; if (GlobalS.c)
; r += 4;
; return r;
; }
;
@GlobalS = internal constant %struct.S { i32 42, double 3.140000e+00, ptr null }, align 8

declare void @harmless_use(ptr nocapture readonly) nofree norecurse nosync nounwind readnone willreturn nocallback

;.
; CHECK: @[[GLOBALS:[a-zA-Z0-9_$"\\.-]+]] = internal constant [[STRUCT_S:%.*]] { i32 42, double 3.140000e+00, ptr null }, align 8
;.
define i32 @testOneFieldGlobalS() {
; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
; CHECK-LABEL: define {{[^@]+}}@testOneFieldGlobalS
; CHECK-SAME: () #[[ATTR1:[0-9]+]] {
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[IF_END:%.*]]
; CHECK: if.then:
; CHECK-NEXT: unreachable
; CHECK: if.end:
; CHECK-NEXT: br label [[IF_THEN2:%.*]]
; CHECK: if.then2:
; CHECK-NEXT: [[ADD3:%.*]] = add nsw i32 0, 2
; CHECK-NEXT: br label [[IF_END4:%.*]]
; CHECK: if.end4:
; CHECK-NEXT: br label [[IF_END7:%.*]]
; CHECK: if.then5:
; CHECK-NEXT: unreachable
; CHECK: if.end7:
; CHECK-NEXT: ret i32 2
;
entry:
%i = load i32, ptr @GlobalS, align 8
call void @harmless_use(ptr @GlobalS)
%cmp = icmp ne i32 %i, 42
br i1 %cmp, label %if.then, label %if.end

if.then: ; preds = %entry
%add = add nsw i32 0, 1
br label %if.end

if.end: ; preds = %if.then, %entry
%r.0 = phi i32 [ %add, %if.then ], [ 0, %entry ]
%i1 = load double, ptr getelementptr inbounds (%struct.S, ptr @GlobalS, i32 0, i32 1), align 8
%cmp1 = fcmp oeq double %i1, 3.140000e+00
br i1 %cmp1, label %if.then2, label %if.end4

if.then2: ; preds = %if.end
%add3 = add nsw i32 %r.0, 2
br label %if.end4

if.end4: ; preds = %if.then2, %if.end
%r.1 = phi i32 [ %add3, %if.then2 ], [ %r.0, %if.end ]
%i2 = load ptr, ptr getelementptr inbounds (%struct.S, ptr @GlobalS, i32 0, i32 2), align 8
%tobool = icmp ne ptr %i2, null
br i1 %tobool, label %if.then5, label %if.end7

if.then5: ; preds = %if.end4
%add6 = add nsw i32 %r.1, 4
br label %if.end7

if.end7: ; preds = %if.then5, %if.end4
%r.2 = phi i32 [ %add6, %if.then5 ], [ %r.1, %if.end4 ]
ret i32 %r.2
}

define i32 @testOneFieldGlobalS_type_mismatch() {
; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
; CHECK-LABEL: define {{[^@]+}}@testOneFieldGlobalS_type_mismatch
; CHECK-SAME: () #[[ATTR1]] {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[I:%.*]] = load double, ptr @GlobalS, align 8
; CHECK-NEXT: [[IC:%.*]] = fptosi double [[I]] to i32
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[IC]], 42
; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
; CHECK: if.then:
; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 0, 1
; CHECK-NEXT: br label [[IF_END]]
; CHECK: if.end:
; CHECK-NEXT: [[R_0:%.*]] = phi i32 [ [[ADD]], [[IF_THEN]] ], [ 0, [[ENTRY:%.*]] ]
; CHECK-NEXT: [[I1:%.*]] = load i64, ptr getelementptr inbounds ([[STRUCT_S:%.*]], ptr @GlobalS, i32 0, i32 1), align 8
; CHECK-NEXT: [[I1C:%.*]] = sitofp i64 [[I1]] to double
; CHECK-NEXT: [[CMP1:%.*]] = fcmp oeq double [[I1C]], 3.140000e+00
; CHECK-NEXT: br i1 [[CMP1]], label [[IF_THEN2:%.*]], label [[IF_END4:%.*]]
; CHECK: if.then2:
; CHECK-NEXT: [[ADD3:%.*]] = add nsw i32 [[R_0]], 2
; CHECK-NEXT: br label [[IF_END4]]
; CHECK: if.end4:
; CHECK-NEXT: [[R_1:%.*]] = phi i32 [ [[ADD3]], [[IF_THEN2]] ], [ [[R_0]], [[IF_END]] ]
; CHECK-NEXT: br label [[IF_END7:%.*]]
; CHECK: if.then5:
; CHECK-NEXT: unreachable
; CHECK: if.end7:
; CHECK-NEXT: ret i32 [[R_1]]
;
entry:
%i = load double, ptr @GlobalS, align 8
%ic = fptosi double %i to i32
%cmp = icmp ne i32 %ic, 42
br i1 %cmp, label %if.then, label %if.end

if.then: ; preds = %entry
%add = add nsw i32 0, 1
br label %if.end

if.end: ; preds = %if.then, %entry
%r.0 = phi i32 [ %add, %if.then ], [ 0, %entry ]
%i1 = load i64, ptr getelementptr inbounds (%struct.S, ptr @GlobalS, i32 0, i32 1), align 8
%i1c = sitofp i64 %i1 to double
%cmp1 = fcmp oeq double %i1c, 3.140000e+00
br i1 %cmp1, label %if.then2, label %if.end4

if.then2: ; preds = %if.end
%add3 = add nsw i32 %r.0, 2
br label %if.end4

if.end4: ; preds = %if.then2, %if.end
%r.1 = phi i32 [ %add3, %if.then2 ], [ %r.0, %if.end ]
%i2 = load i64, ptr getelementptr inbounds (%struct.S, ptr @GlobalS, i32 0, i32 2), align 8
%i2c = inttoptr i64 %i2 to ptr
%tobool = icmp ne ptr %i2c, null
br i1 %tobool, label %if.then5, label %if.end7

if.then5: ; preds = %if.end4
%add6 = add nsw i32 %r.1, 4
br label %if.end7

if.end7: ; preds = %if.then5, %if.end4
%r.2 = phi i32 [ %add6, %if.then5 ], [ %r.1, %if.end4 ]
ret i32 %r.2
}

define i32 @testOneFieldGlobalS_byte_offset_wrong() {
; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
; CHECK-LABEL: define {{[^@]+}}@testOneFieldGlobalS_byte_offset_wrong
; CHECK-SAME: () #[[ATTR1]] {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[I:%.*]] = load i32, ptr getelementptr inbounds (i32, ptr @GlobalS, i32 1), align 8
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[I]], 42
; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
; CHECK: if.then:
; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 0, 1
; CHECK-NEXT: br label [[IF_END]]
; CHECK: if.end:
; CHECK-NEXT: [[R_0:%.*]] = phi i32 [ [[ADD]], [[IF_THEN]] ], [ 0, [[ENTRY:%.*]] ]
; CHECK-NEXT: [[I1:%.*]] = load double, ptr getelementptr (double, ptr @GlobalS, i32 3), align 8
; CHECK-NEXT: [[CMP1:%.*]] = fcmp oeq double [[I1]], 3.140000e+00
; CHECK-NEXT: br i1 [[CMP1]], label [[IF_THEN2:%.*]], label [[IF_END4:%.*]]
; CHECK: if.then2:
; CHECK-NEXT: [[ADD3:%.*]] = add nsw i32 [[R_0]], 2
; CHECK-NEXT: br label [[IF_END4]]
; CHECK: if.end4:
; CHECK-NEXT: [[R_1:%.*]] = phi i32 [ [[ADD3]], [[IF_THEN2]] ], [ [[R_0]], [[IF_END]] ]
; CHECK-NEXT: [[I2:%.*]] = load ptr, ptr getelementptr (ptr, ptr @GlobalS, i32 11), align 8
; CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne ptr [[I2]], null
; CHECK-NEXT: br i1 [[TOBOOL]], label [[IF_THEN5:%.*]], label [[IF_END7:%.*]]
; CHECK: if.then5:
; CHECK-NEXT: [[ADD6:%.*]] = add nsw i32 [[R_1]], 4
; CHECK-NEXT: br label [[IF_END7]]
; CHECK: if.end7:
; CHECK-NEXT: [[R_2:%.*]] = phi i32 [ [[ADD6]], [[IF_THEN5]] ], [ [[R_1]], [[IF_END4]] ]
; CHECK-NEXT: ret i32 [[R_2]]
;
entry:
%i = load i32, ptr getelementptr (i32, ptr @GlobalS, i32 1), align 8
%cmp = icmp ne i32 %i, 42
br i1 %cmp, label %if.then, label %if.end

if.then: ; preds = %entry
%add = add nsw i32 0, 1
br label %if.end

if.end: ; preds = %if.then, %entry
%r.0 = phi i32 [ %add, %if.then ], [ 0, %entry ]
%i1 = load double, ptr getelementptr (double, ptr @GlobalS, i32 3), align 8
%cmp1 = fcmp oeq double %i1, 3.140000e+00
br i1 %cmp1, label %if.then2, label %if.end4

if.then2: ; preds = %if.end
%add3 = add nsw i32 %r.0, 2
br label %if.end4

if.end4: ; preds = %if.then2, %if.end
%r.1 = phi i32 [ %add3, %if.then2 ], [ %r.0, %if.end ]
%i2 = load ptr, ptr getelementptr (ptr, ptr @GlobalS, i32 11), align 8
%tobool = icmp ne ptr %i2, null
br i1 %tobool, label %if.then5, label %if.end7

if.then5: ; preds = %if.end4
%add6 = add nsw i32 %r.1, 4
br label %if.end7

if.end7: ; preds = %if.then5, %if.end4
%r.2 = phi i32 [ %add6, %if.then5 ], [ %r.1, %if.end4 ]
ret i32 %r.2
}
;.
; CHECK: attributes #[[ATTR0:[0-9]+]] = { nocallback nofree norecurse nosync nounwind readnone willreturn }
; CHECK: attributes #[[ATTR1]] = { nofree norecurse nosync nounwind readnone willreturn }
;.
5 changes: 1 addition & 4 deletions llvm/test/Transforms/OpenMP/parallel_deletion.ll
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,7 @@ entry:
;
; FIXME: We do not realize that `a` is dead and all accesses to it can be removed
; making the parallel regions readonly and deletable.
; This is still true except the (non-atomic) reduction update is already deleted.
define void @delete_parallel_2() {
; CHECK-LABEL: define {{[^@]+}}@delete_parallel_2() {
; CHECK-NEXT: entry:
Expand Down Expand Up @@ -553,10 +554,6 @@ define internal void @.omp_outlined..6(i32* noalias %.global_tid., i32* noalias
; CHECK-NEXT: i32 2, label [[DOTOMP_REDUCTION_CASE2:%.*]]
; CHECK-NEXT: ]
; CHECK: .omp.reduction.case1:
; CHECK-NEXT: [[TMP5:%.*]] = load i32, i32* [[A]], align 4
; CHECK-NEXT: [[TMP6:%.*]] = load i32, i32* [[A1]], align 4
; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP5]], [[TMP6]]
; CHECK-NEXT: store i32 [[ADD]], i32* [[A]], align 4
; CHECK-NEXT: call void @__kmpc_end_reduce_nowait(%struct.ident_t* noundef nonnull @[[GLOB2]], i32 [[TMP2]], [8 x i32]* noundef nonnull @.gomp_critical_user_.reduction.var)
; CHECK-NEXT: br label [[DOTOMP_REDUCTION_DEFAULT]]
; CHECK: .omp.reduction.case2:
Expand Down
6 changes: 3 additions & 3 deletions llvm/test/Transforms/OpenMP/remove_globalization.ll
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,13 @@ define internal void @foo() {
; CHECK-LABEL: define {{[^@]+}}@foo
; CHECK-SAME: () #[[ATTR0]] {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[TMP0:%.*]] = alloca i8, i64 4, align 1
; CHECK-NEXT: [[DOTH2S:%.*]] = alloca i8, i64 4, align 1
; CHECK-NEXT: ret void
;
; CHECK-DISABLED-LABEL: define {{[^@]+}}@foo
; CHECK-DISABLED-SAME: () #[[ATTR0]] {
; CHECK-DISABLED-NEXT: entry:
; CHECK-DISABLED-NEXT: [[TMP0:%.*]] = alloca i8, i64 4, align 1
; CHECK-DISABLED-NEXT: [[DOTH2S:%.*]] = alloca i8, i64 4, align 1
; CHECK-DISABLED-NEXT: ret void
;
entry:
Expand Down Expand Up @@ -132,7 +132,7 @@ entry:
define void @unused() {
; CHECK-LABEL: define {{[^@]+}}@unused() {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[TMP0:%.*]] = alloca i8, i64 4, align 1
; CHECK-NEXT: [[DOTH2S:%.*]] = alloca i8, i64 4, align 1
; CHECK-NEXT: call void @use(i8* undef)
; CHECK-NEXT: ret void
;
Expand Down