/// See AbstractAttribute::initialize(...).
void initialize(Attributor &A) override {
- AANoCapture::initialize(A);
+ if (hasAttr(getAttrKind(), /* IgnoreSubsumingPositions */ true)) {
+ indicateOptimisticFixpoint();
+ return;
+ }
+ Function *AnchorScope = getAnchorScope();
+ if (isFnInterfaceKind() &&
+ (!AnchorScope || !AnchorScope->hasExactDefinition())) {
+ indicatePessimisticFixpoint();
+ return;
+ }
// You cannot "capture" null in the default address space.
if (isa<ConstantPointerNull>(getAssociatedValue()) &&
return;
}
- const IRPosition &IRP = getIRPosition();
- const Function *F =
- getArgNo() >= 0 ? IRP.getAssociatedFunction() : IRP.getAnchorScope();
+ const Function *F = getArgNo() >= 0 ? getAssociatedFunction() : AnchorScope;
// Check what state the associated function can actually capture.
if (F)
- determineFunctionCaptureCapabilities(IRP, *F, *this);
+ determineFunctionCaptureCapabilities(getIRPosition(), *F, *this);
else
indicatePessimisticFixpoint();
}
ret i32* %call
}
+
+declare i32* @unknown_i32p(i32*)
+define void @nocapture_is_not_subsumed_1(i32* nocapture %b) {
+; CHECK-LABEL: define {{[^@]+}}@nocapture_is_not_subsumed_1
+; CHECK-SAME: (i32* nocapture [[B:%.*]])
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[CALL:%.*]] = call i32* @unknown_i32p(i32* [[B:%.*]])
+; CHECK-NEXT: store i32 0, i32* [[CALL]]
+; CHECK-NEXT: ret void
+;
+entry:
+ %call = call i32* @unknown_i32p(i32* %b)
+ store i32 0, i32* %call
+ ret void
+}
+
+declare i32* @readonly_i32p(i32*) readonly
+define void @nocapture_is_not_subsumed_2(i32* nocapture %b) {
+; CHECK-LABEL: define {{[^@]+}}@nocapture_is_not_subsumed_2
+; CHECK-SAME: (i32* nocapture [[B:%.*]])
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[CALL:%.*]] = call i32* @readonly_i32p(i32* readonly [[B:%.*]])
+; CHECK-NEXT: store i32 0, i32* [[CALL]]
+; CHECK-NEXT: ret void
+;
+entry:
+ %call = call i32* @readonly_i32p(i32* %b)
+ store i32 0, i32* %call
+ ret void
+}
+
attributes #0 = { noinline nounwind uwtable }