diff options
| -rw-r--r-- | llvm/lib/Transforms/IPO/Attributor.cpp | 54 | ||||
| -rw-r--r-- | llvm/test/Transforms/FunctionAttrs/noalias_returned.ll | 76 | 
2 files changed, 126 insertions, 4 deletions
diff --git a/llvm/lib/Transforms/IPO/Attributor.cpp b/llvm/lib/Transforms/IPO/Attributor.cpp index 064791897a5..94ed7003c96 100644 --- a/llvm/lib/Transforms/IPO/Attributor.cpp +++ b/llvm/lib/Transforms/IPO/Attributor.cpp @@ -1672,8 +1672,9 @@ struct AANoAliasFloating final : AANoAliasImpl {    /// 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(...). @@ -1711,8 +1712,53 @@ struct AANoAliasCallSiteArgument final : AANoAliasImpl {    /// 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() diff --git a/llvm/test/Transforms/FunctionAttrs/noalias_returned.ll b/llvm/test/Transforms/FunctionAttrs/noalias_returned.ll index ccbfb3a5dfd..2f71d1e5791 100644 --- a/llvm/test/Transforms/FunctionAttrs/noalias_returned.ll +++ b/llvm/test/Transforms/FunctionAttrs/noalias_returned.ll @@ -191,3 +191,79 @@ define void @test11(i8* noalias %a) {    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 +}  | 

