[llvm] r366728 - [Attributor] NoAlias on return values.

Stefan Stipanovic via llvm-commits llvm-commits at lists.llvm.org
Mon Jul 22 12:36:27 PDT 2019


Author: sstefan
Date: Mon Jul 22 12:36:27 2019
New Revision: 366728

URL: http://llvm.org/viewvc/llvm-project?rev=366728&view=rev
Log:
[Attributor] NoAlias on return values.

Porting function return value attribute noalias to attributor.
This will be followed with a patch for callsite and function argumets.

Reviewers: jdoerfert

Subscribers: lebedev.ri, hiraditya, llvm-commits

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

Added:
    llvm/trunk/test/Transforms/FunctionAttrs/noalias_returned.ll
Modified:
    llvm/trunk/include/llvm/Transforms/IPO/Attributor.h
    llvm/trunk/lib/Transforms/IPO/Attributor.cpp
    llvm/trunk/test/Transforms/FunctionAttrs/nonnull.ll

Modified: llvm/trunk/include/llvm/Transforms/IPO/Attributor.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/IPO/Attributor.h?rev=366728&r1=366727&r2=366728&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Transforms/IPO/Attributor.h (original)
+++ llvm/trunk/include/llvm/Transforms/IPO/Attributor.h Mon Jul 22 12:36:27 2019
@@ -784,6 +784,27 @@ struct AAWillReturn : public AbstractAtt
   /// The identifier used by the Attributor for this class of attributes.
   static constexpr Attribute::AttrKind ID = Attribute::WillReturn;
 };
+
+/// An abstract interface for all noalias attributes.
+struct AANoAlias : public AbstractAttribute {
+
+  /// See AbstractAttribute::AbstractAttribute(...).
+  AANoAlias(Value &V, InformationCache &InfoCache)
+      : AbstractAttribute(V, InfoCache) {}
+
+  /// Return true if we assume that the underlying value is alias.
+  virtual bool isAssumedNoAlias() const = 0;
+
+  /// Return true if we know that underlying value is noalias.
+  virtual bool isKnownNoAlias() const = 0;
+
+  /// See AbastractState::getAttrKind().
+  Attribute::AttrKind getAttrKind() const override { return ID; }
+
+  /// The identifier used by the Attributor for this class of attributes.
+  static constexpr Attribute::AttrKind ID = Attribute::NoAlias;
+};
+
 } // end namespace llvm
 
 #endif // LLVM_TRANSFORMS_IPO_FUNCTIONATTRS_H

Modified: llvm/trunk/lib/Transforms/IPO/Attributor.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/Attributor.cpp?rev=366728&r1=366727&r2=366728&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/IPO/Attributor.cpp (original)
+++ llvm/trunk/lib/Transforms/IPO/Attributor.cpp Mon Jul 22 12:36:27 2019
@@ -20,6 +20,7 @@
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/Statistic.h"
+#include "llvm/Analysis/CaptureTracking.h"
 #include "llvm/Analysis/GlobalsModRef.h"
 #include "llvm/Analysis/ValueTracking.h"
 #include "llvm/IR/Argument.h"
@@ -59,6 +60,7 @@ STATISTIC(NumFnReturnedNonNull,
 STATISTIC(NumFnArgumentNonNull, "Number of function arguments marked nonnull");
 STATISTIC(NumCSArgumentNonNull, "Number of call site arguments marked nonnull");
 STATISTIC(NumFnWillReturn, "Number of functions marked willreturn");
+STATISTIC(NumFnArgumentNoAlias, "Number of function arguments marked noalias");
 
 // TODO: Determine a good default value.
 //
@@ -134,6 +136,9 @@ static void bookkeeping(AbstractAttribut
   case Attribute::WillReturn:
     NumFnWillReturn++;
     break;
+  case Attribute::NoAlias:
+    NumFnArgumentNoAlias++;
+    return;
   default:
     return;
   }
@@ -1311,6 +1316,101 @@ ChangeStatus AAWillReturnFunction::updat
   return ChangeStatus::UNCHANGED;
 }
 
+/// ------------------------ NoAlias Argument Attribute ------------------------
+
+struct AANoAliasImpl : AANoAlias, BooleanState {
+
+  AANoAliasImpl(Value &V, InformationCache &InfoCache)
+      : AANoAlias(V, InfoCache) {}
+
+  /// See AbstractAttribute::getState()
+  /// {
+  AbstractState &getState() override { return *this; }
+  const AbstractState &getState() const override { return *this; }
+  /// }
+
+  const std::string getAsStr() const override {
+    return getAssumed() ? "noalias" : "may-alias";
+  }
+
+  /// See AANoAlias::isAssumedNoAlias().
+  bool isAssumedNoAlias() const override { return getAssumed(); }
+
+  /// See AANoAlias::isKnowndNoAlias().
+  bool isKnownNoAlias() const override { return getKnown(); }
+};
+
+/// NoAlias attribute for function return value.
+struct AANoAliasReturned : AANoAliasImpl {
+
+  AANoAliasReturned(Function &F, InformationCache &InfoCache)
+      : AANoAliasImpl(F, InfoCache) {}
+
+  /// See AbstractAttribute::getManifestPosition().
+  virtual ManifestPosition getManifestPosition() const override {
+    return MP_RETURNED;
+  }
+
+  /// See AbstractAttriubute::initialize(...).
+  void initialize(Attributor &A) override {
+    Function &F = getAnchorScope();
+
+    // Already noalias.
+    if (F.returnDoesNotAlias()) {
+      indicateOptimisticFixpoint();
+      return;
+    }
+  }
+
+  /// See AbstractAttribute::updateImpl(...).
+  virtual ChangeStatus updateImpl(Attributor &A) override;
+};
+
+ChangeStatus AANoAliasReturned::updateImpl(Attributor &A) {
+  Function &F = getAnchorScope();
+
+  auto *AARetValImpl = A.getAAFor<AAReturnedValuesImpl>(*this, F);
+  if (!AARetValImpl) {
+    indicatePessimisticFixpoint();
+    return ChangeStatus::CHANGED;
+  }
+
+  std::function<bool(Value &)> Pred = [&](Value &RV) -> bool {
+    if (Constant *C = dyn_cast<Constant>(&RV))
+      if (C->isNullValue() || isa<UndefValue>(C))
+        return true;
+
+    /// For now, we can only deduce noalias if we have call sites.
+    /// FIXME: add more support.
+    ImmutableCallSite ICS(&RV);
+    if (!ICS)
+      return false;
+
+    auto *NoAliasAA = A.getAAFor<AANoAlias>(*this, RV);
+
+    if (!ICS.returnDoesNotAlias() && (!NoAliasAA ||
+        !NoAliasAA->isAssumedNoAlias()))
+      return false;
+
+    /// FIXME: We can improve capture check in two ways:
+    /// 1. Use the AANoCapture facilities.
+    /// 2. Use the location of return insts for escape queries.
+    if (PointerMayBeCaptured(&RV, /* ReturnCaptures */ false,
+                             /* StoreCaptures */ true))
+      return false;
+
+
+    return true;
+  };
+
+  if (!AARetValImpl->checkForallReturnedValues(Pred)) {
+    indicatePessimisticFixpoint();
+    return ChangeStatus::CHANGED;
+  }
+
+  return ChangeStatus::UNCHANGED;
+}
+
 /// ----------------------------------------------------------------------------
 ///                               Attributor
 /// ----------------------------------------------------------------------------
@@ -1507,10 +1607,15 @@ void Attributor::identifyDefaultAbstract
     if (!Whitelist || Whitelist->count(AAReturnedValues::ID))
       registerAA(*new AAReturnedValuesImpl(F, InfoCache));
 
-    // Every function with pointer return type might be marked nonnull.
-    if (ReturnType->isPointerTy() &&
-        (!Whitelist || Whitelist->count(AANonNullReturned::ID)))
-      registerAA(*new AANonNullReturned(F, InfoCache));
+    if (ReturnType->isPointerTy()) {
+      // Every function with pointer return type might be marked nonnull.
+      if (!Whitelist || Whitelist->count(AANonNullReturned::ID))
+        registerAA(*new AANonNullReturned(F, InfoCache));
+
+      // Every function with pointer return type might be marked noalias.
+      if (!Whitelist || Whitelist->count(AANoAliasReturned::ID))
+        registerAA(*new AANoAliasReturned(F, InfoCache));
+    }
   }
 
   // Every argument with pointer type might be marked nonnull.

Added: llvm/trunk/test/Transforms/FunctionAttrs/noalias_returned.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionAttrs/noalias_returned.ll?rev=366728&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/FunctionAttrs/noalias_returned.ll (added)
+++ llvm/trunk/test/Transforms/FunctionAttrs/noalias_returned.ll Mon Jul 22 12:36:27 2019
@@ -0,0 +1,140 @@
+; RUN: opt -S -attributor -attributor-disable=false < %s | FileCheck %s
+
+; TEST 1 - negative.
+
+; void *G;
+; void *foo(){
+;   void *V = malloc(4);
+;   G = V;
+;   return V;
+; }
+
+ at G = external global i8*
+
+; CHECK: define i8* @foo()
+define i8* @foo() {
+  %1 = tail call noalias i8* @malloc(i64 4)
+  store i8* %1, i8** @G, align 8
+  ret i8* %1
+}
+
+declare noalias i8* @malloc(i64)
+
+; TEST 2
+; call noalias function in return instruction.
+
+; CHECK: define noalias i8* @return_noalias()
+define i8* @return_noalias(){
+  %1 = tail call noalias i8* @malloc(i64 4)
+  ret i8* %1
+}
+
+declare i8* @alias()
+
+; TEST 3
+; CHECK: define i8* @call_alias()
+; CHECK-NOT: noalias
+define i8* @call_alias(){
+  %1 = tail call i8* @alias()
+  ret i8* %1
+}
+
+; TEST 4
+; void *baz();
+; void *foo(int a);
+;
+; void *bar()  {
+;   foo(0);
+;    return baz();
+; }
+;
+; void *foo(int a)  {
+;   if (a)
+;   bar();
+;   return malloc(4);
+; }
+
+; CHECK: define i8* @bar()
+define i8* @bar() nounwind uwtable {
+  %1 = tail call i8* (...) @baz()
+  ret i8* %1
+}
+
+; CHECK: define noalias i8* @foo1(i32)
+define i8* @foo1(i32) nounwind uwtable {
+  %2 = icmp eq i32 %0, 0
+  br i1 %2, label %5, label %3
+
+3:                                                ; preds = %1
+  %4 = tail call i8* (...) @baz()
+  br label %5
+
+5:                                                ; preds = %1, %3
+  %6 = tail call noalias i8* @malloc(i64 4)
+  ret i8* %6
+}
+
+declare i8* @baz(...) nounwind uwtable
+
+; TEST 5
+
+; Returning global pointer. Should not be noalias.
+; CHECK: define nonnull i8** @getter()
+define i8** @getter() {
+  ret i8** @G
+}
+
+; Returning global pointer. Should not be noalias.
+; CHECK: define nonnull i8** @calle1()
+define i8** @calle1(){
+  %1 = call i8** @getter()
+  ret i8** %1
+}
+
+; TEST 6
+declare noalias i8* @strdup(i8* nocapture) nounwind
+
+; CHECK: define noalias i8* @test6()
+define i8* @test6() nounwind uwtable ssp {
+  %x = alloca [2 x i8], align 1
+  %arrayidx = getelementptr inbounds [2 x i8], [2 x i8]* %x, i64 0, i64 0
+  store i8 97, i8* %arrayidx, align 1
+  %arrayidx1 = getelementptr inbounds [2 x i8], [2 x i8]* %x, i64 0, i64 1
+  store i8 0, i8* %arrayidx1, align 1
+  %call = call noalias i8* @strdup(i8* %arrayidx) nounwind
+  ret i8* %call
+}
+
+; TEST 7
+
+; CHECK: define noalias i8* @test7()
+define i8* @test7() nounwind {
+entry:
+  %A = call noalias i8* @malloc(i64 4) nounwind
+  %tobool = icmp eq i8* %A, null
+  br i1 %tobool, label %return, label %if.end
+
+if.end:
+  store i8 7, i8* %A
+  br label %return
+
+return:
+  %retval.0 = phi i8* [ %A, %if.end ], [ null, %entry ]
+  ret i8* %retval.0
+}
+
+; TEST 8
+
+; CHECK: define noalias i8* @test8(i32*)
+define i8* @test8(i32*) nounwind uwtable {
+  %2 = tail call noalias i8* @malloc(i64 4)
+  %3 = icmp ne i32* %0, null
+  br i1 %3, label %4, label %5
+
+4:                                                ; preds = %1
+  store i8 10, i8* %2
+  br label %5
+
+5:                                                ; preds = %1, %4
+  ret i8* %2
+}

Modified: llvm/trunk/test/Transforms/FunctionAttrs/nonnull.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionAttrs/nonnull.ll?rev=366728&r1=366727&r2=366728&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/FunctionAttrs/nonnull.ll (original)
+++ llvm/trunk/test/Transforms/FunctionAttrs/nonnull.ll Mon Jul 22 12:36:27 2019
@@ -22,7 +22,8 @@ define i8* @test2(i8* nonnull %p) {
 ; Given an SCC where one of the functions can not be marked nonnull,
 ; can we still mark the other one which is trivially nonnull
 define i8* @scc_binder() {
-; BOTH: define i8* @scc_binder
+; FNATTR: define i8* @scc_binder
+; ATTRIBUTOR: define noalias i8* @scc_binder
   call i8* @test3()
   ret i8* null
 }
@@ -39,14 +40,14 @@ define i8* @test3() {
 ; just never return period.)
 define i8* @test4_helper() {
 ; FNATTR: define noalias nonnull i8* @test4_helper
-; ATTRIBUTOR: define nonnull i8* @test4_helper
+; ATTRIBUTOR: define noalias nonnull i8* @test4_helper
   %ret = call i8* @test4()
   ret i8* %ret
 }
 
 define i8* @test4() {
 ; FNATTR: define noalias nonnull i8* @test4
-; ATTRIBUTOR: define nonnull i8* @test4
+; ATTRIBUTOR: define noalias nonnull i8* @test4
   %ret = call i8* @test4_helper()
   ret i8* %ret
 }
@@ -55,14 +56,14 @@ define i8* @test4() {
 ; make sure we haven't marked them as nonnull.
 define i8* @test5_helper() {
 ; FNATTR: define noalias i8* @test5_helper
-; ATTRIBUTOR: define i8* @test5_helper
+; ATTRIBUTOR: define noalias i8* @test5_helper
   %ret = call i8* @test5()
   ret i8* null
 }
 
 define i8* @test5() {
 ; FNATTR: define noalias i8* @test5
-; ATTRIBUTOR: define i8* @test5
+; ATTRIBUTOR: define noalias i8* @test5
   %ret = call i8* @test5_helper()
   ret i8* %ret
 }




More information about the llvm-commits mailing list