// 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()
; 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:%.*]]) {
; 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*
;
; 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
;
;
@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: () #[[ATTR0:[0-9]+]] {
+; CHECK-SAME: () #[[ATTR1:[0-9]+]] {
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[IF_END:%.*]]
; CHECK: if.then:
;
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
define i32 @testOneFieldGlobalS_type_mismatch() {
; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
; CHECK-LABEL: define {{[^@]+}}@testOneFieldGlobalS_type_mismatch
-; CHECK-SAME: () #[[ATTR0]] {
+; CHECK-SAME: () #[[ATTR1]] {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[I:%.*]] = load double, ptr @GlobalS, align 8
; CHECK-NEXT: [[IC:%.*]] = fptosi double [[I]] to i32
define i32 @testOneFieldGlobalS_byte_offset_wrong() {
; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
; CHECK-LABEL: define {{[^@]+}}@testOneFieldGlobalS_byte_offset_wrong
-; CHECK-SAME: () #[[ATTR0]] {
+; 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
ret i32 %r.2
}
;.
-; CHECK: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind readnone willreturn }
+; CHECK: attributes #[[ATTR0:[0-9]+]] = { nocallback nofree norecurse nosync nounwind readnone willreturn }
+; CHECK: attributes #[[ATTR1]] = { nofree norecurse nosync nounwind readnone willreturn }
;.
;
; 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:
; 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: