[PATCH] D59922: [Attributor] Deduce "no-capture" argument attribute
This revision was automatically updated to reflect the committed changes. jdoerfert marked an inline comment as done. Closed by commit rL370817: [Attributor] Deduce no-capture argument attribute (authored by jdoerfert, committed by ). Changed prior to commit: https://reviews.llvm.org/D59922?vs=218109=218528#toc Repository: rL LLVM CHANGES SINCE LAST ACTION https://reviews.llvm.org/D59922/new/ https://reviews.llvm.org/D59922 Files: 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 Index: llvm/trunk/include/llvm/Transforms/IPO/Attributor.h === --- llvm/trunk/include/llvm/Transforms/IPO/Attributor.h +++ llvm/trunk/include/llvm/Transforms/IPO/Attributor.h @@ -270,6 +270,25 @@ } ///} + /// Return the associated argument, if any. + /// + ///{ + Argument *getAssociatedArgument() { +if (auto *Arg = dyn_cast(())) + 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(this)->getAssociatedArgument(); + } + ///} + /// Return the Function surrounding the anchor value. /// ///{ @@ -1549,6 +1568,56 @@ static const char ID; }; +/// An abstract interface for all nocapture attributes. +struct AANoCapture +: public IRAttribute> { + AANoCapture(const IRPosition ) : 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 (const IRPosition , Attributor ); + + /// Unique ID (due to the unique address) + static const char ID; +}; + } // end namespace llvm #endif // LLVM_TRANSFORMS_IPO_FUNCTIONATTRS_H Index: llvm/trunk/test/Transforms/FunctionAttrs/internal-noalias.ll === --- llvm/trunk/test/Transforms/FunctionAttrs/internal-noalias.ll +++ llvm/trunk/test/Transforms/FunctionAttrs/internal-noalias.ll @@ -10,7 +10,7 @@ ; 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 @@ ; FIXME: Should be something like this. ; define internal i32 @noalias_args_argmem(i32* noalias nocapture readonly %A, i32* noalias nocapture readonly %B) -; CHECK: define
[PATCH] D59922: [Attributor] Deduce "no-capture" argument attribute
jdoerfert marked 6 inline comments as done. jdoerfert added inline comments. Comment at: llvm/lib/Transforms/IPO/Attributor.cpp:2618 +else + Attrs.emplace_back(Attribute::get(Ctx, "no-capture-maybe-returned")); + } uenoku wrote: > Maybe we need an exact definition for `no-capture-maybe-returned` in LangRef. I add a flag to disable manifestation in non-testing modes. If we add users we can add it as a enum attribute, for now it is internal. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D59922/new/ https://reviews.llvm.org/D59922 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D59922: [Attributor] Deduce "no-capture" argument attribute
uenoku accepted this revision. uenoku added a comment. This revision is now accepted and ready to land. I think the logic is sound. It looks good to me. Comment at: llvm/lib/Transforms/IPO/Attributor.cpp:2618 +else + Attrs.emplace_back(Attribute::get(Ctx, "no-capture-maybe-returned")); + } Maybe we need an exact definition for `no-capture-maybe-returned` in LangRef. Comment at: llvm/lib/Transforms/IPO/Attributor.cpp:2674 + /// "no-capture-maybe-returned", the user is added to the \p PotentialCopies + /// set. All values in \p PotentialCopies are later tracked aswell. For every + /// explored use we decrement \p RemainingUsesToExplore. Once it reaches 0, aswell Comment at: llvm/lib/Transforms/IPO/Attributor.cpp:2761 + /// Register \p CS as potential copy of the value we are checking. + void addPotentialCopyIfNecessary(CallSite CS) { +PotentialCopies.push_back(CS.getInstruction()); Why `IfNecessary`? It seems there is no check. Comment at: llvm/lib/Transforms/IPO/Attributor.cpp:2819 + + AAAlign::StateType T; + // TODO: Once we have memory behavior attributes we should use them here Align? Comment at: llvm/lib/Transforms/IPO/Attributor.cpp:2864 +// TODO: Once we have call site specific value information we can provide +// call site specific liveness liveness information and then it makes +// sense to specialize attributes for call sites arguments instead of liveness liveness Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D59922/new/ https://reviews.llvm.org/D59922 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D59922: [Attributor] Deduce "no-capture" argument attribute
jdoerfert updated this revision to Diff 218109. jdoerfert added a comment. Update tests Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D59922/new/ https://reviews.llvm.org/D59922 Files: llvm/include/llvm/Transforms/IPO/Attributor.h llvm/lib/Transforms/IPO/Attributor.cpp llvm/test/Transforms/FunctionAttrs/align.ll llvm/test/Transforms/FunctionAttrs/arg_nocapture.ll llvm/test/Transforms/FunctionAttrs/arg_returned.ll llvm/test/Transforms/FunctionAttrs/dereferenceable.ll llvm/test/Transforms/FunctionAttrs/internal-noalias.ll llvm/test/Transforms/FunctionAttrs/liveness.ll llvm/test/Transforms/FunctionAttrs/noalias_returned.ll llvm/test/Transforms/FunctionAttrs/nocapture.ll llvm/test/Transforms/FunctionAttrs/nonnull.ll llvm/test/Transforms/FunctionAttrs/nosync.ll llvm/test/Transforms/FunctionAttrs/read_write_returned_arguments_scc.ll Index: llvm/test/Transforms/FunctionAttrs/read_write_returned_arguments_scc.ll === --- llvm/test/Transforms/FunctionAttrs/read_write_returned_arguments_scc.ll +++ llvm/test/Transforms/FunctionAttrs/read_write_returned_arguments_scc.ll @@ -102,7 +102,7 @@ } ; 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 Index: llvm/test/Transforms/FunctionAttrs/nosync.ll === --- llvm/test/Transforms/FunctionAttrs/nosync.ll +++ llvm/test/Transforms/FunctionAttrs/nosync.ll @@ -28,7 +28,7 @@ ; 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 @@ ; 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 @@ ; 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 @@ ; 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 @@ ; 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 @@ ; 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 @@ ; FNATTR: Function Attrs: nofree norecurse nounwind ; FNATTR-NEXT: define void @bar_singlethread(i32* nocapture
[PATCH] D59922: [Attributor] Deduce "no-capture" argument attribute
jdoerfert updated this revision to Diff 217306. jdoerfert added a comment. rebase and update tests Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D59922/new/ https://reviews.llvm.org/D59922 Files: llvm/include/llvm/Transforms/IPO/Attributor.h llvm/lib/Transforms/IPO/Attributor.cpp llvm/test/Transforms/FunctionAttrs/align.ll llvm/test/Transforms/FunctionAttrs/arg_nocapture.ll llvm/test/Transforms/FunctionAttrs/arg_returned.ll llvm/test/Transforms/FunctionAttrs/dereferenceable.ll llvm/test/Transforms/FunctionAttrs/liveness.ll llvm/test/Transforms/FunctionAttrs/noalias_returned.ll llvm/test/Transforms/FunctionAttrs/nocapture.ll llvm/test/Transforms/FunctionAttrs/nonnull.ll llvm/test/Transforms/FunctionAttrs/nosync.ll llvm/test/Transforms/FunctionAttrs/read_write_returned_arguments_scc.ll Index: llvm/test/Transforms/FunctionAttrs/read_write_returned_arguments_scc.ll === --- llvm/test/Transforms/FunctionAttrs/read_write_returned_arguments_scc.ll +++ llvm/test/Transforms/FunctionAttrs/read_write_returned_arguments_scc.ll @@ -102,7 +102,7 @@ } ; 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 Index: llvm/test/Transforms/FunctionAttrs/nosync.ll === --- llvm/test/Transforms/FunctionAttrs/nosync.ll +++ llvm/test/Transforms/FunctionAttrs/nosync.ll @@ -28,7 +28,7 @@ ; 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 @@ ; 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 @@ ; 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 @@ ; 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 @@ ; 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 @@ ; 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 @@ ; FNATTR: Function Attrs: nofree norecurse nounwind ; FNATTR-NEXT: define void @bar_singlethread(i32* nocapture readnone %0, %"struct.std::atomic"* nocapture
[PATCH] D59922: [Attributor] Deduce "no-capture" argument attribute
jdoerfert updated this revision to Diff 215716. jdoerfert added a comment. Add tests accidentally removed Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D59922/new/ https://reviews.llvm.org/D59922 Files: llvm/include/llvm/Transforms/IPO/Attributor.h llvm/lib/Transforms/IPO/Attributor.cpp llvm/test/Transforms/FunctionAttrs/align.ll llvm/test/Transforms/FunctionAttrs/arg_nocapture.ll llvm/test/Transforms/FunctionAttrs/arg_returned.ll llvm/test/Transforms/FunctionAttrs/dereferenceable.ll llvm/test/Transforms/FunctionAttrs/noalias_returned.ll llvm/test/Transforms/FunctionAttrs/nocapture.ll llvm/test/Transforms/FunctionAttrs/nonnull.ll llvm/test/Transforms/FunctionAttrs/nosync.ll llvm/test/Transforms/FunctionAttrs/read_write_returned_arguments_scc.ll Index: llvm/test/Transforms/FunctionAttrs/read_write_returned_arguments_scc.ll === --- llvm/test/Transforms/FunctionAttrs/read_write_returned_arguments_scc.ll +++ llvm/test/Transforms/FunctionAttrs/read_write_returned_arguments_scc.ll @@ -103,7 +103,7 @@ } ; 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 Index: llvm/test/Transforms/FunctionAttrs/nosync.ll === --- llvm/test/Transforms/FunctionAttrs/nosync.ll +++ llvm/test/Transforms/FunctionAttrs/nosync.ll @@ -28,7 +28,7 @@ ; 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 @@ ; 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 @@ ; 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 @@ ; 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 @@ ; 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 @@ ; 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 @@ ; FNATTR: Function Attrs: nofree norecurse nounwind ; FNATTR-NEXT: define void @bar_singlethread(i32* nocapture readnone %0, %"struct.std::atomic"* nocapture readonly %1) ; ATTRIBUTOR: Function
[PATCH] D59922: [Attributor] Deduce "no-capture" argument attribute
jdoerfert updated this revision to Diff 215713. jdoerfert added a comment. Add more test coverage and improve capture information based on dereferenceability Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D59922/new/ https://reviews.llvm.org/D59922 Files: llvm/include/llvm/Transforms/IPO/Attributor.h llvm/lib/Transforms/IPO/Attributor.cpp llvm/test/Transforms/FunctionAttrs/align.ll llvm/test/Transforms/FunctionAttrs/arg_nocapture.ll llvm/test/Transforms/FunctionAttrs/arg_returned.ll llvm/test/Transforms/FunctionAttrs/dereferenceable.ll llvm/test/Transforms/FunctionAttrs/noalias_returned.ll llvm/test/Transforms/FunctionAttrs/nocapture.ll llvm/test/Transforms/FunctionAttrs/nonnull.ll llvm/test/Transforms/FunctionAttrs/nosync.ll llvm/test/Transforms/FunctionAttrs/read_write_returned_arguments_scc.ll Index: llvm/test/Transforms/FunctionAttrs/read_write_returned_arguments_scc.ll === --- llvm/test/Transforms/FunctionAttrs/read_write_returned_arguments_scc.ll +++ llvm/test/Transforms/FunctionAttrs/read_write_returned_arguments_scc.ll @@ -103,7 +103,7 @@ } ; 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 Index: llvm/test/Transforms/FunctionAttrs/nosync.ll === --- llvm/test/Transforms/FunctionAttrs/nosync.ll +++ llvm/test/Transforms/FunctionAttrs/nosync.ll @@ -28,7 +28,7 @@ ; 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 @@ ; 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 @@ ; 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 @@ ; 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 @@ ; 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 @@ ; 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 @@ ; FNATTR: Function Attrs: nofree norecurse nounwind ; FNATTR-NEXT: define void @bar_singlethread(i32* nocapture readnone %0, %"struct.std::atomic"*
[PATCH] D59922: [Attributor] Deduce "no-capture" argument attribute
jdoerfert updated this revision to Diff 215504. jdoerfert added a comment. Extracted CaptureTracking changes Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D59922/new/ https://reviews.llvm.org/D59922 Files: llvm/include/llvm/Transforms/IPO/Attributor.h llvm/lib/Transforms/IPO/Attributor.cpp llvm/test/Transforms/FunctionAttrs/align.ll llvm/test/Transforms/FunctionAttrs/arg_nocapture.ll llvm/test/Transforms/FunctionAttrs/arg_returned.ll llvm/test/Transforms/FunctionAttrs/dereferenceable.ll llvm/test/Transforms/FunctionAttrs/noalias_returned.ll llvm/test/Transforms/FunctionAttrs/nonnull.ll llvm/test/Transforms/FunctionAttrs/nosync.ll llvm/test/Transforms/FunctionAttrs/read_write_returned_arguments_scc.ll Index: llvm/test/Transforms/FunctionAttrs/read_write_returned_arguments_scc.ll === --- llvm/test/Transforms/FunctionAttrs/read_write_returned_arguments_scc.ll +++ llvm/test/Transforms/FunctionAttrs/read_write_returned_arguments_scc.ll @@ -103,7 +103,7 @@ } ; 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 Index: llvm/test/Transforms/FunctionAttrs/nosync.ll === --- llvm/test/Transforms/FunctionAttrs/nosync.ll +++ llvm/test/Transforms/FunctionAttrs/nosync.ll @@ -28,7 +28,7 @@ ; 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 @@ ; 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 @@ ; 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 @@ ; 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 @@ ; 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 @@ ; 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 @@ ; 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
[PATCH] D59922: [Attributor] Deduce "no-capture" argument attribute
jdoerfert updated this revision to Diff 215498. jdoerfert added a comment. Rebase Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D59922/new/ https://reviews.llvm.org/D59922 Files: llvm/include/llvm/Transforms/IPO/Attributor.h llvm/lib/Analysis/CaptureTracking.cpp llvm/lib/Transforms/IPO/Attributor.cpp llvm/test/Transforms/FunctionAttrs/align.ll llvm/test/Transforms/FunctionAttrs/arg_nocapture.ll llvm/test/Transforms/FunctionAttrs/arg_returned.ll llvm/test/Transforms/FunctionAttrs/dereferenceable.ll llvm/test/Transforms/FunctionAttrs/noalias_returned.ll llvm/test/Transforms/FunctionAttrs/nonnull.ll llvm/test/Transforms/FunctionAttrs/nosync.ll llvm/test/Transforms/FunctionAttrs/read_write_returned_arguments_scc.ll Index: llvm/test/Transforms/FunctionAttrs/read_write_returned_arguments_scc.ll === --- llvm/test/Transforms/FunctionAttrs/read_write_returned_arguments_scc.ll +++ llvm/test/Transforms/FunctionAttrs/read_write_returned_arguments_scc.ll @@ -103,7 +103,7 @@ } ; 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 Index: llvm/test/Transforms/FunctionAttrs/nosync.ll === --- llvm/test/Transforms/FunctionAttrs/nosync.ll +++ llvm/test/Transforms/FunctionAttrs/nosync.ll @@ -28,7 +28,7 @@ ; 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 @@ ; 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 @@ ; 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 @@ ; 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 @@ ; 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 @@ ; 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 @@ ; 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:
[PATCH] D59922: [Attributor] Deduce "no-capture" argument attribute
jdoerfert updated this revision to Diff 208811. jdoerfert added a comment. Herald added a subscriber: jfb. Rebase Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D59922/new/ https://reviews.llvm.org/D59922 Files: llvm/include/llvm/Transforms/IPO/Attributor.h llvm/lib/Transforms/IPO/Attributor.cpp llvm/test/Transforms/FunctionAttrs/2009-01-02-LocalStores.ll llvm/test/Transforms/FunctionAttrs/arg_nocapture.ll llvm/test/Transforms/FunctionAttrs/arg_returned.ll llvm/test/Transforms/FunctionAttrs/convergent.ll llvm/test/Transforms/FunctionAttrs/incompatible_fn_attrs.ll llvm/test/Transforms/FunctionAttrs/nocapture.ll llvm/test/Transforms/FunctionAttrs/nonnull.ll llvm/test/Transforms/FunctionAttrs/out-of-bounds-iterator-bug.ll llvm/test/Transforms/FunctionAttrs/read_write_returned_arguments_scc.ll llvm/test/Transforms/FunctionAttrs/readattrs.ll llvm/test/Transforms/FunctionAttrs/readnone.ll Index: llvm/test/Transforms/FunctionAttrs/readnone.ll === --- llvm/test/Transforms/FunctionAttrs/readnone.ll +++ llvm/test/Transforms/FunctionAttrs/readnone.ll @@ -1,13 +1,17 @@ -; RUN: opt < %s -functionattrs -S | FileCheck %s -; RUN: opt < %s -passes=function-attrs -S | FileCheck %s +; RUN: opt < %s -attributor-disable=false -attributor -functionattrs -S | FileCheck %s +; RUN: opt < %s -attributor-disable=false -passes="attributor,cgscc(function-attrs)" -S | FileCheck %s -; CHECK: define void @bar(i8* nocapture readnone) +; FIXME: Because nocapture and readnone deduction in the functionattrs pass are interleaved, it doesn't +;trigger when nocapture is already present. Once the Attributor derives memory behavior, +;this should be fixed. +; FIXME: readnone missing for %0 two times +; CHECK: define void @bar(i8* nocapture readonly) define void @bar(i8* readonly) { call void @foo(i8* %0) ret void } -; CHECK: define void @foo(i8* nocapture readnone) +; CHECK: define void @foo(i8* nocapture readonly) define void @foo(i8* readonly) { call void @bar(i8* %0) ret void Index: llvm/test/Transforms/FunctionAttrs/readattrs.ll === --- llvm/test/Transforms/FunctionAttrs/readattrs.ll +++ llvm/test/Transforms/FunctionAttrs/readattrs.ll @@ -1,5 +1,5 @@ -; RUN: opt < %s -functionattrs -S | FileCheck %s -; RUN: opt < %s -aa-pipeline=basic-aa -passes='cgscc(function-attrs)' -S | FileCheck %s +; RUN: opt < %s -attributor -attributor-disable=false -functionattrs -S | FileCheck %s +; RUN: opt < %s -attributor-disable=false -aa-pipeline=basic-aa -passes='attributor,cgscc(function-attrs)' -S | FileCheck %s @x = global i32 0 declare void @test1_1(i8* %x1_1, i8* readonly %y1_1, ...) @@ -13,7 +13,7 @@ ret void } -; CHECK: define i8* @test2(i8* readnone returned %p) +; CHECK: define i8* @test2(i8* readnone returned "no-capture-maybe-returned" %p) define i8* @test2(i8* %p) { store i32 0, i32* @x ret i8* %p @@ -55,13 +55,13 @@ ret void } -; CHECK: define i32* @test8_1(i32* readnone returned %p) +; CHECK: define i32* @test8_1(i32* readnone returned "no-capture-maybe-returned" %p) define i32* @test8_1(i32* %p) { entry: ret i32* %p } -; CHECK: define void @test8_2(i32* %p) +; CHECK: define void @test8_2(i32* nocapture %p) define void @test8_2(i32* %p) { entry: %call = call i32* @test8_1(i32* %p) Index: llvm/test/Transforms/FunctionAttrs/read_write_returned_arguments_scc.ll === --- llvm/test/Transforms/FunctionAttrs/read_write_returned_arguments_scc.ll +++ llvm/test/Transforms/FunctionAttrs/read_write_returned_arguments_scc.ll @@ -1,5 +1,5 @@ -; RUN: opt -functionattrs -enable-nonnull-arg-prop -attributor -attributor-disable=false -S < %s | FileCheck %s -; RUN: opt -functionattrs -enable-nonnull-arg-prop -attributor -attributor-disable=false -attributor-verify=true -S < %s | FileCheck %s +; RUN: opt -attributor -functionattrs -enable-nonnull-arg-prop -attributor-disable=false -S < %s | FileCheck %s +; RUN: opt -attributor -functionattrs -enable-nonnull-arg-prop -attributor-disable=false -attributor-verify=true -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 @@ -18,20 +18,23 @@ ; as well as how the parameters are (transitively) used (n = readnone, ; r = readonly, w = writeonly). ; -; What we should see is something along the lines of: -; 1 - Number of functions marked as norecurse -; 6 - Number of functions marked argmemonly -; 6 - Number of functions marked as nounwind -; 16 - Number of arguments marked nocapture -; 4 - Number of arguments marked readnone -; 6 - Number of arguments marked writeonly -; 6 - Number of arguments marked readonly -; 6 - Number of arguments
[PATCH] D59922: [Attributor] Deduce "no-capture" argument attribute
jdoerfert added a comment. @hfinkel ping Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D59922/new/ https://reviews.llvm.org/D59922 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D59922: [Attributor] Deduce "no-capture" argument attribute
jdoerfert updated this revision to Diff 193122. jdoerfert added a comment. Rebase Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D59922/new/ https://reviews.llvm.org/D59922 Files: clang/test/CodeGenObjC/os_log.m clang/test/CodeGenOpenCL/as_type.cl llvm/include/llvm/Transforms/IPO/Attributor.h llvm/lib/Transforms/IPO/Attributor.cpp llvm/test/Transforms/FunctionAttrs/2009-01-02-LocalStores.ll llvm/test/Transforms/FunctionAttrs/SCC1.ll llvm/test/Transforms/FunctionAttrs/arg_nocapture.ll llvm/test/Transforms/FunctionAttrs/arg_returned.ll llvm/test/Transforms/FunctionAttrs/incompatible_fn_attrs.ll llvm/test/Transforms/FunctionAttrs/nocapture.ll llvm/test/Transforms/FunctionAttrs/readattrs.ll Index: llvm/test/Transforms/FunctionAttrs/readattrs.ll === --- llvm/test/Transforms/FunctionAttrs/readattrs.ll +++ llvm/test/Transforms/FunctionAttrs/readattrs.ll @@ -13,7 +13,7 @@ ret void } -; CHECK: define i8* @test2(i8* readnone returned %p) +; CHECK: define i8* @test2(i8* readnone returned "no-capture-maybe-returned" %p) define i8* @test2(i8* %p) { store i32 0, i32* @x ret i8* %p @@ -55,13 +55,13 @@ ret void } -; CHECK: define i32* @test8_1(i32* readnone returned %p) +; CHECK: define i32* @test8_1(i32* readnone returned "no-capture-maybe-returned" %p) define i32* @test8_1(i32* %p) { entry: ret i32* %p } -; CHECK: define void @test8_2(i32* %p) +; CHECK: define void @test8_2(i32* nocapture %p) define void @test8_2(i32* %p) { entry: %call = call i32* @test8_1(i32* %p) Index: llvm/test/Transforms/FunctionAttrs/nocapture.ll === --- llvm/test/Transforms/FunctionAttrs/nocapture.ll +++ llvm/test/Transforms/FunctionAttrs/nocapture.ll @@ -1,9 +1,9 @@ ; RUN: opt < %s -attributor -functionattrs -S | FileCheck %s -; RUN: opt < %s -passes='attributor,cgscc(function-attrs)' -S | FileCheck %s +; RUN: opt < %s -passes='cgscc(attributor,function-attrs)' -S | FileCheck %s @g = global i32* null ; [#uses=1] -; CHECK: define i32* @c1(i32* readnone returned %q) +; CHECK: define i32* @c1(i32* readnone returned "no-capture-maybe-returned" %q) define i32* @c1(i32* %q) { ret i32* %q } @@ -134,7 +134,7 @@ ret void } -; CHECK: define void @test1_1(i8* nocapture readnone %x1_1, i8* %y1_1) +; CHECK: define void @test1_1(i8* nocapture %x1_1, i8* nocapture %y1_1) ; 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) @@ -142,7 +142,7 @@ ret void } -; CHECK: define i8* @test1_2(i8* nocapture readnone %x1_2, i8* returned %y1_2) +; CHECK: define i8* @test1_2(i8* nocapture %x1_2, i8* returned "no-capture-maybe-returned" %y1_2) define i8* @test1_2(i8* %x1_2, i8* %y1_2) { call void @test1_1(i8* %x1_2, i8* %y1_2) store i32* null, i32** @g @@ -156,21 +156,21 @@ ret void } -; CHECK: define void @test3(i8* nocapture readnone %x3, i8* nocapture readnone %y3, i8* nocapture readnone %z3) +; CHECK: define void @test3(i8* nocapture %x3, i8* nocapture readnone %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) +; CHECK: define void @test4_1(i8* nocapture readnone %x4_1) define void @test4_1(i8* %x4_1) { call i8* @test4_2(i8* %x4_1, i8* %x4_1, i8* %x4_1) 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) +; CHECK: define i8* @test4_2(i8* nocapture readnone %x4_2, i8* readnone returned "no-capture-maybe-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) store i32* null, i32** @g Index: llvm/test/Transforms/FunctionAttrs/incompatible_fn_attrs.ll === --- llvm/test/Transforms/FunctionAttrs/incompatible_fn_attrs.ll +++ llvm/test/Transforms/FunctionAttrs/incompatible_fn_attrs.ll @@ -6,21 +6,21 @@ ; Function Attrs: argmemonly define i32* @given_argmem_infer_readnone(i32* %p) #0 { -; CHECK: define i32* @given_argmem_infer_readnone(i32* readnone returned %p) #0 { +; CHECK: define i32* @given_argmem_infer_readnone(i32* readnone returned "no-capture-maybe-returned" %p) #0 { entry: ret i32* %p } ; Function Attrs: inaccessiblememonly define i32* @given_inaccessible_infer_readnone(i32* %p) #1 { -; CHECK: define i32* @given_inaccessible_infer_readnone(i32* readnone returned %p) #0 { +; CHECK: define i32* @given_inaccessible_infer_readnone(i32* readnone returned "no-capture-maybe-returned" %p) #0 { entry: ret i32* %p } ; Function Attrs: inaccessiblemem_or_argmemonly define i32*
[PATCH] D59922: [Attributor] Deduce "no-capture" argument attribute
jdoerfert updated this revision to Diff 192962. jdoerfert added a comment. Closed a side-channel through "integers" Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D59922/new/ https://reviews.llvm.org/D59922 Files: clang/test/CodeGenObjC/os_log.m clang/test/CodeGenOpenCL/as_type.cl llvm/include/llvm/Transforms/IPO/Attributor.h llvm/lib/Transforms/IPO/Attributor.cpp llvm/test/Transforms/FunctionAttrs/2009-01-02-LocalStores.ll llvm/test/Transforms/FunctionAttrs/SCC1.ll llvm/test/Transforms/FunctionAttrs/arg_nocapture.ll llvm/test/Transforms/FunctionAttrs/arg_returned.ll llvm/test/Transforms/FunctionAttrs/incompatible_fn_attrs.ll llvm/test/Transforms/FunctionAttrs/nocapture.ll llvm/test/Transforms/FunctionAttrs/readattrs.ll Index: llvm/test/Transforms/FunctionAttrs/readattrs.ll === --- llvm/test/Transforms/FunctionAttrs/readattrs.ll +++ llvm/test/Transforms/FunctionAttrs/readattrs.ll @@ -12,7 +12,7 @@ ret void } -; CHECK: define i8* @test2(i8* readnone returned %p) +; CHECK: define i8* @test2(i8* readnone returned "no-capture-maybe-returned" %p) define i8* @test2(i8* %p) { store i32 0, i32* @x ret i8* %p @@ -54,13 +54,13 @@ ret void } -; CHECK: define i32* @test8_1(i32* readnone returned %p) +; CHECK: define i32* @test8_1(i32* readnone returned "no-capture-maybe-returned" %p) define i32* @test8_1(i32* %p) { entry: ret i32* %p } -; CHECK: define void @test8_2(i32* %p) +; CHECK: define void @test8_2(i32* nocapture %p) define void @test8_2(i32* %p) { entry: %call = call i32* @test8_1(i32* %p) Index: llvm/test/Transforms/FunctionAttrs/nocapture.ll === --- llvm/test/Transforms/FunctionAttrs/nocapture.ll +++ llvm/test/Transforms/FunctionAttrs/nocapture.ll @@ -3,7 +3,7 @@ @g = global i32* null ; [#uses=1] -; CHECK: define i32* @c1(i32* readnone returned %q) +; CHECK: define i32* @c1(i32* readnone returned "no-capture-maybe-returned" %q) define i32* @c1(i32* %q) { ret i32* %q } @@ -134,7 +134,7 @@ ret void } -; CHECK: define void @test1_1(i8* nocapture readnone %x1_1, i8* %y1_1) +; CHECK: define void @test1_1(i8* nocapture %x1_1, i8* nocapture %y1_1) ; 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) @@ -142,7 +142,7 @@ ret void } -; CHECK: define i8* @test1_2(i8* nocapture readnone %x1_2, i8* returned %y1_2) +; CHECK: define i8* @test1_2(i8* nocapture %x1_2, i8* returned "no-capture-maybe-returned" %y1_2) define i8* @test1_2(i8* %x1_2, i8* %y1_2) { call void @test1_1(i8* %x1_2, i8* %y1_2) store i32* null, i32** @g @@ -156,21 +156,21 @@ ret void } -; CHECK: define void @test3(i8* nocapture readnone %x3, i8* nocapture readnone %y3, i8* nocapture readnone %z3) +; CHECK: define void @test3(i8* nocapture %x3, i8* nocapture readnone %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) +; CHECK: define void @test4_1(i8* nocapture readnone %x4_1) define void @test4_1(i8* %x4_1) { call i8* @test4_2(i8* %x4_1, i8* %x4_1, i8* %x4_1) 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) +; CHECK: define i8* @test4_2(i8* nocapture readnone %x4_2, i8* readnone returned "no-capture-maybe-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) store i32* null, i32** @g Index: llvm/test/Transforms/FunctionAttrs/incompatible_fn_attrs.ll === --- llvm/test/Transforms/FunctionAttrs/incompatible_fn_attrs.ll +++ llvm/test/Transforms/FunctionAttrs/incompatible_fn_attrs.ll @@ -6,21 +6,21 @@ ; Function Attrs: argmemonly define i32* @given_argmem_infer_readnone(i32* %p) #0 { -; CHECK: define i32* @given_argmem_infer_readnone(i32* readnone returned %p) #0 { +; CHECK: define i32* @given_argmem_infer_readnone(i32* readnone returned "no-capture-maybe-returned" %p) #0 { entry: ret i32* %p } ; Function Attrs: inaccessiblememonly define i32* @given_inaccessible_infer_readnone(i32* %p) #1 { -; CHECK: define i32* @given_inaccessible_infer_readnone(i32* readnone returned %p) #0 { +; CHECK: define i32* @given_inaccessible_infer_readnone(i32* readnone returned "no-capture-maybe-returned" %p) #0 { entry: ret i32* %p } ; Function Attrs: inaccessiblemem_or_argmemonly define i32* @given_inaccessible_or_argmem_infer_readnone(i32* %p) #2 { -; CHECK: define i32* @given_inaccessible_or_argmem_infer_readnone(i32* readnone returned %p) #0 { +; CHECK: define i32*
[PATCH] D59922: [Attributor] Deduce "no-capture" argument attribute
jdoerfert marked 2 inline comments as done. jdoerfert added inline comments. Comment at: llvm/test/Transforms/FunctionAttrs/arg_nocapture.ll:103 -; FIXME: returned missing for %a ; FIXME: We should *not* derive any attributes for the return value not present on the argument! ; CHECK: define dso_local noalias nonnull i32* @srec16(i32* nocapture readnone %a) The comments on this one were off from the very beginning, I'll fix them and there won't be a change during this commit. Comment at: llvm/test/Transforms/FunctionAttrs/nocapture.ll:137 -; CHECK: define void @test1_1(i8* nocapture readnone %x1_1, i8* %y1_1) ; It would be acceptable to add readnone to %y1_1 and %y1_2. So, the old FuncAttr deduction interleaves one of two memory behavior deductions with the capture analysis. With this patch capture analysis becomes obsolete, as the attributor added annotations, and certain memory behavior attributes are not detected anymore. There will be a memory behavior detection for the attributor soon which should make this problem go away. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D59922/new/ https://reviews.llvm.org/D59922 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D59922: [Attributor] Deduce "no-capture" argument attribute
jdoerfert created this revision. jdoerfert added reviewers: homerdin, hfinkel, fedor.sergeev, sanjoy, spatel, nlopes, nicholas, reames. Herald added subscribers: cfe-commits, bollu, hiraditya. Herald added projects: clang, LLVM. 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. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D59922 Files: clang/test/CodeGenObjC/os_log.m clang/test/CodeGenOpenCL/as_type.cl llvm/include/llvm/Transforms/IPO/Attributor.h llvm/lib/Transforms/IPO/Attributor.cpp llvm/test/Transforms/FunctionAttrs/2009-01-02-LocalStores.ll llvm/test/Transforms/FunctionAttrs/SCC1.ll llvm/test/Transforms/FunctionAttrs/arg_nocapture.ll llvm/test/Transforms/FunctionAttrs/arg_returned.ll llvm/test/Transforms/FunctionAttrs/incompatible_fn_attrs.ll llvm/test/Transforms/FunctionAttrs/nocapture.ll llvm/test/Transforms/FunctionAttrs/readattrs.ll Index: llvm/test/Transforms/FunctionAttrs/readattrs.ll === --- llvm/test/Transforms/FunctionAttrs/readattrs.ll +++ llvm/test/Transforms/FunctionAttrs/readattrs.ll @@ -12,7 +12,7 @@ ret void } -; CHECK: define i8* @test2(i8* readnone returned %p) +; CHECK: define i8* @test2(i8* readnone returned "no-capture-maybe-returned" %p) define i8* @test2(i8* %p) { store i32 0, i32* @x ret i8* %p @@ -54,13 +54,13 @@ ret void } -; CHECK: define i32* @test8_1(i32* readnone returned %p) +; CHECK: define i32* @test8_1(i32* readnone returned "no-capture-maybe-returned" %p) define i32* @test8_1(i32* %p) { entry: ret i32* %p } -; CHECK: define void @test8_2(i32* %p) +; CHECK: define void @test8_2(i32* nocapture %p) define void @test8_2(i32* %p) { entry: %call = call i32* @test8_1(i32* %p) Index: llvm/test/Transforms/FunctionAttrs/nocapture.ll === --- llvm/test/Transforms/FunctionAttrs/nocapture.ll +++ llvm/test/Transforms/FunctionAttrs/nocapture.ll @@ -3,7 +3,7 @@ @g = global i32* null ; [#uses=1] -; CHECK: define i32* @c1(i32* readnone returned %q) +; CHECK: define i32* @c1(i32* readnone returned "no-capture-maybe-returned" %q) define i32* @c1(i32* %q) { ret i32* %q } @@ -134,7 +134,7 @@ ret void } -; CHECK: define void @test1_1(i8* nocapture readnone %x1_1, i8* %y1_1) +; CHECK: define void @test1_1(i8* nocapture %x1_1, i8* nocapture %y1_1) ; 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) @@ -142,7 +142,7 @@ ret void } -; CHECK: define i8* @test1_2(i8* nocapture readnone %x1_2, i8* returned %y1_2) +; CHECK: define i8* @test1_2(i8* nocapture %x1_2, i8* returned "no-capture-maybe-returned" %y1_2) define i8* @test1_2(i8* %x1_2, i8* %y1_2) { call void @test1_1(i8* %x1_2, i8* %y1_2) store i32* null, i32** @g @@ -156,21 +156,21 @@ ret void } -; CHECK: define void @test3(i8* nocapture readnone %x3, i8* nocapture readnone %y3, i8* nocapture readnone %z3) +; CHECK: define void @test3(i8* nocapture %x3, i8* nocapture readnone %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) +; CHECK: define void @test4_1(i8* nocapture readnone %x4_1) define void @test4_1(i8* %x4_1) { call i8* @test4_2(i8* %x4_1, i8* %x4_1, i8* %x4_1) 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) +; CHECK: define i8* @test4_2(i8* nocapture readnone %x4_2, i8* readnone returned "no-capture-maybe-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) store i32* null, i32** @g Index: llvm/test/Transforms/FunctionAttrs/incompatible_fn_attrs.ll === --- llvm/test/Transforms/FunctionAttrs/incompatible_fn_attrs.ll +++ llvm/test/Transforms/FunctionAttrs/incompatible_fn_attrs.ll @@ -6,21 +6,21 @@ ; Function Attrs: argmemonly define i32* @given_argmem_infer_readnone(i32* %p) #0 { -; CHECK: define i32* @given_argmem_infer_readnone(i32* readnone returned %p) #0 { +; CHECK: define i32* @given_argmem_infer_readnone(i32* readnone returned "no-capture-maybe-returned" %p) #0 { entry: ret i32* %p } ; Function Attrs: inaccessiblememonly define i32* @given_inaccessible_infer_readnone(i32* %p) #1 { -; CHECK: define i32* @given_inaccessible_infer_readnone(i32* readnone returned %p) #0 { +; CHECK: define i32* @given_inaccessible_infer_readnone(i32* readnone returned