/// See AbstractAttribute::initialize(...).
void initialize(Attributor &A) override {
- // TODO: It isn't sound to initialize as the same with `AANoAliasImpl`
- // because `noalias` may not be valid in the current position.
+ AANoAliasImpl::initialize(A);
+ if (isa<AllocaInst>(getAnchorValue()))
+ indicateOptimisticFixpoint();
}
/// See AbstractAttribute::updateImpl(...).
/// See AbstractAttribute::updateImpl(...).
ChangeStatus updateImpl(Attributor &A) override {
- // TODO: Implement this.
- return indicatePessimisticFixpoint();
+ // We can deduce "noalias" if the following conditions hold.
+ // (i) Associated value is assumed to be noalias in the definition.
+ // (ii) Associated value is assumed to be no-capture in all the uses
+ // possibly executed before this callsite.
+ // (iii) There is no other pointer argument which could alias with the
+ // value.
+
+ const Value &V = getAssociatedValue();
+ const IRPosition IRP = IRPosition::value(V);
+
+ // (i) Check whether noalias holds in the definition.
+
+ auto &NoAliasAA = A.getAAFor<AANoAlias>(*this, IRP);
+
+ if (!NoAliasAA.isAssumedNoAlias())
+ return indicatePessimisticFixpoint();
+
+ LLVM_DEBUG(dbgs() << "[Attributor][AANoAliasCSArg] " << V
+ << " is assumed NoAlias in the definition\n");
+
+ // (ii) Check whether the value is captured in the scope using AANoCapture.
+ // FIXME: This is conservative though, it is better to look at CFG and
+ // check only uses possibly executed before this callsite.
+
+ auto &NoCaptureAA = A.getAAFor<AANoCapture>(*this, IRP);
+ if (!NoCaptureAA.isAssumedNoCaptureMaybeReturned())
+ return indicatePessimisticFixpoint();
+
+ // (iii) Check there is no other pointer argument which could alias with the
+ // value.
+ ImmutableCallSite ICS(&getAnchorValue());
+ for (unsigned i = 0; i < ICS.getNumArgOperands(); i++) {
+ if (getArgNo() == (int)i)
+ continue;
+ const Value *ArgOp = ICS.getArgOperand(i);
+ if (!ArgOp->getType()->isPointerTy())
+ continue;
+
+ // TODO: Use AliasAnalysis
+ // AAResults& AAR = ..;
+ // if(AAR.isNoAlias(&getAssociatedValue(), ArgOp))
+ // return indicatePessimitisicFixpoint();
+
+ return indicatePessimisticFixpoint();
+ }
+
+ return ChangeStatus::UNCHANGED;
}
/// See AbstractAttribute::trackStatistics()
tail call void @test11_helper(i8* %a, i8* %a)
ret void
}
+
+
+; TEST 12
+; CallSite Argument
+declare void @use_nocapture(i8* nocapture)
+declare void @use(i8*)
+define void @test12_1() {
+; CHECK-LABEL: @test12_1(
+; CHECK-NEXT: [[A:%.*]] = alloca i8, align 4
+; CHECK-NEXT: [[B:%.*]] = tail call noalias i8* @malloc(i64 4)
+; CHECK-NEXT: tail call void @use_nocapture(i8* noalias nonnull align 4 dereferenceable(1) [[A]])
+; CHECK-NEXT: tail call void @use_nocapture(i8* noalias nonnull align 4 dereferenceable(1) [[A]])
+; CHECK-NEXT: tail call void @use_nocapture(i8* noalias [[B]])
+; CHECK-NEXT: tail call void @use_nocapture(i8* noalias [[B]])
+; CHECK-NEXT: ret void
+;
+ %A = alloca i8, align 4
+ %B = tail call noalias i8* @malloc(i64 4)
+ tail call void @use_nocapture(i8* %A)
+ tail call void @use_nocapture(i8* %A)
+ tail call void @use_nocapture(i8* %B)
+ tail call void @use_nocapture(i8* %B)
+ ret void
+}
+
+define void @test12_2(){
+; CHECK-LABEL: @test12_2(
+; CHECK-NEXT: [[A:%.*]] = tail call noalias i8* @malloc(i64 4)
+; FIXME: This should be @use_nocapture(i8* noalias [[A]])
+; CHECK-NEXT: tail call void @use_nocapture(i8* [[A]])
+; FIXME: This should be @use_nocapture(i8* noalias [[A]])
+; CHECK-NEXT: tail call void @use_nocapture(i8* [[A]])
+; CHECK-NEXT: tail call void @use(i8* [[A]])
+; CHECK-NEXT: tail call void @use_nocapture(i8* [[A]])
+; CHECK-NEXT: ret void
+;
+ %A = tail call noalias i8* @malloc(i64 4)
+ tail call void @use_nocapture(i8* %A)
+ tail call void @use_nocapture(i8* %A)
+ tail call void @use(i8* %A)
+ tail call void @use_nocapture(i8* %A)
+ ret void
+}
+
+declare void @two_args(i8* nocapture , i8* nocapture)
+define void @test12_3(){
+; CHECK-LABEL: @test12_3(
+ %A = tail call noalias i8* @malloc(i64 4)
+; CHECK: tail call void @two_args(i8* %A, i8* %A)
+ tail call void @two_args(i8* %A, i8* %A)
+ ret void
+}
+
+define void @test12_4(){
+; CHECK-LABEL: @test12_4(
+ %A = tail call noalias i8* @malloc(i64 4)
+ %B = tail call noalias i8* @malloc(i64 4)
+ %A_0 = getelementptr i8, i8* %A, i64 0
+ %A_1 = getelementptr i8, i8* %A, i64 1
+ %B_0 = getelementptr i8, i8* %B, i64 0
+
+; FIXME: This should be @two_args(i8* noalias %A, i8* noalias %B)
+; CHECK: tail call void @two_args(i8* %A, i8* %B)
+ tail call void @two_args(i8* %A, i8* %B)
+
+; CHECK: tail call void @two_args(i8* %A, i8* %A_0)
+ tail call void @two_args(i8* %A, i8* %A_0)
+
+; CHECK: tail call void @two_args(i8* %A, i8* %A_1)
+ tail call void @two_args(i8* %A, i8* %A_1)
+
+; FIXME: This should be @two_args(i8* noalias %A_0, i8* noalias %B_0)
+; CHECK: tail call void @two_args(i8* %A_0, i8* %B_0)
+ tail call void @two_args(i8* %A_0, i8* %B_0)
+ ret void
+}