[llvm] 9655203 - [Attributor] Copy or port test cases related to Attributor to` Attributor` test folder

Hideto Ueno via llvm-commits llvm-commits at lists.llvm.org
Mon Dec 2 07:37:33 PST 2019


Author: Hideto Ueno
Date: 2019-12-02T15:36:29Z
New Revision: 96552036e307f7b0dd6477583c3fdb7de17e8aac

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

LOG: [Attributor] Copy or port test cases related to Attributor to` Attributor` test folder

Summary:
This patch moves the test cases related to Attributor to `Transforms/Attributor` folder.
We have used `Transforms/FunctionAttrs` as the primary folder for Attributor test but we need to change testing way now.

For the test cases which I think functionattrs doesn't infer anything something like (willreturn, nosync, value-simplify, h2s ..etc), I moved them with the command `git mv`.

For the test cases in which functoinattrs and attributor are tested, I copied the test to the folder and remove the check only used by functoinattrs.

Reviewers: jdoerfert, sstefan1

Reviewed By: jdoerfert

Subscribers: jfb, llvm-commits

Tags: #llvm

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

Added: 
    llvm/test/Transforms/Attributor/align.ll
    llvm/test/Transforms/Attributor/callbacks.ll
    llvm/test/Transforms/Attributor/dereferenceable-1.ll
    llvm/test/Transforms/Attributor/dereferenceable-2.ll
    llvm/test/Transforms/Attributor/heap_to_stack.ll
    llvm/test/Transforms/Attributor/internal-noalias.ll
    llvm/test/Transforms/Attributor/liveness.ll
    llvm/test/Transforms/Attributor/misc.ll
    llvm/test/Transforms/Attributor/new_attributes.ll
    llvm/test/Transforms/Attributor/noalias.ll
    llvm/test/Transforms/Attributor/nocapture-1.ll
    llvm/test/Transforms/Attributor/nocapture-2.ll
    llvm/test/Transforms/Attributor/nofree.ll
    llvm/test/Transforms/Attributor/nonnull.ll
    llvm/test/Transforms/Attributor/norecurse.ll
    llvm/test/Transforms/Attributor/noreturn.ll
    llvm/test/Transforms/Attributor/noreturn_async.ll
    llvm/test/Transforms/Attributor/noreturn_sync.ll
    llvm/test/Transforms/Attributor/nosync.ll
    llvm/test/Transforms/Attributor/nounwind.ll
    llvm/test/Transforms/Attributor/read_write_returned_arguments_scc.ll
    llvm/test/Transforms/Attributor/readattrs.ll
    llvm/test/Transforms/Attributor/returned.ll
    llvm/test/Transforms/Attributor/value-simplify.ll
    llvm/test/Transforms/Attributor/willreturn.ll

Modified: 
    llvm/test/Transforms/FunctionAttrs/arg_returned.ll
    llvm/test/Transforms/FunctionAttrs/nocapture.ll
    llvm/test/Transforms/FunctionAttrs/nofree-attributor.ll
    llvm/test/Transforms/FunctionAttrs/nonnull.ll
    llvm/test/Transforms/FunctionAttrs/norecurse.ll
    llvm/test/Transforms/FunctionAttrs/nounwind.ll
    llvm/test/Transforms/FunctionAttrs/readattrs.ll
    llvm/test/Transforms/InferFunctionAttrs/dereferenceable.ll

Removed: 
    llvm/test/Transforms/FunctionAttrs/align.ll
    llvm/test/Transforms/FunctionAttrs/arg_nocapture.ll
    llvm/test/Transforms/FunctionAttrs/callbacks.ll
    llvm/test/Transforms/FunctionAttrs/dereferenceable.ll
    llvm/test/Transforms/FunctionAttrs/fn_noreturn.ll
    llvm/test/Transforms/FunctionAttrs/heap_to_stack.ll
    llvm/test/Transforms/FunctionAttrs/internal-noalias.ll
    llvm/test/Transforms/FunctionAttrs/liveness.ll
    llvm/test/Transforms/FunctionAttrs/misc.ll
    llvm/test/Transforms/FunctionAttrs/new_attributes.ll
    llvm/test/Transforms/FunctionAttrs/noalias_returned.ll
    llvm/test/Transforms/FunctionAttrs/noreturn_async.ll
    llvm/test/Transforms/FunctionAttrs/noreturn_sync.ll
    llvm/test/Transforms/FunctionAttrs/nosync.ll
    llvm/test/Transforms/FunctionAttrs/read_write_returned_arguments_scc.ll
    llvm/test/Transforms/FunctionAttrs/value-simplify.ll
    llvm/test/Transforms/FunctionAttrs/willreturn.ll


################################################################################
diff  --git a/llvm/test/Transforms/FunctionAttrs/align.ll b/llvm/test/Transforms/Attributor/align.ll
similarity index 100%
rename from llvm/test/Transforms/FunctionAttrs/align.ll
rename to llvm/test/Transforms/Attributor/align.ll

diff  --git a/llvm/test/Transforms/FunctionAttrs/callbacks.ll b/llvm/test/Transforms/Attributor/callbacks.ll
similarity index 100%
rename from llvm/test/Transforms/FunctionAttrs/callbacks.ll
rename to llvm/test/Transforms/Attributor/callbacks.ll

diff  --git a/llvm/test/Transforms/FunctionAttrs/dereferenceable.ll b/llvm/test/Transforms/Attributor/dereferenceable-1.ll
similarity index 100%
rename from llvm/test/Transforms/FunctionAttrs/dereferenceable.ll
rename to llvm/test/Transforms/Attributor/dereferenceable-1.ll

diff  --git a/llvm/test/Transforms/Attributor/dereferenceable-2.ll b/llvm/test/Transforms/Attributor/dereferenceable-2.ll
new file mode 100644
index 000000000000..b3c0440f930f
--- /dev/null
+++ b/llvm/test/Transforms/Attributor/dereferenceable-2.ll
@@ -0,0 +1,356 @@
+; RUN: opt < %s -attributor --attributor-disable=false -S | FileCheck %s --check-prefix=ATTRIBUTOR
+; Copied from Transforms/InferFunctionAttrs/dereferenceable.ll
+
+; Determine dereference-ability before unused loads get deleted:
+; https://bugs.llvm.org/show_bug.cgi?id=21780
+
+define <4 x double> @PR21780(double* %ptr) {
+; ATTRIBUTOR-LABEL: @PR21780(double* nocapture nofree nonnull readonly align 8 dereferenceable(32) %ptr)
+
+  ; GEP of index 0 is simplified away.
+  %arrayidx1 = getelementptr inbounds double, double* %ptr, i64 1
+  %arrayidx2 = getelementptr inbounds double, double* %ptr, i64 2
+  %arrayidx3 = getelementptr inbounds double, double* %ptr, i64 3
+
+  %t0 = load double, double* %ptr, align 8
+  %t1 = load double, double* %arrayidx1, align 8
+  %t2 = load double, double* %arrayidx2, align 8
+  %t3 = load double, double* %arrayidx3, align 8
+
+  %vecinit0 = insertelement <4 x double> undef, double %t0, i32 0
+  %vecinit1 = insertelement <4 x double> %vecinit0, double %t1, i32 1
+  %vecinit2 = insertelement <4 x double> %vecinit1, double %t2, i32 2
+  %vecinit3 = insertelement <4 x double> %vecinit2, double %t3, i32 3
+  %shuffle = shufflevector <4 x double> %vecinit3, <4 x double> %vecinit3, <4 x i32> <i32 0, i32 0, i32 2, i32 2>
+  ret <4 x double> %shuffle
+}
+
+
+define double @PR21780_only_access3_with_inbounds(double* %ptr) {
+; ATTRIBUTOR-LABEL: @PR21780_only_access3_with_inbounds(double* nocapture nofree nonnull readonly align 8 dereferenceable(32) %ptr)
+
+  %arrayidx3 = getelementptr inbounds double, double* %ptr, i64 3
+  %t3 = load double, double* %arrayidx3, align 8
+  ret double %t3
+}
+
+define double @PR21780_only_access3_without_inbounds(double* %ptr) {
+; ATTRIBUTOR-LABEL: @PR21780_only_access3_without_inbounds(double* nocapture nofree readonly align 8 %ptr)
+  %arrayidx3 = getelementptr double, double* %ptr, i64 3
+  %t3 = load double, double* %arrayidx3, align 8
+  ret double %t3
+}
+
+define double @PR21780_without_inbounds(double* %ptr) {
+; ATTRIBUTOR-LABEL: @PR21780_without_inbounds(double* nocapture nofree nonnull readonly align 8 dereferenceable(32) %ptr)
+
+  %arrayidx1 = getelementptr double, double* %ptr, i64 1
+  %arrayidx2 = getelementptr double, double* %ptr, i64 2
+  %arrayidx3 = getelementptr double, double* %ptr, i64 3
+
+  %t0 = load double, double* %ptr, align 8
+  %t1 = load double, double* %arrayidx1, align 8
+  %t2 = load double, double* %arrayidx2, align 8
+  %t3 = load double, double* %arrayidx3, align 8
+
+  ret double %t3
+}
+
+; Unsimplified, but still valid. Also, throw in some bogus arguments.
+
+define void @gep0(i8* %unused, i8* %other, i8* %ptr) {
+; ATTRIBUTOR-LABEL: @gep0(i8* nocapture nofree readnone %unused, i8* nocapture nofree nonnull writeonly dereferenceable(1) %other, i8* nocapture nofree nonnull readonly dereferenceable(3) %ptr)
+  %arrayidx0 = getelementptr i8, i8* %ptr, i64 0
+  %arrayidx1 = getelementptr i8, i8* %ptr, i64 1
+  %arrayidx2 = getelementptr i8, i8* %ptr, i64 2
+  %t0 = load i8, i8* %arrayidx0
+  %t1 = load i8, i8* %arrayidx1
+  %t2 = load i8, i8* %arrayidx2
+  store i8 %t2, i8* %other
+  ret void
+}
+
+; Order of accesses does not change computation.
+; Multiple arguments may be dereferenceable.
+
+define void @ordering(i8* %ptr1, i32* %ptr2) {
+; ATTRIBUTOR-LABEL: @ordering(i8* nocapture nofree nonnull readonly dereferenceable(3) %ptr1, i32* nocapture nofree nonnull readonly dereferenceable(8) %ptr2)
+  %a20 = getelementptr i32, i32* %ptr2, i64 0
+  %a12 = getelementptr i8, i8* %ptr1, i64 2
+  %t12 = load i8, i8* %a12
+  %a11 = getelementptr i8, i8* %ptr1, i64 1
+  %t20 = load i32, i32* %a20
+  %a10 = getelementptr i8, i8* %ptr1, i64 0
+  %t10 = load i8, i8* %a10
+  %t11 = load i8, i8* %a11
+  %a21 = getelementptr i32, i32* %ptr2, i64 1
+  %t21 = load i32, i32* %a21
+  ret void
+}
+
+; Not in entry block.
+
+define void @not_entry_but_guaranteed_to_execute(i8* %ptr) {
+; ATTRIBUTOR-LABEL: @not_entry_but_guaranteed_to_execute(i8* nocapture nofree nonnull readonly dereferenceable(3) %ptr)
+entry:
+  br label %exit
+exit:
+  %arrayidx0 = getelementptr i8, i8* %ptr, i64 0
+  %arrayidx1 = getelementptr i8, i8* %ptr, i64 1
+  %arrayidx2 = getelementptr i8, i8* %ptr, i64 2
+  %t0 = load i8, i8* %arrayidx0
+  %t1 = load i8, i8* %arrayidx1
+  %t2 = load i8, i8* %arrayidx2
+  ret void
+}
+
+; Not in entry block and not guaranteed to execute.
+
+define void @not_entry_not_guaranteed_to_execute(i8* %ptr, i1 %cond) {
+; ATTRIBUTOR-LABEL: @not_entry_not_guaranteed_to_execute(i8* nocapture nofree readonly %ptr, i1 %cond)
+entry:
+  br i1 %cond, label %loads, label %exit
+loads:
+  %arrayidx0 = getelementptr i8, i8* %ptr, i64 0
+  %arrayidx1 = getelementptr i8, i8* %ptr, i64 1
+  %arrayidx2 = getelementptr i8, i8* %ptr, i64 2
+  %t0 = load i8, i8* %arrayidx0
+  %t1 = load i8, i8* %arrayidx1
+  %t2 = load i8, i8* %arrayidx2
+  ret void
+exit:
+  ret void
+}
+
+; The last load may not execute, so derefenceable bytes only covers the 1st two loads.
+
+define void @partial_in_entry(i16* %ptr, i1 %cond) {
+; ATTRIBUTOR-LABEL: @partial_in_entry(i16* nocapture nofree nonnull readonly dereferenceable(4) %ptr, i1 %cond)
+entry:
+  %arrayidx0 = getelementptr i16, i16* %ptr, i64 0
+  %arrayidx1 = getelementptr i16, i16* %ptr, i64 1
+  %arrayidx2 = getelementptr i16, i16* %ptr, i64 2
+  %t0 = load i16, i16* %arrayidx0
+  %t1 = load i16, i16* %arrayidx1
+  br i1 %cond, label %loads, label %exit
+loads:
+  %t2 = load i16, i16* %arrayidx2
+  ret void
+exit:
+  ret void
+}
+
+; The volatile load can't be used to prove a non-volatile access is allowed.
+; The 2nd and 3rd loads may never execute.
+
+define void @volatile_is_not_dereferenceable(i16* %ptr) {
+; ATTRIBUTOR-LABEL: @volatile_is_not_dereferenceable(i16* nofree %ptr)
+  %arrayidx0 = getelementptr i16, i16* %ptr, i64 0
+  %arrayidx1 = getelementptr i16, i16* %ptr, i64 1
+  %arrayidx2 = getelementptr i16, i16* %ptr, i64 2
+  %t0 = load volatile i16, i16* %arrayidx0
+  %t1 = load i16, i16* %arrayidx1
+  %t2 = load i16, i16* %arrayidx2
+  ret void
+}
+
+; TODO: We should allow inference for atomic (but not volatile) ops.
+
+define void @atomic_is_alright(i16* %ptr) {
+; ATTRIBUTOR-LABEL: @atomic_is_alright(i16* nocapture nofree nonnull readonly align 2 dereferenceable(6) %ptr)
+  %arrayidx0 = getelementptr i16, i16* %ptr, i64 0
+  %arrayidx1 = getelementptr i16, i16* %ptr, i64 1
+  %arrayidx2 = getelementptr i16, i16* %ptr, i64 2
+  %t0 = load atomic i16, i16* %arrayidx0 unordered, align 2
+  %t1 = load i16, i16* %arrayidx1
+  %t2 = load i16, i16* %arrayidx2
+  ret void
+}
+
+declare void @may_not_return()
+
+define void @not_guaranteed_to_transfer_execution(i16* %ptr) {
+; ATTRIBUTOR-LABEL: @not_guaranteed_to_transfer_execution(i16* nocapture nonnull readonly dereferenceable(2) %ptr)
+  %arrayidx0 = getelementptr i16, i16* %ptr, i64 0
+  %arrayidx1 = getelementptr i16, i16* %ptr, i64 1
+  %arrayidx2 = getelementptr i16, i16* %ptr, i64 2
+  %t0 = load i16, i16* %arrayidx0
+  call void @may_not_return()
+  %t1 = load i16, i16* %arrayidx1
+  %t2 = load i16, i16* %arrayidx2
+  ret void
+}
+
+; We must have consecutive accesses.
+
+define void @variable_gep_index(i8* %unused, i8* %ptr, i64 %variable_index) {
+; ATTRIBUTOR-LABEL: @variable_gep_index(i8* nocapture nofree readnone %unused, i8* nocapture nofree nonnull readonly dereferenceable(1) %ptr, i64 %variable_index)
+  %arrayidx1 = getelementptr i8, i8* %ptr, i64 %variable_index
+  %arrayidx2 = getelementptr i8, i8* %ptr, i64 2
+  %t0 = load i8, i8* %ptr
+  %t1 = load i8, i8* %arrayidx1
+  %t2 = load i8, i8* %arrayidx2
+  ret void
+}
+
+; Deal with >1 GEP index.
+
+define void @multi_index_gep(<4 x i8>* %ptr) {
+; FIXME: %ptr should be dereferenceable(4)
+; ATTRIBUTOR-LABEL: @multi_index_gep(<4 x i8>* nocapture nofree nonnull readonly dereferenceable(1) %ptr)
+  %arrayidx00 = getelementptr <4 x i8>, <4 x i8>* %ptr, i64 0, i64 0
+  %t0 = load i8, i8* %arrayidx00
+  ret void
+}
+
+; Could round weird bitwidths down?
+
+define void @not_byte_multiple(i9* %ptr) {
+; ATTRIBUTOR-LABEL: @not_byte_multiple(i9* nocapture nofree nonnull readonly dereferenceable(2) %ptr) 
+  %arrayidx0 = getelementptr i9, i9* %ptr, i64 0
+  %t0 = load i9, i9* %arrayidx0
+  ret void
+}
+
+; Missing direct access from the pointer.
+
+define void @no_pointer_deref(i16* %ptr) {
+; ATTRIBUTOR-LABEL: @no_pointer_deref(i16* nocapture nofree readonly %ptr)
+  %arrayidx1 = getelementptr i16, i16* %ptr, i64 1
+  %arrayidx2 = getelementptr i16, i16* %ptr, i64 2
+  %t1 = load i16, i16* %arrayidx1
+  %t2 = load i16, i16* %arrayidx2
+  ret void
+}
+
+; Out-of-order is ok, but missing access concludes dereferenceable range.
+
+define void @non_consecutive(i32* %ptr) {
+; ATTRIBUTOR-LABEL: @non_consecutive(i32* nocapture nofree nonnull readonly dereferenceable(8) %ptr)
+  %arrayidx1 = getelementptr i32, i32* %ptr, i64 1
+  %arrayidx0 = getelementptr i32, i32* %ptr, i64 0
+  %arrayidx3 = getelementptr i32, i32* %ptr, i64 3
+  %t1 = load i32, i32* %arrayidx1
+  %t0 = load i32, i32* %arrayidx0
+  %t3 = load i32, i32* %arrayidx3
+  ret void
+}
+
+; Improve on existing dereferenceable attribute.
+
+define void @more_bytes(i32* dereferenceable(8) %ptr) {
+; ATTRIBUTOR-LABEL: @more_bytes(i32* nocapture nofree nonnull readonly dereferenceable(16) %ptr)
+  %arrayidx3 = getelementptr i32, i32* %ptr, i64 3
+  %arrayidx1 = getelementptr i32, i32* %ptr, i64 1
+  %arrayidx0 = getelementptr i32, i32* %ptr, i64 0
+  %arrayidx2 = getelementptr i32, i32* %ptr, i64 2
+  %t3 = load i32, i32* %arrayidx3
+  %t1 = load i32, i32* %arrayidx1
+  %t2 = load i32, i32* %arrayidx2
+  %t0 = load i32, i32* %arrayidx0
+  ret void
+}
+
+; Improve on existing dereferenceable_or_null attribute.
+
+define void @more_bytes_and_not_null(i32* dereferenceable_or_null(8) %ptr) {
+; ATTRIBUTOR-LABEL: @more_bytes_and_not_null(i32* nocapture nofree nonnull readonly dereferenceable(16) %ptr)
+  %arrayidx3 = getelementptr i32, i32* %ptr, i64 3
+  %arrayidx1 = getelementptr i32, i32* %ptr, i64 1
+  %arrayidx0 = getelementptr i32, i32* %ptr, i64 0
+  %arrayidx2 = getelementptr i32, i32* %ptr, i64 2
+  %t3 = load i32, i32* %arrayidx3
+  %t1 = load i32, i32* %arrayidx1
+  %t2 = load i32, i32* %arrayidx2
+  %t0 = load i32, i32* %arrayidx0
+  ret void
+}
+
+; But don't pessimize existing dereferenceable attribute.
+
+define void @better_bytes(i32* dereferenceable(100) %ptr) {
+; ATTRIBUTOR-LABEL: @better_bytes(i32* nocapture nofree nonnull readonly dereferenceable(100) %ptr)
+  %arrayidx3 = getelementptr i32, i32* %ptr, i64 3
+  %arrayidx1 = getelementptr i32, i32* %ptr, i64 1
+  %arrayidx0 = getelementptr i32, i32* %ptr, i64 0
+  %arrayidx2 = getelementptr i32, i32* %ptr, i64 2
+  %t3 = load i32, i32* %arrayidx3
+  %t1 = load i32, i32* %arrayidx1
+  %t2 = load i32, i32* %arrayidx2
+  %t0 = load i32, i32* %arrayidx0
+  ret void
+}
+
+define void @bitcast(i32* %arg) {
+; ATTRIBUTOR-LABEL: @bitcast(i32* nocapture nofree nonnull readonly dereferenceable(8) %arg)
+  %ptr = bitcast i32* %arg to float*
+  %arrayidx0 = getelementptr float, float* %ptr, i64 0
+  %arrayidx1 = getelementptr float, float* %ptr, i64 1
+  %t0 = load float, float* %arrayidx0
+  %t1 = load float, float* %arrayidx1
+  ret void
+}
+
+define void @bitcast_
diff erent_sizes(double* %arg1, i8* %arg2) {
+; ATTRIBUTOR-LABEL: @bitcast_
diff erent_sizes(double* nocapture nofree nonnull readonly dereferenceable(12) %arg1, i8* nocapture nofree nonnull readonly dereferenceable(16) %arg2)
+  %ptr1 = bitcast double* %arg1 to float*
+  %a10 = getelementptr float, float* %ptr1, i64 0
+  %a11 = getelementptr float, float* %ptr1, i64 1
+  %a12 = getelementptr float, float* %ptr1, i64 2
+  %ld10 = load float, float* %a10
+  %ld11 = load float, float* %a11
+  %ld12 = load float, float* %a12
+
+  %ptr2 = bitcast i8* %arg2 to i64*
+  %a20 = getelementptr i64, i64* %ptr2, i64 0
+  %a21 = getelementptr i64, i64* %ptr2, i64 1
+  %ld20 = load i64, i64* %a20
+  %ld21 = load i64, i64* %a21
+  ret void
+}
+
+define void @negative_offset(i32* %arg) {
+; ATTRIBUTOR-LABEL: @negative_offset(i32* nocapture nofree nonnull readonly dereferenceable(4) %arg)
+  %ptr = bitcast i32* %arg to float*
+  %arrayidx0 = getelementptr float, float* %ptr, i64 0
+  %arrayidx1 = getelementptr float, float* %ptr, i64 -1
+  %t0 = load float, float* %arrayidx0
+  %t1 = load float, float* %arrayidx1
+  ret void
+}
+
+define void @stores(i32* %arg) {
+; ATTRIBUTOR-LABEL: @stores(i32* nocapture nofree nonnull writeonly dereferenceable(8) %arg)
+  %ptr = bitcast i32* %arg to float*
+  %arrayidx0 = getelementptr float, float* %ptr, i64 0
+  %arrayidx1 = getelementptr float, float* %ptr, i64 1
+  store float 1.0, float* %arrayidx0
+  store float 2.0, float* %arrayidx1
+  ret void
+}
+
+define void @load_store(i32* %arg) {
+; ATTRIBUTOR-LABEL: @load_store(i32* nocapture nofree nonnull dereferenceable(8) %arg)
+  %ptr = bitcast i32* %arg to float*
+  %arrayidx0 = getelementptr float, float* %ptr, i64 0
+  %arrayidx1 = getelementptr float, float* %ptr, i64 1
+  %t1 = load float, float* %arrayidx0
+  store float 2.0, float* %arrayidx1
+  ret void
+}
+
+define void @
diff erent_size1(i32* %arg) {
+; ATTRIBUTOR-LABEL: @
diff erent_size1(i32* nocapture nofree nonnull writeonly dereferenceable(8) %arg)
+  %arg-cast = bitcast i32* %arg to double*
+  store double 0.000000e+00, double* %arg-cast
+  store i32 0, i32* %arg
+  ret void
+}
+
+define void @
diff erent_size2(i32* %arg) {
+; ATTRIBUTOR-LABEL: @
diff erent_size2(i32* nocapture nofree nonnull writeonly dereferenceable(8) %arg)
+  store i32 0, i32* %arg
+  %arg-cast = bitcast i32* %arg to double*
+  store double 0.000000e+00, double* %arg-cast
+  ret void
+}

diff  --git a/llvm/test/Transforms/FunctionAttrs/heap_to_stack.ll b/llvm/test/Transforms/Attributor/heap_to_stack.ll
similarity index 100%
rename from llvm/test/Transforms/FunctionAttrs/heap_to_stack.ll
rename to llvm/test/Transforms/Attributor/heap_to_stack.ll

diff  --git a/llvm/test/Transforms/FunctionAttrs/internal-noalias.ll b/llvm/test/Transforms/Attributor/internal-noalias.ll
similarity index 100%
rename from llvm/test/Transforms/FunctionAttrs/internal-noalias.ll
rename to llvm/test/Transforms/Attributor/internal-noalias.ll

diff  --git a/llvm/test/Transforms/FunctionAttrs/liveness.ll b/llvm/test/Transforms/Attributor/liveness.ll
similarity index 100%
rename from llvm/test/Transforms/FunctionAttrs/liveness.ll
rename to llvm/test/Transforms/Attributor/liveness.ll

diff  --git a/llvm/test/Transforms/FunctionAttrs/misc.ll b/llvm/test/Transforms/Attributor/misc.ll
similarity index 100%
rename from llvm/test/Transforms/FunctionAttrs/misc.ll
rename to llvm/test/Transforms/Attributor/misc.ll

diff  --git a/llvm/test/Transforms/FunctionAttrs/new_attributes.ll b/llvm/test/Transforms/Attributor/new_attributes.ll
similarity index 100%
rename from llvm/test/Transforms/FunctionAttrs/new_attributes.ll
rename to llvm/test/Transforms/Attributor/new_attributes.ll

diff  --git a/llvm/test/Transforms/FunctionAttrs/noalias_returned.ll b/llvm/test/Transforms/Attributor/noalias.ll
similarity index 100%
rename from llvm/test/Transforms/FunctionAttrs/noalias_returned.ll
rename to llvm/test/Transforms/Attributor/noalias.ll

diff  --git a/llvm/test/Transforms/Attributor/nocapture-1.ll b/llvm/test/Transforms/Attributor/nocapture-1.ll
new file mode 100644
index 000000000000..abb148d883ed
--- /dev/null
+++ b/llvm/test/Transforms/Attributor/nocapture-1.ll
@@ -0,0 +1,346 @@
+; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -S -attributor-annotate-decl-cs < %s | FileCheck %s --check-prefixes=ATTRIBUTOR
+; RUN: opt -passes=attributor -attributor-manifest-internal -attributor-disable=false -S -attributor-annotate-decl-cs < %s | FileCheck %s --check-prefixes=ATTRIBUTOR
+; Copied from Transforms/FunctoinAttrs/nocapture.ll
+
+ at g = global i32* null		; <i32**> [#uses=1]
+
+; ATTRIBUTOR: define i32* @c1(i32* nofree readnone returned "no-capture-maybe-returned" %q)
+define i32* @c1(i32* %q) {
+	ret i32* %q
+}
+
+; ATTRIBUTOR: define void @c2(i32* nofree writeonly %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
+}
+
+; ATTRIBUTOR: define void @c3(i32* nofree writeonly %q)
+define void @c3(i32* %q) {
+	call void @c2(i32* %q)
+	ret void
+}
+
+; ATTRIBUTOR: define i1 @c4(i32* nofree readnone %q, i32 %bitno)
+define i1 @c4(i32* %q, i32 %bitno) {
+	%tmp = ptrtoint i32* %q to i32
+	%tmp2 = lshr i32 %tmp, %bitno
+	%bit = trunc i32 %tmp2 to i1
+	br i1 %bit, label %l1, label %l0
+l0:
+	ret i1 0 ; escaping value not caught by def-use chaining.
+l1:
+	ret i1 1 ; escaping value not caught by def-use chaining.
+}
+
+; c4b is c4 but without the escaping part
+; ATTRIBUTOR: define i1 @c4b(i32* nocapture nofree readnone %q, i32 %bitno)
+define i1 @c4b(i32* %q, i32 %bitno) {
+	%tmp = ptrtoint i32* %q to i32
+	%tmp2 = lshr i32 %tmp, %bitno
+	%bit = trunc i32 %tmp2 to i1
+	br i1 %bit, label %l1, label %l0
+l0:
+	ret i1 0 ; not escaping!
+l1:
+	ret i1 0 ; not escaping!
+}
+
+ at lookup_table = global [2 x i1] [ i1 0, i1 1 ]
+
+; ATTRIBUTOR: define i1 @c5(i32* nofree readonly %q, i32 %bitno)
+define i1 @c5(i32* %q, i32 %bitno) {
+	%tmp = ptrtoint i32* %q to i32
+	%tmp2 = lshr i32 %tmp, %bitno
+	%bit = and i32 %tmp2, 1
+        ; subtle escape mechanism follows
+	%lookup = getelementptr [2 x i1], [2 x i1]* @lookup_table, i32 0, i32 %bit
+	%val = load i1, i1* %lookup
+	ret i1 %val
+}
+
+declare void @throw_if_bit_set(i8*, i8) readonly
+
+; ATTRIBUTOR: define i1 @c6(i8* readonly %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
+ret0:
+	ret i1 0
+ret1:
+        %exn = landingpad {i8*, i32}
+                 cleanup
+	ret i1 1
+}
+
+declare i32 @__gxx_personality_v0(...)
+
+define i1* @lookup_bit(i32* %q, i32 %bitno) readnone nounwind {
+	%tmp = ptrtoint i32* %q to i32
+	%tmp2 = lshr i32 %tmp, %bitno
+	%bit = and i32 %tmp2, 1
+	%lookup = getelementptr [2 x i1], [2 x i1]* @lookup_table, i32 0, i32 %bit
+	ret i1* %lookup
+}
+
+; ATTRIBUTOR: define i1 @c7(i32* nofree readonly %q, i32 %bitno)
+define i1 @c7(i32* %q, i32 %bitno) {
+	%ptr = call i1* @lookup_bit(i32* %q, i32 %bitno)
+	%val = load i1, i1* %ptr
+	ret i1 %val
+}
+
+
+; ATTRIBUTOR: define i32 @nc1(i32* nofree %q, i32* nocapture nofree %p, i1 %b)
+define i32 @nc1(i32* %q, i32* %p, i1 %b) {
+e:
+	br label %l
+l:
+	%x = phi i32* [ %p, %e ]
+	%y = phi i32* [ %q, %e ]
+	%tmp = bitcast i32* %x to i32*		; <i32*> [#uses=2]
+	%tmp2 = select i1 %b, i32* %tmp, i32* %y
+	%val = load i32, i32* %tmp2		; <i32> [#uses=1]
+	store i32 0, i32* %tmp
+	store i32* %y, i32** @g
+	ret i32 %val
+}
+
+; ATTRIBUTOR: define i32 @nc1_addrspace(i32* nofree %q, i32 addrspace(1)* nocapture nofree %p, i1 %b)
+define i32 @nc1_addrspace(i32* %q, i32 addrspace(1)* %p, i1 %b) {
+e:
+	br label %l
+l:
+	%x = phi i32 addrspace(1)* [ %p, %e ]
+	%y = phi i32* [ %q, %e ]
+	%tmp = addrspacecast i32 addrspace(1)* %x to i32*		; <i32*> [#uses=2]
+	%tmp2 = select i1 %b, i32* %tmp, i32* %y
+	%val = load i32, i32* %tmp2		; <i32> [#uses=1]
+	store i32 0, i32* %tmp
+	store i32* %y, i32** @g
+	ret i32 %val
+}
+
+; ATTRIBUTOR: define void @nc2(i32* nocapture nofree %p, i32* nofree %q)
+define void @nc2(i32* %p, i32* %q) {
+	%1 = call i32 @nc1(i32* %q, i32* %p, i1 0)		; <i32> [#uses=0]
+	ret void
+}
+
+
+; ATTRIBUTOR: define void @nc3(void ()* nocapture nofree nonnull %p)
+define void @nc3(void ()* %p) {
+	call void %p()
+	ret void
+}
+
+declare void @external(i8*) readonly nounwind
+; ATTRIBUTOR: define void @nc4(i8* nocapture readonly %p)
+define void @nc4(i8* %p) {
+	call void @external(i8* %p)
+	ret void
+}
+
+; ATTRIBUTOR: define void @nc5(void (i8*)* nocapture nofree nonnull %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
+}
+
+; ATTRIBUTOR: define void @test1_1(i8* nocapture nofree readnone %x1_1, i8* nocapture nofree readnone %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, i1 %c) {
+  call i8* @test1_2(i8* %x1_1, i8* %y1_1, i1 %c)
+  store i32* null, i32** @g
+  ret void
+}
+
+; ATTRIBUTOR: define i8* @test1_2(i8* nocapture nofree readnone %x1_2, i8* nofree readnone 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
+}
+
+; ATTRIBUTOR: define void @test2(i8* nocapture nofree readnone %x2)
+define void @test2(i8* %x2) {
+  call void @test2(i8* %x2)
+  store i32* null, i32** @g
+  ret void
+}
+
+; ATTRIBUTOR: define void @test3(i8* nocapture nofree readnone %x3, i8* nocapture nofree readnone %y3, i8* nocapture nofree readnone %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
+}
+
+; ATTRIBUTOR: define void @test4_1(i8* nocapture nofree readnone %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
+}
+
+; ATTRIBUTOR: define i8* @test4_2(i8* nocapture nofree readnone %x4_2, i8* nofree readnone returned "no-capture-maybe-returned" %y4_2, i8* nocapture nofree readnone %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)
+
+; ATTRIBUTOR: 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
+  ret void
+}
+
+declare void @test6_1(i8* %x6_1, i8* nocapture %y6_1, ...)
+
+; ATTRIBUTOR: 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
+}
+
+; ATTRIBUTOR: define void @test_cmpxchg(i32* nocapture nofree nonnull dereferenceable(4) %p)
+define void @test_cmpxchg(i32* %p) {
+  cmpxchg i32* %p, i32 0, i32 1 acquire monotonic
+  ret void
+}
+
+; ATTRIBUTOR: define void @test_cmpxchg_ptr(i32** nocapture nofree nonnull dereferenceable(8) %p, i32* nofree %q)
+define void @test_cmpxchg_ptr(i32** %p, i32* %q) {
+  cmpxchg i32** %p, i32* null, i32* %q acquire monotonic
+  ret void
+}
+
+; ATTRIBUTOR: define void @test_atomicrmw(i32* nocapture nofree nonnull dereferenceable(4) %p)
+define void @test_atomicrmw(i32* %p) {
+  atomicrmw add i32* %p, i32 1 seq_cst
+  ret void
+}
+
+; ATTRIBUTOR: define void @test_volatile(i32* nofree align 4 %x)
+define void @test_volatile(i32* %x) {
+entry:
+  %gep = getelementptr i32, i32* %x, i64 1
+  store volatile i32 0, i32* %gep, align 4
+  ret void
+}
+
+; ATTRIBUTOR: nocaptureLaunder(i8* nocapture %p)
+define void @nocaptureLaunder(i8* %p) {
+entry:
+  %b = call i8* @llvm.launder.invariant.group.p0i8(i8* %p)
+  store i8 42, i8* %b
+  ret void
+}
+
+ at g2 = global i8* null
+; ATTRIBUTOR: 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
+}
+
+; ATTRIBUTOR: @nocaptureStrip(i8* nocapture writeonly %p)
+define void @nocaptureStrip(i8* %p) {
+entry:
+  %b = call i8* @llvm.strip.invariant.group.p0i8(i8* %p)
+  store i8 42, i8* %b
+  ret void
+}
+
+ at g3 = global i8* null
+; ATTRIBUTOR: define void @captureStrip(i8* writeonly %p)
+define void @captureStrip(i8* %p) {
+  %b = call i8* @llvm.strip.invariant.group.p0i8(i8* %p)
+  store i8* %b, i8** @g3
+  ret void
+}
+
+; ATTRIBUTOR: define i1 @captureICmp(i32* nofree readnone %x)
+define i1 @captureICmp(i32* %x) {
+  %1 = icmp eq i32* %x, null
+  ret i1 %1
+}
+
+; ATTRIBUTOR: define i1 @captureICmpRev(i32* nofree readnone %x)
+define i1 @captureICmpRev(i32* %x) {
+  %1 = icmp eq i32* null, %x
+  ret i1 %1
+}
+
+; ATTRIBUTOR: define i1 @nocaptureInboundsGEPICmp(i32* nocapture nofree nonnull readnone %x)
+define i1 @nocaptureInboundsGEPICmp(i32* %x) {
+  %1 = getelementptr inbounds i32, i32* %x, i32 5
+  %2 = bitcast i32* %1 to i8*
+  %3 = icmp eq i8* %2, null
+  ret i1 %3
+}
+
+; ATTRIBUTOR: define i1 @nocaptureInboundsGEPICmpRev(i32* nocapture nofree nonnull readnone %x)
+define i1 @nocaptureInboundsGEPICmpRev(i32* %x) {
+  %1 = getelementptr inbounds i32, i32* %x, i32 5
+  %2 = bitcast i32* %1 to i8*
+  %3 = icmp eq i8* null, %2
+  ret i1 %3
+}
+
+; ATTRIBUTOR: define i1 @nocaptureDereferenceableOrNullICmp(i32* nocapture nofree readnone 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
+}
+
+; ATTRIBUTOR: define i1 @captureDereferenceableOrNullICmp(i32* nofree readnone 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
+  ret i1 %2
+}
+
+declare void @unknown(i8*)
+define void @test_callsite() {
+entry:
+; We know that 'null' in AS 0 does not alias anything and cannot be captured. Though the latter is not qurried -> derived atm.
+; ATTRIBUTOR: call void @unknown(i8* noalias null)
+  call void @unknown(i8* null)
+  ret void
+}
+
+declare i8* @unknownpi8pi8(i8*,i8* returned)
+define i8* @test_returned1(i8* %A, i8* returned %B) nounwind readonly {
+; ATTRIBUTOR: define i8* @test_returned1(i8* nocapture readonly %A, i8* readonly returned %B)
+entry:
+  %p = call i8* @unknownpi8pi8(i8* %A, i8* %B)
+  ret i8* %p
+}
+
+define i8* @test_returned2(i8* %A, i8* %B) {
+; ATTRIBUTOR: define i8* @test_returned2(i8* nocapture readonly %A, i8* readonly returned %B)
+entry:
+  %p = call i8* @unknownpi8pi8(i8* %A, i8* %B) nounwind readonly
+  ret i8* %p
+}
+
+declare i8* @llvm.launder.invariant.group.p0i8(i8*)
+declare i8* @llvm.strip.invariant.group.p0i8(i8*)

diff  --git a/llvm/test/Transforms/FunctionAttrs/arg_nocapture.ll b/llvm/test/Transforms/Attributor/nocapture-2.ll
similarity index 100%
rename from llvm/test/Transforms/FunctionAttrs/arg_nocapture.ll
rename to llvm/test/Transforms/Attributor/nocapture-2.ll

diff  --git a/llvm/test/Transforms/Attributor/nofree.ll b/llvm/test/Transforms/Attributor/nofree.ll
new file mode 100644
index 000000000000..d06a0ea1e9b0
--- /dev/null
+++ b/llvm/test/Transforms/Attributor/nofree.ll
@@ -0,0 +1,243 @@
+; RUN: opt -attributor --attributor-disable=false -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=2 -S < %s | FileCheck %s --check-prefix=ATTRIBUTOR
+; Copied from Transforms/FunctoinAttrs/nofree-attributor.ll
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+; Test cases specifically designed for the "nofree" function attribute.
+; We use FIXME's to indicate problems and missing attributes.
+
+; Free functions
+declare void @free(i8* nocapture) local_unnamed_addr #1
+declare noalias i8* @realloc(i8* nocapture, i64) local_unnamed_addr #0
+declare void @_ZdaPv(i8*) local_unnamed_addr #2
+
+
+; TEST 1 (positive case)
+; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind readnone uwtable
+; ATTRIBUTOR-NEXT: define void @only_return()
+define void @only_return() #0 {
+    ret void
+}
+
+
+; TEST 2 (negative case)
+; Only free
+; void only_free(char* p) {
+;    free(p);
+; }
+
+; ATTRIBUTOR: Function Attrs: noinline nounwind uwtable
+; ATTRIBUTOR-NOT: nofree
+; ATTRIBUTOR-NEXT: define void @only_free(i8* nocapture %0) local_unnamed_addr #1
+define void @only_free(i8* nocapture %0) local_unnamed_addr #0 {
+    tail call void @free(i8* %0) #1
+    ret void
+}
+
+
+; TEST 3 (negative case)
+; Free occurs in same scc.
+; void free_in_scc1(char*p){
+;    free_in_scc2(p);
+; }
+; void free_in_scc2(char*p){
+;    free_in_scc1(p);
+;    free(p);
+; }
+
+
+; ATTRIBUTOR: Function Attrs: noinline nounwind uwtable
+; ATTRIBUTOR-NOT: nofree
+; ATTRIBUTOR-NEXT :define void @free_in_scc1(i8* nocapture %0) local_unnamed_addr
+define void @free_in_scc1(i8* nocapture %0) local_unnamed_addr #0 {
+  tail call void @free_in_scc2(i8* %0) #1
+  ret void
+}
+
+
+; ATTRIBUTOR: Function Attrs: noinline nounwind uwtable
+; ATTRIBUTOR-NOT: nofree
+; ATTRIBUTOR: define void @free_in_scc2(i8* nocapture %0) local_unnamed_addr
+define void @free_in_scc2(i8* nocapture %0) local_unnamed_addr #0 {
+  %cmp = icmp eq i8* %0, null
+  br i1 %cmp, label %rec, label %call
+call:
+  tail call void @free(i8* %0) #1
+  br label %end
+rec:
+  tail call void @free_in_scc1(i8* %0)
+  br label %end
+end:
+  ret void
+}
+
+
+; TEST 4 (positive case)
+; Free doesn't occur.
+; void mutual_recursion1(){
+;    mutual_recursion2();
+; }
+; void mutual_recursion2(){
+;     mutual_recursion1();
+; }
+
+
+; ATTRIBUTOR: Function Attrs: nofree noinline noreturn nosync nounwind readnone uwtable
+; ATTRIBUTOR-NEXT: define void @mutual_recursion1()
+define void @mutual_recursion1() #0 {
+  call void @mutual_recursion2()
+  ret void
+}
+
+; ATTRIBUTOR: Function Attrs: nofree noinline noreturn nosync nounwind readnone uwtable
+; ATTRIBUTOR-NEXT: define void @mutual_recursion2()
+define void @mutual_recursion2() #0 {
+  call void @mutual_recursion1()
+  ret void
+}
+
+
+; TEST 5
+; C++ delete operation (negative case)
+; void delete_op (char p[]){
+;     delete [] p;
+; }
+
+; ATTRIBUTOR: Function Attrs: noinline nounwind uwtable
+; ATTRIBUTOR-NOT: nofree
+; ATTRIBUTOR-NEXT: define void @_Z9delete_opPc(i8* %0) local_unnamed_addr #1
+define void @_Z9delete_opPc(i8* %0) local_unnamed_addr #0 {
+  %2 = icmp eq i8* %0, null
+  br i1 %2, label %4, label %3
+
+; <label>:3:                                      ; preds = %1
+  tail call void @_ZdaPv(i8* nonnull %0) #2
+  br label %4
+
+; <label>:4:                                      ; preds = %3, %1
+  ret void
+}
+
+
+; TEST 6 (negative case)
+; Call realloc
+; ATTRIBUTOR: Function Attrs: noinline nounwind uwtable
+; ATTRIBUTOR-NOT: nofree
+; ATTRIBUTOR-NEXT: define noalias i8* @call_realloc(i8* nocapture %0, i64 %1) local_unnamed_addr
+define noalias i8* @call_realloc(i8* nocapture %0, i64 %1) local_unnamed_addr #0 {
+    %ret = tail call i8* @realloc(i8* %0, i64 %1) #2
+    ret i8* %ret
+}
+
+
+; TEST 7 (positive case)
+; Call function declaration with "nofree"
+
+
+; ATTRIBUTOR: Function Attrs:  nofree noinline nounwind readnone uwtable 
+; ATTRIBUTOR-NEXT: declare void @nofree_function()
+declare void @nofree_function() nofree readnone #0
+
+; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind readnone uwtable
+; ATTRIBUTOR-NEXT: define void @call_nofree_function()
+define void @call_nofree_function() #0 {
+    tail call void @nofree_function()
+    ret void
+}
+
+; TEST 8 (negative case)
+; Call function declaration without "nofree"
+
+
+; ATTRIBUTOR: Function Attrs: noinline nounwind uwtable
+; ATTRIBUTOR-NEXT: declare void @maybe_free()
+declare void @maybe_free() #0
+
+
+; ATTRIBUTOR: Function Attrs: noinline nounwind uwtable
+; ATTRIBUTOR-NOT: nofree
+; ATTRIBUTOR-NEXT: define void @call_maybe_free()
+define void @call_maybe_free() #0 {
+    tail call void @maybe_free()
+    ret void
+}
+
+
+; TEST 9 (negative case)
+; Call both of above functions
+
+; ATTRIBUTOR: Function Attrs: noinline nounwind uwtable
+; ATTRIBUTOR-NOT: nofree
+; ATTRIBUTOR-NEXT: define void @call_both()
+define void @call_both() #0 {
+    tail call void @maybe_free()
+    tail call void @nofree_function()
+    ret void
+}
+
+
+; TEST 10 (positive case)
+; Call intrinsic function
+; ATTRIBUTOR: Function Attrs: nounwind readnone speculatable
+; ATTRIBUTOR-NEXT: declare float @llvm.floor.f32(float)
+declare float @llvm.floor.f32(float)
+
+; FIXME: missing nofree
+; ATTRIBUTOR: Function Attrs: noinline nosync nounwind readnone uwtable
+; ATTRIBUTOR-NEXT: define void @call_floor(float %a)
+
+define void @call_floor(float %a) #0 {
+    tail call float @llvm.floor.f32(float %a)
+    ret void
+}
+
+; TEST 11 (positive case)
+; Check propagation.
+
+; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind readnone uwtable
+; ATTRIBUTOR-NEXT: define void @f1()
+define void @f1() #0 {
+    tail call void @nofree_function()
+    ret void
+}
+
+; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind readnone uwtable
+; ATTRIBUTOR-NEXT: define void @f2()
+define void @f2() #0 {
+    tail call void @f1()
+    ret void
+}
+
+; TEST 12 NoFree argument - positive.
+; ATTRIBUTOR: define double @test12(double* nocapture nofree nonnull readonly align 8 dereferenceable(8) %a)
+define double @test12(double* nocapture readonly %a) {
+entry:
+	%0 = load double, double* %a, align 8
+	%call = tail call double @cos(double %0) #2
+	ret double %call
+}
+
+declare double @cos(double) nobuiltin nounwind nofree
+
+; FIXME: %a should be nofree.
+; TEST 13 NoFree argument - positive.
+; ATTRIBUTOR: define noalias i32* @test13(i64* nocapture nonnull readonly align 8 dereferenceable(8) %a)
+define noalias i32* @test13(i64* nocapture readonly %a) {
+entry:
+	%0 = load i64, i64* %a, align 8
+	%call = tail call noalias i8* @malloc(i64 %0) #2
+	%1 = bitcast i8* %call to i32*
+	ret i32* %1
+}
+
+; ATTRIBUTOR: define void @test14(i8* nocapture %0, i8* nocapture nofree readnone %1)
+define void @test14(i8* nocapture %0, i8* nocapture %1) {
+	tail call void @free(i8* %0) #1
+	ret void
+}
+
+declare noalias i8* @malloc(i64)
+
+attributes #0 = { nounwind uwtable noinline }
+attributes #1 = { nounwind }
+attributes #2 = { nobuiltin nounwind }

diff  --git a/llvm/test/Transforms/Attributor/nonnull.ll b/llvm/test/Transforms/Attributor/nonnull.ll
new file mode 100644
index 000000000000..260f04c27379
--- /dev/null
+++ b/llvm/test/Transforms/Attributor/nonnull.ll
@@ -0,0 +1,817 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -attributor --attributor-disable=false -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=5 -S < %s | FileCheck %s --check-prefixes=ATTRIBUTOR,ATTRIBUTOR_OPM
+; RUN: opt -passes=attributor --attributor-disable=false -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=5 -S < %s | FileCheck %s --check-prefixes=ATTRIBUTOR,ATTRIBUTOR_NPM
+; Copied from Transforms/FunctoinAttrs/nonnull.ll
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+declare nonnull i8* @ret_nonnull()
+
+; Return a pointer trivially nonnull (call return attribute)
+define i8* @test1() {
+; ATTRIBUTOR: define nonnull i8* @test1
+  %ret = call i8* @ret_nonnull()
+  ret i8* %ret
+}
+
+; Return a pointer trivially nonnull (argument attribute)
+define i8* @test2(i8* nonnull %p) {
+; ATTRIBUTOR: define nonnull i8* @test2
+  ret i8* %p
+}
+
+; Given an SCC where one of the functions can not be marked nonnull,
+; can we still mark the other one which is trivially nonnull
+define i8* @scc_binder(i1 %c) {
+; ATTRIBUTOR: define noalias i8* @scc_binder
+  br i1 %c, label %rec, label %end
+rec:
+  call i8* @test3(i1 %c)
+  br label %end
+end:
+  ret i8* null
+}
+
+define i8* @test3(i1 %c) {
+; ATTRIBUTOR: define nonnull i8* @test3
+  call i8* @scc_binder(i1 %c)
+  %ret = call i8* @ret_nonnull()
+  ret i8* %ret
+}
+
+; Given a mutual recursive set of functions, we can mark them
+; nonnull if neither can ever return null.  (In this case, they
+; just never return period.)
+define i8* @test4_helper() {
+; ATTRIBUTOR: define noalias nonnull align 536870912 dereferenceable(4294967295) i8* @test4_helper
+  %ret = call i8* @test4()
+  ret i8* %ret
+}
+
+define i8* @test4() {
+; ATTRIBUTOR: define noalias nonnull align 536870912 dereferenceable(4294967295) i8* @test4
+  %ret = call i8* @test4_helper()
+  ret i8* %ret
+}
+
+; Given a mutual recursive set of functions which *can* return null
+; make sure we haven't marked them as nonnull.
+define i8* @test5_helper(i1 %c) {
+; ATTRIBUTOR: define noalias i8* @test5_helper
+  br i1 %c, label %rec, label %end
+rec:
+  %ret = call i8* @test5(i1 %c)
+  br label %end
+end:
+  ret i8* null
+}
+
+define i8* @test5(i1 %c) {
+; ATTRIBUTOR: define noalias i8* @test5
+  %ret = call i8* @test5_helper(i1 %c)
+  ret i8* %ret
+}
+
+; Local analysis, but going through a self recursive phi
+; ATTRIBUTOR: Function Attrs: noreturn
+; ATTRIBUTOR: define noalias nonnull align 536870912 dereferenceable(4294967295) i8* @test6a()
+define i8* @test6a() {
+entry:
+  %ret = call i8* @ret_nonnull()
+  br label %loop
+loop:
+  %phi = phi i8* [%ret, %entry], [%phi, %loop]
+  br i1 undef, label %loop, label %exit
+exit:
+  ret i8* %phi
+}
+
+; ATTRIBUTOR: define nonnull i8* @test6b(i1 %c)
+define i8* @test6b(i1 %c) {
+entry:
+  %ret = call i8* @ret_nonnull()
+  br label %loop
+loop:
+  %phi = phi i8* [%ret, %entry], [%phi, %loop]
+  br i1 %c, label %loop, label %exit
+exit:
+  ret i8* %phi
+}
+
+; ATTRIBUTOR: define i8* @test7
+define i8* @test7(i8* %a) {
+  %b = getelementptr inbounds i8, i8* %a, i64 0
+  ret i8* %b
+}
+
+; ATTRIBUTOR: define nonnull i8* @test8
+define i8* @test8(i8* %a) {
+  %b = getelementptr inbounds i8, i8* %a, i64 1
+  ret i8* %b
+}
+
+; ATTRIBUTOR: define i8* @test9
+define i8* @test9(i8* %a, i64 %n) {
+  %b = getelementptr inbounds i8, i8* %a, i64 %n
+  ret i8* %b
+}
+
+declare void @llvm.assume(i1)
+; FIXME: missing nonnull
+; ATTRIBUTOR: define i8* @test10
+define i8* @test10(i8* %a, i64 %n) {
+  %cmp = icmp ne i64 %n, 0
+  call void @llvm.assume(i1 %cmp)
+  %b = getelementptr inbounds i8, i8* %a, i64 %n
+  ret i8* %b
+}
+
+; TEST 11
+; char* test11(char *p) {
+;   return p? p: nonnull();
+; }
+; FIXME: missing nonnull
+; ATTRIBUTOR: define i8* @test11
+define i8* @test11(i8*) local_unnamed_addr {
+  %2 = icmp eq i8* %0, null
+  br i1 %2, label %3, label %5
+
+; <label>:3:                                      ; preds = %1
+  %4 = tail call i8* @ret_nonnull()
+  br label %5
+
+; <label>:5:                                      ; preds = %3, %1
+  %6 = phi i8* [ %4, %3 ], [ %0, %1 ]
+  ret i8* %6
+}
+
+; TEST 12
+; Simple CallSite Test
+declare void @test12_helper(i8*)
+define void @test12(i8* nonnull %a) {
+; ATTRIBUTOR: define void @test12(i8* nonnull %a)
+; ATTRIBUTOR-NEXT: tail call void @test12_helper(i8* nonnull %a)
+  tail call void @test12_helper(i8* %a)
+  ret void
+}
+
+; TEST 13
+; Simple Argument Tests
+declare i8* @unknown()
+define void @test13_helper() {
+  %nonnullptr = tail call i8* @ret_nonnull()
+  %maybenullptr = tail call i8* @unknown()
+  tail call void @test13(i8* %nonnullptr, i8* %nonnullptr, i8* %maybenullptr)
+  tail call void @test13(i8* %nonnullptr, i8* %maybenullptr, i8* %nonnullptr)
+  ret void
+}
+define internal void @test13(i8* %a, i8* %b, i8* %c) {
+; ATTRIBUTOR: define internal void @test13(i8* nocapture nofree nonnull readnone %a, i8* nocapture nofree readnone %b, i8* nocapture nofree readnone %c)
+  ret void
+}
+
+declare nonnull i8* @nonnull()
+
+; TEST 14
+; Complex propagation
+; Argument of f1, f2, f3 can be marked with nonnull.
+
+; * Argument
+; 1. In f1:bb6, %arg can be marked with nonnull because of the comparison in bb1
+; 2. Because f2 is internal function, f2(i32* %arg) -> @f2(i32* nonnull %arg)
+; 3. In f1:bb4 %tmp5 is nonnull and f3 is internal function.
+;    Then, f3(i32* %arg) -> @f3(i32* nonnull %arg)
+; 4. We get nonnull in whole f1 call sites so f1(i32* %arg) -> @f1(i32* nonnull %arg)
+
+
+define internal i32* @f1(i32* %arg) {
+; FIXME: missing nonnull It should be nonnull @f1(i32* nonnull readonly %arg)
+; ATTRIBUTOR: define internal nonnull i32* @f1(i32* nofree readonly %arg)
+
+bb:
+  %tmp = icmp eq i32* %arg, null
+  br i1 %tmp, label %bb9, label %bb1
+
+bb1:                                              ; preds = %bb
+  %tmp2 = load i32, i32* %arg, align 4
+  %tmp3 = icmp eq i32 %tmp2, 0
+  br i1 %tmp3, label %bb6, label %bb4
+
+bb4:                                              ; preds = %bb1
+  %tmp5 = getelementptr inbounds i32, i32* %arg, i64 1
+; ATTRIBUTOR: %tmp5b = tail call nonnull i32* @f3(i32* nofree nonnull %tmp5)
+  %tmp5b = tail call i32* @f3(i32* %tmp5)
+  %tmp5c = getelementptr inbounds i32, i32* %tmp5b, i64 -1
+  br label %bb9
+
+bb6:                                              ; preds = %bb1
+; FIXME: missing nonnull. It should be @f2(i32* nonnull %arg)
+; ATTRIBUTOR: %tmp7 = tail call nonnull i32* @f2(i32* nofree %arg)
+  %tmp7 = tail call i32* @f2(i32* %arg)
+  ret i32* %tmp7
+
+bb9:                                              ; preds = %bb4, %bb
+  %tmp10 = phi i32* [ %tmp5c, %bb4 ], [ inttoptr (i64 4 to i32*), %bb ]
+  ret i32* %tmp10
+}
+
+define internal i32* @f2(i32* %arg) {
+; FIXME: missing nonnull. It should be nonnull @f2(i32* nonnull %arg)
+; ATTRIBUTOR: define internal nonnull i32* @f2(i32* nofree readonly %arg)
+bb:
+
+; FIXME: missing nonnull. It should be @f1(i32* nonnull readonly %arg)
+; ATTRIBUTOR:   %tmp = tail call nonnull i32* @f1(i32* nofree %arg)
+  %tmp = tail call i32* @f1(i32* %arg)
+  ret i32* %tmp
+}
+
+define dso_local noalias i32* @f3(i32* %arg) {
+; FIXME: missing nonnull. It should be nonnull @f3(i32* nonnull readonly %arg)
+; ATTRIBUTOR: define dso_local noalias nonnull i32* @f3(i32* nofree readonly %arg)
+bb:
+; FIXME: missing nonnull. It should be @f1(i32* nonnull readonly %arg)
+; ATTRIBUTOR:   %tmp = call nonnull i32* @f1(i32* nofree %arg)
+  %tmp = call i32* @f1(i32* %arg)
+  ret i32* %tmp
+}
+
+; TEST 15
+define void @f15(i8* %arg) {
+; ATTRIBUTOR:   tail call void @use1(i8* nonnull dereferenceable(4) %arg)
+
+  tail call void @use1(i8* dereferenceable(4) %arg)
+  ret void
+}
+
+declare void @fun0() #1
+declare void @fun1(i8*) #1
+declare void @fun2(i8*, i8*) #1
+declare void @fun3(i8*, i8*, i8*) #1
+; TEST 16 simple path test
+; if(..)
+;   fun2(nonnull %a, nonnull %b)
+; else
+;   fun2(nonnull %a, %b)
+; We can say that %a is nonnull but %b is not.
+define void @f16(i8* %a, i8 * %b, i8 %c) {
+; FIXME: missing nonnull on %a
+; ATTRIBUTOR: define void @f16(i8* %a, i8* %b, i8 %c)
+  %cmp = icmp eq i8 %c, 0
+  br i1 %cmp, label %if.then, label %if.else
+if.then:
+  tail call void @fun2(i8* nonnull %a, i8* nonnull %b)
+  ret void
+if.else:
+  tail call void @fun2(i8* nonnull %a, i8* %b)
+  ret void
+}
+; TEST 17 explore child BB test
+; if(..)
+;    ... (willreturn & nounwind)
+; else
+;    ... (willreturn & nounwind)
+; fun1(nonnull %a)
+; We can say that %a is nonnull
+define void @f17(i8* %a, i8 %c) {
+; ATTRIBUTOR: define void @f17(i8* nonnull %a, i8 %c)
+  %cmp = icmp eq i8 %c, 0
+  br i1 %cmp, label %if.then, label %if.else
+if.then:
+  tail call void @fun0()
+  br label %cont
+if.else:
+  tail call void @fun0()
+  br label %cont
+cont:
+  tail call void @fun1(i8* nonnull %a)
+  ret void
+}
+; TEST 18 More complex test
+; if(..)
+;    ... (willreturn & nounwind)
+; else
+;    ... (willreturn & nounwind)
+; if(..)
+;    ... (willreturn & nounwind)
+; else
+;    ... (willreturn & nounwind)
+; fun1(nonnull %a)
+
+define void @f18(i8* %a, i8* %b, i8 %c) {
+; ATTRIBUTOR: define void @f18(i8* nonnull %a, i8* %b, i8 %c)
+  %cmp1 = icmp eq i8 %c, 0
+  br i1 %cmp1, label %if.then, label %if.else
+if.then:
+  tail call void @fun0()
+  br label %cont
+if.else:
+  tail call void @fun0()
+  br label %cont
+cont:
+  %cmp2 = icmp eq i8 %c, 1
+  br i1 %cmp2, label %cont.then, label %cont.else
+cont.then:
+  tail call void @fun1(i8* nonnull %b)
+  br label %cont2
+cont.else:
+  tail call void @fun0()
+  br label %cont2
+cont2:
+  tail call void @fun1(i8* nonnull %a)
+  ret void
+}
+
+; TEST 19: Loop
+
+define void @f19(i8* %a, i8* %b, i8 %c) {
+; FIXME: missing nonnull on %b
+; ATTRIBUTOR: define void @f19(i8* %a, i8* %b, i8 %c)
+  br label %loop.header
+loop.header:
+  %cmp2 = icmp eq i8 %c, 0
+  br i1 %cmp2, label %loop.body, label %loop.exit
+loop.body:
+  tail call void @fun1(i8* nonnull %b)
+  tail call void @fun1(i8* nonnull %a)
+  br label %loop.header
+loop.exit:
+  tail call void @fun1(i8* nonnull %b)
+  ret void
+}
+
+; Test propagation of nonnull callsite args back to caller.
+
+declare void @use1(i8* %x)
+declare void @use2(i8* %x, i8* %y);
+declare void @use3(i8* %x, i8* %y, i8* %z);
+
+declare void @use1nonnull(i8* nonnull %x);
+declare void @use2nonnull(i8* nonnull %x, i8* nonnull %y);
+declare void @use3nonnull(i8* nonnull %x, i8* nonnull %y, i8* nonnull %z);
+
+declare i8 @use1safecall(i8* %x) readonly nounwind ; readonly+nounwind guarantees that execution continues to successor
+
+; Can't extend non-null to parent for any argument because the 2nd call is not guaranteed to execute.
+
+define void @parent1(i8* %a, i8* %b, i8* %c) {
+; ATTRIBUTOR-LABEL: @parent1(i8* %a, i8* %b, i8* %c)
+; ATTRIBUTOR-NEXT:    call void @use3(i8* %c, i8* %a, i8* %b)
+; ATTRIBUTOR-NEXT:    call void @use3nonnull(i8* nonnull %b, i8* nonnull %c, i8* nonnull %a)
+; ATTRIBUTOR-NEXT:    ret void
+  call void @use3(i8* %c, i8* %a, i8* %b)
+  call void @use3nonnull(i8* %b, i8* %c, i8* %a)
+  ret void
+}
+
+; Extend non-null to parent for all arguments.
+
+define void @parent2(i8* %a, i8* %b, i8* %c) {
+
+; ATTRIBUTOR-LABEL: @parent2(i8* nonnull %a, i8* nonnull %b, i8* nonnull %c)
+; ATTRIBUTOR-NEXT:    call void @use3nonnull(i8* nonnull %b, i8* nonnull %c, i8* nonnull %a)
+; ATTRIBUTOR-NEXT:    call void @use3(i8* nonnull %c, i8* nonnull %a, i8* nonnull %b)
+
+; ATTRIBUTOR-NEXT:    ret void
+  call void @use3nonnull(i8* %b, i8* %c, i8* %a)
+  call void @use3(i8* %c, i8* %a, i8* %b)
+  ret void
+}
+
+; Extend non-null to parent for 1st argument.
+
+define void @parent3(i8* %a, i8* %b, i8* %c) {
+
+; ATTRIBUTOR-LABEL: @parent3(i8* nonnull %a, i8* %b, i8* %c)
+; ATTRIBUTOR-NEXT:    call void @use1nonnull(i8* nonnull %a)
+; ATTRIBUTOR-NEXT:    call void @use3(i8* %c, i8* %b, i8* nonnull %a)
+
+; ATTRIBUTOR-NEXT:  ret void
+
+  call void @use1nonnull(i8* %a)
+  call void @use3(i8* %c, i8* %b, i8* %a)
+  ret void
+}
+
+; Extend non-null to parent for last 2 arguments.
+
+define void @parent4(i8* %a, i8* %b, i8* %c) {
+; CHECK-LABEL: @parent4(i8* %a, i8* nonnull %b, i8* nonnull %c)
+; CHECK-NEXT:    call void @use2nonnull(i8* %c, i8* %b)
+; CHECK-NEXT:    call void @use2(i8* %a, i8* %c)
+; CHECK-NEXT:    call void @use1(i8* %b)
+
+; ATTRIBUTOR-LABEL: @parent4(i8* %a, i8* nonnull %b, i8* nonnull %c)
+; ATTRIBUTOR-NEXT:    call void @use2nonnull(i8* nonnull %c, i8* nonnull %b)
+; ATTRIBUTOR-NEXT:    call void @use2(i8* %a, i8* nonnull %c)
+; ATTRIBUTOR-NEXT:    call void @use1(i8* nonnull %b)
+
+; ATTRIBUTOR: ret void
+
+  call void @use2nonnull(i8* %c, i8* %b)
+  call void @use2(i8* %a, i8* %c)
+  call void @use1(i8* %b)
+  ret void
+}
+
+; The callsite must execute in order for the attribute to transfer to the parent.
+; It appears benign to extend non-null to the parent in this case, but we can't do that
+; because it would incorrectly propagate the wrong information to its callers.
+
+define void @parent5(i8* %a, i1 %a_is_notnull) {
+; ATTRIBUTOR: @parent5(i8* %a, i1 %a_is_notnull)
+; ATTRIBUTOR-NEXT:    br i1 %a_is_notnull, label %t, label %f
+; ATTRIBUTOR:       t:
+; ATTRIBUTOR-NEXT:    call void @use1nonnull(i8* nonnull %a)
+; ATTRIBUTOR-NEXT:    ret void
+; ATTRIBUTOR:       f:
+; ATTRIBUTOR-NEXT:    ret void
+
+  br i1 %a_is_notnull, label %t, label %f
+t:
+  call void @use1nonnull(i8* %a)
+  ret void
+f:
+  ret void
+}
+
+; The callsite must execute in order for the attribute to transfer to the parent.
+; The volatile load can't trap, so we can guarantee that we'll get to the call.
+
+define i8 @parent6(i8* %a, i8* %b) {
+; ATTRIBUTOR-LABEL: @parent6(i8* nonnull %a, i8* %b)
+; ATTRIBUTOR-NEXT:    [[C:%.*]] = load volatile i8, i8* %b
+; ATTRIBUTOR-NEXT:    call void @use1nonnull(i8* nonnull %a)
+; ATTRIBUTOR-NEXT:    ret i8 [[C]]
+
+  %c = load volatile i8, i8* %b
+  call void @use1nonnull(i8* %a)
+  ret i8 %c
+}
+
+; The nonnull callsite is guaranteed to execute, so the argument must be nonnull throughout the parent.
+
+define i8 @parent7(i8* %a) {
+
+
+; ATTRIBUTOR-LABEL: @parent7(i8* nonnull %a)
+; ATTRIBUTOR-NEXT:    [[RET:%.*]] = call i8 @use1safecall(i8* nonnull %a)
+; ATTRIBUTOR-NEXT:    call void @use1nonnull(i8* nonnull %a)
+
+; ATTRIBUTOR-NEXT: ret i8 [[RET]]
+
+  %ret = call i8 @use1safecall(i8* %a)
+  call void @use1nonnull(i8* %a)
+  ret i8 %ret
+}
+
+; Make sure that an invoke works similarly to a call.
+
+declare i32 @esfp(...)
+
+define i1 @parent8(i8* %a, i8* %bogus1, i8* %b) personality i8* bitcast (i32 (...)* @esfp to i8*){
+; ATTRIBUTOR-LABEL: @parent8(i8* nonnull %a, i8* nocapture nofree readnone %bogus1, i8* nonnull %b)
+; ATTRIBUTOR-NEXT:  entry:
+; ATTRIBUTOR-NEXT:    invoke void @use2nonnull(i8* nonnull %a, i8* nonnull %b)
+; ATTRIBUTOR-NEXT:    to label %cont unwind label %exc
+; ATTRIBUTOR:       cont:
+; ATTRIBUTOR-NEXT:    [[NULL_CHECK:%.*]] = icmp eq i8* %b, null
+; ATTRIBUTOR-NEXT:    ret i1 [[NULL_CHECK]]
+; ATTRIBUTOR:       exc:
+; ATTRIBUTOR-NEXT:    [[LP:%.*]] = landingpad { i8*, i32 }
+; ATTRIBUTOR-NEXT:    filter [0 x i8*] zeroinitializer
+; ATTRIBUTOR-NEXT:    unreachable
+
+entry:
+  invoke void @use2nonnull(i8* %a, i8* %b)
+  to label %cont unwind label %exc
+
+cont:
+  %null_check = icmp eq i8* %b, null
+  ret i1 %null_check
+
+exc:
+  %lp = landingpad { i8*, i32 }
+  filter [0 x i8*] zeroinitializer
+  unreachable
+}
+
+; ATTRIBUTOR: define nonnull i32* @gep1(
+define i32* @gep1(i32* %p) {
+  %q = getelementptr inbounds i32, i32* %p, i32 1
+  ret i32* %q
+}
+
+define i32* @gep1_no_null_opt(i32* %p) #0 {
+; Should't be able to derive nonnull based on gep.
+; ATTRIBUTOR: define i32* @gep1_no_null_opt(
+  %q = getelementptr inbounds i32, i32* %p, i32 1
+  ret i32* %q
+}
+
+; ATTRIBUTOR: define i32 addrspace(3)* @gep2(
+define i32 addrspace(3)* @gep2(i32 addrspace(3)* %p) {
+  %q = getelementptr inbounds i32, i32 addrspace(3)* %p, i32 1
+  ret i32 addrspace(3)* %q
+}
+
+; FIXME: We should propagate dereferenceable here but *not* nonnull
+; ATTRIBUTOR: define dereferenceable_or_null(4) i32 addrspace(3)* @as(i32 addrspace(3)* nofree readnone returned dereferenceable(4) dereferenceable_or_null(4) %p)
+define i32 addrspace(3)* @as(i32 addrspace(3)* dereferenceable(4) %p) {
+  ret i32 addrspace(3)* %p
+}
+
+; ATTRIBUTOR: define internal nonnull i32* @g2()
+define internal i32* @g2() {
+  ret i32* inttoptr (i64 4 to i32*)
+}
+
+define  i32* @g1() {
+ %c = call i32* @g2()
+  ret i32* %c
+}
+
+declare void @use_i32_ptr(i32*) readnone nounwind
+; ATTRIBUTOR: define internal void @called_by_weak(i32* nocapture nonnull readnone %a)
+define internal void @called_by_weak(i32* %a) {
+  call void @use_i32_ptr(i32* %a)
+  ret void
+}
+
+; Check we do not annotate the function interface of this weak function.
+; ATTRIBUTOR: define weak_odr void @weak_caller(i32* nonnull %a)
+define weak_odr void @weak_caller(i32* nonnull %a) {
+  call void @called_by_weak(i32* %a)
+  ret void
+}
+
+; Expect nonnull
+; ATTRIBUTOR: define internal void @control(i32* nocapture nonnull readnone align 16 dereferenceable(8) %a)
+define internal void @control(i32* dereferenceable(4) %a) {
+  call void @use_i32_ptr(i32* %a)
+  ret void
+}
+; Avoid nonnull as we do not touch naked functions
+; ATTRIBUTOR: define internal void @naked(i32* dereferenceable(4) %a)
+define internal void @naked(i32* dereferenceable(4) %a) naked {
+  call void @use_i32_ptr(i32* %a)
+  ret void
+}
+; Avoid nonnull as we do not touch optnone
+; ATTRIBUTOR: define internal void @optnone(i32* dereferenceable(4) %a)
+define internal void @optnone(i32* dereferenceable(4) %a) optnone noinline {
+  call void @use_i32_ptr(i32* %a)
+  ret void
+}
+define void @make_live(i32* nonnull dereferenceable(8) %a) {
+  call void @naked(i32* nonnull dereferenceable(8) align 16 %a)
+  call void @control(i32* nonnull dereferenceable(8) align 16 %a)
+  call void @optnone(i32* nonnull dereferenceable(8) align 16 %a)
+  ret void
+}
+
+;int f(int *u, int n){
+;  for(int i = 0;i<n;i++){
+;    h(u);
+;  }
+;  return g(nonnull u);
+;}
+declare void @h(i32*) willreturn nounwind
+declare i32 @g(i32*) willreturn nounwind
+define i32 @nonnull_exec_ctx_1(i32* %a, i32 %b) {
+;
+; ATTRIBUTOR-LABEL: define {{[^@]+}}@nonnull_exec_ctx_1
+; ATTRIBUTOR-SAME: (i32* [[A:%.*]], i32 [[B:%.*]])
+; ATTRIBUTOR-NEXT:  en:
+; ATTRIBUTOR-NEXT:    [[TMP3:%.*]] = icmp eq i32 [[B:%.*]], 0
+; ATTRIBUTOR-NEXT:    br i1 [[TMP3]], label [[EX:%.*]], label [[HD:%.*]]
+; ATTRIBUTOR:       ex:
+; ATTRIBUTOR-NEXT:    [[TMP5:%.*]] = tail call i32 @g(i32* nonnull [[A:%.*]])
+; ATTRIBUTOR-NEXT:    ret i32 [[TMP5]]
+; ATTRIBUTOR:       hd:
+; ATTRIBUTOR-NEXT:    [[TMP7:%.*]] = phi i32 [ [[TMP8:%.*]], [[HD]] ], [ 0, [[EN:%.*]] ]
+; ATTRIBUTOR-NEXT:    tail call void @h(i32* [[A]])
+; ATTRIBUTOR-NEXT:    [[TMP8]] = add nuw i32 [[TMP7]], 1
+; ATTRIBUTOR-NEXT:    [[TMP9:%.*]] = icmp eq i32 [[TMP8]], [[B]]
+; ATTRIBUTOR-NEXT:    br i1 [[TMP9]], label [[EX]], label [[HD]]
+;
+en:
+  %tmp3 = icmp eq i32 %b, 0
+  br i1 %tmp3, label %ex, label %hd
+
+ex:
+  %tmp5 = tail call i32 @g(i32* nonnull %a)
+  ret i32 %tmp5
+
+hd:
+  %tmp7 = phi i32 [ %tmp8, %hd ], [ 0, %en ]
+  tail call void @h(i32* %a)
+  %tmp8 = add nuw i32 %tmp7, 1
+  %tmp9 = icmp eq i32 %tmp8, %b
+  br i1 %tmp9, label %ex, label %hd
+}
+
+define i32 @nonnull_exec_ctx_1b(i32* %a, i32 %b) {
+;
+; ATTRIBUTOR-LABEL: define {{[^@]+}}@nonnull_exec_ctx_1b
+; ATTRIBUTOR-SAME: (i32* [[A:%.*]], i32 [[B:%.*]])
+; ATTRIBUTOR-NEXT:  en:
+; ATTRIBUTOR-NEXT:    [[TMP3:%.*]] = icmp eq i32 [[B:%.*]], 0
+; ATTRIBUTOR-NEXT:    br i1 [[TMP3]], label [[EX:%.*]], label [[HD:%.*]]
+; ATTRIBUTOR:       ex:
+; ATTRIBUTOR-NEXT:    [[TMP5:%.*]] = tail call i32 @g(i32* nonnull [[A:%.*]])
+; ATTRIBUTOR-NEXT:    ret i32 [[TMP5]]
+; ATTRIBUTOR:       hd:
+; ATTRIBUTOR-NEXT:    [[TMP7:%.*]] = phi i32 [ [[TMP8:%.*]], [[HD2:%.*]] ], [ 0, [[EN:%.*]] ]
+; ATTRIBUTOR-NEXT:    tail call void @h(i32* [[A]])
+; ATTRIBUTOR-NEXT:    br label [[HD2]]
+; ATTRIBUTOR:       hd2:
+; ATTRIBUTOR-NEXT:    [[TMP8]] = add nuw i32 [[TMP7]], 1
+; ATTRIBUTOR-NEXT:    [[TMP9:%.*]] = icmp eq i32 [[TMP8]], [[B]]
+; ATTRIBUTOR-NEXT:    br i1 [[TMP9]], label [[EX]], label [[HD]]
+;
+en:
+  %tmp3 = icmp eq i32 %b, 0
+  br i1 %tmp3, label %ex, label %hd
+
+ex:
+  %tmp5 = tail call i32 @g(i32* nonnull %a)
+  ret i32 %tmp5
+
+hd:
+  %tmp7 = phi i32 [ %tmp8, %hd2 ], [ 0, %en ]
+  tail call void @h(i32* %a)
+  br label %hd2
+
+hd2:
+  %tmp8 = add nuw i32 %tmp7, 1
+  %tmp9 = icmp eq i32 %tmp8, %b
+  br i1 %tmp9, label %ex, label %hd
+}
+
+define i32 @nonnull_exec_ctx_2(i32* %a, i32 %b) willreturn nounwind {
+;
+; ATTRIBUTOR-LABEL: define {{[^@]+}}@nonnull_exec_ctx_2
+; ATTRIBUTOR-SAME: (i32* [[A:%.*]], i32 [[B:%.*]])
+; ATTRIBUTOR-NEXT:  en:
+; ATTRIBUTOR-NEXT:    [[TMP3:%.*]] = icmp eq i32 [[B:%.*]], 0
+; ATTRIBUTOR-NEXT:    br i1 [[TMP3]], label [[EX:%.*]], label [[HD:%.*]]
+; ATTRIBUTOR:       ex:
+; ATTRIBUTOR-NEXT:    [[TMP5:%.*]] = tail call i32 @g(i32* nonnull [[A:%.*]])
+; ATTRIBUTOR-NEXT:    ret i32 [[TMP5]]
+; ATTRIBUTOR:       hd:
+; ATTRIBUTOR-NEXT:    [[TMP7:%.*]] = phi i32 [ [[TMP8:%.*]], [[HD]] ], [ 0, [[EN:%.*]] ]
+; ATTRIBUTOR-NEXT:    tail call void @h(i32* nonnull [[A]])
+; ATTRIBUTOR-NEXT:    [[TMP8]] = add nuw i32 [[TMP7]], 1
+; ATTRIBUTOR-NEXT:    [[TMP9:%.*]] = icmp eq i32 [[TMP8]], [[B]]
+; ATTRIBUTOR-NEXT:    br i1 [[TMP9]], label [[EX]], label [[HD]]
+;
+en:
+  %tmp3 = icmp eq i32 %b, 0
+  br i1 %tmp3, label %ex, label %hd
+
+ex:
+  %tmp5 = tail call i32 @g(i32* nonnull %a)
+  ret i32 %tmp5
+
+hd:
+  %tmp7 = phi i32 [ %tmp8, %hd ], [ 0, %en ]
+  tail call void @h(i32* %a)
+  %tmp8 = add nuw i32 %tmp7, 1
+  %tmp9 = icmp eq i32 %tmp8, %b
+  br i1 %tmp9, label %ex, label %hd
+}
+
+define i32 @nonnull_exec_ctx_2b(i32* %a, i32 %b) willreturn nounwind {
+;
+; ATTRIBUTOR-LABEL: define {{[^@]+}}@nonnull_exec_ctx_2b
+; ATTRIBUTOR-SAME: (i32* [[A:%.*]], i32 [[B:%.*]])
+; ATTRIBUTOR-NEXT:  en:
+; ATTRIBUTOR-NEXT:    [[TMP3:%.*]] = icmp eq i32 [[B:%.*]], 0
+; ATTRIBUTOR-NEXT:    br i1 [[TMP3]], label [[EX:%.*]], label [[HD:%.*]]
+; ATTRIBUTOR:       ex:
+; ATTRIBUTOR-NEXT:    [[TMP5:%.*]] = tail call i32 @g(i32* nonnull [[A:%.*]])
+; ATTRIBUTOR-NEXT:    ret i32 [[TMP5]]
+; ATTRIBUTOR:       hd:
+; ATTRIBUTOR-NEXT:    [[TMP7:%.*]] = phi i32 [ [[TMP8:%.*]], [[HD2:%.*]] ], [ 0, [[EN:%.*]] ]
+; ATTRIBUTOR-NEXT:    tail call void @h(i32* nonnull [[A]])
+; ATTRIBUTOR-NEXT:    br label [[HD2]]
+; ATTRIBUTOR:       hd2:
+; ATTRIBUTOR-NEXT:    [[TMP8]] = add nuw i32 [[TMP7]], 1
+; ATTRIBUTOR-NEXT:    [[TMP9:%.*]] = icmp eq i32 [[TMP8]], [[B]]
+; ATTRIBUTOR-NEXT:    br i1 [[TMP9]], label [[EX]], label [[HD]]
+;
+en:
+  %tmp3 = icmp eq i32 %b, 0
+  br i1 %tmp3, label %ex, label %hd
+
+ex:
+  %tmp5 = tail call i32 @g(i32* nonnull %a)
+  ret i32 %tmp5
+
+hd:
+  %tmp7 = phi i32 [ %tmp8, %hd2 ], [ 0, %en ]
+  tail call void @h(i32* %a)
+  br label %hd2
+
+hd2:
+  %tmp8 = add nuw i32 %tmp7, 1
+  %tmp9 = icmp eq i32 %tmp8, %b
+  br i1 %tmp9, label %ex, label %hd
+}
+
+; Original from PR43833
+declare void @sink(i32*)
+
+; FIXME: the sink argument should be marked nonnull as in @PR43833_simple.
+define void @PR43833(i32* %0, i32 %1) {
+; ATTRIBUTOR-LABEL: @PR43833(
+; ATTRIBUTOR-NEXT:    [[TMP3:%.*]] = icmp sgt i32 [[TMP1:%.*]], 1
+; ATTRIBUTOR-NEXT:    br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP7:%.*]]
+; ATTRIBUTOR:       4:
+; ATTRIBUTOR-NEXT:    [[TMP5:%.*]] = zext i32 [[TMP1]] to i64
+; ATTRIBUTOR-NEXT:    [[TMP6:%.*]] = getelementptr inbounds i32, i32* [[TMP0:%.*]], i64 [[TMP5]]
+; ATTRIBUTOR-NEXT:    br label [[TMP8:%.*]]
+; ATTRIBUTOR:       7:
+; ATTRIBUTOR-NEXT:    ret void
+; ATTRIBUTOR:       8:
+; ATTRIBUTOR-NEXT:    [[TMP9:%.*]] = phi i32 [ 1, [[TMP4]] ], [ [[TMP10:%.*]], [[TMP8]] ]
+; ATTRIBUTOR-NEXT:    tail call void @sink(i32* [[TMP6]])
+; ATTRIBUTOR-NEXT:    [[TMP10]] = add nuw nsw i32 [[TMP9]], 1
+; ATTRIBUTOR-NEXT:    [[TMP11:%.*]] = icmp eq i32 [[TMP10]], [[TMP1]]
+; ATTRIBUTOR-NEXT:    br i1 [[TMP11]], label [[TMP7]], label [[TMP8]]
+;
+  %3 = icmp sgt i32 %1, 1
+  br i1 %3, label %4, label %7
+
+4:                                                ; preds = %2
+  %5 = zext i32 %1 to i64
+  %6 = getelementptr inbounds i32, i32* %0, i64 %5
+  br label %8
+
+7:                                                ; preds = %8, %2
+  ret void
+
+8:                                                ; preds = %8, %4
+  %9 = phi i32 [ 1, %4 ], [ %10, %8 ]
+  tail call void @sink(i32* %6)
+  %10 = add nuw nsw i32 %9, 1
+  %11 = icmp eq i32 %10, %1
+  br i1 %11, label %7, label %8
+}
+
+; Adjusted from PR43833
+define void @PR43833_simple(i32* %0, i32 %1) {
+; ATTRIBUTOR_OPM-LABEL: @PR43833_simple(
+; ATTRIBUTOR_OPM-NEXT:    [[TMP3:%.*]] = icmp ne i32 [[TMP1:%.*]], 0
+; ATTRIBUTOR_OPM-NEXT:    br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP7:%.*]]
+; ATTRIBUTOR_OPM:       4:
+; ATTRIBUTOR_OPM-NEXT:    [[TMP5:%.*]] = zext i32 [[TMP1]] to i64
+; ATTRIBUTOR_OPM-NEXT:    [[TMP6:%.*]] = getelementptr inbounds i32, i32* [[TMP0:%.*]], i64 [[TMP5]]
+; ATTRIBUTOR_OPM-NEXT:    br label [[TMP8:%.*]]
+; ATTRIBUTOR_OPM:       7:
+; ATTRIBUTOR_OPM-NEXT:    ret void
+; ATTRIBUTOR_OPM:       8:
+; ATTRIBUTOR_OPM-NEXT:    [[TMP9:%.*]] = phi i32 [ 1, [[TMP4]] ], [ [[TMP10:%.*]], [[TMP8]] ]
+; ATTRIBUTOR_OPM-NEXT:    tail call void @sink(i32* [[TMP6]])
+; ATTRIBUTOR_OPM-NEXT:    [[TMP10]] = add nuw nsw i32 [[TMP9]], 1
+; ATTRIBUTOR_OPM-NEXT:    [[TMP11:%.*]] = icmp eq i32 [[TMP10]], [[TMP1]]
+; ATTRIBUTOR_OPM-NEXT:    br i1 [[TMP11]], label [[TMP7]], label [[TMP8]]
+;
+; ATTRIBUTOR_NPM-LABEL: @PR43833_simple(
+; ATTRIBUTOR_NPM-NEXT:    [[TMP3:%.*]] = icmp ne i32 [[TMP1:%.*]], 0
+; ATTRIBUTOR_NPM-NEXT:    br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP7:%.*]]
+; ATTRIBUTOR_NPM:       4:
+; ATTRIBUTOR_NPM-NEXT:    [[TMP5:%.*]] = zext i32 [[TMP1]] to i64
+; ATTRIBUTOR_NPM-NEXT:    [[TMP6:%.*]] = getelementptr inbounds i32, i32* [[TMP0:%.*]], i64 [[TMP5]]
+; ATTRIBUTOR_NPM-NEXT:    br label [[TMP8:%.*]]
+; ATTRIBUTOR_NPM:       7:
+; ATTRIBUTOR_NPM-NEXT:    ret void
+; ATTRIBUTOR_NPM:       8:
+; ATTRIBUTOR_NPM-NEXT:    [[TMP9:%.*]] = phi i32 [ 1, [[TMP4]] ], [ [[TMP10:%.*]], [[TMP8]] ]
+; ATTRIBUTOR_NPM-NEXT:    tail call void @sink(i32* [[TMP6]])
+; ATTRIBUTOR_NPM-NEXT:    [[TMP10]] = add nuw nsw i32 [[TMP9]], 1
+; ATTRIBUTOR_NPM-NEXT:    [[TMP11:%.*]] = icmp eq i32 [[TMP10]], [[TMP1]]
+; ATTRIBUTOR_NPM-NEXT:    br i1 [[TMP11]], label [[TMP7]], label [[TMP8]]
+;
+  %3 = icmp ne i32 %1, 0
+  br i1 %3, label %4, label %7
+
+4:                                                ; preds = %2
+  %5 = zext i32 %1 to i64
+  %6 = getelementptr inbounds i32, i32* %0, i64 %5
+  br label %8
+
+7:                                                ; preds = %8, %2
+  ret void
+
+8:                                                ; preds = %8, %4
+  %9 = phi i32 [ 1, %4 ], [ %10, %8 ]
+  tail call void @sink(i32* %6)
+  %10 = add nuw nsw i32 %9, 1
+  %11 = icmp eq i32 %10, %1
+  br i1 %11, label %7, label %8
+}
+
+attributes #0 = { "null-pointer-is-valid"="true" }
+attributes #1 = { nounwind willreturn}

diff  --git a/llvm/test/Transforms/Attributor/norecurse.ll b/llvm/test/Transforms/Attributor/norecurse.ll
new file mode 100644
index 000000000000..25f7fdee5f13
--- /dev/null
+++ b/llvm/test/Transforms/Attributor/norecurse.ll
@@ -0,0 +1,147 @@
+; RUN: opt -passes=attributor --attributor-disable=false -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=2 -S < %s | FileCheck %s --check-prefixes=ATTRIBUTOR
+; Copied from Transforms/FunctoinAttrs/norecurse.ll
+
+; ATTRIBUTOR: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
+; ATTRIBUTOR-NEXT: define i32 @leaf()
+define i32 @leaf() {
+  ret i32 1
+}
+
+; ATTRIBUTOR: Function Attrs
+; ATTRIBUTOR-SAME: readnone
+; ATTRIBUTOR-NOT: norecurse
+; ATTRIBUTOR-NEXT: define i32 @self_rec()
+define i32 @self_rec() {
+  %a = call i32 @self_rec()
+  ret i32 4
+}
+
+; ATTRIBUTOR: Function Attrs
+; ATTRIBUTOR-SAME: readnone
+; ATTRIBUTOR-NOT: norecurse
+; ATTRIBUTOR-NEXT: define i32 @indirect_rec()
+define i32 @indirect_rec() {
+  %a = call i32 @indirect_rec2()
+  ret i32 %a
+}
+; ATTRIBUTOR: Function Attrs
+; ATTRIBUTOR-SAME: readnone
+; ATTRIBUTOR-NOT: norecurse
+; ATTRIBUTOR-NEXT: define i32 @indirect_rec2()
+define i32 @indirect_rec2() {
+  %a = call i32 @indirect_rec()
+  ret i32 %a
+}
+
+; ATTRIBUTOR: Function Attrs
+; ATTRIBUTOR-SAME: readnone
+; ATTRIBUTOR-NOT: norecurse
+; ATTRIBUTOR-NEXT: define i32 @extern()
+define i32 @extern() {
+  %a = call i32 @k()
+  ret i32 %a
+}
+
+; ATTRIBUTOR: Function Attrs
+; ATTRIBUTOR-NEXT: declare i32 @k()
+declare i32 @k() readnone
+
+; ATTRIBUTOR: Function Attrs
+; ATTRIBUTOR-NOT: norecurse
+; ATTRIBUTOR-NEXT: define void @intrinsic(i8* nocapture writeonly %dest, i8* nocapture readonly %src, i32 %len)
+define void @intrinsic(i8* %dest, i8* %src, i32 %len) {
+  call void @llvm.memcpy.p0i8.p0i8.i32(i8* %dest, i8* %src, i32 %len, i1 false)
+  ret void
+}
+
+; ATTRIBUTOR: Function Attrs
+; ATTRIBUTOR-NEXT: declare void @llvm.memcpy.p0i8.p0i8.i32
+declare void @llvm.memcpy.p0i8.p0i8.i32(i8*, i8*, i32, i1)
+
+; ATTRIBUTOR: Function Attrs
+; FIXME: missing "norecurse"
+; ATTRIBUTOR-SAME: nosync readnone
+define internal i32 @called_by_norecurse() {
+  %a = call i32 @k()
+  ret i32 %a
+}
+; ATTRIBUTOR: Function Attrs
+; ATTRIBUTOR-NEXT: define void @m()
+define void @m() norecurse {
+  %a = call i32 @called_by_norecurse()
+  ret void
+}
+
+; ATTRIBUTOR: Function Attrs
+; FIXME: missing "norecurse"
+; ATTRIBUTOR-SAME: nosync
+define internal i32 @called_by_norecurse_indirectly() {
+  %a = call i32 @k()
+  ret i32 %a
+}
+define internal void @o() {
+  %a = call i32 @called_by_norecurse_indirectly()
+  ret void
+}
+define void @p() norecurse {
+  call void @o()
+  ret void
+}
+
+; ATTRIBUTOR: Function Attrs: nofree nosync nounwind
+; ATTRIBUTOR-NEXT: define void @f(i32 %x)
+define void @f(i32 %x)  {
+entry:
+  %x.addr = alloca i32, align 4
+  store i32 %x, i32* %x.addr, align 4
+  %0 = load i32, i32* %x.addr, align 4
+  %tobool = icmp ne i32 %0, 0
+  br i1 %tobool, label %if.then, label %if.end
+
+if.then:
+  call void @g() norecurse
+  br label %if.end
+
+if.end:
+  ret void
+}
+
+; ATTRIBUTOR: define void @g()
+define void @g() norecurse {
+entry:
+  call void @f(i32 0)
+  ret void
+}
+
+; ATTRIBUTOR-NOT: Function Attrs
+; ATTRIBUTOR: define linkonce_odr i32 @leaf_redefinable()
+define linkonce_odr i32 @leaf_redefinable() {
+  ret i32 1
+}
+
+; Call through a function pointer
+; ATTRIBUTOR-NOT: Function Attrs
+; ATTRIBUTOR: define i32 @eval_func1(i32 (i32)* nocapture nofree nonnull %0, i32 %1)
+define i32 @eval_func1(i32 (i32)* , i32) local_unnamed_addr {
+  %3 = tail call i32 %0(i32 %1) #2
+  ret i32 %3
+}
+
+; ATTRIBUTOR-NOT: Function Attrs
+; ATTRIBUTOR: define i32 @eval_func2(i32 (i32)* nocapture nofree %0, i32 %1)
+define i32 @eval_func2(i32 (i32)* , i32) local_unnamed_addr "null-pointer-is-valid"="true"{
+  %3 = tail call i32 %0(i32 %1) #2
+  ret i32 %3
+}
+
+declare void @unknown()
+; Call an unknown function in a dead block.
+; ATTRIBUTOR: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
+; ATTRIBUTOR: define i32 @call_unknown_in_dead_block()
+define i32 @call_unknown_in_dead_block() local_unnamed_addr {
+  ret i32 0
+Dead:
+  tail call void @unknown()
+  ret i32 1
+}
+

diff  --git a/llvm/test/Transforms/FunctionAttrs/fn_noreturn.ll b/llvm/test/Transforms/Attributor/noreturn.ll
similarity index 100%
rename from llvm/test/Transforms/FunctionAttrs/fn_noreturn.ll
rename to llvm/test/Transforms/Attributor/noreturn.ll

diff  --git a/llvm/test/Transforms/FunctionAttrs/noreturn_async.ll b/llvm/test/Transforms/Attributor/noreturn_async.ll
similarity index 96%
rename from llvm/test/Transforms/FunctionAttrs/noreturn_async.ll
rename to llvm/test/Transforms/Attributor/noreturn_async.ll
index 3d2dd9f47da6..7c00a5a0b5cb 100644
--- a/llvm/test/Transforms/FunctionAttrs/noreturn_async.ll
+++ b/llvm/test/Transforms/Attributor/noreturn_async.ll
@@ -1,4 +1,4 @@
-; RUN: opt -functionattrs -attributor -attributor-disable=false -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=2 -S < %s | FileCheck %s
+; RUN: opt -attributor -attributor-disable=false -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=2 -S < %s | FileCheck %s
 ;
 ; This file is the same as noreturn_sync.ll but with a personality which
 ; indicates that the exception handler *can* catch asynchronous exceptions. As

diff  --git a/llvm/test/Transforms/FunctionAttrs/noreturn_sync.ll b/llvm/test/Transforms/Attributor/noreturn_sync.ll
similarity index 96%
rename from llvm/test/Transforms/FunctionAttrs/noreturn_sync.ll
rename to llvm/test/Transforms/Attributor/noreturn_sync.ll
index b5a70e762716..4e6f13737a7e 100644
--- a/llvm/test/Transforms/FunctionAttrs/noreturn_sync.ll
+++ b/llvm/test/Transforms/Attributor/noreturn_sync.ll
@@ -1,4 +1,4 @@
-; RUN: opt -functionattrs -attributor -attributor-disable=false -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=2 -S < %s | FileCheck %s
+; RUN: opt -attributor -attributor-disable=false -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=2 -S < %s | FileCheck %s
 ;
 ; This file is the same as noreturn_async.ll but with a personality which
 ; indicates that the exception handler *cannot* catch asynchronous exceptions.

diff  --git a/llvm/test/Transforms/FunctionAttrs/nosync.ll b/llvm/test/Transforms/Attributor/nosync.ll
similarity index 82%
rename from llvm/test/Transforms/FunctionAttrs/nosync.ll
rename to llvm/test/Transforms/Attributor/nosync.ll
index abb40cf26697..cd01a0caa58d 100644
--- a/llvm/test/Transforms/FunctionAttrs/nosync.ll
+++ b/llvm/test/Transforms/Attributor/nosync.ll
@@ -1,4 +1,3 @@
-; RUN: opt -functionattrs -S < %s | FileCheck %s --check-prefix=FNATTR
 ; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=2 -S < %s | FileCheck %s --check-prefix=ATTRIBUTOR
 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
 
@@ -25,8 +24,6 @@ target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
 %struct.RT = type { i8, [10 x [20 x i32]], i8 }
 %struct.ST = type { i32, double, %struct.RT }
 
-; 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* nofree nonnull readnone "no-capture-maybe-returned" %s)
 define i32* @foo(%struct.ST* %s) nounwind uwtable readnone optsize ssp {
@@ -42,8 +39,6 @@ entry:
 ;   return n;
 ; }
 
-; FNATTR: Function Attrs: nofree norecurse nounwind uwtable
-; FNATTR-NEXT: define i32 @load_monotonic(i32* nocapture readonly %0)
 ; ATTRIBUTOR: Function Attrs: nofree norecurse nosync nounwind uwtable
 ; ATTRIBUTOR-NEXT: define i32 @load_monotonic(i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) %0)
 define i32 @load_monotonic(i32* nocapture readonly %0) norecurse nounwind uwtable {
@@ -58,8 +53,6 @@ define i32 @load_monotonic(i32* nocapture readonly %0) norecurse nounwind uwtabl
 ;   atomic_load_explicit(num, memory_order_relaxed);
 ; }
 
-; FNATTR: Function Attrs: nofree norecurse nounwind uwtable
-; FNATTR-NEXT: define void @store_monotonic(i32* nocapture %0)
 ; ATTRIBUTOR: Function Attrs: nofree norecurse nosync nounwind uwtable
 ; ATTRIBUTOR-NEXT: define void @store_monotonic(i32* nocapture nofree nonnull writeonly align 4 dereferenceable(4) %0)
 define void @store_monotonic(i32* nocapture %0) norecurse nounwind uwtable {
@@ -74,8 +67,6 @@ define void @store_monotonic(i32* nocapture %0) norecurse nounwind uwtable {
 ;   return n;
 ; }
 
-; FNATTR: Function Attrs: nofree norecurse nounwind uwtable
-; FNATTR-NEXT: define i32 @load_acquire(i32* nocapture readonly %0)
 ; ATTRIBUTOR: Function Attrs: nofree norecurse nounwind uwtable
 ; ATTRIBUTOR-NOT: nosync
 ; ATTRIBUTOR-NEXT: define i32 @load_acquire(i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) %0)
@@ -90,8 +81,6 @@ define i32 @load_acquire(i32* nocapture readonly %0) norecurse nounwind uwtable
 ;   atomic_store_explicit(num, 10, memory_order_release);
 ; }
 
-; FNATTR: Function Attrs: nofree norecurse nounwind uwtable
-; FNATTR-NEXT: define void @load_release(i32* nocapture %0)
 ; ATTRIBUTOR: Function Attrs: nofree norecurse nounwind uwtable
 ; ATTRIBUTOR-NOT: nosync
 ; ATTRIBUTOR-NEXT: define void @load_release(i32* nocapture nofree writeonly align 4 %0)
@@ -102,8 +91,6 @@ define void @load_release(i32* nocapture %0) norecurse nounwind uwtable {
 
 ; TEST 6 - negative volatile, relaxed atomic
 
-; FNATTR: Function Attrs: nofree norecurse nounwind uwtable
-; FNATTR-NEXT: define void @load_volatile_release(i32* nocapture %0)
 ; ATTRIBUTOR: Function Attrs: nofree norecurse nounwind uwtable
 ; ATTRIBUTOR-NOT: nosync
 ; ATTRIBUTOR-NEXT: define void @load_volatile_release(i32* nocapture nofree writeonly align 4 %0)
@@ -118,8 +105,6 @@ define void @load_volatile_release(i32* nocapture %0) norecurse nounwind uwtable
 ;   *num = 14;
 ; }
 
-; FNATTR: Function Attrs: nofree norecurse nounwind uwtable
-; FNATTR-NEXT: define void @volatile_store(i32* %0)
 ; ATTRIBUTOR: Function Attrs: nofree norecurse nounwind uwtable
 ; ATTRIBUTOR-NOT: nosync
 ; ATTRIBUTOR-NEXT: define void @volatile_store(i32* nofree align 4 %0)
@@ -135,8 +120,6 @@ define void @volatile_store(i32* %0) norecurse nounwind uwtable {
 ;   return n;
 ; }
 
-; FNATTR: Function Attrs: nofree norecurse nounwind uwtable
-; FNATTR-NEXT: define i32 @volatile_load(i32* %0)
 ; ATTRIBUTOR: Function Attrs: nofree norecurse nounwind uwtable
 ; ATTRIBUTOR-NOT: nosync
 ; ATTRIBUTOR-NEXT: define i32 @volatile_load(i32* nofree align 4 %0)
@@ -147,14 +130,10 @@ define i32 @volatile_load(i32* %0) norecurse nounwind uwtable {
 
 ; TEST 9
 
-; FNATTR: Function Attrs: noinline nosync nounwind uwtable
-; FNATTR-NEXT: declare void @nosync_function()
 ; ATTRIBUTOR: Function Attrs: noinline nosync nounwind uwtable
 ; ATTRIBUTOR-NEXT: declare void @nosync_function()
 declare void @nosync_function() noinline nounwind uwtable nosync
 
-; FNATTR: Function Attrs: noinline nounwind uwtable
-; FNATTR-NEXT: define void @call_nosync_function()
 ; ATTRIBUTOR: Function Attrs: noinline nosync nounwind uwtable
 ; ATTRIBUTOR-next: define void @call_nosync_function()
 define void @call_nosync_function() nounwind uwtable noinline {
@@ -164,14 +143,10 @@ define void @call_nosync_function() nounwind uwtable noinline {
 
 ; TEST 10 - negative, should not deduce nosync
 
-; FNATTR: Function Attrs: noinline nounwind uwtable
-; FNATTR-NEXT: declare void @might_sync()
 ; ATTRIBUTOR: Function Attrs: noinline nounwind uwtable
 ; ATTRIBUTOR-NEXT: declare void @might_sync()
 declare void @might_sync() noinline nounwind uwtable
 
-; FNATTR: Function Attrs: noinline nounwind uwtable
-; FNATTR-NEXT: define void @call_might_sync()
 ; ATTRIBUTOR: Function Attrs: noinline nounwind uwtable
 ; ATTRIBUTOR-NOT: nosync
 ; ATTRIBUTOR-NEXT: define void @call_might_sync()
@@ -183,8 +158,6 @@ define void @call_might_sync() nounwind uwtable noinline {
 ; TEST 11 - positive, should deduce nosync
 ; volatile operation in same scc but dead. Call volatile_load defined in TEST 8.
 
-; FNATTR: Function Attrs: nofree noinline nounwind uwtable
-; FNATTR-NEXT: define i32 @scc1(i32* %0)
 ; ATTRIBUTOR: Function Attrs: nofree noinline noreturn nosync nounwind readnone uwtable
 ; ATTRIBUTOR-NEXT: define i32 @scc1(i32* nocapture nofree readnone %0)
 define i32 @scc1(i32* %0) noinline nounwind uwtable {
@@ -193,8 +166,6 @@ define i32 @scc1(i32* %0) noinline nounwind uwtable {
   ret i32 %val;
 }
 
-; FNATTR: Function Attrs: nofree noinline nounwind uwtable
-; FNATTR-NEXT: define void @scc2(i32* %0)
 ; ATTRIBUTOR: Function Attrs: nofree noinline noreturn nosync nounwind readnone uwtable
 ; ATTRIBUTOR-NEXT: define void @scc2(i32* nocapture nofree readnone %0)
 define void @scc2(i32* %0) noinline nounwind uwtable {
@@ -221,8 +192,6 @@ define void @scc2(i32* %0) noinline nounwind uwtable {
 %"struct.std::atomic" = type { %"struct.std::__atomic_base" }
 %"struct.std::__atomic_base" = type { i8 }
 
-; 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* nocapture nofree nonnull writeonly align 4 dereferenceable(4) %0, %"struct.std::atomic"* nocapture nofree nonnull writeonly dereferenceable(1) %1)
 
@@ -234,8 +203,6 @@ define void @foo1(i32* %0, %"struct.std::atomic"* %1) {
   ret void
 }
 
-; 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* nocapture nofree readnone %0, %"struct.std::atomic"* nocapture nofree nonnull readonly dereferenceable(1) %1)
 define void @bar(i32* %0, %"struct.std::atomic"* %1) {
@@ -254,8 +221,6 @@ define void @bar(i32* %0, %"struct.std::atomic"* %1) {
 }
 
 ; TEST 13 - Fence syncscope("singlethread") seq_cst
-; 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 nounwind willreturn
 ; ATTRIBUTOR: define void @foo1_singlethread(i32* nocapture nofree nonnull writeonly align 4 dereferenceable(4) %0, %"struct.std::atomic"* nocapture nofree nonnull writeonly dereferenceable(1) %1)
 
@@ -267,8 +232,6 @@ define void @foo1_singlethread(i32* %0, %"struct.std::atomic"* %1) {
   ret void
 }
 
-; 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 nounwind
 ; ATTRIBUTOR: define void @bar_singlethread(i32* nocapture nofree readnone %0, %"struct.std::atomic"* nocapture nofree nonnull readonly dereferenceable(1) %1)
 define void @bar_singlethread(i32* %0, %"struct.std::atomic"* %1) {

diff  --git a/llvm/test/Transforms/Attributor/nounwind.ll b/llvm/test/Transforms/Attributor/nounwind.ll
new file mode 100644
index 000000000000..e569095c8d41
--- /dev/null
+++ b/llvm/test/Transforms/Attributor/nounwind.ll
@@ -0,0 +1,98 @@
+; RUN: opt < %s -attributor -attributor-disable=false -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=3 -S | FileCheck %s --check-prefix=ATTRIBUTOR
+; Copied from Transforms/FunctoinAttrs/nounwind.ll
+
+; TEST 1
+; ATTRIBUTOR: Function Attrs: nofree nosync nounwind
+; ATTRIBUTOR-NEXT: define i32 @foo1()
+define i32 @foo1() {
+  ret i32 1
+}
+
+; TEST 2
+; ATTRIBUTOR: Function Attrs: nofree noreturn nosync nounwind
+; ATTRIBUTOR-NEXT: define i32 @scc1_foo()
+define i32 @scc1_foo() {
+  %1 = call i32 @scc1_bar()
+  ret i32 1
+}
+
+
+; TEST 3
+; ATTRIBUTOR: Function Attrs: nofree noreturn nosync nounwind
+; ATTRIBUTOR-NEXT: define i32 @scc1_bar()
+define i32 @scc1_bar() {
+  %1 = call i32 @scc1_foo()
+  ret i32 1
+}
+
+declare i32 @non_nounwind()
+
+; TEST 4
+; ATTRIBUTOR: define void @call_non_nounwind() {
+define void @call_non_nounwind(){
+    tail call i32 @non_nounwind()
+    ret void
+}
+
+; TEST 5 - throw
+; int maybe_throw(bool canThrow) {
+;   if (canThrow)
+;     throw;
+;   else
+;     return -1;
+; }
+
+; ATTRIBUTOR: define i32 @maybe_throw(i1 zeroext %0)
+define i32 @maybe_throw(i1 zeroext %0) {
+  br i1 %0, label %2, label %3
+
+2:                                                ; preds = %1
+  tail call void @__cxa_rethrow() #1
+  unreachable
+
+3:                                                ; preds = %1
+  ret i32 -1
+}
+
+declare void @__cxa_rethrow()
+
+; TEST 6 - catch
+; int catch_thing() {
+;   try {
+;       int a = doThing(true);
+;   }
+;   catch(...) { return -1; }
+;   return 1;
+; }
+
+; ATTRIBUTOR: define i32 @catch_thing()
+define i32 @catch_thing() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
+  invoke void @__cxa_rethrow() #1
+          to label %1 unwind label %2
+
+1:                                                ; preds = %0
+  unreachable
+
+2:                                                ; preds = %0
+  %3 = landingpad { i8*, i32 }
+          catch i8* null
+  %4 = extractvalue { i8*, i32 } %3, 0
+  %5 = tail call i8* @__cxa_begin_catch(i8* %4) #2
+  tail call void @__cxa_end_catch()
+  ret i32 -1
+}
+
+define i32 @catch_thing_user() {
+; ATTRIBUTOR:     define i32 @catch_thing_user
+; ATTRIBUTOR-NEXT: %catch_thing_call = call
+; ATTRIBUTOR-NEXT: ret i32 -1
+  %catch_thing_call = call i32 @catch_thing()
+  ret i32 %catch_thing_call
+}
+
+
+declare i32 @__gxx_personality_v0(...)
+
+declare i8* @__cxa_begin_catch(i8*)
+
+declare void @__cxa_end_catch()

diff  --git a/llvm/test/Transforms/FunctionAttrs/read_write_returned_arguments_scc.ll b/llvm/test/Transforms/Attributor/read_write_returned_arguments_scc.ll
similarity index 100%
rename from llvm/test/Transforms/FunctionAttrs/read_write_returned_arguments_scc.ll
rename to llvm/test/Transforms/Attributor/read_write_returned_arguments_scc.ll

diff  --git a/llvm/test/Transforms/Attributor/readattrs.ll b/llvm/test/Transforms/Attributor/readattrs.ll
new file mode 100644
index 000000000000..9c148ef160bf
--- /dev/null
+++ b/llvm/test/Transforms/Attributor/readattrs.ll
@@ -0,0 +1,145 @@
+; RUN: opt < %s -attributor -attributor-disable=false -S -attributor-annotate-decl-cs | FileCheck %s --check-prefixes=ATTRIBUTOR
+; RUN: opt < %s -aa-pipeline=basic-aa -passes='attributor' -attributor-disable=false -S -attributor-annotate-decl-cs | FileCheck %s --check-prefixes=ATTRIBUTOR
+; Copied from Transforms/FunctionAttrs/readattrs.ll
+
+ at x = global i32 0
+
+declare void @test1_1(i8* %x1_1, i8* readonly %y1_1, ...)
+
+; NOTE: readonly for %y1_2 would be OK here but not for the similar situation in test13.
+;
+; ATTRIBUTOR: define void @test1_2(i8* %x1_2, i8* %y1_2, i8* %z1_2)
+define void @test1_2(i8* %x1_2, i8* %y1_2, i8* %z1_2) {
+  call void (i8*, i8*, ...) @test1_1(i8* %x1_2, i8* %y1_2, i8* %z1_2)
+  store i32 0, i32* @x
+  ret void
+}
+
+; ATTRIBUTOR: define i8* @test2(i8* nofree readnone returned %p)
+define i8* @test2(i8* %p) {
+  store i32 0, i32* @x
+  ret i8* %p
+}
+
+; ATTRIBUTOR: define i1 @test3(i8* nofree readnone %p, i8* nofree readnone %q)
+define i1 @test3(i8* %p, i8* %q) {
+  %A = icmp ult i8* %p, %q
+  ret i1 %A
+}
+
+declare void @test4_1(i8* nocapture) readonly
+
+; ATTRIBUTOR: define void @test4_2(i8* nocapture readonly %p)
+define void @test4_2(i8* %p) {
+  call void @test4_1(i8* %p)
+  ret void
+}
+
+; ATTRIBUTOR: define void @test5(i8** nocapture nofree nonnull writeonly dereferenceable(8) %p, i8* nofree writeonly %q)
+; Missed optz'n: we could make %q readnone, but don't break test6!
+define void @test5(i8** %p, i8* %q) {
+  store i8* %q, i8** %p
+  ret void
+}
+
+declare void @test6_1()
+; ATTRIBUTOR: define void @test6_2(i8** nocapture nonnull writeonly dereferenceable(8) %p, i8* %q)
+; This is not a missed optz'n.
+define void @test6_2(i8** %p, i8* %q) {
+  store i8* %q, i8** %p
+  call void @test6_1()
+  ret void
+}
+
+; ATTRIBUTOR: define void @test7_1(i32* inalloca nocapture nofree writeonly %a)
+; inalloca parameters are always considered written
+define void @test7_1(i32* inalloca %a) {
+  ret void
+}
+
+; ATTRIBUTOR: define i32* @test8_1(i32* nofree readnone returned %p)
+define i32* @test8_1(i32* %p) {
+entry:
+  ret i32* %p
+}
+
+; ATTRIBUTOR: define void @test8_2(i32* nocapture nofree writeonly %p)
+define void @test8_2(i32* %p) {
+entry:
+  %call = call i32* @test8_1(i32* %p)
+  store i32 10, i32* %call, align 4
+  ret void
+}
+
+; ATTRIBUTOR: declare void @llvm.masked.scatter
+declare void @llvm.masked.scatter.v4i32.v4p0i32(<4 x i32>%val, <4 x i32*>, i32, <4 x i1>)
+
+; ATTRIBUTOR-NOT: readnone
+; ATTRIBUTOR-NOT: readonly
+; ATTRIBUTOR: define void @test9
+define void @test9(<4 x i32*> %ptrs, <4 x i32>%val) {
+  call void @llvm.masked.scatter.v4i32.v4p0i32(<4 x i32>%val, <4 x i32*> %ptrs, i32 4, <4 x i1><i1 true, i1 false, i1 true, i1 false>)
+  ret void
+}
+
+; ATTRIBUTOR: declare <4 x i32> @llvm.masked.gather
+declare <4 x i32> @llvm.masked.gather.v4i32.v4p0i32(<4 x i32*>, i32, <4 x i1>, <4 x i32>)
+; ATTRIBUTOR: readonly
+; ATTRIBUTOR: define <4 x i32> @test10
+define <4 x i32> @test10(<4 x i32*> %ptrs) {
+  %res = call <4 x i32> @llvm.masked.gather.v4i32.v4p0i32(<4 x i32*> %ptrs, i32 4, <4 x i1><i1 true, i1 false, i1 true, i1 false>, <4 x i32>undef)
+  ret <4 x i32> %res
+}
+
+; ATTRIBUTOR: declare <4 x i32> @test11_1
+declare <4 x i32> @test11_1(<4 x i32*>) argmemonly nounwind readonly
+; ATTRIBUTOR: readonly
+; ATTRIBUTOR-NOT: readnone
+; ATTRIBUTOR: define <4 x i32> @test11_2
+define <4 x i32> @test11_2(<4 x i32*> %ptrs) {
+  %res = call <4 x i32> @test11_1(<4 x i32*> %ptrs)
+  ret <4 x i32> %res
+}
+
+declare <4 x i32> @test12_1(<4 x i32*>) argmemonly nounwind
+; ATTRIBUTOR-NOT: readnone
+; ATTRIBUTOR: define <4 x i32> @test12_2
+define <4 x i32> @test12_2(<4 x i32*> %ptrs) {
+  %res = call <4 x i32> @test12_1(<4 x i32*> %ptrs)
+  ret <4 x i32> %res
+}
+
+; ATTRIBUTOR: define i32 @volatile_load(
+; ATTRIBUTOR-NOT: readonly
+; ATTRIBUTOR: ret
+define i32 @volatile_load(i32* %p) {
+  %load = load volatile i32, i32* %p
+  ret i32 %load
+}
+
+declare void @escape_readnone_ptr(i8** %addr, i8* readnone %ptr)
+declare void @escape_readonly_ptr(i8** %addr, i8* readonly %ptr)
+
+; The argument pointer %escaped_then_written cannot be marked readnone/only even
+; though the only direct use, in @escape_readnone_ptr/@escape_readonly_ptr,
+; is marked as readnone/only. However, the functions can write the pointer into
+; %addr, causing the store to write to %escaped_then_written.
+;
+;
+; ATTRIBUTOR: define void @unsound_readnone(i8* nocapture nofree readnone %ignored, i8* %escaped_then_written)
+; ATTRIBUTOR: define void @unsound_readonly(i8* nocapture nofree readnone %ignored, i8* %escaped_then_written)
+define void @unsound_readnone(i8* %ignored, i8* %escaped_then_written) {
+  %addr = alloca i8*
+  call void @escape_readnone_ptr(i8** %addr, i8* %escaped_then_written)
+  %addr.ld = load i8*, i8** %addr
+  store i8 0, i8* %addr.ld
+  ret void
+}
+
+define void @unsound_readonly(i8* %ignored, i8* %escaped_then_written) {
+  %addr = alloca i8*
+  call void @escape_readonly_ptr(i8** %addr, i8* %escaped_then_written)
+  %addr.ld = load i8*, i8** %addr
+  store i8 0, i8* %addr.ld
+  ret void
+}

diff  --git a/llvm/test/Transforms/Attributor/returned.ll b/llvm/test/Transforms/Attributor/returned.ll
new file mode 100644
index 000000000000..85ab69a0d99a
--- /dev/null
+++ b/llvm/test/Transforms/Attributor/returned.ll
@@ -0,0 +1,812 @@
+; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=5 -S < %s | FileCheck %s --check-prefix=ATTRIBUTOR
+; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -attributor-annotate-decl-cs -functionattrs -S < %s | FileCheck %s --check-prefix=BOTH
+;
+; Copied from Transforms/FunctoinAttrs/read_write_returned_arguments_scc.ll
+; 
+; Test cases specifically designed for the "returned" argument attribute.
+; We use FIXME's to indicate problems and missing attributes.
+;
+
+; TEST SCC test returning an integer value argument
+;
+; BOTH: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable
+; BOTH-NEXT: define i32 @sink_r0(i32 returned %r)
+; BOTH: Function Attrs: nofree noinline nosync nounwind readnone uwtable
+; BOTH-NEXT: define i32 @scc_r1(i32 %a, i32 returned %r, i32 %b)
+; BOTH: Function Attrs: nofree noinline nosync nounwind readnone uwtable
+; BOTH-NEXT: define i32 @scc_r2(i32 %a, i32 %b, i32 returned %r)
+; BOTH: Function Attrs: nofree noinline nosync nounwind readnone uwtable
+; BOTH-NEXT: define i32 @scc_rX(i32 %a, i32 %b, i32 %r)
+;
+;
+; ATTRIBUTOR: define i32 @sink_r0(i32 returned %r)
+; ATTRIBUTOR: define i32 @scc_r1(i32 %a, i32 returned %r, i32 %b)
+; ATTRIBUTOR: define i32 @scc_r2(i32 %a, i32 %b, i32 returned %r)
+; ATTRIBUTOR: define i32 @scc_rX(i32 %a, i32 %b, i32 %r)
+;
+; int scc_r1(int a, int b, int r);
+; int scc_r2(int a, int b, int r);
+;
+; __attribute__((noinline)) int sink_r0(int r) {
+;   return r;
+; }
+;
+; __attribute__((noinline)) int scc_r1(int a, int r, int b) {
+;   return scc_r2(r, a, sink_r0(r));
+; }
+;
+; __attribute__((noinline)) int scc_r2(int a, int b, int r) {
+;   if (a > b)
+;     return scc_r2(b, a, sink_r0(r));
+;   if (a < b)
+;     return scc_r1(sink_r0(b), scc_r2(scc_r1(a, b, r), scc_r1(a, scc_r2(r, r, r), r), scc_r2(a, b, r)), scc_r1(a, b, r));
+;   return a == b ? r : scc_r2(a, b, r);
+; }
+; __attribute__((noinline)) int scc_rX(int a, int b, int r) {
+;   if (a > b)
+;     return scc_r2(b, a, sink_r0(r));
+;   if (a < b)                                                                         // V Diff to scc_r2
+;     return scc_r1(sink_r0(b), scc_r2(scc_r1(a, b, r), scc_r1(a, scc_r2(r, r, r), r), scc_r1(a, b, r)), scc_r1(a, b, r));
+;   return a == b ? r : scc_r2(a, b, r);
+; }
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define i32 @sink_r0(i32 %r) #0 {
+entry:
+  ret i32 %r
+}
+
+define i32 @scc_r1(i32 %a, i32 %r, i32 %b) #0 {
+entry:
+  %call = call i32 @sink_r0(i32 %r)
+  %call1 = call i32 @scc_r2(i32 %r, i32 %a, i32 %call)
+  ret i32 %call1
+}
+
+define i32 @scc_r2(i32 %a, i32 %b, i32 %r) #0 {
+entry:
+  %cmp = icmp sgt i32 %a, %b
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:                                          ; preds = %entry
+  %call = call i32 @sink_r0(i32 %r)
+  %call1 = call i32 @scc_r2(i32 %b, i32 %a, i32 %call)
+  br label %return
+
+if.end:                                           ; preds = %entry
+  %cmp2 = icmp slt i32 %a, %b
+  br i1 %cmp2, label %if.then3, label %if.end12
+
+if.then3:                                         ; preds = %if.end
+  %call4 = call i32 @sink_r0(i32 %b)
+  %call5 = call i32 @scc_r1(i32 %a, i32 %b, i32 %r)
+  %call6 = call i32 @scc_r2(i32 %r, i32 %r, i32 %r)
+  %call7 = call i32 @scc_r1(i32 %a, i32 %call6, i32 %r)
+  %call8 = call i32 @scc_r2(i32 %a, i32 %b, i32 %r)
+  %call9 = call i32 @scc_r2(i32 %call5, i32 %call7, i32 %call8)
+  %call10 = call i32 @scc_r1(i32 %a, i32 %b, i32 %r)
+  %call11 = call i32 @scc_r1(i32 %call4, i32 %call9, i32 %call10)
+  br label %return
+
+if.end12:                                         ; preds = %if.end
+  %cmp13 = icmp eq i32 %a, %b
+  br i1 %cmp13, label %cond.true, label %cond.false
+
+cond.true:                                        ; preds = %if.end12
+  br label %cond.end
+
+cond.false:                                       ; preds = %if.end12
+  %call14 = call i32 @scc_r2(i32 %a, i32 %b, i32 %r)
+  br label %cond.end
+
+cond.end:                                         ; preds = %cond.false, %cond.true
+  %cond = phi i32 [ %r, %cond.true ], [ %call14, %cond.false ]
+  br label %return
+
+return:                                           ; preds = %cond.end, %if.then3, %if.then
+  %retval.0 = phi i32 [ %call1, %if.then ], [ %call11, %if.then3 ], [ %cond, %cond.end ]
+  ret i32 %retval.0
+}
+
+define i32 @scc_rX(i32 %a, i32 %b, i32 %r) #0 {
+entry:
+  %cmp = icmp sgt i32 %a, %b
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:                                          ; preds = %entry
+  %call = call i32 @sink_r0(i32 %r)
+  %call1 = call i32 @scc_r2(i32 %b, i32 %a, i32 %call)
+  br label %return
+
+if.end:                                           ; preds = %entry
+  %cmp2 = icmp slt i32 %a, %b
+  br i1 %cmp2, label %if.then3, label %if.end12
+
+if.then3:                                         ; preds = %if.end
+  %call4 = call i32 @sink_r0(i32 %b)
+  %call5 = call i32 @scc_r1(i32 %a, i32 %b, i32 %r)
+  %call6 = call i32 @scc_r2(i32 %r, i32 %r, i32 %r)
+  %call7 = call i32 @scc_r1(i32 %a, i32 %call6, i32 %r)
+  %call8 = call i32 @scc_r1(i32 %a, i32 %b, i32 %r)
+  %call9 = call i32 @scc_r2(i32 %call5, i32 %call7, i32 %call8)
+  %call10 = call i32 @scc_r1(i32 %a, i32 %b, i32 %r)
+  %call11 = call i32 @scc_r1(i32 %call4, i32 %call9, i32 %call10)
+  br label %return
+
+if.end12:                                         ; preds = %if.end
+  %cmp13 = icmp eq i32 %a, %b
+  br i1 %cmp13, label %cond.true, label %cond.false
+
+cond.true:                                        ; preds = %if.end12
+  br label %cond.end
+
+cond.false:                                       ; preds = %if.end12
+  %call14 = call i32 @scc_r2(i32 %a, i32 %b, i32 %r)
+  br label %cond.end
+
+cond.end:                                         ; preds = %cond.false, %cond.true
+  %cond = phi i32 [ %r, %cond.true ], [ %call14, %cond.false ]
+  br label %return
+
+return:                                           ; preds = %cond.end, %if.then3, %if.then
+  %retval.0 = phi i32 [ %call1, %if.then ], [ %call11, %if.then3 ], [ %cond, %cond.end ]
+  ret i32 %retval.0
+}
+
+
+; TEST SCC test returning a pointer value argument
+;
+;
+; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind readnone uwtable
+; ATTRIBUTOR-NEXT: define double* @ptr_sink_r0(double* nofree readnone returned "no-capture-maybe-returned" %r)
+; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind readnone uwtable
+; ATTRIBUTOR-NEXT: define double* @ptr_scc_r1(double* nofree readnone %a, double* nofree readnone returned %r, double* nocapture nofree readnone %b)
+; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind readnone uwtable
+; ATTRIBUTOR-NEXT: define double* @ptr_scc_r2(double* nofree readnone %a, double* nofree readnone %b, double* nofree readnone returned %r)
+;
+; double* ptr_scc_r1(double* a, double* b, double* r);
+; double* ptr_scc_r2(double* a, double* b, double* r);
+;
+; __attribute__((noinline)) double* ptr_sink_r0(double* r) {
+;   return r;
+; }
+;
+; __attribute__((noinline)) double* ptr_scc_r1(double* a, double* r, double* b) {
+;   return ptr_scc_r2(r, a, ptr_sink_r0(r));
+; }
+;
+; __attribute__((noinline)) double* ptr_scc_r2(double* a, double* b, double* r) {
+;   if (a > b)
+;     return ptr_scc_r2(b, a, ptr_sink_r0(r));
+;   if (a < b)
+;     return ptr_scc_r1(ptr_sink_r0(b), ptr_scc_r2(ptr_scc_r1(a, b, r), ptr_scc_r1(a, ptr_scc_r2(r, r, r), r), ptr_scc_r2(a, b, r)), ptr_scc_r1(a, b, r));
+;   return a == b ? r : ptr_scc_r2(a, b, r);
+; }
+define double* @ptr_sink_r0(double* %r) #0 {
+entry:
+  ret double* %r
+}
+
+define double* @ptr_scc_r1(double* %a, double* %r, double* %b) #0 {
+entry:
+  %call = call double* @ptr_sink_r0(double* %r)
+  %call1 = call double* @ptr_scc_r2(double* %r, double* %a, double* %call)
+  ret double* %call1
+}
+
+define double* @ptr_scc_r2(double* %a, double* %b, double* %r) #0 {
+entry:
+  %cmp = icmp ugt double* %a, %b
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:                                          ; preds = %entry
+  %call = call double* @ptr_sink_r0(double* %r)
+  %call1 = call double* @ptr_scc_r2(double* %b, double* %a, double* %call)
+  br label %return
+
+if.end:                                           ; preds = %entry
+  %cmp2 = icmp ult double* %a, %b
+  br i1 %cmp2, label %if.then3, label %if.end12
+
+if.then3:                                         ; preds = %if.end
+  %call4 = call double* @ptr_sink_r0(double* %b)
+  %call5 = call double* @ptr_scc_r1(double* %a, double* %b, double* %r)
+  %call6 = call double* @ptr_scc_r2(double* %r, double* %r, double* %r)
+  %call7 = call double* @ptr_scc_r1(double* %a, double* %call6, double* %r)
+  %call8 = call double* @ptr_scc_r2(double* %a, double* %b, double* %r)
+  %call9 = call double* @ptr_scc_r2(double* %call5, double* %call7, double* %call8)
+  %call10 = call double* @ptr_scc_r1(double* %a, double* %b, double* %r)
+  %call11 = call double* @ptr_scc_r1(double* %call4, double* %call9, double* %call10)
+  br label %return
+
+if.end12:                                         ; preds = %if.end
+  %cmp13 = icmp eq double* %a, %b
+  br i1 %cmp13, label %cond.true, label %cond.false
+
+cond.true:                                        ; preds = %if.end12
+  br label %cond.end
+
+cond.false:                                       ; preds = %if.end12
+  %call14 = call double* @ptr_scc_r2(double* %a, double* %b, double* %r)
+  br label %cond.end
+
+cond.end:                                         ; preds = %cond.false, %cond.true
+  %cond = phi double* [ %r, %cond.true ], [ %call14, %cond.false ]
+  br label %return
+
+return:                                           ; preds = %cond.end, %if.then3, %if.then
+  %retval.0 = phi double* [ %call1, %if.then ], [ %call11, %if.then3 ], [ %cond, %cond.end ]
+  ret double* %retval.0
+}
+
+
+; TEST a no-return singleton SCC
+;
+; int* rt0(int *a) {
+;   return *a ? a : rt0(a);
+; }
+;
+; BOTH:      Function Attrs: nofree noinline norecurse noreturn nosync nounwind readonly uwtable
+; BOTH-NEXT: define noalias nonnull align 536870912 dereferenceable(4294967295) i32* @rt0(i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) %a)
+define i32* @rt0(i32* %a) #0 {
+entry:
+  %v = load i32, i32* %a, align 4
+  %tobool = icmp ne i32 %v, 0
+  %call = call i32* @rt0(i32* %a)
+  %sel = select i1 %tobool, i32* %a, i32* %call
+  ret i32* %sel
+}
+
+; TEST a no-return singleton SCC
+;
+; int* rt1(int *a) {
+;   return *a ? undef : rt1(a);
+; }
+;
+; BOTH: Function Attrs: nofree noinline norecurse noreturn nosync nounwind readonly uwtable
+; BOTH-NEXT:    define noalias nonnull align 536870912 dereferenceable(4294967295) i32* @rt1(i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) %a)
+define i32* @rt1(i32* %a) #0 {
+entry:
+  %v = load i32, i32* %a, align 4
+  %tobool = icmp ne i32 %v, 0
+  %call = call i32* @rt1(i32* %a)
+  %sel = select i1 %tobool, i32* undef, i32* %call
+  ret i32* %sel
+}
+
+; TEST another SCC test
+;
+; BOTH:    define i32* @rt2_helper(i32* nofree readnone returned %a)
+; BOTH:    define i32* @rt2(i32* nofree readnone %a, i32* nofree readnone "no-capture-maybe-returned" %b)
+define i32* @rt2_helper(i32* %a) #0 {
+entry:
+  %call = call i32* @rt2(i32* %a, i32* %a)
+  ret i32* %call
+}
+
+define i32* @rt2(i32* %a, i32 *%b) #0 {
+entry:
+  %cmp = icmp eq i32* %a, null
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  %call = call i32* @rt2_helper(i32* %a)
+  br label %if.end
+
+if.end:
+  %sel = phi i32* [ %b, %entry], [%call, %if.then]
+  ret i32* %sel
+}
+
+; TEST another SCC test
+;
+; BOTH:    define i32* @rt3_helper(i32* nofree readnone %a, i32* nofree readnone returned "no-capture-maybe-returned" %b)
+; BOTH:    define i32* @rt3(i32* nofree readnone %a, i32* nofree 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)
+  ret i32* %call
+}
+
+define i32* @rt3(i32* %a, i32 *%b) #0 {
+entry:
+  %cmp = icmp eq i32* %a, null
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  %call = call i32* @rt3_helper(i32* %a, i32* %b)
+  br label %if.end
+
+if.end:
+  %sel = phi i32* [ %b, %entry], [%call, %if.then]
+  ret i32* %sel
+}
+
+; TEST address taken function with call to an external functions
+;
+;  void unknown_fn(void *);
+;
+;  int* calls_unknown_fn(int *r) {
+;    unknown_fn(&calls_unknown_fn);
+;    return r;
+;  }
+;
+; BOTH: declare void @unknown_fn(i32* (i32*)*)
+;
+; BOTH:       Function Attrs: noinline nounwind uwtable
+; BOTH-NEXT:  define i32* @calls_unknown_fn(i32* readnone returned "no-capture-maybe-returned" %r)
+; ATTRIBUTOR: define i32* @calls_unknown_fn(i32* readnone returned "no-capture-maybe-returned" %r)
+declare void @unknown_fn(i32* (i32*)*) #0
+
+define i32* @calls_unknown_fn(i32* %r) #0 {
+  tail call void @unknown_fn(i32* (i32*)* nonnull @calls_unknown_fn)
+  ret i32* %r
+}
+
+
+; TEST call to a function that might be redifined at link time
+;
+;  int *maybe_redefined_fn(int *r) {
+;    return r;
+;  }
+;
+;  int *calls_maybe_redefined_fn(int *r) {
+;    maybe_redefined_fn(r);
+;    return r;
+;  }
+;
+; Verify the maybe-redefined function is not annotated:
+;
+; ATTRIBUTOR: Function Attrs: noinline nounwind uwtable
+; ATTRIBUTOR: define linkonce_odr i32* @maybe_redefined_fn(i32* %r)
+;
+; ATTRIBUTOR: Function Attrs: noinline nounwind uwtable
+; ATTRIBUTOR: define i32* @calls_maybe_redefined_fn(i32* returned %r)
+;
+; BOTH: Function Attrs: noinline nounwind uwtable
+; BOTH-NEXT: define linkonce_odr i32* @maybe_redefined_fn(i32* %r)
+;
+; BOTH: Function Attrs: noinline nounwind uwtable
+; BOTH-NEXT: define i32* @calls_maybe_redefined_fn(i32* returned %r)
+define linkonce_odr i32* @maybe_redefined_fn(i32* %r) #0 {
+entry:
+  ret i32* %r
+}
+
+define i32* @calls_maybe_redefined_fn(i32* %r) #0 {
+entry:
+  %call = call i32* @maybe_redefined_fn(i32* %r)
+  ret i32* %r
+}
+
+; TEST return call to a function that might be redifined at link time
+;
+;  int *maybe_redefined_fn2(int *r) {
+;    return r;
+;  }
+;
+;  int *calls_maybe_redefined_fn2(int *r) {
+;    return maybe_redefined_fn2(r);
+;  }
+;
+; Verify the maybe-redefined function is not annotated:
+;
+; BOTH: Function Attrs: noinline nounwind uwtable
+; BOTH-NEXT: define linkonce_odr i32* @maybe_redefined_fn2(i32* %r)
+; BOTH: Function Attrs: noinline nounwind uwtable
+; BOTH-NEXT: define i32* @calls_maybe_redefined_fn2(i32* %r)
+;
+; ATTRIBUTOR: define i32* @calls_maybe_redefined_fn2(i32* %r)
+define linkonce_odr i32* @maybe_redefined_fn2(i32* %r) #0 {
+entry:
+  ret i32* %r
+}
+
+define i32* @calls_maybe_redefined_fn2(i32* %r) #0 {
+entry:
+  %call = call i32* @maybe_redefined_fn2(i32* %r)
+  ret i32* %call
+}
+
+
+; TEST returned argument goes through select and phi
+;
+; double select_and_phi(double b) {
+;   double x = b;
+;   if (b > 0)
+;     x = b;
+;   return b == 0? b : x;
+; }
+;
+; BOTH: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable
+; BOTH-NEXT: define double @select_and_phi(double returned %b)
+;
+; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind readnone uwtable
+; ATTRIBUTOR-NEXT: define double @select_and_phi(double returned %b)
+define double @select_and_phi(double %b) #0 {
+entry:
+  %cmp = fcmp ogt double %b, 0.000000e+00
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:                                          ; preds = %entry
+  br label %if.end
+
+if.end:                                           ; preds = %if.then, %entry
+  %phi = phi double [ %b, %if.then ], [ %b, %entry ]
+  %cmp1 = fcmp oeq double %b, 0.000000e+00
+  %sel = select i1 %cmp1, double %b, double %phi
+  ret double %sel
+}
+
+
+; TEST returned argument goes through recursion, select, and phi
+;
+; double recursion_select_and_phi(int a, double b) {
+;   double x = b;
+;   if (a-- > 0)
+;     x = recursion_select_and_phi(a, b);
+;   return b == 0? b : x;
+; }
+;
+; BOTH: Function Attrs: nofree noinline nosync nounwind readnone uwtable
+; BOTH-NEXT: define double @recursion_select_and_phi(i32 %a, double returned %b)
+;
+;
+; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind readnone uwtable
+; ATTRIBUTOR-NEXT: define double @recursion_select_and_phi(i32 %a, double returned %b)
+define double @recursion_select_and_phi(i32 %a, double %b) #0 {
+entry:
+  %dec = add nsw i32 %a, -1
+  %cmp = icmp sgt i32 %a, 0
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:                                          ; preds = %entry
+  %call = call double @recursion_select_and_phi(i32 %dec, double %b)
+  br label %if.end
+
+if.end:                                           ; preds = %if.then, %entry
+  %phi = phi double [ %call, %if.then ], [ %b, %entry ]
+  %cmp1 = fcmp oeq double %b, 0.000000e+00
+  %sel = select i1 %cmp1, double %b, double %phi
+  ret double %sel
+}
+
+
+; TEST returned argument goes through bitcasts
+;
+; double* bitcast(int* b) {
+;   return (double*)b;
+; }
+;
+; BOTH: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable
+; BOTH-NEXT:  define double* @bitcast(i32* nofree readnone returned "no-capture-maybe-returned" %b)
+;
+;
+; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind readnone uwtable
+; ATTRIBUTOR-NEXT: define double* @bitcast(i32* nofree readnone returned "no-capture-maybe-returned" %b)
+define double* @bitcast(i32* %b) #0 {
+entry:
+  %bc0 = bitcast i32* %b to double*
+  ret double* %bc0
+}
+
+
+; TEST returned argument goes through select and phi interleaved with bitcasts
+;
+; double* bitcasts_select_and_phi(int* b) {
+;   double* x = b;
+;   if (b == 0)
+;     x = b;
+;   return b != 0 ? b : x;
+; }
+;
+; BOTH: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable
+; BOTH-NEXT: define double* @bitcasts_select_and_phi(i32* nofree readnone returned %b)
+;
+;
+; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind readnone uwtable
+; ATTRIBUTOR-NEXT: define double* @bitcasts_select_and_phi(i32* nofree readnone returned %b)
+define double* @bitcasts_select_and_phi(i32* %b) #0 {
+entry:
+  %bc0 = bitcast i32* %b to double*
+  %cmp = icmp eq double* %bc0, null
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:                                          ; preds = %entry
+  %bc1 = bitcast i32* %b to double*
+  br label %if.end
+
+if.end:                                           ; preds = %if.then, %entry
+  %phi = phi double* [ %bc1, %if.then ], [ %bc0, %entry ]
+  %bc2 = bitcast double* %phi to i8*
+  %bc3 = bitcast i32* %b to i8*
+  %cmp2 = icmp ne double* %bc0, null
+  %sel = select i1 %cmp2, i8* %bc2, i8* %bc3
+  %bc4 = bitcast i8* %sel to double*
+  ret double* %bc4
+}
+
+
+; TEST return argument or argument or undef
+;
+; double* ret_arg_arg_undef(int* b) {
+;   if (b == 0)
+;     return (double*)b;
+;   if (b == 0)
+;     return (double*)b;
+;   /* return undef */
+; }
+;
+; BOTH: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable
+; BOTH-NEXT:  define double* @ret_arg_arg_undef(i32* nofree readnone returned %b)
+;
+;
+; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind readnone uwtable
+; ATTRIBUTOR-NEXT: define double* @ret_arg_arg_undef(i32* nofree readnone returned %b)
+define double* @ret_arg_arg_undef(i32* %b) #0 {
+entry:
+  %bc0 = bitcast i32* %b to double*
+  %cmp = icmp eq double* %bc0, null
+  br i1 %cmp, label %ret_arg0, label %if.end
+
+ret_arg0:
+  %bc1 = bitcast i32* %b to double*
+  ret double* %bc1
+
+if.end:
+  br i1 %cmp, label %ret_arg1, label %ret_undef
+
+ret_arg1:
+  ret double* %bc0
+
+ret_undef:
+  ret double *undef
+}
+
+
+; TEST return undef or argument or argument
+;
+; double* ret_undef_arg_arg(int* b) {
+;   if (b == 0)
+;     return (double*)b;
+;   if (b == 0)
+;     return (double*)b;
+;   /* return undef */
+; }
+;
+; BOTH: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable
+; BOTH-NEXT:  define double* @ret_undef_arg_arg(i32* nofree readnone returned %b)
+;
+;
+; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind readnone uwtable
+; ATTRIBUTOR-NEXT: define double* @ret_undef_arg_arg(i32* nofree readnone returned %b)
+define double* @ret_undef_arg_arg(i32* %b) #0 {
+entry:
+  %bc0 = bitcast i32* %b to double*
+  %cmp = icmp eq double* %bc0, null
+  br i1 %cmp, label %ret_undef, label %if.end
+
+ret_undef:
+  ret double *undef
+
+if.end:
+  br i1 %cmp, label %ret_arg0, label %ret_arg1
+
+ret_arg0:
+  ret double* %bc0
+
+ret_arg1:
+  %bc1 = bitcast i32* %b to double*
+  ret double* %bc1
+}
+
+
+; TEST return undef or argument or undef
+;
+; double* ret_undef_arg_undef(int* b) {
+;   if (b == 0)
+;     /* return undef */
+;   if (b == 0)
+;     return (double*)b;
+;   /* return undef */
+; }
+;
+; BOTH: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable
+; BOTH-NEXT:  define double* @ret_undef_arg_undef(i32* nofree readnone returned %b)
+;
+; ATTRIBUTOR: define double* @ret_undef_arg_undef(i32* nofree readnone returned %b)
+define double* @ret_undef_arg_undef(i32* %b) #0 {
+entry:
+  %bc0 = bitcast i32* %b to double*
+  %cmp = icmp eq double* %bc0, null
+  br i1 %cmp, label %ret_undef0, label %if.end
+
+ret_undef0:
+  ret double *undef
+
+if.end:
+  br i1 %cmp, label %ret_arg, label %ret_undef1
+
+ret_arg:
+  ret double* %bc0
+
+ret_undef1:
+  ret double *undef
+}
+
+; TEST return argument or unknown call result
+;
+; int* ret_arg_or_unknown(int* b) {
+;   if (b == 0)
+;     return b;
+;   return unknown();
+; }
+;
+; Verify we do not assume b is returned
+;
+; ATTRIBUTOR: define i32* @ret_arg_or_unknown(i32* %b)
+; ATTRIBUTOR: define i32* @ret_arg_or_unknown_through_phi(i32* %b)
+; BOTH:       define i32* @ret_arg_or_unknown(i32* %b)
+; BOTH:       define i32* @ret_arg_or_unknown_through_phi(i32* %b)
+declare i32* @unknown(i32*)
+
+define i32* @ret_arg_or_unknown(i32* %b) #0 {
+entry:
+  %cmp = icmp eq i32* %b, null
+  br i1 %cmp, label %ret_arg, label %ret_unknown
+
+ret_arg:
+  ret i32* %b
+
+ret_unknown:
+  %call = call i32* @unknown(i32* %b)
+  ret i32* %call
+}
+
+define i32* @ret_arg_or_unknown_through_phi(i32* %b) #0 {
+entry:
+  %cmp = icmp eq i32* %b, null
+  br i1 %cmp, label %ret_arg, label %ret_unknown
+
+ret_arg:
+  br label %r
+
+ret_unknown:
+  %call = call i32* @unknown(i32* %b)
+  br label %r
+
+r:
+  %phi = phi i32* [ %b, %ret_arg ], [ %call, %ret_unknown ]
+  ret i32* %phi
+}
+
+; TEST inconsistent IR in dead code.
+;
+; ATTRIBUTOR: define i32 @deadblockcall1(i32 returned %A)
+; ATTRIBUTOR: define i32 @deadblockcall2(i32 returned %A)
+; ATTRIBUTOR: define i32 @deadblockphi1(i32 returned %A)
+; ATTRIBUTOR: define i32 @deadblockphi2(i32 returned %A)
+; BOTH:       define i32 @deadblockcall1(i32 returned %A)
+; BOTH:       define i32 @deadblockcall2(i32 returned %A)
+; BOTH:       define i32 @deadblockphi1(i32 returned %A)
+; BOTH:       define i32 @deadblockphi2(i32 returned %A)
+define i32 @deadblockcall1(i32 %A) #0 {
+entry:
+  ret i32 %A
+unreachableblock:
+  %B = call i32 @deadblockcall1(i32 %B)
+  ret i32 %B
+}
+
+declare i32 @deadblockcall_helper(i32 returned %A);
+
+define i32 @deadblockcall2(i32 %A) #0 {
+entry:
+  ret i32 %A
+unreachableblock1:
+  %B = call i32 @deadblockcall_helper(i32 %B)
+  ret i32 %B
+unreachableblock2:
+  %C = call i32 @deadblockcall1(i32 %C)
+  ret i32 %C
+}
+
+define i32 @deadblockphi1(i32 %A) #0 {
+entry:
+  br label %r
+unreachableblock1:
+  %B = call i32 @deadblockcall_helper(i32 %B)
+  ret i32 %B
+unreachableblock2:
+  %C = call i32 @deadblockcall1(i32 %C)
+  br label %r
+r:
+  %PHI = phi i32 [%A, %entry], [%C, %unreachableblock2]
+  ret i32 %PHI
+}
+
+define i32 @deadblockphi2(i32 %A) #0 {
+entry:
+  br label %r
+unreachableblock1:
+  %B = call i32 @deadblockcall_helper(i32 %B)
+  br label %unreachableblock3
+unreachableblock2:
+  %C = call i32 @deadblockcall1(i32 %C)
+  br label %unreachableblock3
+unreachableblock3:
+  %PHI1 = phi i32 [%B, %unreachableblock1], [%C, %unreachableblock2]
+  br label %r
+r:
+  %PHI2 = phi i32 [%A, %entry], [%PHI1, %unreachableblock3]
+  ret i32 %PHI2
+}
+
+declare void @noreturn() noreturn;
+
+define i32 @deadblockphi3(i32 %A, i1 %c) #0 {
+entry:
+  br i1 %c, label %r, label %unreachablecall
+unreachablecall:
+  call void @noreturn();
+  %B = call i32 @deadblockcall_helper(i32 0)
+  br label %unreachableblock3
+unreachableblock2:
+  %C = call i32 @deadblockcall1(i32 %C)
+  br label %unreachableblock3
+unreachableblock3:
+  %PHI1 = phi i32 [%B, %unreachablecall], [%C, %unreachableblock2]
+  br label %r
+r:
+  %PHI2 = phi i32 [%A, %entry], [%PHI1, %unreachableblock3]
+  ret i32 %PHI2
+}
+
+define weak_odr i32 @non_exact_0() {
+  ret i32 0
+}
+define weak_odr i32 @non_exact_1(i32 %a) {
+  ret i32 %a
+}
+define weak_odr i32 @non_exact_2(i32 returned %a) {
+  ret i32 %a
+}
+define weak_odr i32* @non_exact_3(i32* align 32 returned %a) {
+  ret i32* %a
+}
+define i32 @exact(i32* %a) {
+  %c0 = call i32 @non_exact_0()
+  %c1 = call i32 @non_exact_1(i32 1)
+  %c2 = call i32 @non_exact_2(i32 2)
+  %c3 = call i32* @non_exact_3(i32* %a)
+; We can use the information of the weak function non_exact_3 because it was
+; given to us and not derived (the alignment of the returned argument).
+; ATTRIBUTOR:  %c4 = load i32, i32* %c3, align 32
+  %c4 = load i32, i32* %c3
+; FIXME: %c2 and %c3 should be replaced but not %c0 or %c1!
+; ATTRIBUTOR:  %add1 = add i32 %c0, %c1
+; ATTRIBUTOR:  %add2 = add i32 %add1, %c2
+; ATTRIBUTOR:  %add3 = add i32 %add2, %c4
+  %add1 = add i32 %c0, %c1
+  %add2 = add i32 %add1, %c2
+  %add3 = add i32 %add2, %c4
+  ret i32 %add3
+}
+
+ at G = external global i8
+define i32* @ret_const() #0 {
+  %bc = bitcast i8* @G to i32*
+  ret i32* %bc
+}
+define i32* @use_const() #0 {
+  %c = call i32* @ret_const()
+  ; ATTRIBUTOR: ret i32* bitcast (i8* @G to i32*)
+  ret i32* %c
+}
+define i32* @dont_use_const() #0 {
+  %c = musttail call i32* @ret_const()
+  ; ATTRIBUTOR: ret i32* %c
+  ret i32* %c
+}
+
+attributes #0 = { noinline nounwind uwtable }

diff  --git a/llvm/test/Transforms/FunctionAttrs/value-simplify.ll b/llvm/test/Transforms/Attributor/value-simplify.ll
similarity index 100%
rename from llvm/test/Transforms/FunctionAttrs/value-simplify.ll
rename to llvm/test/Transforms/Attributor/value-simplify.ll

diff  --git a/llvm/test/Transforms/FunctionAttrs/willreturn.ll b/llvm/test/Transforms/Attributor/willreturn.ll
similarity index 78%
rename from llvm/test/Transforms/FunctionAttrs/willreturn.ll
rename to llvm/test/Transforms/Attributor/willreturn.ll
index 8f7e46837c1e..90fef48b2a90 100644
--- a/llvm/test/Transforms/FunctionAttrs/willreturn.ll
+++ b/llvm/test/Transforms/Attributor/willreturn.ll
@@ -1,4 +1,3 @@
-; RUN: opt -functionattrs -S < %s | FileCheck %s --check-prefix=FNATTR
 ; RUN: opt -passes=attributor --attributor-disable=false -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=2 -S < %s | FileCheck %s --check-prefix=ATTRIBUTOR
 
 
@@ -9,8 +8,6 @@ target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
 
 
 ; TEST 1 (positive case)
-; FNATTR: Function Attrs: noinline norecurse nounwind readnone uwtable
-; FNATTR-NEXT: define void @only_return()
 ; ATTRIBUTOR: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable willreturn
 ; ATTRIBUTOR-NEXT: define void @only_return()
 define void @only_return() #0 {
@@ -25,8 +22,6 @@ define void @only_return() #0 {
 ;    return n<=1? n : fib(n-1) + fib(n-2);
 ; }
 
-; FNATTR: Function Attrs: noinline nounwind readnone uwtable
-; FNATTR-NEXT: define i32 @fib(i32 %0)
 ; FIXME: missing willreturn
 ; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind readnone uwtable
 ; ATTRIBUTOR-NEXT: define i32 @fib(i32 %0) local_unnamed_addr
@@ -56,9 +51,6 @@ define i32 @fib(i32 %0) local_unnamed_addr #0 {
 ; }
 ; fact_maybe_not(-1) doesn't stop.
 
-; FNATTR: Function Attrs: noinline norecurse nounwind readnone uwtable
-; FNATTR-NOT: willreturn
-; FNATTR-NEXT: define i32 @fact_maybe_not_halt(i32 %0) local_unnamed_addr
 ; ATTRIBUTOR: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable
 ; ATTRIBUTOR-NOT: willreturn
 ; ATTRIBUTOR-NEXT: define i32 @fact_maybe_not_halt(i32 %0) local_unnamed_addr
@@ -93,8 +85,6 @@ define i32 @fact_maybe_not_halt(i32 %0) local_unnamed_addr #0 {
 ; }
 
 ; FIXME: missing willreturn
-; FNATTR: Function Attrs: noinline norecurse nounwind readnone uwtable
-; FNATTR-NEXT: define i32 @fact_loop(i32 %0)
 ; ATTRIBUTOR: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable
 ; ATTRIBUTOR-NEXT: define i32 @fact_loop(i32 %0) local_unnamed_addr
 define i32 @fact_loop(i32 %0) local_unnamed_addr #0 {
@@ -123,9 +113,6 @@ define i32 @fact_loop(i32 %0) local_unnamed_addr #0 {
 ;     mutual_recursion1();
 ; }
 
-; FNATTR: Function Attrs: noinline nounwind readnone uwtable
-; FNATTR-NOT: willreturn
-; FNATTR-NEXT: define void @mutual_recursion1(i1 %c)
 ; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind readnone uwtable
 ; ATTRIBUTOR-NOT: willreturn
 ; ATTRIBUTOR-NEXT: define void @mutual_recursion1(i1 %c)
@@ -139,9 +126,6 @@ end:
 }
 
 
-; FNATTR: Function Attrs: noinline nounwind readnone uwtable
-; FNATTR-NOT: willreturn
-; FNATTR-NEXT: define void @mutual_recursion2(i1 %c)
 ; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind readnone uwtable
 ; ATTRIBUTOR-NOT: willreturn
 ; ATTRIBUTOR-NEXT: define void @mutual_recursion2(i1 %c)
@@ -153,15 +137,10 @@ define void @mutual_recursion2(i1 %c) #0 {
 
 ; TEST 5 (negative case)
 ; call exit/abort (has noreturn attribute)
-; FNATTR: Function Attrs: noreturn
-; FNATTR-NEXT: declare void @exit(i32) local_unnamed_addr
 ; ATTRIBUTOR: Function Attrs: noreturn
 ; ATTRIBUTOR-NEXT: declare void @exit(i32) local_unnamed_add
 declare void @exit(i32 %0) local_unnamed_addr noreturn
 
-; FNATTR: Function Attrs: noinline nounwind uwtable
-; FNATTR-NOT: willreturn
-; FNATTR-NEXT: define void @only_exit()
 ; ATTRIBUTOR: Function Attrs: noinline noreturn nounwind uwtable
 ; ATTRIBUTOR-NOT: willreturn
 ; ATTRIBUTOR-NEXT: define void @only_exit() local_unnamed_addr
@@ -180,9 +159,6 @@ define void @only_exit() local_unnamed_addr #0 {
 ;     }
 ;     return;
 ; }
-; FNATTR: Function Attrs: noinline nounwind uwtable
-; FNATTR-NOT: willreturn
-; FNATTR-NEXT: define void @conditional_exit(i32 %0, i32* nocapture readonly %1) local_unnamed_addr
 ; ATTRIBUTOR: Function Attrs: noinline nounwind uwtable
 ; ATTRIBUTOR-NOT: willreturn
 ; ATTRIBUTOR-NEXT: define void @conditional_exit(i32 %0, i32* nocapture readonly %1) local_unnamed_addr
@@ -210,14 +186,10 @@ define void @conditional_exit(i32 %0, i32* nocapture readonly %1) local_unnamed_
 ; TEST 6 (positive case)
 ; Call intrinsic function
 ; FIXME: missing willreturn
-; FNATTRS: Function Attrs: noinline readnone speculatable
-; FNATTRS-NEXT: declare float @llvm.floor.f32(float %0)
 ; ATTRIBUTOR: Function Attrs: nounwind readnone speculatable
 ; ATTRIBUTOR-NEXT: declare float @llvm.floor.f32(float)
 declare float @llvm.floor.f32(float)
 
-; FNATTRS: Function Attrs: noinline nounwind readnone uwtable
-; FNATTRS-NEXT: define void @call_floor(float %a)
 ; FIXME: missing willreturn
 ; ATTRIBUTOR: Function Attrs: noinline nosync nounwind readnone uwtable
 ; ATTRIBUTOR-NEXT: define void @call_floor(float %a)
@@ -230,17 +202,11 @@ define void @call_floor(float %a) #0 {
 ; TEST 7 (negative case)
 ; Call function declaration without willreturn
 
-; FNATTR: Function Attrs: noinline nounwind uwtable
-; FNATTR-NOT: willreturn
-; FNATTR-NEXT: declare void @maybe_noreturn()
 ; ATTRIBUTOR: Function Attrs: noinline nounwind uwtable
 ; ATTRIBUTOR-NOT: willreturn
 ; ATTRIBUTOR-NEXT: declare void @maybe_noreturn()
 declare void @maybe_noreturn() #0
 
-; FNATTR: Function Attrs: noinline nounwind uwtable
-; FNATTR-NOT: willreturn
-; FNATTR-NEXT: define void @call_maybe_noreturn()
 ; ATTRIBUTOR: Function Attrs: noinline nounwind uwtable
 ; ATTRIBUTOR-NOT: willreturn
 ; ATTRIBUTOR-NEXT: define void @call_maybe_noreturn()
@@ -253,14 +219,10 @@ define void @call_maybe_noreturn() #0 {
 ; TEST 8 (positive case)
 ; Check propagation.
 
-; FNATTR: Function Attrs: norecurse willreturn
-; FNATTR-NEXT: declare void @will_return()
 ; ATTRIBUTOR: Function Attrs: norecurse willreturn
 ; ATTRIBUTOR-NEXT: declare void @will_return()
 declare void @will_return() willreturn norecurse
 
-; FNATTR: Function Attrs: noinline norecurse nounwind uwtable
-; FNATTR-NEXT: define void @f1()
 ; ATTRIBUTOR: Function Attrs: noinline norecurse nounwind uwtable willreturn
 ; ATTRIBUTOR-NEXT: define void @f1()
 define void @f1() #0 {
@@ -268,8 +230,6 @@ define void @f1() #0 {
     ret void
 }
 
-; FNATTR: Function Attrs: noinline norecurse nounwind uwtable
-; FNATTR-NEXT: define void @f2()
 ; ATTRIBUTOR: Function Attrs: noinline norecurse nounwind uwtable willreturn
 ; ATTRIBUTOR-NEXT: define void @f2()
 define void @f2() #0 {
@@ -281,9 +241,6 @@ define void @f2() #0 {
 ; TEST 9 (negative case)
 ; call willreturn function in endless loop.
 
-; FNATTR: Function Attrs: noinline norecurse nounwind uwtable
-; FNATTR-NOT: willreturn
-; FNATTR-NEXT: define void @call_will_return_but_has_loop()
 ; ATTRIBUTOR: Function Attrs: noinline norecurse noreturn nounwind uwtable
 ; ATTRIBUTOR-NOT: willreturn
 ; ATTRIBUTOR-NEXT: define void @call_will_return_but_has_loop()
@@ -300,14 +257,10 @@ label2:
 ; TEST 10 (positive case)
 ; invoke a function with willreturn
 
-; FNATTR: Function Attrs: noinline uwtable willreturn
-; FNATTR-NEXT: declare i1 @maybe_raise_exception()
 ; ATTRIBUTOR: Function Attrs: noinline uwtable willreturn
 ; ATTRIBUTOR-NEXT: declare i1 @maybe_raise_exception()
 declare i1 @maybe_raise_exception() #1 willreturn
 
-; FNATTR: Function Attrs: nounwind
-; FNATTR-NEXT: define void @invoke_test()
 ; ATTRIBUTOR: Function Attrs: nounwind willreturn
 ; ATTRIBUTOR-NEXT: define void @invoke_test()
 define void @invoke_test() personality i32 (...)* @__gxx_personality_v0 {
@@ -335,8 +288,6 @@ declare i32 @__gxx_personality_v0(...)
 ; }
 
 ; FIXME: missing willreturn
-; FNATTR: Function Attrs: noinline norecurse nounwind readonly uwtable
-; FNATTR-NEXT: define i32 @loop_constant_trip_count(i32* nocapture readonly %0)
 ; ATTRIBUTOR: Function Attrs: nofree noinline norecurse nosync nounwind readonly uwtable
 ; ATTRIBUTOR-NEXT: define i32 @loop_constant_trip_count(i32* nocapture nofree readonly %0)
 define i32 @loop_constant_trip_count(i32* nocapture readonly %0) #0 {
@@ -367,9 +318,6 @@ define i32 @loop_constant_trip_count(i32* nocapture readonly %0) #0 {
 ;     }
 ;     return ans;
 ; }
-; FNATTR: Function Attrs: noinline norecurse nounwind readonly uwtable
-; FNATTR-NOT: willreturn
-; FNATTR-NEXT: define i32 @loop_trip_count_unbound(i32 %0, i32 %1, i32* nocapture readonly %2, i32 %3) local_unnamed_addr
 ; ATTRIBUTOR: Function Attrs: nofree noinline norecurse nosync nounwind readonly uwtable
 ; ATTRIBUTOR-NOT: willreturn
 ; ATTRIBUTOR-NEXT: define i32 @loop_trip_count_unbound(i32 %0, i32 %1, i32* nocapture nofree readonly %2, i32 %3) local_unnamed_addr
@@ -406,8 +354,6 @@ define i32 @loop_trip_count_unbound(i32 %0, i32 %1, i32* nocapture readonly %2,
 
 
 ; FIXME: missing willreturn
-; FNATTR: Function Attrs: noinline norecurse nounwind readonly uwtable
-; FNATTR-NEXT: define i32 @loop_trip_dec(i32 %0, i32* nocapture readonly %1)
 ; ATTRIBUTOR: Function Attrs: nofree noinline norecurse nosync nounwind readonly uwtable
 ; ATTRIBUTOR-NEXT: define i32 @loop_trip_dec(i32 %0, i32* nocapture nofree readonly %1) local_unnamed_addr
 
@@ -437,8 +383,6 @@ define i32 @loop_trip_dec(i32 %0, i32* nocapture readonly %1) local_unnamed_addr
 ; TEST 14 (positive case)
 ; multiple return
 
-; FNATTR: Function Attrs: noinline norecurse nounwind readnone uwtable
-; FNATTR-NEXT: define i32 @multiple_return(i32 %a)
 ; ATTRIBUTOR: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable willreturn
 ; ATTRIBUTOR-NEXT: define i32 @multiple_return(i32 %a)
 define i32 @multiple_return(i32 %a) #0 {
@@ -455,8 +399,6 @@ f:
 ; unreachable exit
 
 ; 15.1 (positive case)
-; FNATTR: Function Attrs: noinline nounwind uwtable
-; FNATTR-NEXT: define void @unreachable_exit_positive1()
 ; ATTRIBUTOR: Function Attrs: noinline norecurse nounwind uwtable willreturn
 ; ATTRIBUTOR-NEXT: define void @unreachable_exit_positive1()
 define void @unreachable_exit_positive1() #0 {
@@ -469,8 +411,6 @@ unreachable_label:
 }
 
 ; FIXME: missing willreturn
-; FNATTR: Function Attrs: noinline nounwind uwtable
-; FNATTR-NEXT: define i32 @unreachable_exit_positive2(i32 %0)
 ; ATTRIBUTOR: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable
 ; ATTRIBUTOR-NEXT: define i32 @unreachable_exit_positive2(i32 %0)
 define i32 @unreachable_exit_positive2(i32) local_unnamed_addr #0 {
@@ -497,9 +437,6 @@ unreachable_label:
 
 ;15.2
 
-; FNATTR: Function Attrs: noinline nounwind uwtable
-; FNATTR-NOT: willreturn
-; FNATTR-NEXT: define void @unreachable_exit_negative1()
 ; ATTRIBUTOR: Function Attrs: noinline noreturn nounwind uwtable
 ; ATTRIBUTOR-NOT: willreturn
 ; ATTRIBUTOR-NEXT: define void @unreachable_exit_negative1()
@@ -512,9 +449,6 @@ unreachable_label:
   unreachable
 }
 
-; FNATTR: Function Attrs: noinline nounwind uwtable
-; FNATTR-NOT: willreturn
-; FNATTR-NEXT: define void @unreachable_exit_negative2()
 ; ATTRIBUTOR: Function Attrs: nofree noinline norecurse noreturn nosync nounwind readnone uwtable
 ; ATTRIBUTOR-NOT: willreturn
 ; ATTRIBUTOR-NEXT: define void @unreachable_exit_negative2()
@@ -531,15 +465,10 @@ unreachable_label:
   unreachable
 }
 
-; FNATTR: Function Attrs: noreturn nounwind
-; FNATTR-NEXT: declare void @llvm.eh.sjlj.longjmp(i8*)
 ; ATTRIBUTOR: Function Attrs: noreturn nounwind
 ; ATTRIBUTOR-NEXT: declare void @llvm.eh.sjlj.longjmp(i8*)
 declare void @llvm.eh.sjlj.longjmp(i8*)
 
-; FNATTR: Function Attrs: noinline nounwind uwtable
-; FNATTR-NOT: willreturn
-; FNATTR-NEXT: define void @call_longjmp(i8* nocapture readnone %0) local_unnamed_addr #3 {
 ; ATTRIBUTOR: Function Attrs: noinline noreturn nounwind uwtable
 ; ATTRIBUTOR-NOT: willreturn
 ; ATTRIBUTOR-NEXT: define void @call_longjmp(i8* nocapture readnone %0) local_unnamed_addr

diff  --git a/llvm/test/Transforms/FunctionAttrs/arg_returned.ll b/llvm/test/Transforms/FunctionAttrs/arg_returned.ll
index 5572c0124a07..0adf91cd9aa1 100644
--- a/llvm/test/Transforms/FunctionAttrs/arg_returned.ll
+++ b/llvm/test/Transforms/FunctionAttrs/arg_returned.ll
@@ -1,6 +1,4 @@
 ; RUN: opt -functionattrs -S < %s | FileCheck %s --check-prefix=FNATTR
-; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=5 -S < %s | FileCheck %s --check-prefix=ATTRIBUTOR
-; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -attributor-annotate-decl-cs -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.
@@ -8,24 +6,12 @@
 
 ; TEST SCC test returning an integer value argument
 ;
-; BOTH: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable
-; BOTH-NEXT: define i32 @sink_r0(i32 returned %r)
-; BOTH: Function Attrs: nofree noinline nosync nounwind readnone uwtable
-; BOTH-NEXT: define i32 @scc_r1(i32 %a, i32 returned %r, i32 %b)
-; BOTH: Function Attrs: nofree noinline nosync nounwind readnone uwtable
-; BOTH-NEXT: define i32 @scc_r2(i32 %a, i32 %b, i32 returned %r)
-; BOTH: Function Attrs: nofree noinline nosync nounwind readnone uwtable
-; BOTH-NEXT: define i32 @scc_rX(i32 %a, i32 %b, i32 %r)
 ;
 ; FNATTR: define i32 @sink_r0(i32 returned %r)
 ; FNATTR: define i32 @scc_r1(i32 %a, i32 %r, i32 %b)
 ; FNATTR: define i32 @scc_r2(i32 %a, i32 %b, i32 %r)
 ; FNATTR: define i32 @scc_rX(i32 %a, i32 %b, i32 %r)
 ;
-; ATTRIBUTOR: define i32 @sink_r0(i32 returned %r)
-; ATTRIBUTOR: define i32 @scc_r1(i32 %a, i32 returned %r, i32 %b)
-; ATTRIBUTOR: define i32 @scc_r2(i32 %a, i32 %b, i32 returned %r)
-; ATTRIBUTOR: define i32 @scc_rX(i32 %a, i32 %b, i32 %r)
 ;
 ; int scc_r1(int a, int b, int r);
 ; int scc_r2(int a, int b, int r);
@@ -163,12 +149,6 @@ return:                                           ; preds = %cond.end, %if.then3
 ; FNATTR: define double* @ptr_scc_r1(double* %a, double* readnone %r, double* nocapture readnone %b)
 ; FNATTR: define double* @ptr_scc_r2(double* readnone %a, double* readnone %b, double* readnone %r)
 ;
-; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind readnone uwtable
-; ATTRIBUTOR-NEXT: define double* @ptr_sink_r0(double* nofree readnone returned "no-capture-maybe-returned" %r)
-; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind readnone uwtable
-; ATTRIBUTOR-NEXT: define double* @ptr_scc_r1(double* nofree readnone %a, double* nofree readnone returned %r, double* nocapture nofree readnone %b)
-; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind readnone uwtable
-; ATTRIBUTOR-NEXT: define double* @ptr_scc_r2(double* nofree readnone %a, double* nofree readnone %b, double* nofree readnone returned %r)
 ;
 ; double* ptr_scc_r1(double* a, double* b, double* r);
 ; double* ptr_scc_r2(double* a, double* b, double* r);
@@ -253,8 +233,6 @@ return:                                           ; preds = %cond.end, %if.then3
 ; }
 ;
 ; FNATTR:  define i32* @rt0(i32* readonly %a)
-; BOTH:      Function Attrs: nofree noinline norecurse noreturn nosync nounwind readonly uwtable
-; BOTH-NEXT: define noalias nonnull align 536870912 dereferenceable(4294967295) i32* @rt0(i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) %a)
 define i32* @rt0(i32* %a) #0 {
 entry:
   %v = load i32, i32* %a, align 4
@@ -271,8 +249,6 @@ entry:
 ; }
 ;
 ; FNATTR:  define noalias i32* @rt1(i32* nocapture readonly %a)
-; BOTH: Function Attrs: nofree noinline norecurse noreturn nosync nounwind readonly uwtable
-; BOTH-NEXT:    define noalias nonnull align 536870912 dereferenceable(4294967295) i32* @rt1(i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) %a)
 define i32* @rt1(i32* %a) #0 {
 entry:
   %v = load i32, i32* %a, align 4
@@ -286,8 +262,6 @@ entry:
 ;
 ; FNATTR:  define i32* @rt2_helper(i32* %a)
 ; FNATTR:  define i32* @rt2(i32* readnone %a, i32* readnone %b)
-; BOTH:    define i32* @rt2_helper(i32* nofree readnone returned %a)
-; BOTH:    define i32* @rt2(i32* nofree readnone %a, i32* nofree readnone "no-capture-maybe-returned" %b)
 define i32* @rt2_helper(i32* %a) #0 {
 entry:
   %call = call i32* @rt2(i32* %a, i32* %a)
@@ -312,8 +286,6 @@ 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* nofree readnone %a, i32* nofree readnone returned "no-capture-maybe-returned" %b)
-; BOTH:    define i32* @rt3(i32* nofree readnone %a, i32* nofree 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)
@@ -343,12 +315,8 @@ if.end:
 ;    return r;
 ;  }
 ;
-; BOTH: declare void @unknown_fn(i32* (i32*)*)
 ;
-; BOTH:       Function Attrs: noinline nounwind uwtable
-; 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* readnone returned "no-capture-maybe-returned" %r)
 declare void @unknown_fn(i32* (i32*)*) #0
 
 define i32* @calls_unknown_fn(i32* %r) #0 {
@@ -357,41 +325,6 @@ define i32* @calls_unknown_fn(i32* %r) #0 {
 }
 
 
-; TEST call to a function that might be redifined at link time
-;
-;  int *maybe_redefined_fn(int *r) {
-;    return r;
-;  }
-;
-;  int *calls_maybe_redefined_fn(int *r) {
-;    maybe_redefined_fn(r);
-;    return r;
-;  }
-;
-; Verify the maybe-redefined function is not annotated:
-;
-; ATTRIBUTOR: Function Attrs: noinline nounwind uwtable
-; ATTRIBUTOR: define linkonce_odr i32* @maybe_redefined_fn(i32* %r)
-;
-; ATTRIBUTOR: Function Attrs: noinline nounwind uwtable
-; ATTRIBUTOR: define i32* @calls_maybe_redefined_fn(i32* returned %r)
-;
-; BOTH: Function Attrs: noinline nounwind uwtable
-; BOTH-NEXT: define linkonce_odr i32* @maybe_redefined_fn(i32* %r)
-;
-; BOTH: Function Attrs: noinline nounwind uwtable
-; BOTH-NEXT: define i32* @calls_maybe_redefined_fn(i32* returned %r)
-define linkonce_odr i32* @maybe_redefined_fn(i32* %r) #0 {
-entry:
-  ret i32* %r
-}
-
-define i32* @calls_maybe_redefined_fn(i32* %r) #0 {
-entry:
-  %call = call i32* @maybe_redefined_fn(i32* %r)
-  ret i32* %r
-}
-
 ; TEST return call to a function that might be redifined at link time
 ;
 ;  int *maybe_redefined_fn2(int *r) {
@@ -404,13 +337,8 @@ entry:
 ;
 ; Verify the maybe-redefined function is not annotated:
 ;
-; BOTH: Function Attrs: noinline nounwind uwtable
-; BOTH-NEXT: define linkonce_odr i32* @maybe_redefined_fn2(i32* %r)
-; BOTH: Function Attrs: noinline nounwind uwtable
-; BOTH-NEXT: define i32* @calls_maybe_redefined_fn2(i32* %r)
 ;
 ; FNATTR:     define i32* @calls_maybe_redefined_fn2(i32* %r)
-; ATTRIBUTOR: define i32* @calls_maybe_redefined_fn2(i32* %r)
 define linkonce_odr i32* @maybe_redefined_fn2(i32* %r) #0 {
 entry:
   ret i32* %r
@@ -432,12 +360,8 @@ entry:
 ;   return b == 0? b : x;
 ; }
 ;
-; BOTH: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable
-; BOTH-NEXT: define double @select_and_phi(double returned %b)
 ;
 ; FNATTR:     define double @select_and_phi(double %b)
-; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind readnone uwtable
-; ATTRIBUTOR-NEXT: define double @select_and_phi(double returned %b)
 define double @select_and_phi(double %b) #0 {
 entry:
   %cmp = fcmp ogt double %b, 0.000000e+00
@@ -463,13 +387,9 @@ if.end:                                           ; preds = %if.then, %entry
 ;   return b == 0? b : x;
 ; }
 ;
-; BOTH: Function Attrs: nofree noinline nosync nounwind readnone uwtable
-; BOTH-NEXT: define double @recursion_select_and_phi(i32 %a, double returned %b)
 ;
 ; FNATTR:     define double @recursion_select_and_phi(i32 %a, double %b)
 ;
-; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind readnone uwtable
-; ATTRIBUTOR-NEXT: define double @recursion_select_and_phi(i32 %a, double returned %b)
 define double @recursion_select_and_phi(i32 %a, double %b) #0 {
 entry:
   %dec = add nsw i32 %a, -1
@@ -494,13 +414,9 @@ if.end:                                           ; preds = %if.then, %entry
 ;   return (double*)b;
 ; }
 ;
-; BOTH: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable
-; BOTH-NEXT:  define double* @bitcast(i32* nofree readnone returned "no-capture-maybe-returned" %b)
 ;
 ; FNATTR:     define double* @bitcast(i32* readnone %b)
 ;
-; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind readnone uwtable
-; ATTRIBUTOR-NEXT: define double* @bitcast(i32* nofree readnone returned "no-capture-maybe-returned" %b)
 define double* @bitcast(i32* %b) #0 {
 entry:
   %bc0 = bitcast i32* %b to double*
@@ -517,13 +433,9 @@ entry:
 ;   return b != 0 ? b : x;
 ; }
 ;
-; BOTH: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable
-; BOTH-NEXT: define double* @bitcasts_select_and_phi(i32* nofree readnone returned %b)
 ;
 ; FNATTR:     define double* @bitcasts_select_and_phi(i32* readnone %b)
 ;
-; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind readnone uwtable
-; ATTRIBUTOR-NEXT: define double* @bitcasts_select_and_phi(i32* nofree readnone returned %b)
 define double* @bitcasts_select_and_phi(i32* %b) #0 {
 entry:
   %bc0 = bitcast i32* %b to double*
@@ -555,13 +467,9 @@ if.end:                                           ; preds = %if.then, %entry
 ;   /* return undef */
 ; }
 ;
-; BOTH: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable
-; BOTH-NEXT:  define double* @ret_arg_arg_undef(i32* nofree readnone returned %b)
 ;
 ; FNATTR:     define double* @ret_arg_arg_undef(i32* readnone %b)
 ;
-; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind readnone uwtable
-; ATTRIBUTOR-NEXT: define double* @ret_arg_arg_undef(i32* nofree readnone returned %b)
 define double* @ret_arg_arg_undef(i32* %b) #0 {
 entry:
   %bc0 = bitcast i32* %b to double*
@@ -593,13 +501,9 @@ ret_undef:
 ;   /* return undef */
 ; }
 ;
-; BOTH: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable
-; BOTH-NEXT:  define double* @ret_undef_arg_arg(i32* nofree readnone returned %b)
 ;
 ; FNATTR:     define double* @ret_undef_arg_arg(i32* readnone %b)
 ;
-; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind readnone uwtable
-; ATTRIBUTOR-NEXT: define double* @ret_undef_arg_arg(i32* nofree readnone returned %b)
 define double* @ret_undef_arg_arg(i32* %b) #0 {
 entry:
   %bc0 = bitcast i32* %b to double*
@@ -631,11 +535,8 @@ ret_arg1:
 ;   /* return undef */
 ; }
 ;
-; BOTH: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable
-; BOTH-NEXT:  define double* @ret_undef_arg_undef(i32* nofree readnone returned %b)
 ;
 ; FNATTR:     define double* @ret_undef_arg_undef(i32* readnone %b)
-; ATTRIBUTOR: define double* @ret_undef_arg_undef(i32* nofree readnone returned %b)
 define double* @ret_undef_arg_undef(i32* %b) #0 {
 entry:
   %bc0 = bitcast i32* %b to double*
@@ -667,10 +568,6 @@ ret_undef1:
 ;
 ; FNATTR:     define i32* @ret_arg_or_unknown(i32* %b)
 ; FNATTR:     define i32* @ret_arg_or_unknown_through_phi(i32* %b)
-; ATTRIBUTOR: define i32* @ret_arg_or_unknown(i32* %b)
-; ATTRIBUTOR: define i32* @ret_arg_or_unknown_through_phi(i32* %b)
-; BOTH:       define i32* @ret_arg_or_unknown(i32* %b)
-; BOTH:       define i32* @ret_arg_or_unknown_through_phi(i32* %b)
 declare i32* @unknown(i32*)
 
 define i32* @ret_arg_or_unknown(i32* %b) #0 {
@@ -709,14 +606,6 @@ r:
 ; FNATTR:     define i32 @deadblockcall2(i32 %A)
 ; FNATTR:     define i32 @deadblockphi1(i32 %A)
 ; FNATTR:     define i32 @deadblockphi2(i32 %A)
-; ATTRIBUTOR: define i32 @deadblockcall1(i32 returned %A)
-; ATTRIBUTOR: define i32 @deadblockcall2(i32 returned %A)
-; ATTRIBUTOR: define i32 @deadblockphi1(i32 returned %A)
-; ATTRIBUTOR: define i32 @deadblockphi2(i32 returned %A)
-; BOTH:       define i32 @deadblockcall1(i32 returned %A)
-; BOTH:       define i32 @deadblockcall2(i32 returned %A)
-; BOTH:       define i32 @deadblockphi1(i32 returned %A)
-; BOTH:       define i32 @deadblockphi2(i32 returned %A)
 define i32 @deadblockcall1(i32 %A) #0 {
 entry:
   ret i32 %A
@@ -789,51 +678,4 @@ r:
   ret i32 %PHI2
 }
 
-define weak_odr i32 @non_exact_0() {
-  ret i32 0
-}
-define weak_odr i32 @non_exact_1(i32 %a) {
-  ret i32 %a
-}
-define weak_odr i32 @non_exact_2(i32 returned %a) {
-  ret i32 %a
-}
-define weak_odr i32* @non_exact_3(i32* align 32 returned %a) {
-  ret i32* %a
-}
-define i32 @exact(i32* %a) {
-  %c0 = call i32 @non_exact_0()
-  %c1 = call i32 @non_exact_1(i32 1)
-  %c2 = call i32 @non_exact_2(i32 2)
-  %c3 = call i32* @non_exact_3(i32* %a)
-; We can use the information of the weak function non_exact_3 because it was
-; given to us and not derived (the alignment of the returned argument).
-; ATTRIBUTOR:  %c4 = load i32, i32* %c3, align 32
-  %c4 = load i32, i32* %c3
-; FIXME: %c2 and %c3 should be replaced but not %c0 or %c1!
-; ATTRIBUTOR:  %add1 = add i32 %c0, %c1
-; ATTRIBUTOR:  %add2 = add i32 %add1, %c2
-; ATTRIBUTOR:  %add3 = add i32 %add2, %c4
-  %add1 = add i32 %c0, %c1
-  %add2 = add i32 %add1, %c2
-  %add3 = add i32 %add2, %c4
-  ret i32 %add3
-}
-
- at G = external global i8
-define i32* @ret_const() #0 {
-  %bc = bitcast i8* @G to i32*
-  ret i32* %bc
-}
-define i32* @use_const() #0 {
-  %c = call i32* @ret_const()
-  ; ATTRIBUTOR: ret i32* bitcast (i8* @G to i32*)
-  ret i32* %c
-}
-define i32* @dont_use_const() #0 {
-  %c = musttail call i32* @ret_const()
-  ; ATTRIBUTOR: ret i32* %c
-  ret i32* %c
-}
-
 attributes #0 = { noinline nounwind uwtable }

diff  --git a/llvm/test/Transforms/FunctionAttrs/nocapture.ll b/llvm/test/Transforms/FunctionAttrs/nocapture.ll
index a78af1041672..25759cffe13f 100644
--- a/llvm/test/Transforms/FunctionAttrs/nocapture.ll
+++ b/llvm/test/Transforms/FunctionAttrs/nocapture.ll
@@ -1,18 +1,14 @@
-; 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 -attributor-annotate-decl-cs < %s | FileCheck %s --check-prefixes=ATTRIBUTOR,EITHER
-; RUN: opt -passes=attributor -attributor-manifest-internal -attributor-disable=false -S -attributor-annotate-decl-cs < %s | FileCheck %s --check-prefixes=ATTRIBUTOR,EITHER
+; RUN: opt -functionattrs -S < %s | FileCheck %s --check-prefixes=FNATTR
+; RUN: opt -passes=function-attrs -S < %s | FileCheck %s --check-prefixes=FNATTR
 
 @g = global i32* null		; <i32**> [#uses=1]
 
 ; FNATTR: define i32* @c1(i32* readnone returned %q)
-; ATTRIBUTOR: define i32* @c1(i32* nofree readnone returned "no-capture-maybe-returned" %q)
 define i32* @c1(i32* %q) {
 	ret i32* %q
 }
 
 ; FNATTR: define void @c2(i32* %q)
-; ATTRIBUTOR: define void @c2(i32* nofree writeonly %q)
 ; It would also be acceptable to mark %q as readnone. Update @c3 too.
 define void @c2(i32* %q) {
 	store i32* %q, i32** @g
@@ -20,14 +16,12 @@ define void @c2(i32* %q) {
 }
 
 ; FNATTR: define void @c3(i32* %q)
-; ATTRIBUTOR: define void @c3(i32* nofree writeonly %q)
 define void @c3(i32* %q) {
 	call void @c2(i32* %q)
 	ret void
 }
 
 ; FNATTR: define i1 @c4(i32* %q, i32 %bitno)
-; ATTRIBUTOR: define i1 @c4(i32* nofree readnone %q, i32 %bitno)
 define i1 @c4(i32* %q, i32 %bitno) {
 	%tmp = ptrtoint i32* %q to i32
 	%tmp2 = lshr i32 %tmp, %bitno
@@ -41,7 +35,6 @@ l1:
 
 ; c4b is c4 but without the escaping part
 ; FNATTR: define i1 @c4b(i32* %q, i32 %bitno)
-; ATTRIBUTOR: define i1 @c4b(i32* nocapture nofree readnone %q, i32 %bitno)
 define i1 @c4b(i32* %q, i32 %bitno) {
 	%tmp = ptrtoint i32* %q to i32
 	%tmp2 = lshr i32 %tmp, %bitno
@@ -56,7 +49,6 @@ l1:
 @lookup_table = global [2 x i1] [ i1 0, i1 1 ]
 
 ; FNATTR: define i1 @c5(i32* %q, i32 %bitno)
-; ATTRIBUTOR: define i1 @c5(i32* nofree readonly %q, i32 %bitno)
 define i1 @c5(i32* %q, i32 %bitno) {
 	%tmp = ptrtoint i32* %q to i32
 	%tmp2 = lshr i32 %tmp, %bitno
@@ -69,7 +61,7 @@ define i1 @c5(i32* %q, i32 %bitno) {
 
 declare void @throw_if_bit_set(i8*, i8) readonly
 
-; EITHER: define i1 @c6(i8* readonly %q, i8 %bit)
+; FNATTR: define i1 @c6(i8* readonly %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
@@ -92,7 +84,6 @@ define i1* @lookup_bit(i32* %q, i32 %bitno) readnone nounwind {
 }
 
 ; FNATTR: define i1 @c7(i32* readonly %q, i32 %bitno)
-; ATTRIBUTOR: define i1 @c7(i32* nofree readonly %q, i32 %bitno)
 define i1 @c7(i32* %q, i32 %bitno) {
 	%ptr = call i1* @lookup_bit(i32* %q, i32 %bitno)
 	%val = load i1, i1* %ptr
@@ -101,7 +92,6 @@ define i1 @c7(i32* %q, i32 %bitno) {
 
 
 ; FNATTR: define i32 @nc1(i32* %q, i32* nocapture %p, i1 %b)
-; ATTRIBUTOR: define i32 @nc1(i32* nofree %q, i32* nocapture nofree %p, i1 %b)
 define i32 @nc1(i32* %q, i32* %p, i1 %b) {
 e:
 	br label %l
@@ -117,7 +107,6 @@ l:
 }
 
 ; FNATTR: define i32 @nc1_addrspace(i32* %q, i32 addrspace(1)* nocapture %p, i1 %b)
-; ATTRIBUTOR: define i32 @nc1_addrspace(i32* nofree %q, i32 addrspace(1)* nocapture nofree %p, i1 %b)
 define i32 @nc1_addrspace(i32* %q, i32 addrspace(1)* %p, i1 %b) {
 e:
 	br label %l
@@ -133,7 +122,6 @@ l:
 }
 
 ; FNATTR: define void @nc2(i32* nocapture %p, i32* %q)
-; ATTRIBUTOR: define void @nc2(i32* nocapture nofree %p, i32* nofree %q)
 define void @nc2(i32* %p, i32* %q) {
 	%1 = call i32 @nc1(i32* %q, i32* %p, i1 0)		; <i32> [#uses=0]
 	ret void
@@ -141,21 +129,19 @@ define void @nc2(i32* %p, i32* %q) {
 
 
 ; FNATTR: define void @nc3(void ()* nocapture %p)
-; ATTRIBUTOR: define void @nc3(void ()* nocapture nofree nonnull %p)
 define void @nc3(void ()* %p) {
 	call void %p()
 	ret void
 }
 
 declare void @external(i8*) readonly nounwind
-; EITHER: define void @nc4(i8* nocapture readonly %p)
+; FNATTR: define void @nc4(i8* nocapture readonly %p)
 define void @nc4(i8* %p) {
 	call void @external(i8* %p)
 	ret void
 }
 
 ; FNATTR: define void @nc5(void (i8*)* nocapture %f, i8* nocapture %p)
-; ATTRIBUTOR: define void @nc5(void (i8*)* nocapture nofree nonnull %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)
@@ -163,7 +149,6 @@ define void @nc5(void (i8*)* %f, i8* %p) {
 }
 
 ; FNATTR:     define void @test1_1(i8* nocapture readnone %x1_1, i8* %y1_1, i1 %c)
-; ATTRIBUTOR: define void @test1_1(i8* nocapture nofree readnone %x1_1, i8* nocapture nofree readnone %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, i1 %c) {
   call i8* @test1_2(i8* %x1_1, i8* %y1_1, i1 %c)
@@ -172,7 +157,6 @@ define void @test1_1(i8* %x1_1, i8* %y1_1, i1 %c) {
 }
 
 ; FNATTR: define i8* @test1_2(i8* nocapture readnone %x1_2, i8* returned %y1_2, i1 %c)
-; ATTRIBUTOR: define i8* @test1_2(i8* nocapture nofree readnone %x1_2, i8* nofree readnone 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:
@@ -184,7 +168,6 @@ f:
 }
 
 ; FNATTR: define void @test2(i8* nocapture readnone %x2)
-; ATTRIBUTOR: define void @test2(i8* nocapture nofree readnone %x2)
 define void @test2(i8* %x2) {
   call void @test2(i8* %x2)
   store i32* null, i32** @g
@@ -192,7 +175,6 @@ define void @test2(i8* %x2) {
 }
 
 ; FNATTR: define void @test3(i8* nocapture readnone %x3, i8* nocapture readnone %y3, i8* nocapture readnone %z3)
-; ATTRIBUTOR: define void @test3(i8* nocapture nofree readnone %x3, i8* nocapture nofree readnone %y3, i8* nocapture nofree readnone %z3)
 define void @test3(i8* %x3, i8* %y3, i8* %z3) {
   call void @test3(i8* %z3, i8* %y3, i8* %x3)
   store i32* null, i32** @g
@@ -200,7 +182,6 @@ define void @test3(i8* %x3, i8* %y3, i8* %z3) {
 }
 
 ; FNATTR: define void @test4_1(i8* %x4_1, i1 %c)
-; ATTRIBUTOR: define void @test4_1(i8* nocapture nofree readnone %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
@@ -208,7 +189,6 @@ define void @test4_1(i8* %x4_1, i1 %c) {
 }
 
 ; 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 nofree readnone %x4_2, i8* nofree readnone returned "no-capture-maybe-returned" %y4_2, i8* nocapture nofree readnone %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:
@@ -221,7 +201,7 @@ f:
 
 declare i8* @test5_1(i8* %x5_1)
 
-; EITHER: define void @test5_2(i8* %x5_2)
+; FNATTR: 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
@@ -230,7 +210,7 @@ define void @test5_2(i8* %x5_2) {
 
 declare void @test6_1(i8* %x6_1, i8* nocapture %y6_1, ...)
 
-; EITHER: define void @test6_2(i8* %x6_2, i8* nocapture %y6_2, i8* %z6_2)
+; FNATTR: 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
@@ -238,28 +218,24 @@ define void @test6_2(i8* %x6_2, i8* %y6_2, i8* %z6_2) {
 }
 
 ; FNATTR: define void @test_cmpxchg(i32* nocapture %p)
-; ATTRIBUTOR: define void @test_cmpxchg(i32* nocapture nofree nonnull dereferenceable(4) %p)
 define void @test_cmpxchg(i32* %p) {
   cmpxchg i32* %p, i32 0, i32 1 acquire monotonic
   ret void
 }
 
 ; FNATTR: define void @test_cmpxchg_ptr(i32** nocapture %p, i32* %q)
-; ATTRIBUTOR: define void @test_cmpxchg_ptr(i32** nocapture nofree nonnull dereferenceable(8) %p, i32* nofree %q)
 define void @test_cmpxchg_ptr(i32** %p, i32* %q) {
   cmpxchg i32** %p, i32* null, i32* %q acquire monotonic
   ret void
 }
 
 ; FNATTR: define void @test_atomicrmw(i32* nocapture %p)
-; ATTRIBUTOR: define void @test_atomicrmw(i32* nocapture nofree nonnull dereferenceable(4) %p)
 define void @test_atomicrmw(i32* %p) {
   atomicrmw add i32* %p, i32 1 seq_cst
   ret void
 }
 
 ; FNATTR: define void @test_volatile(i32* %x)
-; ATTRIBUTOR: define void @test_volatile(i32* nofree align 4 %x)
 define void @test_volatile(i32* %x) {
 entry:
   %gep = getelementptr i32, i32* %x, i64 1
@@ -267,7 +243,7 @@ entry:
   ret void
 }
 
-; EITHER: nocaptureLaunder(i8* nocapture %p)
+; FNATTR: nocaptureLaunder(i8* nocapture %p)
 define void @nocaptureLaunder(i8* %p) {
 entry:
   %b = call i8* @llvm.launder.invariant.group.p0i8(i8* %p)
@@ -276,7 +252,7 @@ entry:
 }
 
 @g2 = global i8* null
-; EITHER: define void @captureLaunder(i8* %p)
+; FNATTR: 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
@@ -284,7 +260,6 @@ define void @captureLaunder(i8* %p) {
 }
 
 ; FNATTR: @nocaptureStrip(i8* nocapture %p)
-; ATTRIBUTOR: @nocaptureStrip(i8* nocapture writeonly %p)
 define void @nocaptureStrip(i8* %p) {
 entry:
   %b = call i8* @llvm.strip.invariant.group.p0i8(i8* %p)
@@ -294,7 +269,6 @@ entry:
 
 @g3 = global i8* null
 ; FNATTR: define void @captureStrip(i8* %p)
-; ATTRIBUTOR: define void @captureStrip(i8* writeonly %p)
 define void @captureStrip(i8* %p) {
   %b = call i8* @llvm.strip.invariant.group.p0i8(i8* %p)
   store i8* %b, i8** @g3
@@ -302,21 +276,18 @@ define void @captureStrip(i8* %p) {
 }
 
 ; FNATTR: define i1 @captureICmp(i32* readnone %x)
-; ATTRIBUTOR: define i1 @captureICmp(i32* nofree readnone %x)
 define i1 @captureICmp(i32* %x) {
   %1 = icmp eq i32* %x, null
   ret i1 %1
 }
 
 ; FNATTR: define i1 @captureICmpRev(i32* readnone %x)
-; ATTRIBUTOR: define i1 @captureICmpRev(i32* nofree readnone %x)
 define i1 @captureICmpRev(i32* %x) {
   %1 = icmp eq i32* null, %x
   ret i1 %1
 }
 
 ; FNATTR: define i1 @nocaptureInboundsGEPICmp(i32* nocapture readnone %x)
-; ATTRIBUTOR: define i1 @nocaptureInboundsGEPICmp(i32* nocapture nofree nonnull readnone %x)
 define i1 @nocaptureInboundsGEPICmp(i32* %x) {
   %1 = getelementptr inbounds i32, i32* %x, i32 5
   %2 = bitcast i32* %1 to i8*
@@ -325,7 +296,6 @@ define i1 @nocaptureInboundsGEPICmp(i32* %x) {
 }
 
 ; FNATTR: define i1 @nocaptureInboundsGEPICmpRev(i32* nocapture readnone %x)
-; ATTRIBUTOR: define i1 @nocaptureInboundsGEPICmpRev(i32* nocapture nofree nonnull readnone %x)
 define i1 @nocaptureInboundsGEPICmpRev(i32* %x) {
   %1 = getelementptr inbounds i32, i32* %x, i32 5
   %2 = bitcast i32* %1 to i8*
@@ -334,7 +304,6 @@ define i1 @nocaptureInboundsGEPICmpRev(i32* %x) {
 }
 
 ; FNATTR: define i1 @nocaptureDereferenceableOrNullICmp(i32* nocapture readnone dereferenceable_or_null(4) %x)
-; ATTRIBUTOR: define i1 @nocaptureDereferenceableOrNullICmp(i32* nocapture nofree readnone 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
@@ -342,36 +311,11 @@ define i1 @nocaptureDereferenceableOrNullICmp(i32* dereferenceable_or_null(4) %x
 }
 
 ; FNATTR: define i1 @captureDereferenceableOrNullICmp(i32* readnone dereferenceable_or_null(4) %x)
-; ATTRIBUTOR: define i1 @captureDereferenceableOrNullICmp(i32* nofree readnone 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
   ret i1 %2
 }
 
-declare void @unknown(i8*)
-define void @test_callsite() {
-entry:
-; We know that 'null' in AS 0 does not alias anything and cannot be captured. Though the latter is not qurried -> derived atm.
-; ATTRIBUTOR: call void @unknown(i8* noalias null)
-  call void @unknown(i8* null)
-  ret void
-}
-
-declare i8* @unknownpi8pi8(i8*,i8* returned)
-define i8* @test_returned1(i8* %A, i8* returned %B) nounwind readonly {
-; ATTRIBUTOR: define i8* @test_returned1(i8* nocapture readonly %A, i8* readonly returned %B)
-entry:
-  %p = call i8* @unknownpi8pi8(i8* %A, i8* %B)
-  ret i8* %p
-}
-
-define i8* @test_returned2(i8* %A, i8* %B) {
-; ATTRIBUTOR: define i8* @test_returned2(i8* nocapture readonly %A, i8* readonly returned %B)
-entry:
-  %p = call i8* @unknownpi8pi8(i8* %A, i8* %B) nounwind readonly
-  ret i8* %p
-}
-
 declare i8* @llvm.launder.invariant.group.p0i8(i8*)
 declare i8* @llvm.strip.invariant.group.p0i8(i8*)

diff  --git a/llvm/test/Transforms/FunctionAttrs/nofree-attributor.ll b/llvm/test/Transforms/FunctionAttrs/nofree-attributor.ll
index 1c007ee11b41..8ac037e5cd8d 100644
--- a/llvm/test/Transforms/FunctionAttrs/nofree-attributor.ll
+++ b/llvm/test/Transforms/FunctionAttrs/nofree-attributor.ll
@@ -1,5 +1,4 @@
 ; RUN: opt -functionattrs --disable-nofree-inference=false -S < %s | FileCheck %s --check-prefix=FNATTR
-; RUN: opt -attributor --attributor-disable=false -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=2 -S < %s | FileCheck %s --check-prefix=ATTRIBUTOR
 
 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
 
@@ -15,8 +14,6 @@ declare void @_ZdaPv(i8*) local_unnamed_addr #2
 ; TEST 1 (positive case)
 ; FNATTR: Function Attrs: noinline norecurse nounwind readnone uwtable
 ; FNATTR-NEXT: define void @only_return()
-; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind readnone uwtable
-; ATTRIBUTOR-NEXT: define void @only_return()
 define void @only_return() #0 {
     ret void
 }
@@ -30,9 +27,6 @@ define void @only_return() #0 {
 
 ; FNATTR: Function Attrs: noinline nounwind uwtable
 ; FNATTR-NEXT: define void @only_free(i8* nocapture %0) local_unnamed_addr
-; ATTRIBUTOR: Function Attrs: noinline nounwind uwtable
-; ATTRIBUTOR-NOT: nofree
-; ATTRIBUTOR-NEXT: define void @only_free(i8* nocapture %0) local_unnamed_addr #1
 define void @only_free(i8* nocapture %0) local_unnamed_addr #0 {
     tail call void @free(i8* %0) #1
     ret void
@@ -52,9 +46,6 @@ define void @only_free(i8* nocapture %0) local_unnamed_addr #0 {
 
 ; FNATTR: Function Attrs: noinline nounwind uwtable
 ; FNATTR-NEXT: define void @free_in_scc1(i8* nocapture %0) local_unnamed_addr
-; ATTRIBUTOR: Function Attrs: noinline nounwind uwtable
-; ATTRIBUTOR-NOT: nofree
-; ATTRIBUTOR-NEXT :define void @free_in_scc1(i8* nocapture %0) local_unnamed_addr
 define void @free_in_scc1(i8* nocapture %0) local_unnamed_addr #0 {
   tail call void @free_in_scc2(i8* %0) #1
   ret void
@@ -63,9 +54,6 @@ define void @free_in_scc1(i8* nocapture %0) local_unnamed_addr #0 {
 
 ; FNATTR: Function Attrs: noinline nounwind uwtable
 ; FNATTR-NEXT: define void @free_in_scc2(i8* nocapture %0) local_unnamed_addr
-; ATTRIBUTOR: Function Attrs: noinline nounwind uwtable
-; ATTRIBUTOR-NOT: nofree
-; ATTRIBUTOR: define void @free_in_scc2(i8* nocapture %0) local_unnamed_addr
 define void @free_in_scc2(i8* nocapture %0) local_unnamed_addr #0 {
   %cmp = icmp eq i8* %0, null
   br i1 %cmp, label %rec, label %call
@@ -92,8 +80,6 @@ end:
 
 ; FNATTR: Function Attrs: noinline nounwind readnone uwtable
 ; FNATTR-NEXT: define void @mutual_recursion1()
-; ATTRIBUTOR: Function Attrs: nofree noinline noreturn nosync nounwind readnone uwtable
-; ATTRIBUTOR-NEXT: define void @mutual_recursion1()
 define void @mutual_recursion1() #0 {
   call void @mutual_recursion2()
   ret void
@@ -101,8 +87,6 @@ define void @mutual_recursion1() #0 {
 
 ; FNATTR: Function Attrs: noinline nounwind readnone uwtable
 ; FNATTR-NEXT: define void @mutual_recursion2()
-; ATTRIBUTOR: Function Attrs: nofree noinline noreturn nosync nounwind readnone uwtable
-; ATTRIBUTOR-NEXT: define void @mutual_recursion2()
 define void @mutual_recursion2() #0 {
   call void @mutual_recursion1()
   ret void
@@ -117,9 +101,6 @@ define void @mutual_recursion2() #0 {
 
 ; FNATTR: Function Attrs: noinline nounwind uwtable
 ; FNATTR-NEXT: define void @_Z9delete_opPc(i8* %0) local_unnamed_addr
-; ATTRIBUTOR: Function Attrs: noinline nounwind uwtable
-; ATTRIBUTOR-NOT: nofree
-; ATTRIBUTOR-NEXT: define void @_Z9delete_opPc(i8* %0) local_unnamed_addr #1
 define void @_Z9delete_opPc(i8* %0) local_unnamed_addr #0 {
   %2 = icmp eq i8* %0, null
   br i1 %2, label %4, label %3
@@ -137,9 +118,6 @@ define void @_Z9delete_opPc(i8* %0) local_unnamed_addr #0 {
 ; Call realloc
 ; FNATTR: Function Attrs: noinline nounwind uwtable
 ; FNATTR-NEXT: define noalias i8* @call_realloc(i8* nocapture %0, i64 %1) local_unnamed_addr
-; ATTRIBUTOR: Function Attrs: noinline nounwind uwtable
-; ATTRIBUTOR-NOT: nofree
-; ATTRIBUTOR-NEXT: define noalias i8* @call_realloc(i8* nocapture %0, i64 %1) local_unnamed_addr
 define noalias i8* @call_realloc(i8* nocapture %0, i64 %1) local_unnamed_addr #0 {
     %ret = tail call i8* @realloc(i8* %0, i64 %1) #2
     ret i8* %ret
@@ -152,14 +130,10 @@ define noalias i8* @call_realloc(i8* nocapture %0, i64 %1) local_unnamed_addr #0
 
 ; FNATTR: Function Attrs: nofree noinline nounwind readnone uwtable
 ; FNATTR-NEXT: declare void @nofree_function()
-; ATTRIBUTOR: Function Attrs:  nofree noinline nounwind readnone uwtable 
-; ATTRIBUTOR-NEXT: declare void @nofree_function()
 declare void @nofree_function() nofree readnone #0
 
 ; FNATTR: Function Attrs: noinline nounwind readnone uwtable
 ; FNATTR-NEXT: define void @call_nofree_function()
-; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind readnone uwtable
-; ATTRIBUTOR-NEXT: define void @call_nofree_function()
 define void @call_nofree_function() #0 {
     tail call void @nofree_function()
     ret void
@@ -169,16 +143,11 @@ define void @call_nofree_function() #0 {
 ; Call function declaration without "nofree"
 
 
-; ATTRIBUTOR: Function Attrs: noinline nounwind uwtable
-; ATTRIBUTOR-NEXT: declare void @maybe_free()
 declare void @maybe_free() #0
 
 
 ; FNATTR: Function Attrs: noinline nounwind uwtable
 ; FNATTR: define void @call_maybe_free()
-; ATTRIBUTOR: Function Attrs: noinline nounwind uwtable
-; ATTRIBUTOR-NOT: nofree
-; ATTRIBUTOR-NEXT: define void @call_maybe_free()
 define void @call_maybe_free() #0 {
     tail call void @maybe_free()
     ret void
@@ -190,9 +159,6 @@ define void @call_maybe_free() #0 {
 
 ; FNATTR: Function Attrs: noinline nounwind uwtable
 ; FNATTR-NEXT: define void @call_both()
-; ATTRIBUTOR: Function Attrs: noinline nounwind uwtable
-; ATTRIBUTOR-NOT: nofree
-; ATTRIBUTOR-NEXT: define void @call_both()
 define void @call_both() #0 {
     tail call void @maybe_free()
     tail call void @nofree_function()
@@ -204,15 +170,11 @@ define void @call_both() #0 {
 ; Call intrinsic function
 ; FNATTRS: Function Attrs: noinline readnone speculatable
 ; FNATTRS-NEXT: declare float @llvm.floor.f32(float %0)
-; ATTRIBUTOR: Function Attrs: nounwind readnone speculatable
-; ATTRIBUTOR-NEXT: declare float @llvm.floor.f32(float)
 declare float @llvm.floor.f32(float)
 
 ; FNATTRS: Function Attrs: noinline nounwind uwtable
 ; FNATTRS-NEXT: define void @call_floor(float %a)
 ; FIXME: missing nofree
-; ATTRIBUTOR: Function Attrs: noinline nosync nounwind readnone uwtable
-; ATTRIBUTOR-NEXT: define void @call_floor(float %a)
 
 define void @call_floor(float %a) #0 {
     tail call float @llvm.floor.f32(float %a)
@@ -224,8 +186,6 @@ define void @call_floor(float %a) #0 {
 
 ; FNATTRS: Function Attrs: noinline nounwind uwtable
 ; FNATTRS-NEXT: define void @f1()
-; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind readnone uwtable
-; ATTRIBUTOR-NEXT: define void @f1()
 define void @f1() #0 {
     tail call void @nofree_function()
     ret void
@@ -233,40 +193,11 @@ define void @f1() #0 {
 
 ; FNATTRS: Function Attrs: noinline nounwind uwtable
 ; FNATTRS-NEXT: define void @f2()
-; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind readnone uwtable
-; ATTRIBUTOR-NEXT: define void @f2()
 define void @f2() #0 {
     tail call void @f1()
     ret void
 }
 
-; TEST 12 NoFree argument - positive.
-; ATTRIBUTOR: define double @test12(double* nocapture nofree nonnull readonly align 8 dereferenceable(8) %a)
-define double @test12(double* nocapture readonly %a) {
-entry:
-	%0 = load double, double* %a, align 8
-	%call = tail call double @cos(double %0) #2
-	ret double %call
-}
-
-declare double @cos(double) nobuiltin nounwind nofree
-
-; FIXME: %a should be nofree.
-; TEST 13 NoFree argument - positive.
-; ATTRIBUTOR: define noalias i32* @test13(i64* nocapture nonnull readonly align 8 dereferenceable(8) %a)
-define noalias i32* @test13(i64* nocapture readonly %a) {
-entry:
-	%0 = load i64, i64* %a, align 8
-	%call = tail call noalias i8* @malloc(i64 %0) #2
-	%1 = bitcast i8* %call to i32*
-	ret i32* %1
-}
-
-; ATTRIBUTOR: define void @test14(i8* nocapture %0, i8* nocapture nofree readnone %1)
-define void @test14(i8* nocapture %0, i8* nocapture %1) {
-	tail call void @free(i8* %0) #1
-	ret void
-}
 
 declare noalias i8* @malloc(i64)
 

diff  --git a/llvm/test/Transforms/FunctionAttrs/nonnull.ll b/llvm/test/Transforms/FunctionAttrs/nonnull.ll
index 42923cee7708..128a2bdbe50c 100644
--- a/llvm/test/Transforms/FunctionAttrs/nonnull.ll
+++ b/llvm/test/Transforms/FunctionAttrs/nonnull.ll
@@ -1,8 +1,6 @@
 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -S -functionattrs -enable-nonnull-arg-prop %s | FileCheck %s --check-prefixes=BOTH,FNATTR,OLD
-; RUN: opt -S -passes=function-attrs -enable-nonnull-arg-prop %s | FileCheck %s --check-prefixes=BOTH,FNATTR,OLD
-; RUN: opt -attributor --attributor-disable=false -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=5 -S < %s | FileCheck %s --check-prefixes=BOTH,OLD,ATTRIBUTOR,ATTRIBUTOR_OPM
-; RUN: opt -passes=attributor --attributor-disable=false -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=5 -S < %s | FileCheck %s --check-prefixes=BOTH,ATTRIBUTOR,ATTRIBUTOR_NPM
+; RUN: opt -S -functionattrs -enable-nonnull-arg-prop %s | FileCheck %s --check-prefixes=FNATTR
+; RUN: opt -S -passes=function-attrs -enable-nonnull-arg-prop %s | FileCheck %s --check-prefixes=FNATTR
 
 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
 
@@ -10,14 +8,14 @@ declare nonnull i8* @ret_nonnull()
 
 ; Return a pointer trivially nonnull (call return attribute)
 define i8* @test1() {
-; BOTH: define nonnull i8* @test1
+; FNATTR: define nonnull i8* @test1
   %ret = call i8* @ret_nonnull()
   ret i8* %ret
 }
 
 ; Return a pointer trivially nonnull (argument attribute)
 define i8* @test2(i8* nonnull %p) {
-; BOTH: define nonnull i8* @test2
+; FNATTR: define nonnull i8* @test2
   ret i8* %p
 }
 
@@ -25,7 +23,6 @@ define i8* @test2(i8* nonnull %p) {
 ; can we still mark the other one which is trivially nonnull
 define i8* @scc_binder(i1 %c) {
 ; FNATTR: define i8* @scc_binder
-; ATTRIBUTOR: define noalias i8* @scc_binder
   br i1 %c, label %rec, label %end
 rec:
   call i8* @test3(i1 %c)
@@ -35,7 +32,7 @@ end:
 }
 
 define i8* @test3(i1 %c) {
-; BOTH: define nonnull i8* @test3
+; FNATTR: define nonnull i8* @test3
   call i8* @scc_binder(i1 %c)
   %ret = call i8* @ret_nonnull()
   ret i8* %ret
@@ -46,14 +43,12 @@ define i8* @test3(i1 %c) {
 ; just never return period.)
 define i8* @test4_helper() {
 ; FNATTR: define noalias nonnull i8* @test4_helper
-; ATTRIBUTOR: define noalias nonnull align 536870912 dereferenceable(4294967295) i8* @test4_helper
   %ret = call i8* @test4()
   ret i8* %ret
 }
 
 define i8* @test4() {
 ; FNATTR: define noalias nonnull i8* @test4
-; ATTRIBUTOR: define noalias nonnull align 536870912 dereferenceable(4294967295) i8* @test4
   %ret = call i8* @test4_helper()
   ret i8* %ret
 }
@@ -62,7 +57,6 @@ define i8* @test4() {
 ; make sure we haven't marked them as nonnull.
 define i8* @test5_helper(i1 %c) {
 ; FNATTR: define noalias i8* @test5_helper
-; ATTRIBUTOR: define noalias i8* @test5_helper
   br i1 %c, label %rec, label %end
 rec:
   %ret = call i8* @test5(i1 %c)
@@ -73,14 +67,11 @@ end:
 
 define i8* @test5(i1 %c) {
 ; FNATTR: define noalias i8* @test5
-; ATTRIBUTOR: define noalias i8* @test5
   %ret = call i8* @test5_helper(i1 %c)
   ret i8* %ret
 }
 
 ; Local analysis, but going through a self recursive phi
-; ATTRIBUTOR: Function Attrs: noreturn
-; ATTRIBUTOR: define noalias nonnull align 536870912 dereferenceable(4294967295) i8* @test6a()
 define i8* @test6a() {
 entry:
   %ret = call i8* @ret_nonnull()
@@ -92,7 +83,6 @@ exit:
   ret i8* %phi
 }
 
-; ATTRIBUTOR: define nonnull i8* @test6b(i1 %c)
 define i8* @test6b(i1 %c) {
 entry:
   %ret = call i8* @ret_nonnull()
@@ -104,19 +94,19 @@ exit:
   ret i8* %phi
 }
 
-; BOTH: define i8* @test7
+; FNATTR: define i8* @test7
 define i8* @test7(i8* %a) {
   %b = getelementptr inbounds i8, i8* %a, i64 0
   ret i8* %b
 }
 
-; BOTH: define nonnull i8* @test8
+; FNATTR: define nonnull i8* @test8
 define i8* @test8(i8* %a) {
   %b = getelementptr inbounds i8, i8* %a, i64 1
   ret i8* %b
 }
 
-; BOTH: define i8* @test9
+; FNATTR: define i8* @test9
 define i8* @test9(i8* %a, i64 %n) {
   %b = getelementptr inbounds i8, i8* %a, i64 %n
   ret i8* %b
@@ -125,7 +115,6 @@ define i8* @test9(i8* %a, i64 %n) {
 declare void @llvm.assume(i1)
 ; FNATTR: define i8* @test10
 ; FIXME: missing nonnull
-; ATTRIBUTOR: define i8* @test10
 define i8* @test10(i8* %a, i64 %n) {
   %cmp = icmp ne i64 %n, 0
   call void @llvm.assume(i1 %cmp)
@@ -139,7 +128,6 @@ define i8* @test10(i8* %a, i64 %n) {
 ; }
 ; FNATTR: define i8* @test11
 ; FIXME: missing nonnull
-; ATTRIBUTOR: define i8* @test11
 define i8* @test11(i8*) local_unnamed_addr {
   %2 = icmp eq i8* %0, null
   br i1 %2, label %3, label %5
@@ -157,8 +145,6 @@ define i8* @test11(i8*) local_unnamed_addr {
 ; Simple CallSite Test
 declare void @test12_helper(i8*)
 define void @test12(i8* nonnull %a) {
-; ATTRIBUTOR: define void @test12(i8* nonnull %a)
-; ATTRIBUTOR-NEXT: tail call void @test12_helper(i8* nonnull %a)
   tail call void @test12_helper(i8* %a)
   ret void
 }
@@ -174,7 +160,6 @@ define void @test13_helper() {
   ret void
 }
 define internal void @test13(i8* %a, i8* %b, i8* %c) {
-; ATTRIBUTOR: define internal void @test13(i8* nocapture nofree nonnull readnone %a, i8* nocapture nofree readnone %b, i8* nocapture nofree readnone %c)
   ret void
 }
 
@@ -194,7 +179,6 @@ declare nonnull i8* @nonnull()
 
 define internal i32* @f1(i32* %arg) {
 ; FIXME: missing nonnull It should be nonnull @f1(i32* nonnull readonly %arg)
-; ATTRIBUTOR: define internal nonnull i32* @f1(i32* nofree readonly %arg)
 
 bb:
   %tmp = icmp eq i32* %arg, null
@@ -207,14 +191,12 @@ bb1:                                              ; preds = %bb
 
 bb4:                                              ; preds = %bb1
   %tmp5 = getelementptr inbounds i32, i32* %arg, i64 1
-; ATTRIBUTOR: %tmp5b = tail call nonnull i32* @f3(i32* nofree nonnull %tmp5)
   %tmp5b = tail call i32* @f3(i32* %tmp5)
   %tmp5c = getelementptr inbounds i32, i32* %tmp5b, i64 -1
   br label %bb9
 
 bb6:                                              ; preds = %bb1
 ; FIXME: missing nonnull. It should be @f2(i32* nonnull %arg)
-; ATTRIBUTOR: %tmp7 = tail call nonnull i32* @f2(i32* nofree %arg)
   %tmp7 = tail call i32* @f2(i32* %arg)
   ret i32* %tmp7
 
@@ -225,28 +207,23 @@ bb9:                                              ; preds = %bb4, %bb
 
 define internal i32* @f2(i32* %arg) {
 ; FIXME: missing nonnull. It should be nonnull @f2(i32* nonnull %arg)
-; ATTRIBUTOR: define internal nonnull i32* @f2(i32* nofree readonly %arg)
 bb:
 
 ; FIXME: missing nonnull. It should be @f1(i32* nonnull readonly %arg)
-; ATTRIBUTOR:   %tmp = tail call nonnull i32* @f1(i32* nofree %arg)
   %tmp = tail call i32* @f1(i32* %arg)
   ret i32* %tmp
 }
 
 define dso_local noalias i32* @f3(i32* %arg) {
 ; FIXME: missing nonnull. It should be nonnull @f3(i32* nonnull readonly %arg)
-; ATTRIBUTOR: define dso_local noalias nonnull i32* @f3(i32* nofree readonly %arg)
 bb:
 ; FIXME: missing nonnull. It should be @f1(i32* nonnull readonly %arg)
-; ATTRIBUTOR:   %tmp = call nonnull i32* @f1(i32* nofree %arg)
   %tmp = call i32* @f1(i32* %arg)
   ret i32* %tmp
 }
 
 ; TEST 15
 define void @f15(i8* %arg) {
-; ATTRIBUTOR:   tail call void @use1(i8* nonnull dereferenceable(4) %arg)
 
   tail call void @use1(i8* dereferenceable(4) %arg)
   ret void
@@ -264,7 +241,6 @@ declare void @fun3(i8*, i8*, i8*) #1
 ; We can say that %a is nonnull but %b is not.
 define void @f16(i8* %a, i8 * %b, i8 %c) {
 ; FIXME: missing nonnull on %a
-; ATTRIBUTOR: define void @f16(i8* %a, i8* %b, i8 %c)
   %cmp = icmp eq i8 %c, 0
   br i1 %cmp, label %if.then, label %if.else
 if.then:
@@ -282,7 +258,6 @@ if.else:
 ; fun1(nonnull %a)
 ; We can say that %a is nonnull
 define void @f17(i8* %a, i8 %c) {
-; ATTRIBUTOR: define void @f17(i8* nonnull %a, i8 %c)
   %cmp = icmp eq i8 %c, 0
   br i1 %cmp, label %if.then, label %if.else
 if.then:
@@ -307,7 +282,6 @@ cont:
 ; fun1(nonnull %a)
 
 define void @f18(i8* %a, i8* %b, i8 %c) {
-; ATTRIBUTOR: define void @f18(i8* nonnull %a, i8* %b, i8 %c)
   %cmp1 = icmp eq i8 %c, 0
   br i1 %cmp1, label %if.then, label %if.else
 if.then:
@@ -334,7 +308,6 @@ cont2:
 
 define void @f19(i8* %a, i8* %b, i8 %c) {
 ; FIXME: missing nonnull on %b
-; ATTRIBUTOR: define void @f19(i8* %a, i8* %b, i8 %c)
   br label %loop.header
 loop.header:
   %cmp2 = icmp eq i8 %c, 0
@@ -363,11 +336,10 @@ declare i8 @use1safecall(i8* %x) readonly nounwind ; readonly+nounwind guarantee
 ; Can't extend non-null to parent for any argument because the 2nd call is not guaranteed to execute.
 
 define void @parent1(i8* %a, i8* %b, i8* %c) {
-; BOTH-LABEL: @parent1(i8* %a, i8* %b, i8* %c)
-; BOTH-NEXT:    call void @use3(i8* %c, i8* %a, i8* %b)
+; FNATTR-LABEL: @parent1(i8* %a, i8* %b, i8* %c)
+; FNATTR-NEXT:    call void @use3(i8* %c, i8* %a, i8* %b)
 ; FNATTR-NEXT:    call void @use3nonnull(i8* %b, i8* %c, i8* %a)
-; ATTRIBUTOR-NEXT:    call void @use3nonnull(i8* nonnull %b, i8* nonnull %c, i8* nonnull %a)
-; BOTH-NEXT:    ret void
+; FNATTR-NEXT:    ret void
   call void @use3(i8* %c, i8* %a, i8* %b)
   call void @use3nonnull(i8* %b, i8* %c, i8* %a)
   ret void
@@ -380,11 +352,8 @@ define void @parent2(i8* %a, i8* %b, i8* %c) {
 ; FNATTR-NEXT:    call void @use3nonnull(i8* %b, i8* %c, i8* %a)
 ; FNATTR-NEXT:    call void @use3(i8* %c, i8* %a, i8* %b)
 
-; ATTRIBUTOR-LABEL: @parent2(i8* nonnull %a, i8* nonnull %b, i8* nonnull %c)
-; ATTRIBUTOR-NEXT:    call void @use3nonnull(i8* nonnull %b, i8* nonnull %c, i8* nonnull %a)
-; ATTRIBUTOR-NEXT:    call void @use3(i8* nonnull %c, i8* nonnull %a, i8* nonnull %b)
 
-; BOTH-NEXT:    ret void
+; FNATTR-NEXT:    ret void
   call void @use3nonnull(i8* %b, i8* %c, i8* %a)
   call void @use3(i8* %c, i8* %a, i8* %b)
   ret void
@@ -397,11 +366,8 @@ define void @parent3(i8* %a, i8* %b, i8* %c) {
 ; FNATTR-NEXT:    call void @use1nonnull(i8* %a)
 ; FNATTR-NEXT:    call void @use3(i8* %c, i8* %b, i8* %a)
 
-; ATTRIBUTOR-LABEL: @parent3(i8* nonnull %a, i8* %b, i8* %c)
-; ATTRIBUTOR-NEXT:    call void @use1nonnull(i8* nonnull %a)
-; ATTRIBUTOR-NEXT:    call void @use3(i8* %c, i8* %b, i8* nonnull %a)
 
-; BOTH-NEXT:  ret void
+; FNATTR-NEXT:  ret void
 
   call void @use1nonnull(i8* %a)
   call void @use3(i8* %c, i8* %b, i8* %a)
@@ -416,12 +382,8 @@ define void @parent4(i8* %a, i8* %b, i8* %c) {
 ; CHECK-NEXT:    call void @use2(i8* %a, i8* %c)
 ; CHECK-NEXT:    call void @use1(i8* %b)
 
-; ATTRIBUTOR-LABEL: @parent4(i8* %a, i8* nonnull %b, i8* nonnull %c)
-; ATTRIBUTOR-NEXT:    call void @use2nonnull(i8* nonnull %c, i8* nonnull %b)
-; ATTRIBUTOR-NEXT:    call void @use2(i8* %a, i8* nonnull %c)
-; ATTRIBUTOR-NEXT:    call void @use1(i8* nonnull %b)
 
-; BOTH: ret void
+; FNATTR: ret void
 
   call void @use2nonnull(i8* %c, i8* %b)
   call void @use2(i8* %a, i8* %c)
@@ -434,14 +396,13 @@ define void @parent4(i8* %a, i8* %b, i8* %c) {
 ; because it would incorrectly propagate the wrong information to its callers.
 
 define void @parent5(i8* %a, i1 %a_is_notnull) {
-; BOTH: @parent5(i8* %a, i1 %a_is_notnull)
-; BOTH-NEXT:    br i1 %a_is_notnull, label %t, label %f
-; BOTH:       t:
+; FNATTR: @parent5(i8* %a, i1 %a_is_notnull)
+; FNATTR-NEXT:    br i1 %a_is_notnull, label %t, label %f
+; FNATTR:       t:
 ; FNATTR-NEXT:    call void @use1nonnull(i8* %a)
-; ATTRIBUTOR-NEXT:    call void @use1nonnull(i8* nonnull %a)
-; BOTH-NEXT:    ret void
-; BOTH:       f:
-; BOTH-NEXT:    ret void
+; FNATTR-NEXT:    ret void
+; FNATTR:       f:
+; FNATTR-NEXT:    ret void
 
   br i1 %a_is_notnull, label %t, label %f
 t:
@@ -456,11 +417,9 @@ f:
 
 define i8 @parent6(i8* %a, i8* %b) {
 ; FNATTR-LABEL: @parent6(i8* nonnull %a, i8* %b)
-; ATTRIBUTOR-LABEL: @parent6(i8* nonnull %a, i8* %b)
-; BOTH-NEXT:    [[C:%.*]] = load volatile i8, i8* %b
+; FNATTR-NEXT:    [[C:%.*]] = load volatile i8, i8* %b
 ; FNATTR-NEXT:    call void @use1nonnull(i8* %a)
-; ATTRIBUTOR-NEXT:    call void @use1nonnull(i8* nonnull %a)
-; BOTH-NEXT:    ret i8 [[C]]
+; FNATTR-NEXT:    ret i8 [[C]]
 
   %c = load volatile i8, i8* %b
   call void @use1nonnull(i8* %a)
@@ -475,11 +434,8 @@ define i8 @parent7(i8* %a) {
 ; FNATTR-NEXT:    call void @use1nonnull(i8* %a)
 
 
-; ATTRIBUTOR-LABEL: @parent7(i8* nonnull %a)
-; ATTRIBUTOR-NEXT:    [[RET:%.*]] = call i8 @use1safecall(i8* nonnull %a)
-; ATTRIBUTOR-NEXT:    call void @use1nonnull(i8* nonnull %a)
 
-; BOTH-NEXT: ret i8 [[RET]]
+; FNATTR-NEXT: ret i8 [[RET]]
 
   %ret = call i8 @use1safecall(i8* %a)
   call void @use1nonnull(i8* %a)
@@ -492,18 +448,16 @@ 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)
-; ATTRIBUTOR-LABEL: @parent8(i8* nonnull %a, i8* nocapture nofree readnone %bogus1, i8* nonnull %b)
-; BOTH-NEXT:  entry:
+; FNATTR-NEXT:  entry:
 ; FNATTR-NEXT:    invoke void @use2nonnull(i8* %a, i8* %b)
-; ATTRIBUTOR-NEXT:    invoke void @use2nonnull(i8* nonnull %a, i8* nonnull %b)
-; BOTH-NEXT:    to label %cont unwind label %exc
-; BOTH:       cont:
-; BOTH-NEXT:    [[NULL_CHECK:%.*]] = icmp eq i8* %b, null
-; BOTH-NEXT:    ret i1 [[NULL_CHECK]]
-; BOTH:       exc:
-; BOTH-NEXT:    [[LP:%.*]] = landingpad { i8*, i32 }
-; BOTH-NEXT:    filter [0 x i8*] zeroinitializer
-; BOTH-NEXT:    unreachable
+; FNATTR-NEXT:    to label %cont unwind label %exc
+; FNATTR:       cont:
+; FNATTR-NEXT:    [[NULL_CHECK:%.*]] = icmp eq i8* %b, null
+; FNATTR-NEXT:    ret i1 [[NULL_CHECK]]
+; FNATTR:       exc:
+; FNATTR-NEXT:    [[LP:%.*]] = landingpad { i8*, i32 }
+; FNATTR-NEXT:    filter [0 x i8*] zeroinitializer
+; FNATTR-NEXT:    unreachable
 
 entry:
   invoke void @use2nonnull(i8* %a, i8* %b)
@@ -519,7 +473,7 @@ exc:
   unreachable
 }
 
-; BOTH: define nonnull i32* @gep1(
+; FNATTR: define nonnull i32* @gep1(
 define i32* @gep1(i32* %p) {
   %q = getelementptr inbounds i32, i32* %p, i32 1
   ret i32* %q
@@ -527,12 +481,12 @@ define i32* @gep1(i32* %p) {
 
 define i32* @gep1_no_null_opt(i32* %p) #0 {
 ; Should't be able to derive nonnull based on gep.
-; BOTH: define i32* @gep1_no_null_opt(
+; FNATTR: define i32* @gep1_no_null_opt(
   %q = getelementptr inbounds i32, i32* %p, i32 1
   ret i32* %q
 }
 
-; BOTH: define i32 addrspace(3)* @gep2(
+; FNATTR: define i32 addrspace(3)* @gep2(
 define i32 addrspace(3)* @gep2(i32 addrspace(3)* %p) {
   %q = getelementptr inbounds i32, i32 addrspace(3)* %p, i32 1
   ret i32 addrspace(3)* %q
@@ -540,12 +494,11 @@ define i32 addrspace(3)* @gep2(i32 addrspace(3)* %p) {
 
 ; FNATTR:     define i32 addrspace(3)* @as(i32 addrspace(3)* readnone returned dereferenceable(4) %p)
 ; FIXME: We should propagate dereferenceable here but *not* nonnull
-; ATTRIBUTOR: define dereferenceable_or_null(4) i32 addrspace(3)* @as(i32 addrspace(3)* nofree readnone returned dereferenceable(4) dereferenceable_or_null(4) %p)
 define i32 addrspace(3)* @as(i32 addrspace(3)* dereferenceable(4) %p) {
   ret i32 addrspace(3)* %p
 }
 
-; BOTH: define internal nonnull i32* @g2()
+; FNATTR: define internal nonnull i32* @g2()
 define internal i32* @g2() {
   ret i32* inttoptr (i64 4 to i32*)
 }
@@ -556,33 +509,28 @@ define  i32* @g1() {
 }
 
 declare void @use_i32_ptr(i32*) readnone nounwind
-; ATTRIBUTOR: define internal void @called_by_weak(i32* nocapture nonnull readnone %a)
 define internal void @called_by_weak(i32* %a) {
   call void @use_i32_ptr(i32* %a)
   ret void
 }
 
 ; Check we do not annotate the function interface of this weak function.
-; ATTRIBUTOR: define weak_odr void @weak_caller(i32* nonnull %a)
 define weak_odr void @weak_caller(i32* nonnull %a) {
   call void @called_by_weak(i32* %a)
   ret void
 }
 
 ; Expect nonnull
-; ATTRIBUTOR: define internal void @control(i32* nocapture nonnull readnone align 16 dereferenceable(8) %a)
 define internal void @control(i32* dereferenceable(4) %a) {
   call void @use_i32_ptr(i32* %a)
   ret void
 }
 ; Avoid nonnull as we do not touch naked functions
-; ATTRIBUTOR: define internal void @naked(i32* dereferenceable(4) %a)
 define internal void @naked(i32* dereferenceable(4) %a) naked {
   call void @use_i32_ptr(i32* %a)
   ret void
 }
 ; Avoid nonnull as we do not touch optnone
-; ATTRIBUTOR: define internal void @optnone(i32* dereferenceable(4) %a)
 define internal void @optnone(i32* dereferenceable(4) %a) optnone noinline {
   call void @use_i32_ptr(i32* %a)
   ret void
@@ -618,20 +566,6 @@ define i32 @nonnull_exec_ctx_1(i32* %a, i32 %b) {
 ; FNATTR-NEXT:    [[TMP9:%.*]] = icmp eq i32 [[TMP8]], [[B]]
 ; FNATTR-NEXT:    br i1 [[TMP9]], label [[EX]], label [[HD]]
 ;
-; ATTRIBUTOR-LABEL: define {{[^@]+}}@nonnull_exec_ctx_1
-; ATTRIBUTOR-SAME: (i32* [[A:%.*]], i32 [[B:%.*]])
-; ATTRIBUTOR-NEXT:  en:
-; ATTRIBUTOR-NEXT:    [[TMP3:%.*]] = icmp eq i32 [[B:%.*]], 0
-; ATTRIBUTOR-NEXT:    br i1 [[TMP3]], label [[EX:%.*]], label [[HD:%.*]]
-; ATTRIBUTOR:       ex:
-; ATTRIBUTOR-NEXT:    [[TMP5:%.*]] = tail call i32 @g(i32* nonnull [[A:%.*]])
-; ATTRIBUTOR-NEXT:    ret i32 [[TMP5]]
-; ATTRIBUTOR:       hd:
-; ATTRIBUTOR-NEXT:    [[TMP7:%.*]] = phi i32 [ [[TMP8:%.*]], [[HD]] ], [ 0, [[EN:%.*]] ]
-; ATTRIBUTOR-NEXT:    tail call void @h(i32* [[A]])
-; ATTRIBUTOR-NEXT:    [[TMP8]] = add nuw i32 [[TMP7]], 1
-; ATTRIBUTOR-NEXT:    [[TMP9:%.*]] = icmp eq i32 [[TMP8]], [[B]]
-; ATTRIBUTOR-NEXT:    br i1 [[TMP9]], label [[EX]], label [[HD]]
 ;
 en:
   %tmp3 = icmp eq i32 %b, 0
@@ -667,22 +601,6 @@ define i32 @nonnull_exec_ctx_1b(i32* %a, i32 %b) {
 ; FNATTR-NEXT:    [[TMP9:%.*]] = icmp eq i32 [[TMP8]], [[B]]
 ; FNATTR-NEXT:    br i1 [[TMP9]], label [[EX]], label [[HD]]
 ;
-; ATTRIBUTOR-LABEL: define {{[^@]+}}@nonnull_exec_ctx_1b
-; ATTRIBUTOR-SAME: (i32* [[A:%.*]], i32 [[B:%.*]])
-; ATTRIBUTOR-NEXT:  en:
-; ATTRIBUTOR-NEXT:    [[TMP3:%.*]] = icmp eq i32 [[B:%.*]], 0
-; ATTRIBUTOR-NEXT:    br i1 [[TMP3]], label [[EX:%.*]], label [[HD:%.*]]
-; ATTRIBUTOR:       ex:
-; ATTRIBUTOR-NEXT:    [[TMP5:%.*]] = tail call i32 @g(i32* nonnull [[A:%.*]])
-; ATTRIBUTOR-NEXT:    ret i32 [[TMP5]]
-; ATTRIBUTOR:       hd:
-; ATTRIBUTOR-NEXT:    [[TMP7:%.*]] = phi i32 [ [[TMP8:%.*]], [[HD2:%.*]] ], [ 0, [[EN:%.*]] ]
-; ATTRIBUTOR-NEXT:    tail call void @h(i32* [[A]])
-; ATTRIBUTOR-NEXT:    br label [[HD2]]
-; ATTRIBUTOR:       hd2:
-; ATTRIBUTOR-NEXT:    [[TMP8]] = add nuw i32 [[TMP7]], 1
-; ATTRIBUTOR-NEXT:    [[TMP9:%.*]] = icmp eq i32 [[TMP8]], [[B]]
-; ATTRIBUTOR-NEXT:    br i1 [[TMP9]], label [[EX]], label [[HD]]
 ;
 en:
   %tmp3 = icmp eq i32 %b, 0
@@ -719,20 +637,6 @@ define i32 @nonnull_exec_ctx_2(i32* %a, i32 %b) willreturn nounwind {
 ; FNATTR-NEXT:    [[TMP9:%.*]] = icmp eq i32 [[TMP8]], [[B]]
 ; FNATTR-NEXT:    br i1 [[TMP9]], label [[EX]], label [[HD]]
 ;
-; ATTRIBUTOR-LABEL: define {{[^@]+}}@nonnull_exec_ctx_2
-; ATTRIBUTOR-SAME: (i32* [[A:%.*]], i32 [[B:%.*]])
-; ATTRIBUTOR-NEXT:  en:
-; ATTRIBUTOR-NEXT:    [[TMP3:%.*]] = icmp eq i32 [[B:%.*]], 0
-; ATTRIBUTOR-NEXT:    br i1 [[TMP3]], label [[EX:%.*]], label [[HD:%.*]]
-; ATTRIBUTOR:       ex:
-; ATTRIBUTOR-NEXT:    [[TMP5:%.*]] = tail call i32 @g(i32* nonnull [[A:%.*]])
-; ATTRIBUTOR-NEXT:    ret i32 [[TMP5]]
-; ATTRIBUTOR:       hd:
-; ATTRIBUTOR-NEXT:    [[TMP7:%.*]] = phi i32 [ [[TMP8:%.*]], [[HD]] ], [ 0, [[EN:%.*]] ]
-; ATTRIBUTOR-NEXT:    tail call void @h(i32* nonnull [[A]])
-; ATTRIBUTOR-NEXT:    [[TMP8]] = add nuw i32 [[TMP7]], 1
-; ATTRIBUTOR-NEXT:    [[TMP9:%.*]] = icmp eq i32 [[TMP8]], [[B]]
-; ATTRIBUTOR-NEXT:    br i1 [[TMP9]], label [[EX]], label [[HD]]
 ;
 en:
   %tmp3 = icmp eq i32 %b, 0
@@ -768,22 +672,6 @@ define i32 @nonnull_exec_ctx_2b(i32* %a, i32 %b) willreturn nounwind {
 ; FNATTR-NEXT:    [[TMP9:%.*]] = icmp eq i32 [[TMP8]], [[B]]
 ; FNATTR-NEXT:    br i1 [[TMP9]], label [[EX]], label [[HD]]
 ;
-; ATTRIBUTOR-LABEL: define {{[^@]+}}@nonnull_exec_ctx_2b
-; ATTRIBUTOR-SAME: (i32* [[A:%.*]], i32 [[B:%.*]])
-; ATTRIBUTOR-NEXT:  en:
-; ATTRIBUTOR-NEXT:    [[TMP3:%.*]] = icmp eq i32 [[B:%.*]], 0
-; ATTRIBUTOR-NEXT:    br i1 [[TMP3]], label [[EX:%.*]], label [[HD:%.*]]
-; ATTRIBUTOR:       ex:
-; ATTRIBUTOR-NEXT:    [[TMP5:%.*]] = tail call i32 @g(i32* nonnull [[A:%.*]])
-; ATTRIBUTOR-NEXT:    ret i32 [[TMP5]]
-; ATTRIBUTOR:       hd:
-; ATTRIBUTOR-NEXT:    [[TMP7:%.*]] = phi i32 [ [[TMP8:%.*]], [[HD2:%.*]] ], [ 0, [[EN:%.*]] ]
-; ATTRIBUTOR-NEXT:    tail call void @h(i32* nonnull [[A]])
-; ATTRIBUTOR-NEXT:    br label [[HD2]]
-; ATTRIBUTOR:       hd2:
-; ATTRIBUTOR-NEXT:    [[TMP8]] = add nuw i32 [[TMP7]], 1
-; ATTRIBUTOR-NEXT:    [[TMP9:%.*]] = icmp eq i32 [[TMP8]], [[B]]
-; ATTRIBUTOR-NEXT:    br i1 [[TMP9]], label [[EX]], label [[HD]]
 ;
 en:
   %tmp3 = icmp eq i32 %b, 0
@@ -809,21 +697,21 @@ declare void @sink(i32*)
 
 ; FIXME: the sink argument should be marked nonnull as in @PR43833_simple.
 define void @PR43833(i32* %0, i32 %1) {
-; BOTH-LABEL: @PR43833(
-; BOTH-NEXT:    [[TMP3:%.*]] = icmp sgt i32 [[TMP1:%.*]], 1
-; BOTH-NEXT:    br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP7:%.*]]
-; BOTH:       4:
-; BOTH-NEXT:    [[TMP5:%.*]] = zext i32 [[TMP1]] to i64
-; BOTH-NEXT:    [[TMP6:%.*]] = getelementptr inbounds i32, i32* [[TMP0:%.*]], i64 [[TMP5]]
-; BOTH-NEXT:    br label [[TMP8:%.*]]
-; BOTH:       7:
-; BOTH-NEXT:    ret void
-; BOTH:       8:
-; BOTH-NEXT:    [[TMP9:%.*]] = phi i32 [ 1, [[TMP4]] ], [ [[TMP10:%.*]], [[TMP8]] ]
-; BOTH-NEXT:    tail call void @sink(i32* [[TMP6]])
-; BOTH-NEXT:    [[TMP10]] = add nuw nsw i32 [[TMP9]], 1
-; BOTH-NEXT:    [[TMP11:%.*]] = icmp eq i32 [[TMP10]], [[TMP1]]
-; BOTH-NEXT:    br i1 [[TMP11]], label [[TMP7]], label [[TMP8]]
+; FNATTR-LABEL: @PR43833(
+; FNATTR-NEXT:    [[TMP3:%.*]] = icmp sgt i32 [[TMP1:%.*]], 1
+; FNATTR-NEXT:    br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP7:%.*]]
+; FNATTR:       4:
+; FNATTR-NEXT:    [[TMP5:%.*]] = zext i32 [[TMP1]] to i64
+; FNATTR-NEXT:    [[TMP6:%.*]] = getelementptr inbounds i32, i32* [[TMP0:%.*]], i64 [[TMP5]]
+; FNATTR-NEXT:    br label [[TMP8:%.*]]
+; FNATTR:       7:
+; FNATTR-NEXT:    ret void
+; FNATTR:       8:
+; FNATTR-NEXT:    [[TMP9:%.*]] = phi i32 [ 1, [[TMP4]] ], [ [[TMP10:%.*]], [[TMP8]] ]
+; FNATTR-NEXT:    tail call void @sink(i32* [[TMP6]])
+; FNATTR-NEXT:    [[TMP10]] = add nuw nsw i32 [[TMP9]], 1
+; FNATTR-NEXT:    [[TMP11:%.*]] = icmp eq i32 [[TMP10]], [[TMP1]]
+; FNATTR-NEXT:    br i1 [[TMP11]], label [[TMP7]], label [[TMP8]]
 ;
   %3 = icmp sgt i32 %1, 1
   br i1 %3, label %4, label %7
@@ -846,37 +734,22 @@ define void @PR43833(i32* %0, i32 %1) {
 
 ; Adjusted from PR43833
 define void @PR43833_simple(i32* %0, i32 %1) {
-; OLD-LABEL: @PR43833_simple(
-; OLD-NEXT:    [[TMP3:%.*]] = icmp ne i32 [[TMP1:%.*]], 0
-; OLD-NEXT:    br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP7:%.*]]
-; OLD:       4:
-; OLD-NEXT:    [[TMP5:%.*]] = zext i32 [[TMP1]] to i64
-; OLD-NEXT:    [[TMP6:%.*]] = getelementptr inbounds i32, i32* [[TMP0:%.*]], i64 [[TMP5]]
-; OLD-NEXT:    br label [[TMP8:%.*]]
-; OLD:       7:
-; OLD-NEXT:    ret void
-; OLD:       8:
-; OLD-NEXT:    [[TMP9:%.*]] = phi i32 [ 1, [[TMP4]] ], [ [[TMP10:%.*]], [[TMP8]] ]
-; OLD-NEXT:    tail call void @sink(i32* [[TMP6]])
-; OLD-NEXT:    [[TMP10]] = add nuw nsw i32 [[TMP9]], 1
-; OLD-NEXT:    [[TMP11:%.*]] = icmp eq i32 [[TMP10]], [[TMP1]]
-; OLD-NEXT:    br i1 [[TMP11]], label [[TMP7]], label [[TMP8]]
+; FNATTR-LABEL: @PR43833_simple(
+; FNATTR-NEXT:    [[TMP3:%.*]] = icmp ne i32 [[TMP1:%.*]], 0
+; FNATTR-NEXT:    br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP7:%.*]]
+; FNATTR:       4:
+; FNATTR-NEXT:    [[TMP5:%.*]] = zext i32 [[TMP1]] to i64
+; FNATTR-NEXT:    [[TMP6:%.*]] = getelementptr inbounds i32, i32* [[TMP0:%.*]], i64 [[TMP5]]
+; FNATTR-NEXT:    br label [[TMP8:%.*]]
+; FNATTR:       7:
+; FNATTR-NEXT:    ret void
+; FNATTR:       8:
+; FNATTR-NEXT:    [[TMP9:%.*]] = phi i32 [ 1, [[TMP4]] ], [ [[TMP10:%.*]], [[TMP8]] ]
+; FNATTR-NEXT:    tail call void @sink(i32* [[TMP6]])
+; FNATTR-NEXT:    [[TMP10]] = add nuw nsw i32 [[TMP9]], 1
+; FNATTR-NEXT:    [[TMP11:%.*]] = icmp eq i32 [[TMP10]], [[TMP1]]
+; FNATTR-NEXT:    br i1 [[TMP11]], label [[TMP7]], label [[TMP8]]
 ;
-; ATTRIBUTOR_NPM-LABEL: @PR43833_simple(
-; ATTRIBUTOR_NPM-NEXT:    [[TMP3:%.*]] = icmp ne i32 [[TMP1:%.*]], 0
-; ATTRIBUTOR_NPM-NEXT:    br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP7:%.*]]
-; ATTRIBUTOR_NPM:       4:
-; ATTRIBUTOR_NPM-NEXT:    [[TMP5:%.*]] = zext i32 [[TMP1]] to i64
-; ATTRIBUTOR_NPM-NEXT:    [[TMP6:%.*]] = getelementptr inbounds i32, i32* [[TMP0:%.*]], i64 [[TMP5]]
-; ATTRIBUTOR_NPM-NEXT:    br label [[TMP8:%.*]]
-; ATTRIBUTOR_NPM:       7:
-; ATTRIBUTOR_NPM-NEXT:    ret void
-; ATTRIBUTOR_NPM:       8:
-; ATTRIBUTOR_NPM-NEXT:    [[TMP9:%.*]] = phi i32 [ 1, [[TMP4]] ], [ [[TMP10:%.*]], [[TMP8]] ]
-; ATTRIBUTOR_NPM-NEXT:    tail call void @sink(i32* [[TMP6]])
-; ATTRIBUTOR_NPM-NEXT:    [[TMP10]] = add nuw nsw i32 [[TMP9]], 1
-; ATTRIBUTOR_NPM-NEXT:    [[TMP11:%.*]] = icmp eq i32 [[TMP10]], [[TMP1]]
-; ATTRIBUTOR_NPM-NEXT:    br i1 [[TMP11]], label [[TMP7]], label [[TMP8]]
 ;
   %3 = icmp ne i32 %1, 0
   br i1 %3, label %4, label %7

diff  --git a/llvm/test/Transforms/FunctionAttrs/norecurse.ll b/llvm/test/Transforms/FunctionAttrs/norecurse.ll
index de5d35d63429..b780bb7b7189 100644
--- a/llvm/test/Transforms/FunctionAttrs/norecurse.ll
+++ b/llvm/test/Transforms/FunctionAttrs/norecurse.ll
@@ -1,88 +1,83 @@
-; RUN: opt < %s -basicaa -functionattrs -rpo-functionattrs -S | FileCheck %s --check-prefixes=CHECK,BOTH
-; RUN: opt < %s -aa-pipeline=basic-aa -passes='cgscc(function-attrs),rpo-functionattrs' -S | FileCheck %s --check-prefixes=CHECK,BOTH
-; RUN: opt -passes=attributor --attributor-disable=false -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=2 -S < %s | FileCheck %s --check-prefixes=ATTRIBUTOR,BOTH
+; RUN: opt < %s -basicaa -functionattrs -rpo-functionattrs -S | FileCheck %s 
+; RUN: opt < %s -aa-pipeline=basic-aa -passes='cgscc(function-attrs),rpo-functionattrs' -S | FileCheck %s
 
 ; CHECK: Function Attrs
 ; CHECK-SAME: norecurse nounwind readnone
-; ATTRIBUTOR: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
-; BOTH-NEXT: define i32 @leaf()
+; CHECK-NEXT: define i32 @leaf()
 define i32 @leaf() {
   ret i32 1
 }
 
-; BOTH: Function Attrs
-; BOTH-SAME: readnone
-; BOTH-NOT: norecurse
-; BOTH-NEXT: define i32 @self_rec()
+; CHECK: Function Attrs
+; CHECK-SAME: readnone
+; CHECK-NOT: norecurse
+; CHECK-NEXT: define i32 @self_rec()
 define i32 @self_rec() {
   %a = call i32 @self_rec()
   ret i32 4
 }
 
-; BOTH: Function Attrs
-; BOTH-SAME: readnone
-; BOTH-NOT: norecurse
-; BOTH-NEXT: define i32 @indirect_rec()
+; CHECK: Function Attrs
+; CHECK-SAME: readnone
+; CHECK-NOT: norecurse
+; CHECK-NEXT: define i32 @indirect_rec()
 define i32 @indirect_rec() {
   %a = call i32 @indirect_rec2()
   ret i32 %a
 }
-; BOTH: Function Attrs
-; BOTH-SAME: readnone
-; BOTH-NOT: norecurse
-; BOTH-NEXT: define i32 @indirect_rec2()
+; CHECK: Function Attrs
+; CHECK-SAME: readnone
+; CHECK-NOT: norecurse
+; CHECK-NEXT: define i32 @indirect_rec2()
 define i32 @indirect_rec2() {
   %a = call i32 @indirect_rec()
   ret i32 %a
 }
 
-; BOTH: Function Attrs
-; BOTH-SAME: readnone
-; BOTH-NOT: norecurse
-; BOTH-NEXT: define i32 @extern()
+; CHECK: Function Attrs
+; CHECK-SAME: readnone
+; CHECK-NOT: norecurse
+; CHECK-NEXT: define i32 @extern()
 define i32 @extern() {
   %a = call i32 @k()
   ret i32 %a
 }
 
-; BOTH: Function Attrs
-; BOTH-NEXT: declare i32 @k()
+; CHECK: Function Attrs
+; CHECK-NEXT: declare i32 @k()
 declare i32 @k() readnone
 
-; BOTH: Function Attrs
+; CHECK: Function Attrs
 ; CHECK-SAME: nounwind
-; BOTH-NOT: norecurse
+; CHECK-NOT: norecurse
 ; CHECK-NEXT: define void @intrinsic(i8* nocapture %dest, i8* nocapture readonly %src, i32 %len)
-; ATTRIBUTOR-NEXT: define void @intrinsic(i8* nocapture writeonly %dest, i8* nocapture readonly %src, i32 %len)
 define void @intrinsic(i8* %dest, i8* %src, i32 %len) {
   call void @llvm.memcpy.p0i8.p0i8.i32(i8* %dest, i8* %src, i32 %len, i1 false)
   ret void
 }
 
-; BOTH: Function Attrs
-; BOTH-NEXT: declare void @llvm.memcpy.p0i8.p0i8.i32
+; CHECK: Function Attrs
+; CHECK-NEXT: declare void @llvm.memcpy.p0i8.p0i8.i32
 declare void @llvm.memcpy.p0i8.p0i8.i32(i8*, i8*, i32, i1)
 
-; BOTH: Function Attrs
+; CHECK: Function Attrs
 ; CHECK-SAME: norecurse readnone
 ; FIXME: missing "norecurse"
-; ATTRIBUTOR-SAME: nosync readnone
 ; CHECK-NEXT: define internal i32 @called_by_norecurse()
 define internal i32 @called_by_norecurse() {
   %a = call i32 @k()
   ret i32 %a
 }
-; BOTH: Function Attrs
-; BOTH-NEXT: define void @m()
+; CHECK: Function Attrs
+; CHECK-NEXT: define void @m()
 define void @m() norecurse {
   %a = call i32 @called_by_norecurse()
   ret void
 }
 
-; BOTH: Function Attrs
+; CHECK: Function Attrs
 ; CHECK-SAME: norecurse readnone
 ; FIXME: missing "norecurse"
-; ATTRIBUTOR-SAME: nosync
 ; CHECK-NEXT: define internal i32 @called_by_norecurse_indirectly()
 define internal i32 @called_by_norecurse_indirectly() {
   %a = call i32 @k()
@@ -96,61 +91,3 @@ define void @p() norecurse {
   call void @o()
   ret void
 }
-
-; ATTRIBUTOR: Function Attrs: nofree nosync nounwind
-; ATTRIBUTOR-NEXT: define void @f(i32 %x)
-define void @f(i32 %x)  {
-entry:
-  %x.addr = alloca i32, align 4
-  store i32 %x, i32* %x.addr, align 4
-  %0 = load i32, i32* %x.addr, align 4
-  %tobool = icmp ne i32 %0, 0
-  br i1 %tobool, label %if.then, label %if.end
-
-if.then:
-  call void @g() norecurse
-  br label %if.end
-
-if.end:
-  ret void
-}
-
-; BOTH: define void @g()
-define void @g() norecurse {
-entry:
-  call void @f(i32 0)
-  ret void
-}
-
-; ATTRIBUTOR-NOT: Function Attrs
-; ATTRIBUTOR: define linkonce_odr i32 @leaf_redefinable()
-define linkonce_odr i32 @leaf_redefinable() {
-  ret i32 1
-}
-
-; Call through a function pointer
-; ATTRIBUTOR-NOT: Function Attrs
-; ATTRIBUTOR: define i32 @eval_func1(i32 (i32)* nocapture nofree nonnull %0, i32 %1)
-define i32 @eval_func1(i32 (i32)* , i32) local_unnamed_addr {
-  %3 = tail call i32 %0(i32 %1) #2
-  ret i32 %3
-}
-
-; ATTRIBUTOR-NOT: Function Attrs
-; ATTRIBUTOR: define i32 @eval_func2(i32 (i32)* nocapture nofree %0, i32 %1)
-define i32 @eval_func2(i32 (i32)* , i32) local_unnamed_addr "null-pointer-is-valid"="true"{
-  %3 = tail call i32 %0(i32 %1) #2
-  ret i32 %3
-}
-
-declare void @unknown()
-; Call an unknown function in a dead block.
-; ATTRIBUTOR: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
-; ATTRIBUTOR: define i32 @call_unknown_in_dead_block()
-define i32 @call_unknown_in_dead_block() local_unnamed_addr {
-  ret i32 0
-Dead:
-  tail call void @unknown()
-  ret i32 1
-}
-

diff  --git a/llvm/test/Transforms/FunctionAttrs/nounwind.ll b/llvm/test/Transforms/FunctionAttrs/nounwind.ll
index ed7576c970bf..6d5e3a2ea5b2 100644
--- a/llvm/test/Transforms/FunctionAttrs/nounwind.ll
+++ b/llvm/test/Transforms/FunctionAttrs/nounwind.ll
@@ -1,11 +1,8 @@
 ; RUN: opt < %s -functionattrs -S | FileCheck %s
-; RUN: opt < %s -attributor -attributor-disable=false -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=3 -S | FileCheck %s --check-prefix=ATTRIBUTOR
 
 ; TEST 1
 ; CHECK: Function Attrs: norecurse nounwind readnone
 ; CHECK-NEXT: define i32 @foo1()
-; ATTRIBUTOR: Function Attrs: nofree nosync nounwind
-; ATTRIBUTOR-NEXT: define i32 @foo1()
 define i32 @foo1() {
   ret i32 1
 }
@@ -13,8 +10,6 @@ define i32 @foo1() {
 ; TEST 2
 ; CHECK: Function Attrs: nounwind readnone
 ; CHECK-NEXT: define i32 @scc1_foo()
-; ATTRIBUTOR: Function Attrs: nofree noreturn nosync nounwind
-; ATTRIBUTOR-NEXT: define i32 @scc1_foo()
 define i32 @scc1_foo() {
   %1 = call i32 @scc1_bar()
   ret i32 1
@@ -24,8 +19,6 @@ define i32 @scc1_foo() {
 ; TEST 3
 ; CHECK: Function Attrs: nounwind readnone
 ; CHECK-NEXT: define i32 @scc1_bar()
-; ATTRIBUTOR: Function Attrs: nofree noreturn nosync nounwind
-; ATTRIBUTOR-NEXT: define i32 @scc1_bar()
 define i32 @scc1_bar() {
   %1 = call i32 @scc1_foo()
   ret i32 1
@@ -36,7 +29,6 @@ declare i32 @non_nounwind()
 
 ; TEST 4
 ; CHECK: define void @call_non_nounwind() {
-; ATTRIBUTOR: define void @call_non_nounwind() {
 define void @call_non_nounwind(){
     tail call i32 @non_nounwind()
     ret void
@@ -51,7 +43,6 @@ define void @call_non_nounwind(){
 ; }
 
 ; CHECK: define i32 @maybe_throw(i1 zeroext %0)
-; ATTRIBUTOR: define i32 @maybe_throw(i1 zeroext %0)
 define i32 @maybe_throw(i1 zeroext %0) {
   br i1 %0, label %2, label %3
 
@@ -75,7 +66,6 @@ declare void @__cxa_rethrow()
 ; }
 
 ; CHECK: define i32 @catch_thing()
-; ATTRIBUTOR: define i32 @catch_thing()
 define i32 @catch_thing() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
   invoke void @__cxa_rethrow() #1
           to label %1 unwind label %2
@@ -93,9 +83,6 @@ define i32 @catch_thing() personality i8* bitcast (i32 (...)* @__gxx_personality
 }
 
 define i32 @catch_thing_user() {
-; ATTRIBUTOR:     define i32 @catch_thing_user
-; ATTRIBUTOR-NEXT: %catch_thing_call = call
-; ATTRIBUTOR-NEXT: ret i32 -1
   %catch_thing_call = call i32 @catch_thing()
   ret i32 %catch_thing_call
 }

diff  --git a/llvm/test/Transforms/FunctionAttrs/readattrs.ll b/llvm/test/Transforms/FunctionAttrs/readattrs.ll
index dc1fbf652f9e..b11b3edcebfc 100644
--- a/llvm/test/Transforms/FunctionAttrs/readattrs.ll
+++ b/llvm/test/Transforms/FunctionAttrs/readattrs.ll
@@ -1,7 +1,5 @@
-; RUN: opt < %s -functionattrs -S | FileCheck %s --check-prefixes=CHECK,FNATTR
-; RUN: opt < %s -aa-pipeline=basic-aa -passes='cgscc(function-attrs)' -S | FileCheck %s --check-prefixes=CHECK,FNATTR
-; RUN: opt < %s -attributor -attributor-disable=false -S -attributor-annotate-decl-cs | FileCheck %s --check-prefixes=CHECK,ATTRIBUTOR
-; RUN: opt < %s -aa-pipeline=basic-aa -passes='attributor' -attributor-disable=false -S -attributor-annotate-decl-cs | FileCheck %s --check-prefixes=CHECK,ATTRIBUTOR
+; RUN: opt < %s -functionattrs -S | FileCheck %s
+; RUN: opt < %s -aa-pipeline=basic-aa -passes='cgscc(function-attrs)' -S | FileCheck %s
 
 @x = global i32 0
 
@@ -9,23 +7,20 @@ declare void @test1_1(i8* %x1_1, i8* readonly %y1_1, ...)
 
 ; NOTE: readonly for %y1_2 would be OK here but not for the similar situation in test13.
 ;
-; FNATTR: define void @test1_2(i8* %x1_2, i8* readonly %y1_2, i8* %z1_2)
-; ATTRIBUTOR: define void @test1_2(i8* %x1_2, i8* %y1_2, i8* %z1_2)
+; CHECK: define void @test1_2(i8* %x1_2, i8* readonly %y1_2, i8* %z1_2)
 define void @test1_2(i8* %x1_2, i8* %y1_2, i8* %z1_2) {
   call void (i8*, i8*, ...) @test1_1(i8* %x1_2, i8* %y1_2, i8* %z1_2)
   store i32 0, i32* @x
   ret void
 }
 
-; FNATTR: define i8* @test2(i8* readnone returned %p)
-; ATTRIBUTOR: define i8* @test2(i8* nofree readnone returned %p)
+; CHECK: define i8* @test2(i8* readnone returned %p)
 define i8* @test2(i8* %p) {
   store i32 0, i32* @x
   ret i8* %p
 }
 
-; FNATTR: define i1 @test3(i8* readnone %p, i8* readnone %q)
-; ATTRIBUTOR: define i1 @test3(i8* nofree readnone %p, i8* nofree readnone %q)
+; CHECK: define i1 @test3(i8* readnone %p, i8* readnone %q)
 define i1 @test3(i8* %p, i8* %q) {
   %A = icmp ult i8* %p, %q
   ret i1 %A
@@ -39,8 +34,7 @@ define void @test4_2(i8* %p) {
   ret void
 }
 
-; FNATTR: define void @test5(i8** nocapture %p, i8* %q)
-; ATTRIBUTOR: define void @test5(i8** nocapture nofree nonnull writeonly dereferenceable(8) %p, i8* nofree writeonly %q)
+; CHECK: define void @test5(i8** nocapture %p, i8* %q)
 ; Missed optz'n: we could make %q readnone, but don't break test6!
 define void @test5(i8** %p, i8* %q) {
   store i8* %q, i8** %p
@@ -48,8 +42,7 @@ define void @test5(i8** %p, i8* %q) {
 }
 
 declare void @test6_1()
-; FNATTR: define void @test6_2(i8** nocapture %p, i8* %q)
-; ATTRIBUTOR: define void @test6_2(i8** nocapture nonnull writeonly dereferenceable(8) %p, i8* %q)
+; CHECK: define void @test6_2(i8** nocapture %p, i8* %q)
 ; This is not a missed optz'n.
 define void @test6_2(i8** %p, i8* %q) {
   store i8* %q, i8** %p
@@ -57,22 +50,19 @@ define void @test6_2(i8** %p, i8* %q) {
   ret void
 }
 
-; FNATTR: define void @test7_1(i32* inalloca nocapture %a)
-; ATTRIBUTOR: define void @test7_1(i32* inalloca nocapture nofree writeonly %a)
+; CHECK: define void @test7_1(i32* inalloca nocapture %a)
 ; inalloca parameters are always considered written
 define void @test7_1(i32* inalloca %a) {
   ret void
 }
 
-; FNATTR: define i32* @test8_1(i32* readnone returned %p)
-; ATTRIBUTOR: define i32* @test8_1(i32* nofree readnone returned %p)
+; CHECK: define i32* @test8_1(i32* readnone returned %p)
 define i32* @test8_1(i32* %p) {
 entry:
   ret i32* %p
 }
 
-; FNATTR: define void @test8_2(i32* %p)
-; ATTRIBUTOR: define void @test8_2(i32* nocapture nofree writeonly %p)
+; CHECK: define void @test8_2(i32* %p)
 define void @test8_2(i32* %p) {
 entry:
   %call = call i32* @test8_1(i32* %p)
@@ -136,11 +126,9 @@ declare void @escape_readonly_ptr(i8** %addr, i8* readonly %ptr)
 ;
 ; FIXME: This test currently exposes a bug in functionattrs!
 ;
-; FNATTR: define void @unsound_readnone(i8* nocapture readnone %ignored, i8* readnone %escaped_then_written)
-; FNATTR: define void @unsound_readonly(i8* nocapture readnone %ignored, i8* readonly %escaped_then_written)
+; CHECK: define void @unsound_readnone(i8* nocapture readnone %ignored, i8* readnone %escaped_then_written)
+; CHECK: define void @unsound_readonly(i8* nocapture readnone %ignored, i8* readonly %escaped_then_written)
 ;
-; ATTRIBUTOR: define void @unsound_readnone(i8* nocapture nofree readnone %ignored, i8* %escaped_then_written)
-; ATTRIBUTOR: define void @unsound_readonly(i8* nocapture nofree readnone %ignored, i8* %escaped_then_written)
 define void @unsound_readnone(i8* %ignored, i8* %escaped_then_written) {
   %addr = alloca i8*
   call void @escape_readnone_ptr(i8** %addr, i8* %escaped_then_written)

diff  --git a/llvm/test/Transforms/InferFunctionAttrs/dereferenceable.ll b/llvm/test/Transforms/InferFunctionAttrs/dereferenceable.ll
index b6b699fac85e..e707b88b54ac 100644
--- a/llvm/test/Transforms/InferFunctionAttrs/dereferenceable.ll
+++ b/llvm/test/Transforms/InferFunctionAttrs/dereferenceable.ll
@@ -1,5 +1,4 @@
 ; RUN: opt < %s -inferattrs -S | FileCheck %s
-; RUN: opt < %s -attributor --attributor-disable=false -S | FileCheck %s --check-prefix=ATTRIBUTOR
 
 
 
@@ -8,7 +7,6 @@
 
 define <4 x double> @PR21780(double* %ptr) {
 ; CHECK-LABEL: @PR21780(double* %ptr)
-; ATTRIBUTOR-LABEL: @PR21780(double* nocapture nofree nonnull readonly align 8 dereferenceable(32) %ptr)
 
   ; GEP of index 0 is simplified away.
   %arrayidx1 = getelementptr inbounds double, double* %ptr, i64 1
@@ -31,7 +29,6 @@ define <4 x double> @PR21780(double* %ptr) {
 
 define double @PR21780_only_access3_with_inbounds(double* %ptr) {
 ; CHECK-LABEL: @PR21780_only_access3_with_inbounds(double* %ptr)
-; ATTRIBUTOR-LABEL: @PR21780_only_access3_with_inbounds(double* nocapture nofree nonnull readonly align 8 dereferenceable(32) %ptr)
 
   %arrayidx3 = getelementptr inbounds double, double* %ptr, i64 3
   %t3 = load double, double* %arrayidx3, align 8
@@ -40,7 +37,6 @@ define double @PR21780_only_access3_with_inbounds(double* %ptr) {
 
 define double @PR21780_only_access3_without_inbounds(double* %ptr) {
 ; CHECK-LABEL: @PR21780_only_access3_without_inbounds(double* %ptr)
-; ATTRIBUTOR-LABEL: @PR21780_only_access3_without_inbounds(double* nocapture nofree readonly align 8 %ptr)
   %arrayidx3 = getelementptr double, double* %ptr, i64 3
   %t3 = load double, double* %arrayidx3, align 8
   ret double %t3
@@ -48,7 +44,6 @@ define double @PR21780_only_access3_without_inbounds(double* %ptr) {
 
 define double @PR21780_without_inbounds(double* %ptr) {
 ; CHECK-LABEL: @PR21780_without_inbounds(double* %ptr)
-; ATTRIBUTOR-LABEL: @PR21780_without_inbounds(double* nocapture nofree nonnull readonly align 8 dereferenceable(32) %ptr)
 
   %arrayidx1 = getelementptr double, double* %ptr, i64 1
   %arrayidx2 = getelementptr double, double* %ptr, i64 2
@@ -66,7 +61,6 @@ define double @PR21780_without_inbounds(double* %ptr) {
 
 define void @gep0(i8* %unused, i8* %other, i8* %ptr) {
 ; CHECK-LABEL: @gep0(i8* %unused, i8* %other, i8* %ptr)
-; ATTRIBUTOR-LABEL: @gep0(i8* nocapture nofree readnone %unused, i8* nocapture nofree nonnull writeonly dereferenceable(1) %other, i8* nocapture nofree nonnull readonly dereferenceable(3) %ptr)
   %arrayidx0 = getelementptr i8, i8* %ptr, i64 0
   %arrayidx1 = getelementptr i8, i8* %ptr, i64 1
   %arrayidx2 = getelementptr i8, i8* %ptr, i64 2
@@ -82,7 +76,6 @@ define void @gep0(i8* %unused, i8* %other, i8* %ptr) {
 
 define void @ordering(i8* %ptr1, i32* %ptr2) {
 ; CHECK-LABEL: @ordering(i8* %ptr1, i32* %ptr2)
-; ATTRIBUTOR-LABEL: @ordering(i8* nocapture nofree nonnull readonly dereferenceable(3) %ptr1, i32* nocapture nofree nonnull readonly dereferenceable(8) %ptr2)
   %a20 = getelementptr i32, i32* %ptr2, i64 0
   %a12 = getelementptr i8, i8* %ptr1, i64 2
   %t12 = load i8, i8* %a12
@@ -100,7 +93,6 @@ define void @ordering(i8* %ptr1, i32* %ptr2) {
 
 define void @not_entry_but_guaranteed_to_execute(i8* %ptr) {
 ; CHECK-LABEL: @not_entry_but_guaranteed_to_execute(i8* %ptr)
-; ATTRIBUTOR-LABEL: @not_entry_but_guaranteed_to_execute(i8* nocapture nofree nonnull readonly dereferenceable(3) %ptr)
 entry:
   br label %exit
 exit:
@@ -117,7 +109,6 @@ exit:
 
 define void @not_entry_not_guaranteed_to_execute(i8* %ptr, i1 %cond) {
 ; CHECK-LABEL: @not_entry_not_guaranteed_to_execute(i8* %ptr, i1 %cond)
-; ATTRIBUTOR-LABEL: @not_entry_not_guaranteed_to_execute(i8* nocapture nofree readonly %ptr, i1 %cond)
 entry:
   br i1 %cond, label %loads, label %exit
 loads:
@@ -136,7 +127,6 @@ exit:
 
 define void @partial_in_entry(i16* %ptr, i1 %cond) {
 ; CHECK-LABEL: @partial_in_entry(i16* %ptr, i1 %cond)
-; ATTRIBUTOR-LABEL: @partial_in_entry(i16* nocapture nofree nonnull readonly dereferenceable(4) %ptr, i1 %cond)
 entry:
   %arrayidx0 = getelementptr i16, i16* %ptr, i64 0
   %arrayidx1 = getelementptr i16, i16* %ptr, i64 1
@@ -156,7 +146,6 @@ exit:
 
 define void @volatile_is_not_dereferenceable(i16* %ptr) {
 ; CHECK-LABEL: @volatile_is_not_dereferenceable(i16* %ptr)
-; ATTRIBUTOR-LABEL: @volatile_is_not_dereferenceable(i16* nofree %ptr)
   %arrayidx0 = getelementptr i16, i16* %ptr, i64 0
   %arrayidx1 = getelementptr i16, i16* %ptr, i64 1
   %arrayidx2 = getelementptr i16, i16* %ptr, i64 2
@@ -170,7 +159,6 @@ define void @volatile_is_not_dereferenceable(i16* %ptr) {
 
 define void @atomic_is_alright(i16* %ptr) {
 ; CHECK-LABEL: @atomic_is_alright(i16* %ptr)
-; ATTRIBUTOR-LABEL: @atomic_is_alright(i16* nocapture nofree nonnull readonly align 2 dereferenceable(6) %ptr)
   %arrayidx0 = getelementptr i16, i16* %ptr, i64 0
   %arrayidx1 = getelementptr i16, i16* %ptr, i64 1
   %arrayidx2 = getelementptr i16, i16* %ptr, i64 2
@@ -184,7 +172,6 @@ declare void @may_not_return()
 
 define void @not_guaranteed_to_transfer_execution(i16* %ptr) {
 ; CHECK-LABEL: @not_guaranteed_to_transfer_execution(i16* %ptr)
-; ATTRIBUTOR-LABEL: @not_guaranteed_to_transfer_execution(i16* nocapture nonnull readonly dereferenceable(2) %ptr)
   %arrayidx0 = getelementptr i16, i16* %ptr, i64 0
   %arrayidx1 = getelementptr i16, i16* %ptr, i64 1
   %arrayidx2 = getelementptr i16, i16* %ptr, i64 2
@@ -199,7 +186,6 @@ define void @not_guaranteed_to_transfer_execution(i16* %ptr) {
 
 define void @variable_gep_index(i8* %unused, i8* %ptr, i64 %variable_index) {
 ; CHECK-LABEL: @variable_gep_index(i8* %unused, i8* %ptr, i64 %variable_index)
-; ATTRIBUTOR-LABEL: @variable_gep_index(i8* nocapture nofree readnone %unused, i8* nocapture nofree nonnull readonly dereferenceable(1) %ptr, i64 %variable_index)
   %arrayidx1 = getelementptr i8, i8* %ptr, i64 %variable_index
   %arrayidx2 = getelementptr i8, i8* %ptr, i64 2
   %t0 = load i8, i8* %ptr
@@ -213,7 +199,6 @@ define void @variable_gep_index(i8* %unused, i8* %ptr, i64 %variable_index) {
 define void @multi_index_gep(<4 x i8>* %ptr) {
 ; CHECK-LABEL: @multi_index_gep(<4 x i8>* %ptr)
 ; FIXME: %ptr should be dereferenceable(4)
-; ATTRIBUTOR-LABEL: @multi_index_gep(<4 x i8>* nocapture nofree nonnull readonly dereferenceable(1) %ptr)
   %arrayidx00 = getelementptr <4 x i8>, <4 x i8>* %ptr, i64 0, i64 0
   %t0 = load i8, i8* %arrayidx00
   ret void
@@ -223,7 +208,6 @@ define void @multi_index_gep(<4 x i8>* %ptr) {
 
 define void @not_byte_multiple(i9* %ptr) {
 ; CHECK-LABEL: @not_byte_multiple(i9* %ptr)
-; ATTRIBUTOR-LABEL: @not_byte_multiple(i9* nocapture nofree nonnull readonly dereferenceable(2) %ptr) 
   %arrayidx0 = getelementptr i9, i9* %ptr, i64 0
   %t0 = load i9, i9* %arrayidx0
   ret void
@@ -233,7 +217,6 @@ define void @not_byte_multiple(i9* %ptr) {
 
 define void @no_pointer_deref(i16* %ptr) {
 ; CHECK-LABEL: @no_pointer_deref(i16* %ptr)
-; ATTRIBUTOR-LABEL: @no_pointer_deref(i16* nocapture nofree readonly %ptr)
   %arrayidx1 = getelementptr i16, i16* %ptr, i64 1
   %arrayidx2 = getelementptr i16, i16* %ptr, i64 2
   %t1 = load i16, i16* %arrayidx1
@@ -245,7 +228,6 @@ define void @no_pointer_deref(i16* %ptr) {
 
 define void @non_consecutive(i32* %ptr) {
 ; CHECK-LABEL: @non_consecutive(i32* %ptr)
-; ATTRIBUTOR-LABEL: @non_consecutive(i32* nocapture nofree nonnull readonly dereferenceable(8) %ptr)
   %arrayidx1 = getelementptr i32, i32* %ptr, i64 1
   %arrayidx0 = getelementptr i32, i32* %ptr, i64 0
   %arrayidx3 = getelementptr i32, i32* %ptr, i64 3
@@ -259,7 +241,6 @@ define void @non_consecutive(i32* %ptr) {
 
 define void @more_bytes(i32* dereferenceable(8) %ptr) {
 ; CHECK-LABEL: @more_bytes(i32* dereferenceable(8) %ptr)
-; ATTRIBUTOR-LABEL: @more_bytes(i32* nocapture nofree nonnull readonly dereferenceable(16) %ptr)
   %arrayidx3 = getelementptr i32, i32* %ptr, i64 3
   %arrayidx1 = getelementptr i32, i32* %ptr, i64 1
   %arrayidx0 = getelementptr i32, i32* %ptr, i64 0
@@ -275,7 +256,6 @@ define void @more_bytes(i32* dereferenceable(8) %ptr) {
 
 define void @more_bytes_and_not_null(i32* dereferenceable_or_null(8) %ptr) {
 ; CHECK-LABEL: @more_bytes_and_not_null(i32* dereferenceable_or_null(8) %ptr)
-; ATTRIBUTOR-LABEL: @more_bytes_and_not_null(i32* nocapture nofree nonnull readonly dereferenceable(16) %ptr)
   %arrayidx3 = getelementptr i32, i32* %ptr, i64 3
   %arrayidx1 = getelementptr i32, i32* %ptr, i64 1
   %arrayidx0 = getelementptr i32, i32* %ptr, i64 0
@@ -291,7 +271,6 @@ define void @more_bytes_and_not_null(i32* dereferenceable_or_null(8) %ptr) {
 
 define void @better_bytes(i32* dereferenceable(100) %ptr) {
 ; CHECK-LABEL: @better_bytes(i32* dereferenceable(100) %ptr)
-; ATTRIBUTOR-LABEL: @better_bytes(i32* nocapture nofree nonnull readonly dereferenceable(100) %ptr)
   %arrayidx3 = getelementptr i32, i32* %ptr, i64 3
   %arrayidx1 = getelementptr i32, i32* %ptr, i64 1
   %arrayidx0 = getelementptr i32, i32* %ptr, i64 0
@@ -305,7 +284,6 @@ define void @better_bytes(i32* dereferenceable(100) %ptr) {
 
 define void @bitcast(i32* %arg) {
 ; CHECK-LABEL: @bitcast(i32* %arg)
-; ATTRIBUTOR-LABEL: @bitcast(i32* nocapture nofree nonnull readonly dereferenceable(8) %arg)
   %ptr = bitcast i32* %arg to float*
   %arrayidx0 = getelementptr float, float* %ptr, i64 0
   %arrayidx1 = getelementptr float, float* %ptr, i64 1
@@ -316,7 +294,6 @@ define void @bitcast(i32* %arg) {
 
 define void @bitcast_
diff erent_sizes(double* %arg1, i8* %arg2) {
 ; CHECK-LABEL: @bitcast_
diff erent_sizes(double* %arg1, i8* %arg2)
-; ATTRIBUTOR-LABEL: @bitcast_
diff erent_sizes(double* nocapture nofree nonnull readonly dereferenceable(12) %arg1, i8* nocapture nofree nonnull readonly dereferenceable(16) %arg2)
   %ptr1 = bitcast double* %arg1 to float*
   %a10 = getelementptr float, float* %ptr1, i64 0
   %a11 = getelementptr float, float* %ptr1, i64 1
@@ -335,7 +312,6 @@ define void @bitcast_
diff erent_sizes(double* %arg1, i8* %arg2) {
 
 define void @negative_offset(i32* %arg) {
 ; CHECK-LABEL: @negative_offset(i32* %arg)
-; ATTRIBUTOR-LABEL: @negative_offset(i32* nocapture nofree nonnull readonly dereferenceable(4) %arg)
   %ptr = bitcast i32* %arg to float*
   %arrayidx0 = getelementptr float, float* %ptr, i64 0
   %arrayidx1 = getelementptr float, float* %ptr, i64 -1
@@ -346,7 +322,6 @@ define void @negative_offset(i32* %arg) {
 
 define void @stores(i32* %arg) {
 ; CHECK-LABEL: @stores(i32* %arg)
-; ATTRIBUTOR-LABEL: @stores(i32* nocapture nofree nonnull writeonly dereferenceable(8) %arg)
   %ptr = bitcast i32* %arg to float*
   %arrayidx0 = getelementptr float, float* %ptr, i64 0
   %arrayidx1 = getelementptr float, float* %ptr, i64 1
@@ -357,7 +332,6 @@ define void @stores(i32* %arg) {
 
 define void @load_store(i32* %arg) {
 ; CHECK-LABEL: @load_store(i32* %arg)
-; ATTRIBUTOR-LABEL: @load_store(i32* nocapture nofree nonnull dereferenceable(8) %arg)
   %ptr = bitcast i32* %arg to float*
   %arrayidx0 = getelementptr float, float* %ptr, i64 0
   %arrayidx1 = getelementptr float, float* %ptr, i64 1
@@ -368,7 +342,6 @@ define void @load_store(i32* %arg) {
 
 define void @
diff erent_size1(i32* %arg) {
 ; CHECK-LABEL: @
diff erent_size1(i32* %arg)
-; ATTRIBUTOR-LABEL: @
diff erent_size1(i32* nocapture nofree nonnull writeonly dereferenceable(8) %arg)
   %arg-cast = bitcast i32* %arg to double*
   store double 0.000000e+00, double* %arg-cast
   store i32 0, i32* %arg
@@ -377,7 +350,6 @@ define void @
diff erent_size1(i32* %arg) {
 
 define void @
diff erent_size2(i32* %arg) {
 ; CHECK-LABEL: @
diff erent_size2(i32* %arg)
-; ATTRIBUTOR-LABEL: @
diff erent_size2(i32* nocapture nofree nonnull writeonly dereferenceable(8) %arg)
   store i32 0, i32* %arg
   %arg-cast = bitcast i32* %arg to double*
   store double 0.000000e+00, double* %arg-cast


        


More information about the llvm-commits mailing list