[llvm] r370817 - [Attributor] Deduce "no-capture" argument attribute
Johannes Doerfert via llvm-commits
llvm-commits at lists.llvm.org
Tue Sep 3 13:37:24 PDT 2019
Author: jdoerfert
Date: Tue Sep 3 13:37:24 2019
New Revision: 370817
URL: http://llvm.org/viewvc/llvm-project?rev=370817&view=rev
Log:
[Attributor] Deduce "no-capture" argument attribute
Add the no-capture argument attribute deduction to the Attributor
fixpoint framework.
The new string attributed "no-capture-maybe-returned" is introduced to
allow deduction of no-capture through functions that "capture" an
argument but only by "returning" it. It is only used by the Attributor
for testing.
Differential Revision: https://reviews.llvm.org/D59922
Modified:
llvm/trunk/include/llvm/Transforms/IPO/Attributor.h
llvm/trunk/lib/Transforms/IPO/Attributor.cpp
llvm/trunk/test/Transforms/FunctionAttrs/align.ll
llvm/trunk/test/Transforms/FunctionAttrs/arg_nocapture.ll
llvm/trunk/test/Transforms/FunctionAttrs/arg_returned.ll
llvm/trunk/test/Transforms/FunctionAttrs/dereferenceable.ll
llvm/trunk/test/Transforms/FunctionAttrs/internal-noalias.ll
llvm/trunk/test/Transforms/FunctionAttrs/liveness.ll
llvm/trunk/test/Transforms/FunctionAttrs/noalias_returned.ll
llvm/trunk/test/Transforms/FunctionAttrs/nocapture.ll
llvm/trunk/test/Transforms/FunctionAttrs/nonnull.ll
llvm/trunk/test/Transforms/FunctionAttrs/nosync.ll
llvm/trunk/test/Transforms/FunctionAttrs/read_write_returned_arguments_scc.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=370817&r1=370816&r2=370817&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Transforms/IPO/Attributor.h (original)
+++ llvm/trunk/include/llvm/Transforms/IPO/Attributor.h Tue Sep 3 13:37:24 2019
@@ -270,6 +270,25 @@ struct IRPosition {
}
///}
+ /// Return the associated argument, if any.
+ ///
+ ///{
+ Argument *getAssociatedArgument() {
+ if (auto *Arg = dyn_cast<Argument>(&getAnchorValue()))
+ return Arg;
+ int ArgNo = getArgNo();
+ if (ArgNo < 0)
+ return nullptr;
+ Function *AssociatedFn = getAssociatedFunction();
+ if (!AssociatedFn || AssociatedFn->arg_size() <= unsigned(ArgNo))
+ return nullptr;
+ return AssociatedFn->arg_begin() + ArgNo;
+ }
+ const Argument *getAssociatedArgument() const {
+ return const_cast<IRPosition *>(this)->getAssociatedArgument();
+ }
+ ///}
+
/// Return the Function surrounding the anchor value.
///
///{
@@ -1547,6 +1566,56 @@ struct AAAlign
/// Unique ID (due to the unique address)
static const char ID;
+};
+
+/// An abstract interface for all nocapture attributes.
+struct AANoCapture
+ : public IRAttribute<Attribute::NoCapture,
+ StateWrapper<IntegerState, AbstractAttribute>> {
+ AANoCapture(const IRPosition &IRP) : IRAttribute(IRP) {}
+
+ /// State encoding bits. A set bit in the state means the property holds.
+ /// NO_CAPTURE is the best possible state, 0 the worst possible state.
+ enum {
+ NOT_CAPTURED_IN_MEM = 1 << 0,
+ NOT_CAPTURED_IN_INT = 1 << 1,
+ NOT_CAPTURED_IN_RET = 1 << 2,
+
+ /// If we do not capture the value in memory or through integers we can only
+ /// communicate it back as a derived pointer.
+ NO_CAPTURE_MAYBE_RETURNED = NOT_CAPTURED_IN_MEM | NOT_CAPTURED_IN_INT,
+
+ /// If we do not capture the value in memory, through integers, or as a
+ /// derived pointer we know it is not captured.
+ NO_CAPTURE =
+ NOT_CAPTURED_IN_MEM | NOT_CAPTURED_IN_INT | NOT_CAPTURED_IN_RET,
+ };
+
+ /// Return true if we know that the underlying value is not captured in its
+ /// respective scope.
+ bool isKnownNoCapture() const { return isKnown(NO_CAPTURE); }
+
+ /// Return true if we assume that the underlying value is not captured in its
+ /// respective scope.
+ bool isAssumedNoCapture() const { return isAssumed(NO_CAPTURE); }
+
+ /// Return true if we know that the underlying value is not captured in its
+ /// respective scope but we allow it to escape through a "return".
+ bool isKnownNoCaptureMaybeReturned() const {
+ return isKnown(NO_CAPTURE_MAYBE_RETURNED);
+ }
+
+ /// Return true if we assume that the underlying value is not captured in its
+ /// respective scope but we allow it to escape through a "return".
+ bool isAssumedNoCaptureMaybeReturned() const {
+ return isAssumed(NO_CAPTURE_MAYBE_RETURNED);
+ }
+
+ /// Create an abstract attribute view for the position \p IRP.
+ static AANoCapture &createForPosition(const IRPosition &IRP, Attributor &A);
+
+ /// Unique ID (due to the unique address)
+ static const char ID;
};
} // end namespace llvm
Modified: llvm/trunk/lib/Transforms/IPO/Attributor.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/Attributor.cpp?rev=370817&r1=370816&r2=370817&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/IPO/Attributor.cpp (original)
+++ llvm/trunk/lib/Transforms/IPO/Attributor.cpp Tue Sep 3 13:37:24 2019
@@ -117,6 +117,11 @@ static cl::opt<bool> DisableAttributor(
cl::desc("Disable the attributor inter-procedural deduction pass."),
cl::init(true));
+static cl::opt<bool> ManifestInternal(
+ "attributor-manifest-internal", cl::Hidden,
+ cl::desc("Manifest Attributor internal string attributes."),
+ cl::init(false));
+
static cl::opt<bool> VerifyAttributor(
"attributor-verify", cl::Hidden,
cl::desc("Verify the Attributor deduction and "
@@ -1760,19 +1765,13 @@ struct AANoAliasReturned final : AANoAli
if (!ICS)
return false;
- const auto &NoAliasAA =
- A.getAAFor<AANoAlias>(*this, IRPosition::callsite_returned(ICS));
+ const IRPosition &RVPos = IRPosition::value(RV);
+ const auto &NoAliasAA = A.getAAFor<AANoAlias>(*this, RVPos);
if (!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;
+ const auto &NoCaptureAA = A.getAAFor<AANoCapture>(*this, RVPos);
+ return NoCaptureAA.isAssumedNoCaptureMaybeReturned();
};
if (!A.checkForAllReturnedValues(CheckReturnValue, *this))
@@ -2585,6 +2584,347 @@ struct AANoReturnCallSite final : AANoRe
void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(noreturn); }
};
+/// ----------------------- Variable Capturing ---------------------------------
+
+/// A class to hold the state of for no-capture attributes.
+struct AANoCaptureImpl : public AANoCapture {
+ AANoCaptureImpl(const IRPosition &IRP) : AANoCapture(IRP) {}
+
+ /// See AbstractAttribute::initialize(...).
+ void initialize(Attributor &A) override {
+ if (hasAttr(Attribute::NoCapture)) {
+ indicateOptimisticFixpoint();
+ return;
+ }
+
+ const IRPosition &IRP = getIRPosition();
+ const Function *F =
+ getArgNo() >= 0 ? IRP.getAssociatedFunction() : IRP.getAnchorScope();
+
+ // Check what state the associated function can actually capture.
+ if (F)
+ determineFunctionCaptureCapabilities(*F, *this);
+
+ if (!F || !F->hasExactDefinition())
+ indicatePessimisticFixpoint();
+ }
+
+ /// See AbstractAttribute::updateImpl(...).
+ ChangeStatus updateImpl(Attributor &A) override;
+
+ /// see AbstractAttribute::isAssumedNoCaptureMaybeReturned(...).
+ virtual void
+ getDeducedAttributes(LLVMContext &Ctx,
+ SmallVectorImpl<Attribute> &Attrs) const override {
+ if (!isAssumedNoCaptureMaybeReturned())
+ return;
+
+ if (isAssumedNoCapture())
+ Attrs.emplace_back(Attribute::get(Ctx, Attribute::NoCapture));
+ else if (ManifestInternal)
+ Attrs.emplace_back(Attribute::get(Ctx, "no-capture-maybe-returned"));
+ }
+
+ /// Set the NOT_CAPTURED_IN_MEM and NOT_CAPTURED_IN_RET bits in \p Known
+ /// depending on the ability of the function associated with \p IRP to capture
+ /// state in memory and through "returning/throwing", respectively.
+ static void determineFunctionCaptureCapabilities(const Function &F,
+ IntegerState &State) {
+ // TODO: Once we have memory behavior attributes we should use them here.
+
+ // If we know we cannot communicate or write to memory, we do not care about
+ // ptr2int anymore.
+ if (F.onlyReadsMemory() && F.doesNotThrow() &&
+ F.getReturnType()->isVoidTy()) {
+ State.addKnownBits(NO_CAPTURE);
+ return;
+ }
+
+ // A function cannot capture state in memory if it only reads memory, it can
+ // however return/throw state and the state might be influenced by the
+ // pointer value, e.g., loading from a returned pointer might reveal a bit.
+ if (F.onlyReadsMemory())
+ State.addKnownBits(NOT_CAPTURED_IN_MEM);
+
+ // A function cannot communicate state back if it does not through
+ // exceptions and doesn not return values.
+ if (F.doesNotThrow() && F.getReturnType()->isVoidTy())
+ State.addKnownBits(NOT_CAPTURED_IN_RET);
+ }
+
+ /// See AbstractState::getAsStr().
+ const std::string getAsStr() const override {
+ if (isKnownNoCapture())
+ return "known not-captured";
+ if (isAssumedNoCapture())
+ return "assumed not-captured";
+ if (isKnownNoCaptureMaybeReturned())
+ return "known not-captured-maybe-returned";
+ if (isAssumedNoCaptureMaybeReturned())
+ return "assumed not-captured-maybe-returned";
+ return "assumed-captured";
+ }
+};
+
+/// Attributor-aware capture tracker.
+struct AACaptureUseTracker final : public CaptureTracker {
+
+ /// Create a capture tracker that can lookup in-flight abstract attributes
+ /// through the Attributor \p A.
+ ///
+ /// If a use leads to a potential capture, \p CapturedInMemory is set and the
+ /// search is stopped. If a use leads to a return instruction,
+ /// \p CommunicatedBack is set to true and \p CapturedInMemory is not changed.
+ /// If a use leads to a ptr2int which may capture the value,
+ /// \p CapturedInInteger is set. If a use is found that is currently assumed
+ /// "no-capture-maybe-returned", the user is added to the \p PotentialCopies
+ /// set. All values in \p PotentialCopies are later tracked as well. For every
+ /// explored use we decrement \p RemainingUsesToExplore. Once it reaches 0,
+ /// the search is stopped with \p CapturedInMemory and \p CapturedInInteger
+ /// conservatively set to true.
+ AACaptureUseTracker(Attributor &A, AANoCapture &NoCaptureAA,
+ const AAIsDead &IsDeadAA, IntegerState &State,
+ SmallVectorImpl<const Value *> &PotentialCopies,
+ unsigned &RemainingUsesToExplore)
+ : A(A), NoCaptureAA(NoCaptureAA), IsDeadAA(IsDeadAA), State(State),
+ PotentialCopies(PotentialCopies),
+ RemainingUsesToExplore(RemainingUsesToExplore) {}
+
+ /// Determine if \p V maybe captured. *Also updates the state!*
+ bool valueMayBeCaptured(const Value *V) {
+ if (V->getType()->isPointerTy()) {
+ PointerMayBeCaptured(V, this);
+ } else {
+ State.indicatePessimisticFixpoint();
+ }
+ return State.isAssumed(AANoCapture::NO_CAPTURE_MAYBE_RETURNED);
+ }
+
+ /// See CaptureTracker::tooManyUses().
+ void tooManyUses() override {
+ State.removeAssumedBits(AANoCapture::NO_CAPTURE);
+ }
+
+ bool isDereferenceableOrNull(Value *O, const DataLayout &DL) override {
+ if (CaptureTracker::isDereferenceableOrNull(O, DL))
+ return true;
+ const auto &DerefAA =
+ A.getAAFor<AADereferenceable>(NoCaptureAA, IRPosition::value(*O));
+ return DerefAA.getAssumedDereferenceableBytes();
+ }
+
+ /// See CaptureTracker::captured(...).
+ bool captured(const Use *U) override {
+ Instruction *UInst = cast<Instruction>(U->getUser());
+ LLVM_DEBUG(dbgs() << "Check use: " << *U->get() << " in " << *UInst
+ << "\n");
+
+ // Because we may reuse the tracker multiple times we keep track of the
+ // number of explored uses ourselves as well.
+ if (RemainingUsesToExplore-- == 0) {
+ LLVM_DEBUG(dbgs() << " - too many uses to explore!\n");
+ return isCapturedIn(/* Memory */ true, /* Integer */ true,
+ /* Return */ true);
+ }
+
+ // Deal with ptr2int by following uses.
+ if (isa<PtrToIntInst>(UInst)) {
+ LLVM_DEBUG(dbgs() << " - ptr2int assume the worst!\n");
+ return valueMayBeCaptured(UInst);
+ }
+
+ // Explicitly catch return instructions.
+ if (isa<ReturnInst>(UInst))
+ return isCapturedIn(/* Memory */ false, /* Integer */ false,
+ /* Return */ true);
+
+ // For now we only use special logic for call sites. However, the tracker
+ // itself knows about a lot of other non-capturing cases already.
+ CallSite CS(UInst);
+ if (!CS || !CS.isArgOperand(U))
+ return isCapturedIn(/* Memory */ true, /* Integer */ true,
+ /* Return */ true);
+
+ unsigned ArgNo = CS.getArgumentNo(U);
+ const IRPosition &CSArgPos = IRPosition::callsite_argument(CS, ArgNo);
+ // If we have a abstract no-capture attribute for the argument we can use
+ // it to justify a non-capture attribute here. This allows recursion!
+ auto &ArgNoCaptureAA = A.getAAFor<AANoCapture>(NoCaptureAA, CSArgPos);
+ if (ArgNoCaptureAA.isAssumedNoCapture())
+ return isCapturedIn(/* Memory */ false, /* Integer */ false,
+ /* Return */ false);
+ if (ArgNoCaptureAA.isAssumedNoCaptureMaybeReturned()) {
+ addPotentialCopy(CS);
+ return isCapturedIn(/* Memory */ false, /* Integer */ false,
+ /* Return */ false);
+ }
+
+ // Lastly, we could not find a reason no-capture can be assumed so we don't.
+ return isCapturedIn(/* Memory */ true, /* Integer */ true,
+ /* Return */ true);
+ }
+
+ /// Register \p CS as potential copy of the value we are checking.
+ void addPotentialCopy(CallSite CS) {
+ PotentialCopies.push_back(CS.getInstruction());
+ }
+
+ /// See CaptureTracker::shouldExplore(...).
+ bool shouldExplore(const Use *U) override {
+ // Check liveness.
+ return !IsDeadAA.isAssumedDead(cast<Instruction>(U->getUser()));
+ }
+
+ /// Update the state according to \p CapturedInMem, \p CapturedInInt, and
+ /// \p CapturedInRet, then return the appropriate value for use in the
+ /// CaptureTracker::captured() interface.
+ bool isCapturedIn(bool CapturedInMem, bool CapturedInInt,
+ bool CapturedInRet) {
+ LLVM_DEBUG(dbgs() << " - captures [Mem " << CapturedInMem << "|Int "
+ << CapturedInInt << "|Ret " << CapturedInRet << "]\n");
+ if (CapturedInMem)
+ State.removeAssumedBits(AANoCapture::NOT_CAPTURED_IN_MEM);
+ if (CapturedInInt)
+ State.removeAssumedBits(AANoCapture::NOT_CAPTURED_IN_INT);
+ if (CapturedInRet)
+ State.removeAssumedBits(AANoCapture::NOT_CAPTURED_IN_RET);
+ return !State.isAssumed(AANoCapture::NO_CAPTURE_MAYBE_RETURNED);
+ }
+
+private:
+ /// The attributor providing in-flight abstract attributes.
+ Attributor &A;
+
+ /// The abstract attribute currently updated.
+ AANoCapture &NoCaptureAA;
+
+ /// The abstract liveness state.
+ const AAIsDead &IsDeadAA;
+
+ /// The state currently updated.
+ IntegerState &State;
+
+ /// Set of potential copies of the tracked value.
+ SmallVectorImpl<const Value *> &PotentialCopies;
+
+ /// Global counter to limit the number of explored uses.
+ unsigned &RemainingUsesToExplore;
+};
+
+ChangeStatus AANoCaptureImpl::updateImpl(Attributor &A) {
+ const IRPosition &IRP = getIRPosition();
+ const Value *V =
+ getArgNo() >= 0 ? IRP.getAssociatedArgument() : &IRP.getAssociatedValue();
+ if (!V)
+ return indicatePessimisticFixpoint();
+
+ const Function *F =
+ getArgNo() >= 0 ? IRP.getAssociatedFunction() : IRP.getAnchorScope();
+ assert(F && "Expected a function!");
+ const auto &IsDeadAA = A.getAAFor<AAIsDead>(*this, IRPosition::function(*F));
+
+ AANoCapture::StateType T;
+ // TODO: Once we have memory behavior attributes we should use them here
+ // similar to the reasoning in
+ // AANoCaptureImpl::determineFunctionCaptureCapabilities(...).
+
+ // TODO: Use the AAReturnedValues to learn if the argument can return or
+ // not.
+
+ // Use the CaptureTracker interface and logic with the specialized tracker,
+ // defined in AACaptureUseTracker, that can look at in-flight abstract
+ // attributes and directly updates the assumed state.
+ SmallVector<const Value *, 4> PotentialCopies;
+ unsigned RemainingUsesToExplore = DefaultMaxUsesToExplore;
+ AACaptureUseTracker Tracker(A, *this, IsDeadAA, T, PotentialCopies,
+ RemainingUsesToExplore);
+
+ // Check all potential copies of the associated value until we can assume
+ // none will be captured or we have to assume at least one might be.
+ unsigned Idx = 0;
+ PotentialCopies.push_back(V);
+ while (T.isAssumed(NO_CAPTURE_MAYBE_RETURNED) && Idx < PotentialCopies.size())
+ Tracker.valueMayBeCaptured(PotentialCopies[Idx++]);
+
+ AAAlign::StateType &S = getState();
+ auto Assumed = S.getAssumed();
+ S.intersectAssumedBits(T.getAssumed());
+ return Assumed == S.getAssumed() ? ChangeStatus::UNCHANGED
+ : ChangeStatus::CHANGED;
+}
+
+/// NoCapture attribute for function arguments.
+struct AANoCaptureArgument final : AANoCaptureImpl {
+ AANoCaptureArgument(const IRPosition &IRP) : AANoCaptureImpl(IRP) {}
+
+ /// See AbstractAttribute::trackStatistics()
+ void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(nocapture) }
+};
+
+/// NoCapture attribute for call site arguments.
+struct AANoCaptureCallSiteArgument final : AANoCaptureImpl {
+ AANoCaptureCallSiteArgument(const IRPosition &IRP) : AANoCaptureImpl(IRP) {}
+
+ /// See AbstractAttribute::updateImpl(...).
+ ChangeStatus updateImpl(Attributor &A) override {
+ // TODO: Once we have call site specific value information we can provide
+ // call site specific liveness information and then it makes
+ // sense to specialize attributes for call sites arguments instead of
+ // redirecting requests to the callee argument.
+ Argument *Arg = getAssociatedArgument();
+ if (!Arg)
+ return indicatePessimisticFixpoint();
+ const IRPosition &ArgPos = IRPosition::argument(*Arg);
+ auto &ArgAA = A.getAAFor<AANoCapture>(*this, ArgPos);
+ return clampStateAndIndicateChange(
+ getState(),
+ static_cast<const AANoCapture::StateType &>(ArgAA.getState()));
+ }
+
+ /// See AbstractAttribute::trackStatistics()
+ void trackStatistics() const override{STATS_DECLTRACK_CSARG_ATTR(nocapture)};
+};
+
+/// NoCapture attribute for floating values.
+struct AANoCaptureFloating final : AANoCaptureImpl {
+ AANoCaptureFloating(const IRPosition &IRP) : AANoCaptureImpl(IRP) {}
+
+ /// See AbstractAttribute::trackStatistics()
+ void trackStatistics() const override {
+ STATS_DECLTRACK_FLOATING_ATTR(nocapture)
+ }
+};
+
+/// NoCapture attribute for function return value.
+struct AANoCaptureReturned final : AANoCaptureImpl {
+ AANoCaptureReturned(const IRPosition &IRP) : AANoCaptureImpl(IRP) {
+ llvm_unreachable("NoCapture is not applicable to function returns!");
+ }
+
+ /// See AbstractAttribute::initialize(...).
+ void initialize(Attributor &A) override {
+ llvm_unreachable("NoCapture is not applicable to function returns!");
+ }
+
+ /// See AbstractAttribute::updateImpl(...).
+ ChangeStatus updateImpl(Attributor &A) override {
+ llvm_unreachable("NoCapture is not applicable to function returns!");
+ }
+
+ /// See AbstractAttribute::trackStatistics()
+ void trackStatistics() const override {}
+};
+
+/// NoCapture attribute deduction for a call site return value.
+struct AANoCaptureCallSiteReturned final : AANoCaptureImpl {
+ AANoCaptureCallSiteReturned(const IRPosition &IRP) : AANoCaptureImpl(IRP) {}
+
+ /// See AbstractAttribute::trackStatistics()
+ void trackStatistics() const override {
+ STATS_DECLTRACK_CSRET_ATTR(nocapture)
+ }
+};
+
/// ----------------------------------------------------------------------------
/// Attributor
/// ----------------------------------------------------------------------------
@@ -3075,6 +3415,9 @@ void Attributor::identifyDefaultAbstract
// Every argument with pointer type might be marked align.
checkAndRegisterAA<AAAlignArgument>(ArgPos, *this, Whitelist);
+
+ // Every argument with pointer type might be marked nocapture.
+ checkAndRegisterAA<AANoCaptureArgument>(ArgPos, *this, Whitelist);
}
}
@@ -3295,6 +3638,7 @@ const char AANoReturn::ID = 0;
const char AAIsDead::ID = 0;
const char AADereferenceable::ID = 0;
const char AAAlign::ID = 0;
+const char AANoCapture::ID = 0;
// Macro magic to create the static generator function for attributes that
// follow the naming scheme.
@@ -3355,6 +3699,7 @@ CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSI
CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoAlias)
CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AADereferenceable)
CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAAlign)
+CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoCapture)
#undef CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION
#undef CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION
Modified: llvm/trunk/test/Transforms/FunctionAttrs/align.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionAttrs/align.ll?rev=370817&r1=370816&r2=370817&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/FunctionAttrs/align.ll (original)
+++ llvm/trunk/test/Transforms/FunctionAttrs/align.ll Tue Sep 3 13:37:24 2019
@@ -1,4 +1,4 @@
-; RUN: opt -attributor -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=6 -S < %s | FileCheck %s --check-prefix=ATTRIBUTOR
+; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=6 -S < %s | FileCheck %s --check-prefix=ATTRIBUTOR
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
@@ -7,26 +7,26 @@ target datalayout = "e-m:e-i64:64-f80:12
; TEST 1
-; ATTRIBUTOR: define align 8 i32* @test1(i32* returned align 8 %0)
+; ATTRIBUTOR: define align 8 i32* @test1(i32* returned align 8 "no-capture-maybe-returned" %0)
define i32* @test1(i32* align 8 %0) #0 {
ret i32* %0
}
; TEST 2
-; ATTRIBUTOR: define i32* @test2(i32* returned %0)
+; ATTRIBUTOR: define i32* @test2(i32* returned "no-capture-maybe-returned" %0)
define i32* @test2(i32* %0) #0 {
ret i32* %0
}
; TEST 3
-; ATTRIBUTOR: define align 4 i32* @test3(i32* align 8 %0, i32* align 4 %1, i1 %2)
+; ATTRIBUTOR: define align 4 i32* @test3(i32* align 8 "no-capture-maybe-returned" %0, i32* align 4 "no-capture-maybe-returned" %1, i1 %2)
define i32* @test3(i32* align 8 %0, i32* align 4 %1, i1 %2) #0 {
%ret = select i1 %2, i32* %0, i32* %1
ret i32* %ret
}
; TEST 4
-; ATTRIBUTOR: define align 32 i32* @test4(i32* align 32 %0, i32* align 32 %1, i1 %2)
+; ATTRIBUTOR: define align 32 i32* @test4(i32* align 32 "no-capture-maybe-returned" %0, i32* align 32 "no-capture-maybe-returned" %1, i1 %2)
define i32* @test4(i32* align 32 %0, i32* align 32 %1, i1 %2) #0 {
%ret = select i1 %2, i32* %0, i32* %1
ret i32* %ret
@@ -83,7 +83,7 @@ define i32* @test6_2() #0 {
; Function Attrs: nounwind readnone ssp uwtable
define internal i8* @f1(i8* readnone %0) local_unnamed_addr #0 {
-; ATTRIBUTOR: define internal nonnull align 8 dereferenceable(1) i8* @f1(i8* nonnull readnone align 8 dereferenceable(1) %0)
+; ATTRIBUTOR: define internal nonnull align 8 dereferenceable(1) i8* @f1(i8* nonnull readnone align 8 dereferenceable(1) "no-capture-maybe-returned" %0)
%2 = icmp eq i8* %0, null
br i1 %2, label %3, label %5
@@ -101,13 +101,13 @@ define internal i8* @f1(i8* readnone %0)
; Function Attrs: nounwind readnone ssp uwtable
define internal i8* @f2(i8* readnone %0) local_unnamed_addr #0 {
-; ATTRIBUTOR: define internal nonnull align 8 dereferenceable(1) i8* @f2(i8* nonnull readnone align 8 dereferenceable(1) %0)
+; ATTRIBUTOR: define internal nonnull align 8 dereferenceable(1) i8* @f2(i8* nonnull readnone align 8 dereferenceable(1) "no-capture-maybe-returned" %0)
%2 = icmp eq i8* %0, null
br i1 %2, label %5, label %3
; <label>:3: ; preds = %1
-; ATTRIBUTOR: %4 = tail call i8* @f1(i8* nonnull align 8 dereferenceable(1) %0)
+; ATTRIBUTOR: %4 = tail call i8* @f1(i8* nonnull align 8 dereferenceable(1) "no-capture-maybe-returned" %0)
%4 = tail call i8* @f1(i8* nonnull %0)
br label %7
@@ -123,7 +123,7 @@ define internal i8* @f2(i8* readnone %0)
; Function Attrs: nounwind readnone ssp uwtable
define internal i8* @f3(i8* readnone %0) local_unnamed_addr #0 {
-; ATTRIBUTOR: define internal nonnull align 8 dereferenceable(1) i8* @f3(i8* nonnull readnone align 16 dereferenceable(1) %0)
+; ATTRIBUTOR: define internal nonnull align 8 dereferenceable(1) i8* @f3(i8* nocapture nonnull readnone align 16 dereferenceable(1) %0)
%2 = icmp eq i8* %0, null
br i1 %2, label %3, label %5
@@ -139,7 +139,7 @@ define internal i8* @f3(i8* readnone %0)
; TEST 7
; Better than IR information
-; ATTRIBUTOR: define align 32 i32* @test7(i32* returned align 32 %p)
+; ATTRIBUTOR: define align 32 i32* @test7(i32* returned align 32 "no-capture-maybe-returned" %p)
define align 4 i32* @test7(i32* align 32 %p) #0 {
tail call i8* @f1(i8* align 8 dereferenceable(1) @a1)
ret i32* %p
@@ -162,7 +162,7 @@ define void @test8_helper() {
}
define internal void @test8(i32* %a, i32* %b, i32* %c) {
-; ATTRIBUTOR: define internal void @test8(i32* align 4 %a, i32* align 4 %b, i32* %c)
+; ATTRIBUTOR: define internal void @test8(i32* nocapture align 4 %a, i32* nocapture align 4 %b, i32* nocapture %c)
ret void
}
@@ -174,8 +174,8 @@ define void @test9_traversal(i1 %c, i32*
}
; FIXME: This will work with an upcoming patch (D66618 or similar)
-; define align 32 i32* @test10a(i32* align 32 %p)
-; ATTRIBUTOR: define i32* @test10a(i32* align 32 %p)
+; define align 32 i32* @test10a(i32* align 32 "no-capture-maybe-returned" %p)
+; ATTRIBUTOR: define i32* @test10a(i32* align 32 "no-capture-maybe-returned" %p)
define i32* @test10a(i32* align 32 %p) {
; ATTRIBUTOR: %l = load i32, i32* %p, align 32
%l = load i32, i32* %p
@@ -202,8 +202,8 @@ e:
}
; FIXME: This will work with an upcoming patch (D66618 or similar)
-; define align 32 i32* @test10b(i32* align 32 %p)
-; ATTRIBUTOR: define i32* @test10b(i32* align 32 %p)
+; define align 32 i32* @test10b(i32* align 32 "no-capture-maybe-returned" %p)
+; ATTRIBUTOR: define i32* @test10b(i32* align 32 "no-capture-maybe-returned" %p)
define i32* @test10b(i32* align 32 %p) {
; ATTRIBUTOR: %l = load i32, i32* %p, align 32
%l = load i32, i32* %p
Modified: llvm/trunk/test/Transforms/FunctionAttrs/arg_nocapture.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionAttrs/arg_nocapture.ll?rev=370817&r1=370816&r2=370817&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/FunctionAttrs/arg_nocapture.ll (original)
+++ llvm/trunk/test/Transforms/FunctionAttrs/arg_nocapture.ll Tue Sep 3 13:37:24 2019
@@ -1,4 +1,4 @@
-; RUN: opt -functionattrs -attributor -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=8 -S < %s | FileCheck %s
+; RUN: opt -functionattrs -attributor -attributor-manifest-internal -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=8 -S < %s | FileCheck %s
;
; Test cases specifically designed for the "no-capture" argument attribute.
; We use FIXME's to indicate problems and missing attributes.
@@ -112,15 +112,12 @@ entry:
; TEST SCC with various calls, casts, and comparisons agains NULL
;
-; FIXME: no-capture missing for %a
-; CHECK: define float* @scc_A(i32* readnone returned %a)
+; CHECK: define dereferenceable_or_null(4) float* @scc_A(i32* readnone returned dereferenceable_or_null(4) "no-capture-maybe-returned" %a)
;
-; FIXME: no-capture missing for %a
-; CHECK: define i64* @scc_B(double* readnone returned %a)
+; CHECK: define dereferenceable_or_null(8) i64* @scc_B(double* readnone returned dereferenceable_or_null(8) "no-capture-maybe-returned" %a)
;
; FIXME: readnone missing for %s
-; FIXME: no-capture missing for %a
-; CHECK: define i8* @scc_C(i16* returned %a)
+; CHECK: define dereferenceable_or_null(2) i8* @scc_C(i16* returned dereferenceable_or_null(2) "no-capture-maybe-returned" %a)
;
; float *scc_A(int *a) {
; return (float*)(a ? (int*)scc_A((int*)scc_B((double*)scc_C((short*)a))) : a);
@@ -133,7 +130,7 @@ entry:
; void *scc_C(short *a) {
; return scc_A((int*)(scc_A(a) ? scc_B((double*)a) : scc_C(a)));
; }
-define float* @scc_A(i32* %a) {
+define float* @scc_A(i32* dereferenceable_or_null(4) %a) {
entry:
%tobool = icmp ne i32* %a, null
br i1 %tobool, label %cond.true, label %cond.false
@@ -157,7 +154,7 @@ cond.end:
ret float* %4
}
-define i64* @scc_B(double* %a) {
+define i64* @scc_B(double* dereferenceable_or_null(8) %a) {
entry:
%tobool = icmp ne double* %a, null
br i1 %tobool, label %cond.true, label %cond.false
@@ -181,7 +178,7 @@ cond.end:
ret i64* %4
}
-define i8* @scc_C(i16* %a) {
+define i8* @scc_C(i16* dereferenceable_or_null(2) %a) {
entry:
%bc = bitcast i16* %a to i32*
%call = call float* @scc_A(i32* %bc)
@@ -248,7 +245,7 @@ declare i32 @printf(i8* nocapture, ...)
; }
;
; There should *not* be a no-capture attribute on %a
-; CHECK: define i64* @not_captured_but_returned_0(i64* returned %a)
+; CHECK: define i64* @not_captured_but_returned_0(i64* returned "no-capture-maybe-returned" %a)
define i64* @not_captured_but_returned_0(i64* %a) #0 {
entry:
store i64 0, i64* %a, align 8
@@ -263,7 +260,7 @@ entry:
; }
;
; There should *not* be a no-capture attribute on %a
-; CHECK: define nonnull i64* @not_captured_but_returned_1(i64* %a)
+; CHECK: define nonnull i64* @not_captured_but_returned_1(i64* "no-capture-maybe-returned" %a)
define i64* @not_captured_but_returned_1(i64* %a) #0 {
entry:
%add.ptr = getelementptr inbounds i64, i64* %a, i64 1
@@ -279,7 +276,7 @@ entry:
; }
;
; FIXME: no-capture missing for %a
-; CHECK: define void @test_not_captured_but_returned_calls(i64* %a)
+; CHECK: define void @test_not_captured_but_returned_calls(i64* nocapture %a)
define void @test_not_captured_but_returned_calls(i64* %a) #0 {
entry:
%call = call i64* @not_captured_but_returned_0(i64* %a)
@@ -294,7 +291,7 @@ entry:
; }
;
; There should *not* be a no-capture attribute on %a
-; CHECK: define i64* @negative_test_not_captured_but_returned_call_0a(i64* returned %a)
+; CHECK: define i64* @negative_test_not_captured_but_returned_call_0a(i64* returned "no-capture-maybe-returned" %a)
define i64* @negative_test_not_captured_but_returned_call_0a(i64* %a) #0 {
entry:
%call = call i64* @not_captured_but_returned_0(i64* %a)
@@ -324,7 +321,7 @@ entry:
; }
;
; There should *not* be a no-capture attribute on %a
-; CHECK: define nonnull i64* @negative_test_not_captured_but_returned_call_1a(i64* %a)
+; CHECK: define nonnull i64* @negative_test_not_captured_but_returned_call_1a(i64* "no-capture-maybe-returned" %a)
define i64* @negative_test_not_captured_but_returned_call_1a(i64* %a) #0 {
entry:
%call = call i64* @not_captured_but_returned_1(i64* %a)
Modified: llvm/trunk/test/Transforms/FunctionAttrs/arg_returned.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionAttrs/arg_returned.ll?rev=370817&r1=370816&r2=370817&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/FunctionAttrs/arg_returned.ll (original)
+++ llvm/trunk/test/Transforms/FunctionAttrs/arg_returned.ll Tue Sep 3 13:37:24 2019
@@ -1,6 +1,6 @@
; RUN: opt -functionattrs -S < %s | FileCheck %s --check-prefix=FNATTR
-; RUN: opt -attributor -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=9 -S < %s | FileCheck %s --check-prefix=ATTRIBUTOR
-; RUN: opt -attributor -attributor-disable=false -functionattrs -S < %s | FileCheck %s --check-prefix=BOTH
+; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=9 -S < %s | FileCheck %s --check-prefix=ATTRIBUTOR
+; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -functionattrs -S < %s | FileCheck %s --check-prefix=BOTH
;
; Test cases specifically designed for the "returned" argument attribute.
; We use FIXME's to indicate problems and missing attributes.
@@ -160,7 +160,7 @@ return:
; TEST SCC test returning a pointer value argument
;
; BOTH: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable
-; BOTH-NEXT: define double* @ptr_sink_r0(double* readnone returned %r)
+; BOTH-NEXT: define double* @ptr_sink_r0(double* readnone returned "no-capture-maybe-returned" %r)
; BOTH: Function Attrs: nofree noinline nosync nounwind readnone uwtable
; BOTH-NEXT: define double* @ptr_scc_r1(double* %a, double* readnone returned %r, double* nocapture readnone %b)
; BOTH: Function Attrs: nofree noinline nosync nounwind readnone uwtable
@@ -171,9 +171,9 @@ return:
; FNATTR: define double* @ptr_scc_r2(double* readnone %a, double* readnone %b, double* readnone %r)
;
; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind uwtable
-; ATTRIBUTOR-NEXT: define double* @ptr_sink_r0(double* returned %r)
+; ATTRIBUTOR-NEXT: define double* @ptr_sink_r0(double* returned "no-capture-maybe-returned" %r)
; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind uwtable
-; ATTRIBUTOR-NEXT: define double* @ptr_scc_r1(double* %a, double* returned %r, double* %b)
+; ATTRIBUTOR-NEXT: define double* @ptr_scc_r1(double* %a, double* returned %r, double* nocapture %b)
; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind uwtable
; ATTRIBUTOR-NEXT: define double* @ptr_scc_r2(double* %a, double* %b, double* returned %r)
;
@@ -261,7 +261,7 @@ return:
;
; FNATTR: define i32* @rt0(i32* readonly %a)
; BOTH: Function Attrs: nofree noinline noreturn nosync nounwind readonly uwtable
-; BOTH-NEXT: define noalias nonnull align 536870912 dereferenceable(4294967295) i32* @rt0(i32* readonly %a)
+; BOTH-NEXT: define noalias nonnull align 536870912 dereferenceable(4294967295) i32* @rt0(i32* nocapture readonly %a)
define i32* @rt0(i32* %a) #0 {
entry:
%v = load i32, i32* %a, align 4
@@ -294,7 +294,7 @@ entry:
; FNATTR: define i32* @rt2_helper(i32* %a)
; FNATTR: define i32* @rt2(i32* readnone %a, i32* readnone %b)
; BOTH: define i32* @rt2_helper(i32* returned %a)
-; BOTH: define i32* @rt2(i32* readnone %a, i32* readnone %b)
+; BOTH: define i32* @rt2(i32* readnone %a, i32* readnone "no-capture-maybe-returned" %b)
define i32* @rt2_helper(i32* %a) #0 {
entry:
%call = call i32* @rt2(i32* %a, i32* %a)
@@ -319,8 +319,8 @@ if.end:
;
; FNATTR: define i32* @rt3_helper(i32* %a, i32* %b)
; FNATTR: define i32* @rt3(i32* readnone %a, i32* readnone %b)
-; BOTH: define i32* @rt3_helper(i32* %a, i32* returned %b)
-; BOTH: define i32* @rt3(i32* readnone %a, i32* readnone returned %b)
+; BOTH: define i32* @rt3_helper(i32* %a, i32* returned "no-capture-maybe-returned" %b)
+; BOTH: define i32* @rt3(i32* readnone %a, i32* readnone returned "no-capture-maybe-returned" %b)
define i32* @rt3_helper(i32* %a, i32* %b) #0 {
entry:
%call = call i32* @rt3(i32* %a, i32* %b)
@@ -353,9 +353,9 @@ if.end:
; BOTH: declare void @unknown_fn(i32* (i32*)*)
;
; BOTH: Function Attrs: noinline nounwind uwtable
-; BOTH-NEXT: define i32* @calls_unknown_fn(i32* readnone returned %r)
+; BOTH-NEXT: define i32* @calls_unknown_fn(i32* readnone returned "no-capture-maybe-returned" %r)
; FNATTR: define i32* @calls_unknown_fn(i32* readnone returned %r)
-; ATTRIBUTOR: define i32* @calls_unknown_fn(i32* returned %r)
+; ATTRIBUTOR: define i32* @calls_unknown_fn(i32* returned "no-capture-maybe-returned" %r)
declare void @unknown_fn(i32* (i32*)*) #0
define i32* @calls_unknown_fn(i32* %r) #0 {
@@ -502,12 +502,12 @@ if.end:
; }
;
; BOTH: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable
-; BOTH-NEXT: define double* @bitcast(i32* readnone returned %b)
+; BOTH-NEXT: define double* @bitcast(i32* readnone returned "no-capture-maybe-returned" %b)
;
; FNATTR: define double* @bitcast(i32* readnone %b)
;
; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind uwtable
-; ATTRIBUTOR-NEXT: define double* @bitcast(i32* returned %b)
+; ATTRIBUTOR-NEXT: define double* @bitcast(i32* returned "no-capture-maybe-returned" %b)
define double* @bitcast(i32* %b) #0 {
entry:
%bc0 = bitcast i32* %b to double*
Modified: llvm/trunk/test/Transforms/FunctionAttrs/dereferenceable.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionAttrs/dereferenceable.ll?rev=370817&r1=370816&r2=370817&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/FunctionAttrs/dereferenceable.ll (original)
+++ llvm/trunk/test/Transforms/FunctionAttrs/dereferenceable.ll Tue Sep 3 13:37:24 2019
@@ -1,4 +1,4 @@
-; RUN: opt -attributor --attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=4 -S < %s | FileCheck %s --check-prefixes=ATTRIBUTOR
+; RUN: opt -attributor -attributor-manifest-internal --attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=4 -S < %s | FileCheck %s --check-prefixes=ATTRIBUTOR
declare void @deref_phi_user(i32* %a);
@@ -7,7 +7,7 @@ declare void @deref_phi_user(i32* %a);
; take mininimum of return values
;
define i32* @test1(i32* dereferenceable(4) %0, double* dereferenceable(8) %1, i1 zeroext %2) local_unnamed_addr {
-; ATTRIBUTOR: define nonnull dereferenceable(4) i32* @test1(i32* nonnull dereferenceable(4) %0, double* nonnull dereferenceable(8) %1, i1 zeroext %2)
+; ATTRIBUTOR: define nonnull dereferenceable(4) i32* @test1(i32* nonnull dereferenceable(4) "no-capture-maybe-returned" %0, double* nonnull dereferenceable(8) "no-capture-maybe-returned" %1, i1 zeroext %2)
%4 = bitcast double* %1 to i32*
%5 = select i1 %2, i32* %0, i32* %4
ret i32* %5
@@ -15,7 +15,7 @@ define i32* @test1(i32* dereferenceable(
; TEST 2
define i32* @test2(i32* dereferenceable_or_null(4) %0, double* dereferenceable(8) %1, i1 zeroext %2) local_unnamed_addr {
-; ATTRIBUTOR: define dereferenceable_or_null(4) i32* @test2(i32* dereferenceable_or_null(4) %0, double* nonnull dereferenceable(8) %1, i1 zeroext %2)
+; ATTRIBUTOR: define dereferenceable_or_null(4) i32* @test2(i32* dereferenceable_or_null(4) "no-capture-maybe-returned" %0, double* nonnull dereferenceable(8) "no-capture-maybe-returned" %1, i1 zeroext %2)
%4 = bitcast double* %1 to i32*
%5 = select i1 %2, i32* %0, i32* %4
ret i32* %5
@@ -24,20 +24,20 @@ define i32* @test2(i32* dereferenceable_
; TEST 3
; GEP inbounds
define i32* @test3_1(i32* dereferenceable(8) %0) local_unnamed_addr {
-; ATTRIBUTOR: define nonnull dereferenceable(4) i32* @test3_1(i32* nonnull dereferenceable(8) %0)
+; ATTRIBUTOR: define nonnull dereferenceable(4) i32* @test3_1(i32* nonnull dereferenceable(8) "no-capture-maybe-returned" %0)
%ret = getelementptr inbounds i32, i32* %0, i64 1
ret i32* %ret
}
define i32* @test3_2(i32* dereferenceable_or_null(32) %0) local_unnamed_addr {
; FIXME: Argument should be mark dereferenceable because of GEP `inbounds`.
-; ATTRIBUTOR: define nonnull dereferenceable(16) i32* @test3_2(i32* dereferenceable_or_null(32) %0)
+; ATTRIBUTOR: define nonnull dereferenceable(16) i32* @test3_2(i32* dereferenceable_or_null(32) "no-capture-maybe-returned" %0)
%ret = getelementptr inbounds i32, i32* %0, i64 4
ret i32* %ret
}
define i32* @test3_3(i32* dereferenceable(8) %0, i32* dereferenceable(16) %1, i1 %2) local_unnamed_addr {
-; ATTRIBUTOR: define nonnull dereferenceable(4) i32* @test3_3(i32* nonnull dereferenceable(8) %0, i32* nonnull dereferenceable(16) %1, i1 %2) local_unnamed_addr
+; ATTRIBUTOR: define nonnull dereferenceable(4) i32* @test3_3(i32* nonnull dereferenceable(8) "no-capture-maybe-returned" %0, i32* nonnull dereferenceable(16) "no-capture-maybe-returned" %1, i1 %2) local_unnamed_addr
%ret1 = getelementptr inbounds i32, i32* %0, i64 1
%ret2 = getelementptr inbounds i32, i32* %1, i64 2
%ret = select i1 %2, i32* %ret1, i32* %ret2
@@ -48,7 +48,7 @@ define i32* @test3_3(i32* dereferenceabl
; Better than known in IR.
define dereferenceable(4) i32* @test4(i32* dereferenceable(8) %0) local_unnamed_addr {
-; ATTRIBUTOR: define nonnull dereferenceable(8) i32* @test4(i32* nonnull returned dereferenceable(8) %0)
+; ATTRIBUTOR: define nonnull dereferenceable(8) i32* @test4(i32* nonnull returned dereferenceable(8) "no-capture-maybe-returned" %0)
ret i32* %0
}
Modified: llvm/trunk/test/Transforms/FunctionAttrs/internal-noalias.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionAttrs/internal-noalias.ll?rev=370817&r1=370816&r2=370817&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/FunctionAttrs/internal-noalias.ll (original)
+++ llvm/trunk/test/Transforms/FunctionAttrs/internal-noalias.ll Tue Sep 3 13:37:24 2019
@@ -10,7 +10,7 @@ entry:
; FIXME: Should be something like this.
; define internal i32 @noalias_args(i32* nocapture readonly %A, i32* noalias nocapture readonly %B)
-; CHECK: define internal i32 @noalias_args(i32* %A, i32* %B)
+; CHECK: define internal i32 @noalias_args(i32* nocapture %A, i32* nocapture %B)
define internal i32 @noalias_args(i32* %A, i32* %B) #0 {
entry:
@@ -25,7 +25,7 @@ entry:
; FIXME: Should be something like this.
; define internal i32 @noalias_args_argmem(i32* noalias nocapture readonly %A, i32* noalias nocapture readonly %B)
-; CHECK: define internal i32 @noalias_args_argmem(i32* %A, i32* %B)
+; CHECK: define internal i32 @noalias_args_argmem(i32* nocapture %A, i32* nocapture %B)
;
define internal i32 @noalias_args_argmem(i32* %A, i32* %B) #1 {
entry:
Modified: llvm/trunk/test/Transforms/FunctionAttrs/liveness.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionAttrs/liveness.ll?rev=370817&r1=370816&r2=370817&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/FunctionAttrs/liveness.ll (original)
+++ llvm/trunk/test/Transforms/FunctionAttrs/liveness.ll Tue Sep 3 13:37:24 2019
@@ -40,7 +40,7 @@ define i32 @volatile_load(i32*) norecurs
}
; CHECK: Function Attrs: nofree norecurse nosync nounwind uwtable willreturn
-; CHECK-NEXT: define internal i32 @internal_load(i32* nonnull %0)
+; CHECK-NEXT: define internal i32 @internal_load(i32* nocapture nonnull %0)
define internal i32 @internal_load(i32*) norecurse nounwind uwtable {
%2 = load i32, i32* %0, align 4
ret i32 %2
@@ -48,11 +48,11 @@ define internal i32 @internal_load(i32*)
; TEST 1: Only first block is live.
; CHECK: Function Attrs: nofree noreturn nosync nounwind
-; CHECK-NEXT: define i32 @first_block_no_return(i32 %a, i32* nonnull %ptr1, i32* %ptr2)
+; CHECK-NEXT: define i32 @first_block_no_return(i32 %a, i32* nocapture nonnull %ptr1, i32* nocapture %ptr2)
define i32 @first_block_no_return(i32 %a, i32* nonnull %ptr1, i32* %ptr2) #0 {
entry:
call i32 @internal_load(i32* %ptr1)
- ; CHECK: call i32 @internal_load(i32* nonnull %ptr1)
+ ; CHECK: call i32 @internal_load(i32* nocapture nonnull %ptr1)
call void @no_return_call()
; CHECK: call void @no_return_call()
; CHECK-NEXT: unreachable
@@ -85,7 +85,7 @@ cond.end:
; dead block and check if it is deduced.
; CHECK: Function Attrs: nosync
-; CHECK-NEXT: define i32 @dead_block_present(i32 %a, i32* %ptr1)
+; CHECK-NEXT: define i32 @dead_block_present(i32 %a, i32* nocapture %ptr1)
define i32 @dead_block_present(i32 %a, i32* %ptr1) #0 {
entry:
%cmp = icmp eq i32 %a, 0
@@ -240,7 +240,7 @@ cleanup:
; TEST 6: Undefined behvior, taken from LangRef.
; FIXME: Should be able to detect undefined behavior.
-; CHECK: define void @ub(i32* %0)
+; CHECK: define void @ub(i32* nocapture %0)
define void @ub(i32* %0) {
%poison = sub nuw i32 0, 1 ; Results in a poison value.
%still_poison = and i32 %poison, 0 ; 0, but also poison.
Modified: llvm/trunk/test/Transforms/FunctionAttrs/noalias_returned.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionAttrs/noalias_returned.ll?rev=370817&r1=370816&r2=370817&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/FunctionAttrs/noalias_returned.ll (original)
+++ llvm/trunk/test/Transforms/FunctionAttrs/noalias_returned.ll Tue Sep 3 13:37:24 2019
@@ -29,6 +29,17 @@ define i8* @return_noalias(){
ret i8* %1
}
+define void @nocapture(i8* %a){
+ ret void
+}
+
+; CHECK: define noalias i8* @return_noalias_looks_like_capture()
+define i8* @return_noalias_looks_like_capture(){
+ %1 = tail call noalias i8* @malloc(i64 4)
+ call void @nocapture(i8* %1)
+ ret i8* %1
+}
+
declare i8* @alias()
; TEST 3
@@ -142,7 +153,7 @@ define i8* @test8(i32* %0) nounwind uwta
; TEST 9
; Simple Argument Test
define internal void @test9(i8* %a, i8* %b) {
-; CHECK: define internal void @test9(i8* noalias %a, i8* %b)
+; CHECK: define internal void @test9(i8* noalias nocapture %a, i8* nocapture %b)
ret void
}
define void @test9_helper(i8* %a, i8* %b) {
Modified: llvm/trunk/test/Transforms/FunctionAttrs/nocapture.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionAttrs/nocapture.ll?rev=370817&r1=370816&r2=370817&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/FunctionAttrs/nocapture.ll (original)
+++ llvm/trunk/test/Transforms/FunctionAttrs/nocapture.ll Tue Sep 3 13:37:24 2019
@@ -1,27 +1,30 @@
-; RUN: opt < %s -functionattrs -S | FileCheck %s
-; RUN: opt < %s -passes=function-attrs -S | FileCheck %s
+; RUN: opt -functionattrs -S < %s | FileCheck %s --check-prefixes=FNATTR,EITHER
+; RUN: opt -passes=function-attrs -S < %s | FileCheck %s --check-prefixes=FNATTR,EITHER
+; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -S < %s | FileCheck %s --check-prefixes=ATTRIBUTOR,EITHER
+; RUN: opt -passes=attributor -attributor-manifest-internal -attributor-disable=false -S < %s | FileCheck %s --check-prefixes=ATTRIBUTOR,EITHER
@g = global i32* null ; <i32**> [#uses=1]
-; CHECK: define i32* @c1(i32* readnone returned %q)
+; FNATTR: define i32* @c1(i32* readnone returned %q)
+; ATTRIBUTOR: define i32* @c1(i32* returned "no-capture-maybe-returned" %q)
define i32* @c1(i32* %q) {
ret i32* %q
}
-; CHECK: define void @c2(i32* %q)
+; EITHER: define void @c2(i32* %q)
; It would also be acceptable to mark %q as readnone. Update @c3 too.
define void @c2(i32* %q) {
store i32* %q, i32** @g
ret void
}
-; CHECK: define void @c3(i32* %q)
+; EITHER: define void @c3(i32* %q)
define void @c3(i32* %q) {
call void @c2(i32* %q)
ret void
}
-; CHECK: define i1 @c4(i32* %q, i32 %bitno)
+; EITHER: define i1 @c4(i32* %q, i32 %bitno)
define i1 @c4(i32* %q, i32 %bitno) {
%tmp = ptrtoint i32* %q to i32
%tmp2 = lshr i32 %tmp, %bitno
@@ -35,7 +38,7 @@ l1:
@lookup_table = global [2 x i1] [ i1 0, i1 1 ]
-; CHECK: define i1 @c5(i32* %q, i32 %bitno)
+; EITHER: define i1 @c5(i32* %q, i32 %bitno)
define i1 @c5(i32* %q, i32 %bitno) {
%tmp = ptrtoint i32* %q to i32
%tmp2 = lshr i32 %tmp, %bitno
@@ -48,7 +51,8 @@ define i1 @c5(i32* %q, i32 %bitno) {
declare void @throw_if_bit_set(i8*, i8) readonly
-; CHECK: define i1 @c6(i8* readonly %q, i8 %bit)
+; FNATTR: define i1 @c6(i8* readonly %q, i8 %bit)
+; ATTRIBUTOR: define i1 @c6(i8* %q, i8 %bit)
define i1 @c6(i8* %q, i8 %bit) personality i32 (...)* @__gxx_personality_v0 {
invoke void @throw_if_bit_set(i8* %q, i8 %bit)
to label %ret0 unwind label %ret1
@@ -70,7 +74,8 @@ define i1* @lookup_bit(i32* %q, i32 %bit
ret i1* %lookup
}
-; CHECK: define i1 @c7(i32* readonly %q, i32 %bitno)
+; FNATTR: define i1 @c7(i32* readonly %q, i32 %bitno)
+; ATTRIBUTOR: define i1 @c7(i32* %q, i32 %bitno)
define i1 @c7(i32* %q, i32 %bitno) {
%ptr = call i1* @lookup_bit(i32* %q, i32 %bitno)
%val = load i1, i1* %ptr
@@ -78,7 +83,7 @@ define i1 @c7(i32* %q, i32 %bitno) {
}
-; CHECK: define i32 @nc1(i32* %q, i32* nocapture %p, i1 %b)
+; EITHER: define i32 @nc1(i32* %q, i32* nocapture %p, i1 %b)
define i32 @nc1(i32* %q, i32* %p, i1 %b) {
e:
br label %l
@@ -93,7 +98,7 @@ l:
ret i32 %val
}
-; CHECK: define i32 @nc1_addrspace(i32* %q, i32 addrspace(1)* nocapture %p, i1 %b)
+; EITHER: define i32 @nc1_addrspace(i32* %q, i32 addrspace(1)* nocapture %p, i1 %b)
define i32 @nc1_addrspace(i32* %q, i32 addrspace(1)* %p, i1 %b) {
e:
br label %l
@@ -108,78 +113,93 @@ l:
ret i32 %val
}
-; CHECK: define void @nc2(i32* nocapture %p, i32* %q)
+; EITHER: define void @nc2(i32* nocapture %p, i32* %q)
define void @nc2(i32* %p, i32* %q) {
%1 = call i32 @nc1(i32* %q, i32* %p, i1 0) ; <i32> [#uses=0]
ret void
}
-; CHECK: define void @nc3(void ()* nocapture %p)
+; EITHER: define void @nc3(void ()* nocapture %p)
define void @nc3(void ()* %p) {
call void %p()
ret void
}
declare void @external(i8*) readonly nounwind
-; CHECK: define void @nc4(i8* nocapture readonly %p)
+; FNATTR: define void @nc4(i8* nocapture readonly %p)
+; ATTRIBUTOR: define void @nc4(i8* nocapture %p)
define void @nc4(i8* %p) {
call void @external(i8* %p)
ret void
}
-; CHECK: define void @nc5(void (i8*)* nocapture %f, i8* nocapture %p)
+; EITHER: define void @nc5(void (i8*)* nocapture %f, i8* nocapture %p)
define void @nc5(void (i8*)* %f, i8* %p) {
call void %f(i8* %p) readonly nounwind
call void %f(i8* nocapture %p)
ret void
}
-; CHECK: define void @test1_1(i8* nocapture readnone %x1_1, i8* %y1_1)
+; FNATTR: define void @test1_1(i8* nocapture readnone %x1_1, i8* %y1_1, i1 %c)
+; ATTRIBUTOR: define void @test1_1(i8* nocapture %x1_1, i8* nocapture %y1_1, i1 %c)
; It would be acceptable to add readnone to %y1_1 and %y1_2.
-define void @test1_1(i8* %x1_1, i8* %y1_1) {
- call i8* @test1_2(i8* %x1_1, i8* %y1_1)
+define void @test1_1(i8* %x1_1, i8* %y1_1, i1 %c) {
+ call i8* @test1_2(i8* %x1_1, i8* %y1_1, i1 %c)
store i32* null, i32** @g
ret void
}
-; CHECK: define i8* @test1_2(i8* nocapture readnone %x1_2, i8* returned %y1_2)
-define i8* @test1_2(i8* %x1_2, i8* %y1_2) {
- call void @test1_1(i8* %x1_2, i8* %y1_2)
+; FNATTR: define i8* @test1_2(i8* nocapture readnone %x1_2, i8* returned %y1_2, i1 %c)
+; ATTRIBUTOR: define i8* @test1_2(i8* nocapture %x1_2, i8* returned "no-capture-maybe-returned" %y1_2, i1 %c)
+define i8* @test1_2(i8* %x1_2, i8* %y1_2, i1 %c) {
+ br i1 %c, label %t, label %f
+t:
+ call void @test1_1(i8* %x1_2, i8* %y1_2, i1 %c)
store i32* null, i32** @g
+ br label %f
+f:
ret i8* %y1_2
}
-; CHECK: define void @test2(i8* nocapture readnone %x2)
+; FNATTR: define void @test2(i8* nocapture readnone %x2)
+; ATTRIBUTOR: define void @test2(i8* nocapture %x2)
define void @test2(i8* %x2) {
call void @test2(i8* %x2)
store i32* null, i32** @g
ret void
}
-; CHECK: define void @test3(i8* nocapture readnone %x3, i8* nocapture readnone %y3, i8* nocapture readnone %z3)
+; FNATTR: define void @test3(i8* nocapture readnone %x3, i8* nocapture readnone %y3, i8* nocapture readnone %z3)
+; ATTRIBUTOR: define void @test3(i8* nocapture %x3, i8* nocapture %y3, i8* nocapture %z3)
define void @test3(i8* %x3, i8* %y3, i8* %z3) {
call void @test3(i8* %z3, i8* %y3, i8* %x3)
store i32* null, i32** @g
ret void
}
-; CHECK: define void @test4_1(i8* %x4_1)
-define void @test4_1(i8* %x4_1) {
- call i8* @test4_2(i8* %x4_1, i8* %x4_1, i8* %x4_1)
+; FNATTR: define void @test4_1(i8* %x4_1, i1 %c)
+; ATTRIBUTOR: define void @test4_1(i8* nocapture %x4_1, i1 %c)
+define void @test4_1(i8* %x4_1, i1 %c) {
+ call i8* @test4_2(i8* %x4_1, i8* %x4_1, i8* %x4_1, i1 %c)
store i32* null, i32** @g
ret void
}
-; CHECK: define i8* @test4_2(i8* nocapture readnone %x4_2, i8* readnone returned %y4_2, i8* nocapture readnone %z4_2)
-define i8* @test4_2(i8* %x4_2, i8* %y4_2, i8* %z4_2) {
- call void @test4_1(i8* null)
+; FNATTR: define i8* @test4_2(i8* nocapture readnone %x4_2, i8* readnone returned %y4_2, i8* nocapture readnone %z4_2, i1 %c)
+; ATTRIBUTOR: define i8* @test4_2(i8* nocapture %x4_2, i8* returned "no-capture-maybe-returned" %y4_2, i8* nocapture %z4_2, i1 %c)
+define i8* @test4_2(i8* %x4_2, i8* %y4_2, i8* %z4_2, i1 %c) {
+ br i1 %c, label %t, label %f
+t:
+ call void @test4_1(i8* null, i1 %c)
store i32* null, i32** @g
+ br label %f
+f:
ret i8* %y4_2
}
declare i8* @test5_1(i8* %x5_1)
-; CHECK: define void @test5_2(i8* %x5_2)
+; EITHER: define void @test5_2(i8* %x5_2)
define void @test5_2(i8* %x5_2) {
call i8* @test5_1(i8* %x5_2)
store i32* null, i32** @g
@@ -188,32 +208,32 @@ define void @test5_2(i8* %x5_2) {
declare void @test6_1(i8* %x6_1, i8* nocapture %y6_1, ...)
-; CHECK: define void @test6_2(i8* %x6_2, i8* nocapture %y6_2, i8* %z6_2)
+; EITHER: define void @test6_2(i8* %x6_2, i8* nocapture %y6_2, i8* %z6_2)
define void @test6_2(i8* %x6_2, i8* %y6_2, i8* %z6_2) {
call void (i8*, i8*, ...) @test6_1(i8* %x6_2, i8* %y6_2, i8* %z6_2)
store i32* null, i32** @g
ret void
}
-; CHECK: define void @test_cmpxchg(i32* nocapture %p)
+; EITHER: define void @test_cmpxchg(i32* nocapture %p)
define void @test_cmpxchg(i32* %p) {
cmpxchg i32* %p, i32 0, i32 1 acquire monotonic
ret void
}
-; CHECK: define void @test_cmpxchg_ptr(i32** nocapture %p, i32* %q)
+; EITHER: define void @test_cmpxchg_ptr(i32** nocapture %p, i32* %q)
define void @test_cmpxchg_ptr(i32** %p, i32* %q) {
cmpxchg i32** %p, i32* null, i32* %q acquire monotonic
ret void
}
-; CHECK: define void @test_atomicrmw(i32* nocapture %p)
+; EITHER: define void @test_atomicrmw(i32* nocapture %p)
define void @test_atomicrmw(i32* %p) {
atomicrmw add i32* %p, i32 1 seq_cst
ret void
}
-; CHECK: define void @test_volatile(i32* %x)
+; EITHER: define void @test_volatile(i32* %x)
define void @test_volatile(i32* %x) {
entry:
%gep = getelementptr i32, i32* %x, i64 1
@@ -221,7 +241,7 @@ entry:
ret void
}
-; CHECK: nocaptureLaunder(i8* nocapture %p)
+; EITHER: nocaptureLaunder(i8* nocapture %p)
define void @nocaptureLaunder(i8* %p) {
entry:
%b = call i8* @llvm.launder.invariant.group.p0i8(i8* %p)
@@ -230,14 +250,14 @@ entry:
}
@g2 = global i8* null
-; CHECK: define void @captureLaunder(i8* %p)
+; EITHER: define void @captureLaunder(i8* %p)
define void @captureLaunder(i8* %p) {
%b = call i8* @llvm.launder.invariant.group.p0i8(i8* %p)
store i8* %b, i8** @g2
ret void
}
-; CHECK: @nocaptureStrip(i8* nocapture %p)
+; EITHER: @nocaptureStrip(i8* nocapture %p)
define void @nocaptureStrip(i8* %p) {
entry:
%b = call i8* @llvm.strip.invariant.group.p0i8(i8* %p)
@@ -246,26 +266,29 @@ entry:
}
@g3 = global i8* null
-; CHECK: define void @captureStrip(i8* %p)
+; EITHER: define void @captureStrip(i8* %p)
define void @captureStrip(i8* %p) {
%b = call i8* @llvm.strip.invariant.group.p0i8(i8* %p)
store i8* %b, i8** @g3
ret void
}
-; CHECK: define i1 @captureICmp(i32* readnone %x)
+; FNATTR: define i1 @captureICmp(i32* readnone %x)
+; ATTRIBUTOR: define i1 @captureICmp(i32* %x)
define i1 @captureICmp(i32* %x) {
%1 = icmp eq i32* %x, null
ret i1 %1
}
-; CHECK: define i1 @captureICmpRev(i32* readnone %x)
+; FNATTR: define i1 @captureICmpRev(i32* readnone %x)
+; ATTRIBUTOR: define i1 @captureICmpRev(i32* %x)
define i1 @captureICmpRev(i32* %x) {
%1 = icmp eq i32* null, %x
ret i1 %1
}
-; CHECK: define i1 @nocaptureInboundsGEPICmp(i32* nocapture readnone %x)
+; FNATTR: define i1 @nocaptureInboundsGEPICmp(i32* nocapture readnone %x)
+; ATTRIBUTOR: define i1 @nocaptureInboundsGEPICmp(i32* nocapture %x)
define i1 @nocaptureInboundsGEPICmp(i32* %x) {
%1 = getelementptr inbounds i32, i32* %x, i32 5
%2 = bitcast i32* %1 to i8*
@@ -273,7 +296,8 @@ define i1 @nocaptureInboundsGEPICmp(i32*
ret i1 %3
}
-; CHECK: define i1 @nocaptureInboundsGEPICmpRev(i32* nocapture readnone %x)
+; FNATTR: define i1 @nocaptureInboundsGEPICmpRev(i32* nocapture readnone %x)
+; ATTRIBUTOR: define i1 @nocaptureInboundsGEPICmpRev(i32* nocapture %x)
define i1 @nocaptureInboundsGEPICmpRev(i32* %x) {
%1 = getelementptr inbounds i32, i32* %x, i32 5
%2 = bitcast i32* %1 to i8*
@@ -281,14 +305,16 @@ define i1 @nocaptureInboundsGEPICmpRev(i
ret i1 %3
}
-; CHECK: define i1 @nocaptureDereferenceableOrNullICmp(i32* nocapture readnone dereferenceable_or_null(4) %x)
+; FNATTR: define i1 @nocaptureDereferenceableOrNullICmp(i32* nocapture readnone dereferenceable_or_null(4) %x)
+; ATTRIBUTOR: define i1 @nocaptureDereferenceableOrNullICmp(i32* nocapture dereferenceable_or_null(4) %x)
define i1 @nocaptureDereferenceableOrNullICmp(i32* dereferenceable_or_null(4) %x) {
%1 = bitcast i32* %x to i8*
%2 = icmp eq i8* %1, null
ret i1 %2
}
-; CHECK: define i1 @captureDereferenceableOrNullICmp(i32* readnone dereferenceable_or_null(4) %x)
+; FNATTR: define i1 @captureDereferenceableOrNullICmp(i32* readnone dereferenceable_or_null(4) %x)
+; ATTRIBUTOR: define i1 @captureDereferenceableOrNullICmp(i32* dereferenceable_or_null(4) %x)
define i1 @captureDereferenceableOrNullICmp(i32* dereferenceable_or_null(4) %x) "null-pointer-is-valid"="true" {
%1 = bitcast i32* %x to i8*
%2 = icmp eq i8* %1, null
Modified: llvm/trunk/test/Transforms/FunctionAttrs/nonnull.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionAttrs/nonnull.ll?rev=370817&r1=370816&r2=370817&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/FunctionAttrs/nonnull.ll (original)
+++ llvm/trunk/test/Transforms/FunctionAttrs/nonnull.ll Tue Sep 3 13:37:24 2019
@@ -159,7 +159,7 @@ define void @test13_helper() {
ret void
}
define internal void @test13(i8* %a, i8* %b, i8* %c) {
-; ATTRIBUTOR: define internal void @test13(i8* nonnull %a, i8* %b, i8* %c)
+; ATTRIBUTOR: define internal void @test13(i8* nocapture nonnull %a, i8* nocapture %b, i8* nocapture %c)
ret void
}
@@ -402,7 +402,7 @@ declare i32 @esfp(...)
define i1 @parent8(i8* %a, i8* %bogus1, i8* %b) personality i8* bitcast (i32 (...)* @esfp to i8*){
; FNATTR-LABEL: @parent8(i8* nonnull %a, i8* nocapture readnone %bogus1, i8* nonnull %b)
; FIXME : missing "nonnull", it should be @parent8(i8* nonnull %a, i8* %bogus1, i8* nonnull %b)
-; ATTRIBUTOR-LABEL: @parent8(i8* %a, i8* %bogus1, i8* %b)
+; ATTRIBUTOR-LABEL: @parent8(i8* %a, i8* nocapture %bogus1, i8* %b)
; BOTH-NEXT: entry:
; FNATTR-NEXT: invoke void @use2nonnull(i8* %a, i8* %b)
; ATTRIBUTOR-NEXT: invoke void @use2nonnull(i8* nonnull %a, i8* nonnull %b)
Modified: llvm/trunk/test/Transforms/FunctionAttrs/nosync.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionAttrs/nosync.ll?rev=370817&r1=370816&r2=370817&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/FunctionAttrs/nosync.ll (original)
+++ llvm/trunk/test/Transforms/FunctionAttrs/nosync.ll Tue Sep 3 13:37:24 2019
@@ -1,5 +1,5 @@
; RUN: opt -functionattrs -S < %s | FileCheck %s --check-prefix=FNATTR
-; RUN: opt -attributor -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=4 -S < %s | FileCheck %s --check-prefix=ATTRIBUTOR
+; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=4 -S < %s | FileCheck %s --check-prefix=ATTRIBUTOR
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
; Test cases designed for the nosync function attribute.
@@ -28,7 +28,7 @@ target datalayout = "e-m:e-i64:64-f80:12
; FNATTR: Function Attrs: norecurse nounwind optsize readnone ssp uwtable
; FNATTR-NEXT: define nonnull i32* @foo(%struct.ST* readnone %s)
; ATTRIBUTOR: Function Attrs: nofree nosync nounwind optsize readnone ssp uwtable
-; ATTRIBUTOR-NEXT: define nonnull i32* @foo(%struct.ST* %s)
+; ATTRIBUTOR-NEXT: define nonnull i32* @foo(%struct.ST* "no-capture-maybe-returned" %s)
define i32* @foo(%struct.ST* %s) nounwind uwtable readnone optsize ssp {
entry:
%arrayidx = getelementptr inbounds %struct.ST, %struct.ST* %s, i64 1, i32 2, i32 1, i64 5, i64 13
@@ -186,7 +186,7 @@ define void @call_might_sync() nounwind
; FNATTR: Function Attrs: nofree noinline nounwind uwtable
; FNATTR-NEXT: define i32 @scc1(i32* %0)
; ATTRIBUTOR: Function Attrs: nofree noinline noreturn nosync nounwind uwtable
-; ATTRIBUTOR-NEXT: define i32 @scc1(i32* %0)
+; ATTRIBUTOR-NEXT: define i32 @scc1(i32* nocapture %0)
define i32 @scc1(i32* %0) noinline nounwind uwtable {
tail call void @scc2(i32* %0);
%val = tail call i32 @volatile_load(i32* %0);
@@ -196,7 +196,7 @@ define i32 @scc1(i32* %0) noinline nounw
; FNATTR: Function Attrs: nofree noinline nounwind uwtable
; FNATTR-NEXT: define void @scc2(i32* %0)
; ATTRIBUTOR: Function Attrs: nofree noinline noreturn nosync nounwind uwtable
-; ATTRIBUTOR-NEXT: define void @scc2(i32* %0)
+; ATTRIBUTOR-NEXT: define void @scc2(i32* nocapture %0)
define void @scc2(i32* %0) noinline nounwind uwtable {
tail call i32 @scc1(i32* %0);
ret void;
@@ -224,7 +224,7 @@ define void @scc2(i32* %0) noinline noun
; FNATTR: Function Attrs: nofree norecurse nounwind
; FNATTR-NEXT: define void @foo1(i32* nocapture %0, %"struct.std::atomic"* nocapture %1)
; ATTRIBUTOR-NOT: nosync
-; ATTRIBUTOR: define void @foo1(i32* %0, %"struct.std::atomic"* %1)
+; ATTRIBUTOR: define void @foo1(i32* nocapture %0, %"struct.std::atomic"* nocapture %1)
define void @foo1(i32* %0, %"struct.std::atomic"* %1) {
store i32 100, i32* %0, align 4
fence release
@@ -236,7 +236,7 @@ define void @foo1(i32* %0, %"struct.std:
; FNATTR: Function Attrs: nofree norecurse nounwind
; FNATTR-NEXT: define void @bar(i32* nocapture readnone %0, %"struct.std::atomic"* nocapture readonly %1)
; ATTRIBUTOR-NOT: nosync
-; ATTRIBUTOR: define void @bar(i32* %0, %"struct.std::atomic"* %1)
+; ATTRIBUTOR: define void @bar(i32* nocapture %0, %"struct.std::atomic"* nocapture %1)
define void @bar(i32* %0, %"struct.std::atomic"* %1) {
%3 = getelementptr inbounds %"struct.std::atomic", %"struct.std::atomic"* %1, i64 0, i32 0, i32 0
br label %4
@@ -256,7 +256,7 @@ define void @bar(i32* %0, %"struct.std::
; FNATTR: Function Attrs: nofree norecurse nounwind
; FNATTR-NEXT: define void @foo1_singlethread(i32* nocapture %0, %"struct.std::atomic"* nocapture %1)
; ATTRIBUTOR: Function Attrs: nofree nosync
-; ATTRIBUTOR: define void @foo1_singlethread(i32* %0, %"struct.std::atomic"* %1)
+; ATTRIBUTOR: define void @foo1_singlethread(i32* nocapture %0, %"struct.std::atomic"* nocapture %1)
define void @foo1_singlethread(i32* %0, %"struct.std::atomic"* %1) {
store i32 100, i32* %0, align 4
fence syncscope("singlethread") release
@@ -268,7 +268,7 @@ define void @foo1_singlethread(i32* %0,
; FNATTR: Function Attrs: nofree norecurse nounwind
; FNATTR-NEXT: define void @bar_singlethread(i32* nocapture readnone %0, %"struct.std::atomic"* nocapture readonly %1)
; ATTRIBUTOR: Function Attrs: nofree nosync
-; ATTRIBUTOR: define void @bar_singlethread(i32* %0, %"struct.std::atomic"* %1)
+; ATTRIBUTOR: define void @bar_singlethread(i32* nocapture %0, %"struct.std::atomic"* nocapture %1)
define void @bar_singlethread(i32* %0, %"struct.std::atomic"* %1) {
%3 = getelementptr inbounds %"struct.std::atomic", %"struct.std::atomic"* %1, i64 0, i32 0, i32 0
br label %4
@@ -289,9 +289,11 @@ declare void @llvm.memset(i8* %dest, i8
; TEST 14 - negative, checking volatile intrinsics.
+; It is odd to add nocapture but a result of the llvm.memcpy nocapture.
+;
; ATTRIBUTOR: Function Attrs: nounwind
; ATTRIBUTOR-NOT: nosync
-; ATTRIBUTOR-NEXT: define i32 @memcpy_volatile(i8* %ptr1, i8* %ptr2)
+; ATTRIBUTOR-NEXT: define i32 @memcpy_volatile(i8* nocapture %ptr1, i8* nocapture %ptr2)
define i32 @memcpy_volatile(i8* %ptr1, i8* %ptr2) {
call void @llvm.memcpy(i8* %ptr1, i8* %ptr2, i32 8, i1 1)
ret i32 4
@@ -299,8 +301,10 @@ define i32 @memcpy_volatile(i8* %ptr1, i
; TEST 15 - positive, non-volatile intrinsic.
+; It is odd to add nocapture but a result of the llvm.memset nocapture.
+;
; ATTRIBUTOR: Function Attrs: nosync
-; ATTRIBUTOR-NEXT: define i32 @memset_non_volatile(i8* %ptr1, i8 %val)
+; ATTRIBUTOR-NEXT: define i32 @memset_non_volatile(i8* nocapture %ptr1, i8 %val)
define i32 @memset_non_volatile(i8* %ptr1, i8 %val) {
call void @llvm.memset(i8* %ptr1, i8 %val, i32 8, i1 0)
ret i32 4
Modified: llvm/trunk/test/Transforms/FunctionAttrs/read_write_returned_arguments_scc.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionAttrs/read_write_returned_arguments_scc.ll?rev=370817&r1=370816&r2=370817&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/FunctionAttrs/read_write_returned_arguments_scc.ll (original)
+++ llvm/trunk/test/Transforms/FunctionAttrs/read_write_returned_arguments_scc.ll Tue Sep 3 13:37:24 2019
@@ -1,4 +1,4 @@
-; RUN: opt -functionattrs -enable-nonnull-arg-prop -attributor -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=6 -S < %s | FileCheck %s
+; RUN: opt -functionattrs -enable-nonnull-arg-prop -attributor -attributor-manifest-internal -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=6 -S < %s | FileCheck %s
;
; This is an evolved example to stress test SCC parameter attribute propagation.
; The SCC in this test is made up of the following six function, three of which
@@ -102,7 +102,7 @@ return:
}
; CHECK: Function Attrs: nofree norecurse nosync nounwind
-; CHECK-NEXT: define i32* @external_sink_ret2_nrw(i32* readnone %n0, i32* nocapture readonly %r0, i32* returned %w0)
+; CHECK-NEXT: define i32* @external_sink_ret2_nrw(i32* readnone %n0, i32* nocapture readonly %r0, i32* returned "no-capture-maybe-returned" %w0)
define i32* @external_sink_ret2_nrw(i32* %n0, i32* %r0, i32* %w0) {
entry:
%tobool = icmp ne i32* %n0, null
More information about the llvm-commits
mailing list