[llvm] bf99053 - [Attributor] Improve noalias preservation using reachability

Pankaj Gode via llvm-commits llvm-commits at lists.llvm.org
Fri Mar 13 08:39:16 PDT 2020


Author: Pankaj Gode
Date: 2020-03-13T21:09:08+05:30
New Revision: bf990530ae0f8d7bae77a9c94f4e57fc7fa42b2e

URL: https://github.com/llvm/llvm-project/commit/bf990530ae0f8d7bae77a9c94f4e57fc7fa42b2e
DIFF: https://github.com/llvm/llvm-project/commit/bf990530ae0f8d7bae77a9c94f4e57fc7fa42b2e.diff

LOG: [Attributor] Improve noalias preservation using reachability

Resolution for below fixme:
(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.

Propagates caller argument's noalias attribute to callee.

Reviewed by: jdoerfert, uenoku

Reviewers: jdoerfert, sstefan1, uenoku

Subscribers: uenoku, sstefan1, hiraditya, llvm-commits

Differential Revision: https://reviews.llvm.org/D71617

Added: 
    

Modified: 
    llvm/lib/Transforms/IPO/Attributor.cpp
    llvm/test/Transforms/Attributor/noalias.ll
    llvm/test/Transforms/Attributor/nonnull.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/IPO/Attributor.cpp b/llvm/lib/Transforms/IPO/Attributor.cpp
index a7ac4cc21d16..b8f6b217f03a 100644
--- a/llvm/lib/Transforms/IPO/Attributor.cpp
+++ b/llvm/lib/Transforms/IPO/Attributor.cpp
@@ -2818,13 +2818,55 @@ struct AANoAliasCallSiteArgument final : AANoAliasImpl {
     auto &NoCaptureAA =
         A.getAAFor<AANoCapture>(*this, VIRP, /* TrackDependence */ false);
     // 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.
-    if (!NoCaptureAA.isAssumedNoCaptureMaybeReturned()) {
-      LLVM_DEBUG(
-          dbgs() << "[AANoAliasCSArg] " << getAssociatedValue()
-                 << " cannot be noalias as it is potentially captured\n");
+    //      Look at CFG and check only uses possibly executed before this
+    //      callsite.
+    auto UsePred = [&](const Use &U, bool &Follow) -> bool {
+      Instruction *UserI = cast<Instruction>(U.getUser());
+
+      // If user if curr instr and only use.
+      if ((UserI == getCtxI()) && (UserI->getNumUses() == 1))
+        return true;
+
+      const Function *ScopeFn = VIRP.getAnchorScope();
+      if (ScopeFn) {
+        const auto &ReachabilityAA =
+            A.getAAFor<AAReachability>(*this, IRPosition::function(*ScopeFn));
+
+        if (!ReachabilityAA.isAssumedReachable(UserI, getCtxI()))
+          return true;
+
+        if (auto *CB = dyn_cast<CallBase>(UserI)) {
+          if (CB->isArgOperand(&U)) {
+
+            unsigned ArgNo = CB->getArgOperandNo(&U);
+
+            const auto &NoCaptureAA = A.getAAFor<AANoCapture>(
+                *this, IRPosition::callsite_argument(*CB, ArgNo));
+
+            if (NoCaptureAA.isAssumedNoCapture())
+              return true;
+          }
+        }
+      }
+
+      // For cases which can potentially have more users
+      if (isa<GetElementPtrInst>(U) || isa<BitCastInst>(U) || isa<PHINode>(U) ||
+          isa<SelectInst>(U)) {
+        Follow = true;
+        return true;
+      }
+
+      LLVM_DEBUG(dbgs() << "[AANoAliasCSArg] Unknown user: " << *U << "\n");
       return false;
+    };
+
+    if (!NoCaptureAA.isAssumedNoCaptureMaybeReturned()) {
+      if (!A.checkForAllUses(UsePred, *this, getAssociatedValue())) {
+        LLVM_DEBUG(
+            dbgs() << "[AANoAliasCSArg] " << getAssociatedValue()
+                   << " cannot be noalias as it is potentially captured\n");
+        return false;
+      }
     }
     A.recordDependence(NoCaptureAA, *this, DepClassTy::OPTIONAL);
 

diff  --git a/llvm/test/Transforms/Attributor/noalias.ll b/llvm/test/Transforms/Attributor/noalias.ll
index f0afc3572141..358528546f9d 100644
--- a/llvm/test/Transforms/Attributor/noalias.ll
+++ b/llvm/test/Transforms/Attributor/noalias.ll
@@ -348,3 +348,48 @@ define internal i32 @ret(i32* %arg) {
   ret i32 %l
 }
 
+; Test to propagate noalias where value is assumed to be no-capture in all the
+; uses possibly executed before this callsite.
+; IR referred from musl/src/strtod.c file
+
+%struct._IO_FILE = type { i32, i8*, i8*, i32 (%struct._IO_FILE*)*, i8*, i8*, i8*, i8*, i32 (%struct._IO_FILE*, i8*, i32)*, i32 (%struct._IO_FILE*, i8*, i32)*, i64 (%struct._IO_FILE*, i64, i32)*, i8*, i32, %struct._IO_FILE*, %struct._IO_FILE*, i32, i32, i32, i16, i8, i8, i32, i32, i8*, i64, i8*, i8*, i8*, [4 x i8], i64, i64, %struct._IO_FILE*, %struct._IO_FILE*, %struct.__locale_struct*, [4 x i8] }
+%struct.__locale_struct = type { [6 x %struct.__locale_map*] }
+%struct.__locale_map = type opaque
+
+; Function Attrs: nounwind optsize
+; CHECK: define internal fastcc double @strtox(i8* noalias %s) unnamed_addr
+define internal fastcc double @strtox(i8* %s, i8** %p, i32 %prec) unnamed_addr {
+entry:
+  %f = alloca %struct._IO_FILE, align 8
+  %0 = bitcast %struct._IO_FILE* %f to i8*
+  call void @llvm.lifetime.start.p0i8(i64 144, i8* nonnull %0)
+  %call = call i32 bitcast (i32 (...)* @sh_fromstring to i32 (%struct._IO_FILE*, i8*)*)(%struct._IO_FILE* nonnull %f, i8* %s)
+  call void @__shlim(%struct._IO_FILE* nonnull %f, i64 0)
+  %call1 = call double @__floatscan(%struct._IO_FILE* nonnull %f, i32 %prec, i32 1)
+  call void @llvm.lifetime.end.p0i8(i64 144, i8* nonnull %0)
+
+  ret double %call1
+}
+
+; Function Attrs: nounwind optsize
+define dso_local double @strtod(i8* noalias %s, i8** noalias %p) {
+entry:
+; CHECK: %call = tail call fastcc double @strtox(i8* noalias %s)
+  %call = tail call fastcc double @strtox(i8* %s, i8** %p, i32 1)
+  ret double %call
+}
+
+; Function Attrs: argmemonly nounwind willreturn
+declare void @llvm.lifetime.start.p0i8(i64 immarg, i8* nocapture)
+
+; Function Attrs: optsize
+declare dso_local i32 @sh_fromstring(...) local_unnamed_addr
+
+; Function Attrs: optsize
+declare dso_local void @__shlim(%struct._IO_FILE*, i64) local_unnamed_addr
+
+; Function Attrs: optsize
+declare dso_local double @__floatscan(%struct._IO_FILE*, i32, i32) local_unnamed_addr
+
+; Function Attrs: argmemonly nounwind willreturn
+declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture)

diff  --git a/llvm/test/Transforms/Attributor/nonnull.ll b/llvm/test/Transforms/Attributor/nonnull.ll
index d4b0f9af393a..2aae7aa27706 100644
--- a/llvm/test/Transforms/Attributor/nonnull.ll
+++ b/llvm/test/Transforms/Attributor/nonnull.ll
@@ -1,5 +1,5 @@
 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes
-; RUN: opt -attributor --attributor-disable=false -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=4 -S < %s | FileCheck %s --check-prefixes=ATTRIBUTOR,ATTRIBUTOR_OPM
+; RUN: opt -attributor --attributor-disable=false -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=5 -S < %s | FileCheck %s --check-prefixes=ATTRIBUTOR,ATTRIBUTOR_OPM
 ; RUN: opt -passes=attributor --attributor-disable=false -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=5 -S < %s | FileCheck %s --check-prefixes=ATTRIBUTOR,ATTRIBUTOR_NPM
 ; Copied from Transforms/FunctoinAttrs/nonnull.ll
 


        


More information about the llvm-commits mailing list