Index: clang/lib/CodeGen/CGCall.cpp =================================================================== --- clang/lib/CodeGen/CGCall.cpp +++ clang/lib/CodeGen/CGCall.cpp @@ -2121,6 +2121,15 @@ // The NoBuiltinAttr attached to the target FunctionDecl. const NoBuiltinAttr *NBA = nullptr; + // Some ABIs may result in additional accesses to arguments that may + // otherwise not be present. + auto AddPotentialArgAccess = [&]() { + llvm::Attribute A = FuncAttrs.getAttribute(llvm::Attribute::Memory); + if (A.isValid()) + FuncAttrs.addMemoryAttr(A.getMemoryEffects() | + llvm::MemoryEffects::argMemOnly()); + }; + // Collect function IR attributes based on declaration-specific // information. // FIXME: handle sseregparm someday... @@ -2167,18 +2176,18 @@ // 'const', 'pure' and 'noalias' attributed functions are also nounwind. if (TargetDecl->hasAttr()) { - FuncAttrs.addAttribute(llvm::Attribute::ReadNone); + FuncAttrs.addMemoryAttr(llvm::MemoryEffects::none()); FuncAttrs.addAttribute(llvm::Attribute::NoUnwind); // gcc specifies that 'const' functions have greater restrictions than // 'pure' functions, so they also cannot have infinite loops. FuncAttrs.addAttribute(llvm::Attribute::WillReturn); } else if (TargetDecl->hasAttr()) { - FuncAttrs.addAttribute(llvm::Attribute::ReadOnly); + FuncAttrs.addMemoryAttr(llvm::MemoryEffects::readOnly()); FuncAttrs.addAttribute(llvm::Attribute::NoUnwind); // gcc specifies that 'pure' functions cannot have infinite loops. FuncAttrs.addAttribute(llvm::Attribute::WillReturn); } else if (TargetDecl->hasAttr()) { - FuncAttrs.addAttribute(llvm::Attribute::ArgMemOnly); + FuncAttrs.addMemoryAttr(llvm::MemoryEffects::argMemOnly()); FuncAttrs.addAttribute(llvm::Attribute::NoUnwind); } if (TargetDecl->hasAttr()) @@ -2356,8 +2365,7 @@ case ABIArgInfo::InAlloca: case ABIArgInfo::Indirect: { // inalloca and sret disable readnone and readonly - FuncAttrs.removeAttribute(llvm::Attribute::ReadOnly) - .removeAttribute(llvm::Attribute::ReadNone); + AddPotentialArgAccess(); break; } @@ -2527,9 +2535,7 @@ Attrs.addAlignmentAttr(Align.getQuantity()); // byval disables readnone and readonly. - FuncAttrs.removeAttribute(llvm::Attribute::ReadOnly) - .removeAttribute(llvm::Attribute::ReadNone); - + AddPotentialArgAccess(); break; } case ABIArgInfo::IndirectAliased: { @@ -2545,8 +2551,7 @@ case ABIArgInfo::InAlloca: // inalloca disables readnone and readonly. - FuncAttrs.removeAttribute(llvm::Attribute::ReadOnly) - .removeAttribute(llvm::Attribute::ReadNone); + AddPotentialArgAccess(); continue; } Index: clang/lib/CodeGen/ItaniumCXXABI.cpp =================================================================== --- clang/lib/CodeGen/ItaniumCXXABI.cpp +++ clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -1325,8 +1325,9 @@ llvm::FunctionType *FTy = llvm::FunctionType::get(Int8PtrTy, Args, false); // Mark the function as nounwind readonly. - llvm::Attribute::AttrKind FuncAttrs[] = { llvm::Attribute::NoUnwind, - llvm::Attribute::ReadOnly }; + llvm::AttrBuilder FuncAttrs(CGF.getLLVMContext()); + FuncAttrs.addAttribute(llvm::Attribute::NoUnwind); + FuncAttrs.addMemoryAttr(llvm::MemoryEffects::readOnly()); llvm::AttributeList Attrs = llvm::AttributeList::get( CGF.getLLVMContext(), llvm::AttributeList::FunctionIndex, FuncAttrs); Index: clang/test/CodeGen/asm-attrs.c =================================================================== --- clang/test/CodeGen/asm-attrs.c +++ clang/test/CodeGen/asm-attrs.c @@ -10,9 +10,9 @@ // CHECK: call void asm sideeffect "foo7", {{.*}} [[NOATTRS]] // CHECK: call i32 asm "foo8", {{.*}} [[READNONE]] -// CHECK: attributes [[READNONE]] = { nounwind readnone } +// CHECK: attributes [[READNONE]] = { nounwind memory(none) } // CHECK: attributes [[NOATTRS]] = { nounwind } -// CHECK: attributes [[READONLY]] = { nounwind readonly } +// CHECK: attributes [[READONLY]] = { nounwind memory(read) } int g0, g1; Index: clang/test/CodeGen/builtin-sqrt.c =================================================================== --- clang/test/CodeGen/builtin-sqrt.c +++ clang/test/CodeGen/builtin-sqrt.c @@ -8,8 +8,8 @@ } // HAS_ERRNO: declare float @sqrtf(float noundef) [[ATTR:#[0-9]+]] -// HAS_ERRNO-NOT: attributes [[ATTR]] = {{{.*}} readnone +// HAS_ERRNO-NOT: attributes [[ATTR]] = {{{.*}} memory(none) // NO_ERRNO: declare float @llvm.sqrt.f32(float) [[ATTR:#[0-9]+]] -// NO_ERRNO: attributes [[ATTR]] = { nocallback nofree nosync nounwind readnone {{.*}}} +// NO_ERRNO: attributes [[ATTR]] = { nocallback nofree nosync nounwind speculatable willreturn memory(none) } Index: clang/test/CodeGen/complex-builtins.c =================================================================== --- clang/test/CodeGen/complex-builtins.c +++ clang/test/CodeGen/complex-builtins.c @@ -197,9 +197,9 @@ // HAS_ERRNO: declare { x86_fp80, x86_fp80 } @ctanhl(ptr noundef byval({ x86_fp80, x86_fp80 }) align 16) [[NOT_READNONE]] }; -// NO__ERRNO: attributes [[READNONE]] = { {{.*}}readnone{{.*}} } +// NO__ERRNO: attributes [[READNONE]] = { {{.*}}memory(none){{.*}} } // NO__ERRNO: attributes [[NOT_READNONE]] = { nounwind {{.*}} } // HAS_ERRNO: attributes [[NOT_READNONE]] = { nounwind {{.*}} } -// HAS_ERRNO: attributes [[READNONE]] = { {{.*}}readnone{{.*}} } +// HAS_ERRNO: attributes [[READNONE]] = { {{.*}}memory(none){{.*}} } // HAS_ERRNO: attributes [[WILLRETURN_NOT_READNONE]] = { nounwind willreturn {{.*}} } Index: clang/test/CodeGen/complex-libcalls.c =================================================================== --- clang/test/CodeGen/complex-libcalls.c +++ clang/test/CodeGen/complex-libcalls.c @@ -197,9 +197,9 @@ // HAS_ERRNO: declare { x86_fp80, x86_fp80 } @ctanhl(ptr noundef byval({ x86_fp80, x86_fp80 }) align 16) [[NOT_READNONE]] }; -// NO__ERRNO: attributes [[READNONE]] = { {{.*}}readnone{{.*}} } +// NO__ERRNO: attributes [[READNONE]] = { {{.*}}memory(none){{.*}} } // NO__ERRNO: attributes [[NOT_READNONE]] = { nounwind {{.*}} } // HAS_ERRNO: attributes [[NOT_READNONE]] = { nounwind {{.*}} } -// HAS_ERRNO: attributes [[READNONE]] = { {{.*}}readnone{{.*}} } +// HAS_ERRNO: attributes [[READNONE]] = { {{.*}}memory(none){{.*}} } // HAS_ERRNO: attributes [[WILLRETURN_NOT_READNONE]] = { nounwind willreturn {{.*}} } Index: clang/test/CodeGen/function-attributes.c =================================================================== --- clang/test/CodeGen/function-attributes.c +++ clang/test/CodeGen/function-attributes.c @@ -111,9 +111,9 @@ // CHECK: attributes [[NUW]] = { nounwind optsize{{.*}} } // CHECK: attributes [[AI]] = { alwaysinline nounwind optsize{{.*}} } -// CHECK: attributes [[NUW_OS_RN]] = { nounwind optsize readnone{{.*}} } +// CHECK: attributes [[NUW_OS_RN]] = { nounwind optsize willreturn memory(none){{.*}} } // CHECK: attributes [[SR]] = { nounwind optsize{{.*}} "stackrealign"{{.*}} } // CHECK: attributes [[RT]] = { nounwind optsize returns_twice{{.*}} } // CHECK: attributes [[NR]] = { noreturn optsize } -// CHECK: attributes [[NUW_RN]] = { nounwind optsize readnone willreturn } +// CHECK: attributes [[NUW_RN]] = { nounwind optsize willreturn memory(none) } // CHECK: attributes [[RT_CALL]] = { optsize returns_twice } Index: clang/test/CodeGen/libcall-declarations.c =================================================================== --- clang/test/CodeGen/libcall-declarations.c +++ clang/test/CodeGen/libcall-declarations.c @@ -614,8 +614,8 @@ // CHECK-ERRNO: declare { double, double } @ctanh(double noundef, double noundef) [[NONCONST]] // CHECK-ERRNO: declare <2 x float> @ctanhf(<2 x float> noundef) [[NONCONST]] -// CHECK-NOERRNO: attributes [[NUWRN]] = { nounwind readnone{{.*}} } -// CHECK-NOERRNO: attributes [[NUWRO]] = { nounwind readonly{{.*}} } +// CHECK-NOERRNO: attributes [[NUWRN]] = { nounwind willreturn memory(none){{.*}} } +// CHECK-NOERRNO: attributes [[NUWRO]] = { nounwind willreturn memory(read){{.*}} } -// CHECK-ERRNO: attributes [[NUWRN]] = { nounwind readnone{{.*}} } -// CHECK-ERRNO: attributes [[NUWRO]] = { nounwind readonly{{.*}} } +// CHECK-ERRNO: attributes [[NUWRN]] = { nounwind willreturn memory(none){{.*}} } +// CHECK-ERRNO: attributes [[NUWRO]] = { nounwind willreturn memory(read){{.*}} } Index: clang/test/CodeGen/libcalls.c =================================================================== --- clang/test/CodeGen/libcalls.c +++ clang/test/CodeGen/libcalls.c @@ -124,5 +124,5 @@ } // CHECK-YES: attributes [[NUW]] = { nounwind "frame-pointer"="none" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+cx8,+x87" } -// CHECK-NO-DAG: attributes [[NUW_RN]] = { nounwind readnone{{.*}} } -// CHECK-NO-DAG: attributes [[NUW_RNI]] = { nocallback nofree nosync nounwind readnone speculatable willreturn } +// CHECK-NO-DAG: attributes [[NUW_RN]] = { nounwind willreturn memory(none){{.*}} } +// CHECK-NO-DAG: attributes [[NUW_RNI]] = { nocallback nofree nosync nounwind speculatable willreturn memory(none) } Index: clang/test/CodeGen/math-builtins.c =================================================================== --- clang/test/CodeGen/math-builtins.c +++ clang/test/CodeGen/math-builtins.c @@ -680,16 +680,16 @@ // HAS_ERRNO: declare fp128 @llvm.trunc.f128(fp128) [[READNONE_INTRINSIC]] }; -// NO__ERRNO: attributes [[READNONE]] = { {{.*}}readnone{{.*}} } -// NO__ERRNO: attributes [[READNONE_INTRINSIC]] = { {{.*}}readnone{{.*}} } +// NO__ERRNO: attributes [[READNONE]] = { {{.*}}memory(none){{.*}} } +// NO__ERRNO: attributes [[READNONE_INTRINSIC]] = { {{.*}}memory(none){{.*}} } // NO__ERRNO: attributes [[NOT_READNONE]] = { nounwind {{.*}} } -// NO__ERRNO: attributes [[PURE]] = { {{.*}}readonly{{.*}} } +// NO__ERRNO: attributes [[PURE]] = { {{.*}}memory(read){{.*}} } // HAS_ERRNO: attributes [[NOT_READNONE]] = { nounwind {{.*}} } -// HAS_ERRNO: attributes [[READNONE_INTRINSIC]] = { {{.*}}readnone{{.*}} } -// HAS_ERRNO: attributes [[PURE]] = { {{.*}}readonly{{.*}} } -// HAS_ERRNO: attributes [[READNONE]] = { {{.*}}readnone{{.*}} } +// HAS_ERRNO: attributes [[READNONE_INTRINSIC]] = { {{.*}}memory(none){{.*}} } +// HAS_ERRNO: attributes [[PURE]] = { {{.*}}memory(read){{.*}} } +// HAS_ERRNO: attributes [[READNONE]] = { {{.*}}memory(none){{.*}} } -// HAS_ERRNO_GNU: attributes [[READNONE_INTRINSIC]] = { {{.*}}readnone{{.*}} } -// HAS_ERRNO_WIN: attributes [[READNONE_INTRINSIC]] = { {{.*}}readnone{{.*}} } +// HAS_ERRNO_GNU: attributes [[READNONE_INTRINSIC]] = { {{.*}}memory(none){{.*}} } +// HAS_ERRNO_WIN: attributes [[READNONE_INTRINSIC]] = { {{.*}}memory(none){{.*}} } Index: clang/test/CodeGen/math-libcalls.c =================================================================== --- clang/test/CodeGen/math-libcalls.c +++ clang/test/CodeGen/math-libcalls.c @@ -704,18 +704,18 @@ // HAS_ERRNO: declare x86_fp80 @llvm.trunc.f80(x86_fp80) [[READNONE_INTRINSIC]] }; -// NO__ERRNO: attributes [[READNONE]] = { {{.*}}readnone{{.*}} } -// NO__ERRNO: attributes [[READNONE_INTRINSIC]] = { {{.*}}readnone{{.*}} } +// NO__ERRNO: attributes [[READNONE]] = { {{.*}}memory(none){{.*}} } +// NO__ERRNO: attributes [[READNONE_INTRINSIC]] = { {{.*}}memory(none){{.*}} } // NO__ERRNO: attributes [[NOT_READNONE]] = { nounwind {{.*}} } -// NO__ERRNO: attributes [[READONLY]] = { {{.*}}readonly{{.*}} } +// NO__ERRNO: attributes [[READONLY]] = { {{.*}}memory(read){{.*}} } // HAS_ERRNO: attributes [[NOT_READNONE]] = { nounwind {{.*}} } -// HAS_ERRNO: attributes [[READNONE_INTRINSIC]] = { {{.*}}readnone{{.*}} } -// HAS_ERRNO: attributes [[READONLY]] = { {{.*}}readonly{{.*}} } -// HAS_ERRNO: attributes [[READNONE]] = { {{.*}}readnone{{.*}} } +// HAS_ERRNO: attributes [[READNONE_INTRINSIC]] = { {{.*}}memory(none){{.*}} } +// HAS_ERRNO: attributes [[READONLY]] = { {{.*}}memory(read){{.*}} } +// HAS_ERRNO: attributes [[READNONE]] = { {{.*}}memory(none){{.*}} } // HAS_MAYTRAP: attributes [[NOT_READNONE]] = { nounwind {{.*}} } -// HAS_MAYTRAP: attributes [[READNONE]] = { {{.*}}readnone{{.*}} } +// HAS_MAYTRAP: attributes [[READNONE]] = { {{.*}}memory(none){{.*}} } -// HAS_ERRNO_GNU: attributes [[READNONE_INTRINSIC]] = { {{.*}}readnone{{.*}} } -// HAS_ERRNO_WIN: attributes [[READNONE_INTRINSIC]] = { {{.*}}readnone{{.*}} } +// HAS_ERRNO_GNU: attributes [[READNONE_INTRINSIC]] = { {{.*}}memory(none){{.*}} } +// HAS_ERRNO_WIN: attributes [[READNONE_INTRINSIC]] = { {{.*}}memory(none){{.*}} } Index: clang/test/CodeGen/ms-declspecs.c =================================================================== --- clang/test/CodeGen/ms-declspecs.c +++ clang/test/CodeGen/ms-declspecs.c @@ -41,4 +41,4 @@ // CHECK: attributes [[NUW]] = { nounwind{{.*}} } // CHECK: attributes [[NI]] = { noinline nounwind{{.*}} } // CHECK: attributes [[NR]] = { noreturn } -// CHECK: attributes [[NA]] = { argmemonly nounwind{{.*}} } +// CHECK: attributes [[NA]] = { nounwind memory(argmem: readwrite){{.*}} } Index: clang/test/CodeGen/pragma-weak.c =================================================================== --- clang/test/CodeGen/pragma-weak.c +++ clang/test/CodeGen/pragma-weak.c @@ -202,4 +202,4 @@ int correct_linkage; // CHECK: attributes [[NI]] = { noinline nounwind{{.*}} } -// CHECK: attributes [[RN]] = { noinline nounwind optnone readnone{{.*}} } +// CHECK: attributes [[RN]] = { noinline nounwind optnone willreturn memory(none){{.*}} } Index: clang/test/CodeGen/struct-passing.c =================================================================== --- clang/test/CodeGen/struct-passing.c +++ clang/test/CodeGen/struct-passing.c @@ -23,5 +23,5 @@ // CHECK: declare void @f4({{.*}} byval({{.*}}) align 4) // CHECK: declare void @f5({{.*}} byval({{.*}}) align 4) -// CHECK: attributes [[RN]] = { nounwind readnone{{.*}} } -// CHECK: attributes [[RO]] = { nounwind readonly{{.*}} } +// CHECK: attributes [[RN]] = { nounwind willreturn memory(none){{.*}} } +// CHECK: attributes [[RO]] = { nounwind willreturn memory(read){{.*}} } Index: clang/test/CodeGenCXX/2009-05-04-PureConstNounwind.cpp =================================================================== --- clang/test/CodeGenCXX/2009-05-04-PureConstNounwind.cpp +++ clang/test/CodeGenCXX/2009-05-04-PureConstNounwind.cpp @@ -15,8 +15,8 @@ // CHECK: declare noundef i32 @_Z1tv() [[TF2:#[0-9]+]] // CHECK: attributes [[TF]] = { {{.*}} } -// CHECK: attributes [[NUW_RN]] = { nounwind readnone willreturn{{.*}} } -// CHECK: attributes [[NUW_RO]] = { nounwind readonly willreturn{{.*}} } +// CHECK: attributes [[NUW_RN]] = { nounwind willreturn memory(none){{.*}} } +// CHECK: attributes [[NUW_RO]] = { nounwind willreturn memory(read){{.*}} } // CHECK: attributes [[TF2]] = { {{.*}} } -// CHECK: attributes [[NUW_RN_CALL]] = { nounwind readnone willreturn } -// CHECK: attributes [[NUW_RO_CALL]] = { nounwind readonly willreturn } +// CHECK: attributes [[NUW_RN_CALL]] = { nounwind willreturn memory(none) } +// CHECK: attributes [[NUW_RO_CALL]] = { nounwind willreturn memory(read) } Index: clang/test/CodeGenCXX/dynamic-cast.cpp =================================================================== --- clang/test/CodeGenCXX/dynamic-cast.cpp +++ clang/test/CodeGenCXX/dynamic-cast.cpp @@ -20,5 +20,5 @@ // CHECK: declare ptr @__dynamic_cast(ptr, ptr, ptr, i64) [[NUW_RO:#[0-9]+]] -// CHECK: attributes [[NUW_RO]] = { nounwind readonly } +// CHECK: attributes [[NUW_RO]] = { nounwind memory(read) } // CHECK: attributes [[NR]] = { noreturn } Index: clang/test/CodeGenCXX/threadlocal_address.cpp =================================================================== --- clang/test/CodeGenCXX/threadlocal_address.cpp +++ clang/test/CodeGenCXX/threadlocal_address.cpp @@ -51,4 +51,4 @@ // CHECK-O1-NEXT: store i32 %[[INC]], ptr %[[J_ADDR]] // CHECK-O1-NEXT: ret i32 %[[INC]] // -// CHECK: attributes #[[ATTR_NUM]] = { nocallback nofree nosync nounwind readnone speculatable willreturn } +// CHECK: attributes #[[ATTR_NUM]] = { nocallback nofree nosync nounwind speculatable willreturn memory(none) } Index: clang/test/CodeGenOpenCL/builtins-amdgcn.cl =================================================================== --- clang/test/CodeGenOpenCL/builtins-amdgcn.cl +++ clang/test/CodeGenOpenCL/builtins-amdgcn.cl @@ -796,7 +796,7 @@ // CHECK-DAG: [[$WI_RANGE]] = !{i32 0, i32 1024} // CHECK-DAG: [[$WS_RANGE]] = !{i16 1, i16 1025} -// CHECK-DAG: attributes #[[$NOUNWIND_READONLY:[0-9]+]] = { nofree nounwind readonly } +// CHECK-DAG: attributes #[[$NOUNWIND_READONLY:[0-9]+]] = { nofree nounwind memory(read) } // CHECK-DAG: attributes #[[$READ_EXEC_ATTRS]] = { convergent } // CHECK-DAG: ![[$EXEC]] = !{!"exec"} // CHECK-DAG: ![[$EXEC_LO]] = !{!"exec_lo"} Index: clang/test/CodeGenOpenCL/convergent.cl =================================================================== --- clang/test/CodeGenOpenCL/convergent.cl +++ clang/test/CodeGenOpenCL/convergent.cl @@ -133,7 +133,7 @@ __asm__ volatile("s_barrier"); } -// CHECK: attributes #0 = { nofree noinline norecurse nounwind " +// CHECK: attributes #0 = { nofree noinline norecurse nounwind memory({{.*}}) " // CHECK: attributes #1 = { {{[^}]*}}convergent{{[^}]*}} } // CHECK: attributes #2 = { {{[^}]*}}convergent{{[^}]*}} } // CHECK: attributes #3 = { {{[^}]*}}convergent noduplicate{{[^}]*}} } Index: clang/test/CodeGenOpenCL/fdeclare-opencl-builtins.cl =================================================================== --- clang/test/CodeGenOpenCL/fdeclare-opencl-builtins.cl +++ clang/test/CodeGenOpenCL/fdeclare-opencl-builtins.cl @@ -49,6 +49,6 @@ } // CHECK: attributes [[ATTR_CONST]] = -// CHECK-SAME: readnone +// CHECK-SAME: memory(none) // CHECK: attributes [[ATTR_PURE]] = -// CHECK-SAME: readonly +// CHECK-SAME: memory(read) Index: clang/test/Sema/libbuiltins-ctype-powerpc64.c =================================================================== --- clang/test/Sema/libbuiltins-ctype-powerpc64.c +++ clang/test/Sema/libbuiltins-ctype-powerpc64.c @@ -61,5 +61,5 @@ // CHECK: declare signext i32 @tolower(i32 noundef signext) [[NUW_RO:#[0-9]+]] // CHECK: declare signext i32 @toupper(i32 noundef signext) [[NUW_RO:#[0-9]+]] -// CHECK: attributes [[NUW_RO]] = { nounwind readonly{{.*}} } -// CHECK: attributes [[NUW_RO_CALL]] = { nounwind readonly willreturn } +// CHECK: attributes [[NUW_RO]] = { nounwind willreturn memory(read){{.*}} } +// CHECK: attributes [[NUW_RO_CALL]] = { nounwind willreturn memory(read) } Index: clang/test/Sema/libbuiltins-ctype-x86_64.c =================================================================== --- clang/test/Sema/libbuiltins-ctype-x86_64.c +++ clang/test/Sema/libbuiltins-ctype-x86_64.c @@ -61,5 +61,5 @@ // CHECK: declare i32 @tolower(i32 noundef) [[NUW_RO:#[0-9]+]] // CHECK: declare i32 @toupper(i32 noundef) [[NUW_RO:#[0-9]+]] -// CHECK: attributes [[NUW_RO]] = { nounwind readonly{{.*}} } -// CHECK: attributes [[NUW_RO_CALL]] = { nounwind readonly willreturn } +// CHECK: attributes [[NUW_RO]] = { nounwind willreturn memory(read){{.*}} } +// CHECK: attributes [[NUW_RO_CALL]] = { nounwind willreturn memory(read) } Index: llvm/include/llvm/Frontend/OpenMP/OMPKinds.def =================================================================== --- llvm/include/llvm/Frontend/OpenMP/OMPKinds.def +++ llvm/include/llvm/Frontend/OpenMP/OMPKinds.def @@ -487,6 +487,7 @@ #define EnumAttr(Kind) Attribute::get(Ctx, Attribute::AttrKind::Kind) #define EnumAttrInt(Kind, N) Attribute::get(Ctx, Attribute::AttrKind::Kind, N) #define AllocSizeAttr(N, M) Attribute::getWithAllocSizeArgs(Ctx, N, M) +#define MemoryAttr(ME) Attribute::getWithMemoryEffects(Ctx, ME) #define AttributeSet(...) \ AttributeSet::get(Ctx, ArrayRef({__VA_ARGS__})) @@ -496,27 +497,29 @@ #define __OMP_ATTRS_SET(VarName, AttrSet) OMP_ATTRS_SET(VarName, AttrSet) -__OMP_ATTRS_SET(GetterAttrs, - OptimisticAttributes - ? AttributeSet(EnumAttr(NoUnwind), EnumAttr(ReadOnly), - EnumAttr(NoSync), EnumAttr(NoFree), - EnumAttr(InaccessibleMemOnly), - EnumAttr(WillReturn)) - : AttributeSet(EnumAttr(NoUnwind))) -__OMP_ATTRS_SET(GetterArgWriteAttrs, - OptimisticAttributes - ? AttributeSet(EnumAttr(NoUnwind), EnumAttr(NoSync), - EnumAttr(NoFree), - EnumAttr(InaccessibleMemOrArgMemOnly), - EnumAttr(WillReturn)) - : AttributeSet(EnumAttr(NoUnwind))) -__OMP_ATTRS_SET(SetterAttrs, - OptimisticAttributes - ? AttributeSet(EnumAttr(NoUnwind), EnumAttr(WriteOnly), - EnumAttr(NoSync), EnumAttr(NoFree), - EnumAttr(InaccessibleMemOnly), - EnumAttr(WillReturn)) - : AttributeSet(EnumAttr(NoUnwind))) +__OMP_ATTRS_SET( + GetterAttrs, + OptimisticAttributes + ? AttributeSet( + EnumAttr(NoUnwind), EnumAttr(NoSync), EnumAttr(NoFree), + EnumAttr(WillReturn), + MemoryAttr(MemoryEffects::inaccessibleMemOnly(ModRefInfo::Ref))) + : AttributeSet(EnumAttr(NoUnwind))) +__OMP_ATTRS_SET( + GetterArgWriteAttrs, + OptimisticAttributes + ? AttributeSet(EnumAttr(NoUnwind), EnumAttr(NoSync), EnumAttr(NoFree), + EnumAttr(WillReturn), + MemoryAttr(MemoryEffects::inaccessibleOrArgMemOnly())) + : AttributeSet(EnumAttr(NoUnwind))) +__OMP_ATTRS_SET( + SetterAttrs, + OptimisticAttributes + ? AttributeSet( + EnumAttr(NoUnwind), EnumAttr(NoSync), EnumAttr(NoFree), + EnumAttr(WillReturn), + MemoryAttr(MemoryEffects::inaccessibleMemOnly(ModRefInfo::Mod))) + : AttributeSet(EnumAttr(NoUnwind))) __OMP_ATTRS_SET(DefaultAttrs, OptimisticAttributes @@ -529,12 +532,13 @@ ? AttributeSet(EnumAttr(NoUnwind), EnumAttr(Convergent)) : AttributeSet(EnumAttr(NoUnwind), EnumAttr(Convergent))) -__OMP_ATTRS_SET(InaccessibleArgOnlyAttrs, - OptimisticAttributes - ? AttributeSet(EnumAttr(NoUnwind), EnumAttr(NoSync), - EnumAttr(InaccessibleMemOrArgMemOnly), - EnumAttr(WillReturn), EnumAttr(NoFree)) - : AttributeSet(EnumAttr(NoUnwind))) +__OMP_ATTRS_SET( + InaccessibleArgOnlyAttrs, + OptimisticAttributes + ? AttributeSet(EnumAttr(NoUnwind), EnumAttr(NoSync), EnumAttr(NoFree), + EnumAttr(WillReturn), + MemoryAttr(MemoryEffects::inaccessibleOrArgMemOnly())) + : AttributeSet(EnumAttr(NoUnwind))) __OMP_ATTRS_SET(AlwaysInlineAttrs, OptimisticAttributes @@ -542,12 +546,13 @@ : AttributeSet(EnumAttr(AlwaysInline))) #if 0 -__OMP_ATTRS_SET(InaccessibleOnlyAttrs, - OptimisticAttributes - ? AttributeSet(EnumAttr(NoUnwind), EnumAttr(NoSync), - EnumAttr(InaccessibleMemOnly), - EnumAttr(WillReturn), EnumAttr(NoFree)) - : AttributeSet(EnumAttr(NoUnwind))) +__OMP_ATTRS_SET( + InaccessibleOnlyAttrs, + OptimisticAttributes + ? AttributeSet(EnumAttr(NoUnwind), EnumAttr(NoSync), EnumAttr(NoFree), + EnumAttr(WillReturn), + MemoryAttr(MemoryEffects::inaccessibleMemOnly())) + : AttributeSet(EnumAttr(NoUnwind))) #endif __OMP_ATTRS_SET(AllocAttrs, Index: llvm/include/llvm/IR/Attributes.h =================================================================== --- llvm/include/llvm/IR/Attributes.h +++ llvm/include/llvm/IR/Attributes.h @@ -146,6 +146,7 @@ static Attribute getWithPreallocatedType(LLVMContext &Context, Type *Ty); static Attribute getWithInAllocaType(LLVMContext &Context, Type *Ty); static Attribute getWithUWTableKind(LLVMContext &Context, UWTableKind Kind); + static Attribute getWithMemoryEffects(LLVMContext &Context, MemoryEffects ME); /// For a typed attribute, return the equivalent attribute with the type /// changed to \p ReplacementTy. @@ -379,6 +380,7 @@ Optional getVScaleRangeMax() const; UWTableKind getUWTableKind() const; AllocFnKind getAllocKind() const; + MemoryEffects getMemoryEffects() const; std::string getAsString(bool InAttrGrp = false) const; /// Return true if this attribute set belongs to the LLVMContext. @@ -878,6 +880,9 @@ AllocFnKind getAllocKind() const; + /// Returns memory effects of the function. + MemoryEffects getMemoryEffects() const; + /// Return the attributes at the index as a string. std::string getAsString(unsigned Index, bool InAttrGrp = false) const; Index: llvm/include/llvm/IR/Attributes.td =================================================================== --- llvm/include/llvm/IR/Attributes.td +++ llvm/include/llvm/IR/Attributes.td @@ -65,7 +65,7 @@ def AlwaysInline : EnumAttr<"alwaysinline", [FnAttr]>; /// Function can access memory only using pointers based on its arguments. -def ArgMemOnly : EnumAttr<"argmemonly", [FnAttr]>; +def ArgMemOnly : EnumAttr<"argmemonly", []>; /// Callee is recognized as a builtin, despite nobuiltin attribute on its /// declaration. @@ -107,12 +107,12 @@ def FnRetThunkExtern : EnumAttr<"fn_ret_thunk_extern", [FnAttr]>; /// Function may only access memory that is inaccessible from IR. -def InaccessibleMemOnly : EnumAttr<"inaccessiblememonly", [FnAttr]>; +def InaccessibleMemOnly : EnumAttr<"inaccessiblememonly", []>; /// Function may only access memory that is either inaccessible from the IR, /// or pointed to by its pointer arguments. def InaccessibleMemOrArgMemOnly : EnumAttr<"inaccessiblemem_or_argmemonly", - [FnAttr]>; + []>; /// Pass structure in an alloca. def InAlloca : TypeAttr<"inalloca", [ParamAttr]>; @@ -218,10 +218,10 @@ def Preallocated : TypeAttr<"preallocated", [FnAttr, ParamAttr]>; /// Function does not access memory. -def ReadNone : EnumAttr<"readnone", [FnAttr, ParamAttr]>; +def ReadNone : EnumAttr<"readnone", [ParamAttr]>; /// Function only reads from memory. -def ReadOnly : EnumAttr<"readonly", [FnAttr, ParamAttr]>; +def ReadOnly : EnumAttr<"readonly", [ParamAttr]>; /// Return value is always equal to this argument. def Returned : EnumAttr<"returned", [ParamAttr]>; @@ -306,7 +306,7 @@ def WillReturn : EnumAttr<"willreturn", [FnAttr]>; /// Function only writes to memory. -def WriteOnly : EnumAttr<"writeonly", [FnAttr, ParamAttr]>; +def WriteOnly : EnumAttr<"writeonly", [ParamAttr]>; /// Zero extended before/after call. def ZExt : EnumAttr<"zeroext", [ParamAttr, RetAttr]>; Index: llvm/include/llvm/IR/Function.h =================================================================== --- llvm/include/llvm/IR/Function.h +++ llvm/include/llvm/IR/Function.h @@ -491,54 +491,35 @@ void setPresplitCoroutine() { addFnAttr(Attribute::PresplitCoroutine); } void setSplittedCoroutine() { removeFnAttr(Attribute::PresplitCoroutine); } + MemoryEffects getMemoryEffects() const; + void setMemoryEffects(MemoryEffects ME); + /// Determine if the function does not access memory. - bool doesNotAccessMemory() const { - return hasFnAttribute(Attribute::ReadNone); - } - void setDoesNotAccessMemory() { - addFnAttr(Attribute::ReadNone); - } + bool doesNotAccessMemory() const; + void setDoesNotAccessMemory(); /// Determine if the function does not access or only reads memory. - bool onlyReadsMemory() const { - return doesNotAccessMemory() || hasFnAttribute(Attribute::ReadOnly); - } - void setOnlyReadsMemory() { - addFnAttr(Attribute::ReadOnly); - } + bool onlyReadsMemory() const; + void setOnlyReadsMemory(); /// Determine if the function does not access or only writes memory. - bool onlyWritesMemory() const { - return doesNotAccessMemory() || hasFnAttribute(Attribute::WriteOnly); - } - void setOnlyWritesMemory() { - addFnAttr(Attribute::WriteOnly); - } + bool onlyWritesMemory() const; + void setOnlyWritesMemory(); /// Determine if the call can access memmory only using pointers based /// on its arguments. - bool onlyAccessesArgMemory() const { - return hasFnAttribute(Attribute::ArgMemOnly); - } - void setOnlyAccessesArgMemory() { addFnAttr(Attribute::ArgMemOnly); } + bool onlyAccessesArgMemory() const; + void setOnlyAccessesArgMemory(); /// Determine if the function may only access memory that is /// inaccessible from the IR. - bool onlyAccessesInaccessibleMemory() const { - return hasFnAttribute(Attribute::InaccessibleMemOnly); - } - void setOnlyAccessesInaccessibleMemory() { - addFnAttr(Attribute::InaccessibleMemOnly); - } + bool onlyAccessesInaccessibleMemory() const; + void setOnlyAccessesInaccessibleMemory(); /// Determine if the function may only access memory that is /// either inaccessible from the IR or pointed to by its arguments. - bool onlyAccessesInaccessibleMemOrArgMem() const { - return hasFnAttribute(Attribute::InaccessibleMemOrArgMemOnly); - } - void setOnlyAccessesInaccessibleMemOrArgMem() { - addFnAttr(Attribute::InaccessibleMemOrArgMemOnly); - } + bool onlyAccessesInaccessibleMemOrArgMem() const; + void setOnlyAccessesInaccessibleMemOrArgMem(); /// Determine if the function cannot return. bool doesNotReturn() const { Index: llvm/include/llvm/IR/InstrTypes.h =================================================================== --- llvm/include/llvm/IR/InstrTypes.h +++ llvm/include/llvm/IR/InstrTypes.h @@ -1847,47 +1847,37 @@ /// Return true if the call should not be inlined. bool isNoInline() const { return hasFnAttr(Attribute::NoInline); } void setIsNoInline() { addFnAttr(Attribute::NoInline); } + + MemoryEffects getMemoryEffects() const; + void setMemoryEffects(MemoryEffects ME); + /// Determine if the call does not access memory. - bool doesNotAccessMemory() const { return hasFnAttr(Attribute::ReadNone); } - void setDoesNotAccessMemory() { addFnAttr(Attribute::ReadNone); } + bool doesNotAccessMemory() const; + void setDoesNotAccessMemory(); /// Determine if the call does not access or only reads memory. - bool onlyReadsMemory() const { - return hasImpliedFnAttr(Attribute::ReadOnly); - } - - void setOnlyReadsMemory() { addFnAttr(Attribute::ReadOnly); } + bool onlyReadsMemory() const; + void setOnlyReadsMemory(); /// Determine if the call does not access or only writes memory. - bool onlyWritesMemory() const { - return hasImpliedFnAttr(Attribute::WriteOnly); - } - void setOnlyWritesMemory() { addFnAttr(Attribute::WriteOnly); } + bool onlyWritesMemory() const; + void setOnlyWritesMemory(); /// Determine if the call can access memmory only using pointers based /// on its arguments. - bool onlyAccessesArgMemory() const { - return hasFnAttr(Attribute::ArgMemOnly); - } - void setOnlyAccessesArgMemory() { addFnAttr(Attribute::ArgMemOnly); } + bool onlyAccessesArgMemory() const; + void setOnlyAccessesArgMemory(); /// Determine if the function may only access memory that is /// inaccessible from the IR. - bool onlyAccessesInaccessibleMemory() const { - return hasFnAttr(Attribute::InaccessibleMemOnly); - } - void setOnlyAccessesInaccessibleMemory() { - addFnAttr(Attribute::InaccessibleMemOnly); - } + bool onlyAccessesInaccessibleMemory() const; + void setOnlyAccessesInaccessibleMemory(); /// Determine if the function may only access memory that is /// either inaccessible from the IR or pointed to by its arguments. - bool onlyAccessesInaccessibleMemOrArgMem() const { - return hasFnAttr(Attribute::InaccessibleMemOrArgMemOnly); - } - void setOnlyAccessesInaccessibleMemOrArgMem() { - addFnAttr(Attribute::InaccessibleMemOrArgMemOnly); - } + bool onlyAccessesInaccessibleMemOrArgMem() const; + void setOnlyAccessesInaccessibleMemOrArgMem(); + /// Determine if the call cannot return. bool doesNotReturn() const { return hasFnAttr(Attribute::NoReturn); } void setDoesNotReturn() { addFnAttr(Attribute::NoReturn); } @@ -2107,43 +2097,6 @@ return false; } - /// Is the function attribute S disallowed by some operand bundle on - /// this operand bundle user? - bool isFnAttrDisallowedByOpBundle(StringRef S) const { - // Operand bundles only possibly disallow memory access attributes. All - // String attributes are fine. - return false; - } - - /// Is the function attribute A disallowed by some operand bundle on - /// this operand bundle user? - bool isFnAttrDisallowedByOpBundle(Attribute::AttrKind A) const { - switch (A) { - default: - return false; - - case Attribute::InaccessibleMemOrArgMemOnly: - return hasReadingOperandBundles(); - - case Attribute::InaccessibleMemOnly: - return hasReadingOperandBundles(); - - case Attribute::ArgMemOnly: - return hasReadingOperandBundles(); - - case Attribute::ReadNone: - return hasReadingOperandBundles(); - - case Attribute::ReadOnly: - return hasClobberingOperandBundles(); - - case Attribute::WriteOnly: - return hasReadingOperandBundles(); - } - - llvm_unreachable("switch has a default case!"); - } - /// Used to keep track of an operand bundle. See the main comment on /// OperandBundleUser above. struct BundleOpInfo { @@ -2303,35 +2256,10 @@ if (Attrs.hasFnAttr(Kind)) return true; - // Operand bundles override attributes on the called function, but don't - // override attributes directly present on the call instruction. - if (isFnAttrDisallowedByOpBundle(Kind)) - return false; - return hasFnAttrOnCalledFunction(Kind); } template Attribute getFnAttrOnCalledFunction(AK Kind) const; - /// A specialized version of hasFnAttrImpl for when the caller wants to - /// know if an attribute's semantics are implied, not whether the attribute - /// is actually present. This distinction only exists when checking whether - /// something is readonly or writeonly since readnone implies both. The case - /// which motivates the specialized code is a callee with readnone, and an - /// operand bundle on the call which disallows readnone but not either - /// readonly or writeonly. - bool hasImpliedFnAttr(Attribute::AttrKind Kind) const { - assert((Kind == Attribute::ReadOnly || Kind == Attribute::WriteOnly) && - "use hasFnAttrImpl instead"); - if (Attrs.hasFnAttr(Kind) || Attrs.hasFnAttr(Attribute::ReadNone)) - return true; - - if (isFnAttrDisallowedByOpBundle(Kind)) - return false; - - return hasFnAttrOnCalledFunction(Kind) || - hasFnAttrOnCalledFunction(Attribute::ReadNone); - } - /// Determine whether the return value has the given attribute. Supports /// Attribute::AttrKind and StringRef as \p AttrKind types. template bool hasRetAttrImpl(AttrKind Kind) const { Index: llvm/lib/Analysis/BasicAliasAnalysis.cpp =================================================================== --- llvm/lib/Analysis/BasicAliasAnalysis.cpp +++ llvm/lib/Analysis/BasicAliasAnalysis.cpp @@ -740,30 +740,10 @@ return II && II->getIntrinsicID() == IID; } -static MemoryEffects getMemoryEffectsFromAttrs(AttributeSet Attrs) { - if (Attrs.hasAttribute(Attribute::ReadNone)) - return MemoryEffects::none(); - - ModRefInfo MR = ModRefInfo::ModRef; - if (Attrs.hasAttribute(Attribute::ReadOnly)) - MR = ModRefInfo::Ref; - else if (Attrs.hasAttribute(Attribute::WriteOnly)) - MR = ModRefInfo::Mod; - - if (Attrs.hasAttribute(Attribute::ArgMemOnly)) - return MemoryEffects::argMemOnly(MR); - if (Attrs.hasAttribute(Attribute::InaccessibleMemOnly)) - return MemoryEffects::inaccessibleMemOnly(MR); - if (Attrs.hasAttribute(Attribute::InaccessibleMemOrArgMemOnly)) - return MemoryEffects::inaccessibleOrArgMemOnly(MR); - return MemoryEffects(MR); -} - /// Returns the behavior when calling the given call site. MemoryEffects BasicAAResult::getMemoryEffects(const CallBase *Call, AAQueryInfo &AAQI) { - MemoryEffects Min = - getMemoryEffectsFromAttrs(Call->getAttributes().getFnAttrs()); + MemoryEffects Min = Call->getAttributes().getMemoryEffects(); if (const Function *F = dyn_cast(Call->getCalledOperand())) { MemoryEffects FuncME = AAQI.AAR.getMemoryEffects(F); @@ -791,7 +771,7 @@ MemoryEffects::inaccessibleMemOnly(ModRefInfo::ModRef); } - return getMemoryEffectsFromAttrs(F->getAttributes().getFnAttrs()); + return F->getMemoryEffects(); } /// Returns true if this is a writeonly (i.e Mod only) parameter. Index: llvm/lib/AsmParser/LLParser.cpp =================================================================== --- llvm/lib/AsmParser/LLParser.cpp +++ llvm/lib/AsmParser/LLParser.cpp @@ -1472,6 +1472,31 @@ } } +static bool upgradeMemoryAttr(MemoryEffects &ME, Attribute::AttrKind Attr) { + switch (Attr) { + case Attribute::ReadNone: + ME &= MemoryEffects::none(); + return true; + case Attribute::ReadOnly: + ME &= MemoryEffects::readOnly(); + return true; + case Attribute::WriteOnly: + ME &= MemoryEffects::writeOnly(); + return true; + case Attribute::ArgMemOnly: + ME &= MemoryEffects::argMemOnly(); + return true; + case Attribute::InaccessibleMemOnly: + ME &= MemoryEffects::inaccessibleMemOnly(); + return true; + case Attribute::InaccessibleMemOrArgMemOnly: + ME &= MemoryEffects::inaccessibleOrArgMemOnly(); + return true; + default: + return false; + } +} + /// parseFnAttributeValuePairs /// ::= | '=' bool LLParser::parseFnAttributeValuePairs(AttrBuilder &B, @@ -1481,10 +1506,11 @@ B.clear(); + MemoryEffects ME = MemoryEffects::unknown(); while (true) { lltok::Kind Token = Lex.getKind(); if (Token == lltok::rbrace) - return HaveError; // Finished. + break; // Finished. if (Token == lltok::StringConstant) { if (parseStringAttribute(B)) @@ -1515,10 +1541,15 @@ Attribute::AttrKind Attr = tokenToAttribute(Token); if (Attr == Attribute::None) { if (!InAttrGrp) - return HaveError; + break; return error(Lex.getLoc(), "unterminated attribute group"); } + if (upgradeMemoryAttr(ME, Attr)) { + Lex.Lex(); + continue; + } + if (parseEnumAttribute(Attr, B, InAttrGrp)) return true; @@ -1528,6 +1559,10 @@ if (!Attribute::canUseAsFnAttr(Attr) && Attr != Attribute::Alignment) HaveError |= error(Loc, "this attribute does not apply to functions"); } + + if (ME != MemoryEffects::unknown()) + B.addMemoryAttr(ME); + return HaveError; } //===----------------------------------------------------------------------===// Index: llvm/lib/Bitcode/Reader/BitcodeReader.cpp =================================================================== --- llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -1718,8 +1718,6 @@ case Attribute::Convergent: return 1ULL << 46; case Attribute::SafeStack: return 1ULL << 47; case Attribute::NoRecurse: return 1ULL << 48; - case Attribute::InaccessibleMemOnly: return 1ULL << 49; - case Attribute::InaccessibleMemOrArgMemOnly: return 1ULL << 50; case Attribute::SwiftSelf: return 1ULL << 51; case Attribute::SwiftError: return 1ULL << 52; case Attribute::WriteOnly: return 1ULL << 53; @@ -1767,7 +1765,8 @@ /// been decoded from the given integer. This function must stay in sync with /// 'encodeLLVMAttributesForBitcode'. static void decodeLLVMAttributesForBitcode(AttrBuilder &B, - uint64_t EncodedAttrs) { + uint64_t EncodedAttrs, + uint64_t AttrIdx) { // The alignment is stored as a 16-bit raw value from bits 31--16. We shift // the bits above 31 down by 11 bits. unsigned Alignment = (EncodedAttrs & (0xffffULL << 16)) >> 16; @@ -1776,8 +1775,43 @@ if (Alignment) B.addAlignmentAttr(Alignment); - addRawAttributeValue(B, ((EncodedAttrs & (0xfffffULL << 32)) >> 11) | - (EncodedAttrs & 0xffff)); + + uint64_t Attrs = ((EncodedAttrs & (0xfffffULL << 32)) >> 11) | + (EncodedAttrs & 0xffff); + + if (AttrIdx == AttributeList::FunctionIndex) { + // Upgrade old memory attributes. + MemoryEffects ME = MemoryEffects::unknown(); + if (Attrs & (1ULL << 9)) { + // ReadNone + Attrs &= ~(1ULL << 9); + ME &= MemoryEffects::none(); + } + if (Attrs & (1ULL << 10)) { + // ReadOnly + Attrs &= ~(1ULL << 10); + ME &= MemoryEffects::readOnly(); + } + if (Attrs & (1ULL << 49)) { + // InaccessibleMemOnly + Attrs &= ~(1ULL << 49); + ME &= MemoryEffects::inaccessibleMemOnly(); + } + if (Attrs & (1ULL << 50)) { + // InaccessibleMemOrArgMemOnly + Attrs &= ~(1ULL << 50); + ME &= MemoryEffects::inaccessibleOrArgMemOnly(); + } + if (Attrs & (1ULL << 53)) { + // WriteOnly + Attrs &= ~(1ULL << 53); + ME &= MemoryEffects::writeOnly(); + } + if (ME != MemoryEffects::unknown()) + B.addMemoryAttr(ME); + } + + addRawAttributeValue(B, Attrs); } Error BitcodeReader::parseAttributeBlock() { @@ -1824,7 +1858,7 @@ for (unsigned i = 0, e = Record.size(); i != e; i += 2) { AttrBuilder B(Context); - decodeLLVMAttributesForBitcode(B, Record[i+1]); + decodeLLVMAttributesForBitcode(B, Record[i+1], Record[i]); Attrs.push_back(AttributeList::get(Context, Record[i], B)); } @@ -1851,8 +1885,6 @@ return Attribute::Alignment; case bitc::ATTR_KIND_ALWAYS_INLINE: return Attribute::AlwaysInline; - case bitc::ATTR_KIND_ARGMEMONLY: - return Attribute::ArgMemOnly; case bitc::ATTR_KIND_BUILTIN: return Attribute::Builtin; case bitc::ATTR_KIND_BY_VAL: @@ -1869,10 +1901,6 @@ return Attribute::ElementType; case bitc::ATTR_KIND_FNRETTHUNK_EXTERN: return Attribute::FnRetThunkExtern; - case bitc::ATTR_KIND_INACCESSIBLEMEM_ONLY: - return Attribute::InaccessibleMemOnly; - case bitc::ATTR_KIND_INACCESSIBLEMEM_OR_ARGMEMONLY: - return Attribute::InaccessibleMemOrArgMemOnly; case bitc::ATTR_KIND_INLINE_HINT: return Attribute::InlineHint; case bitc::ATTR_KIND_IN_REG: @@ -2039,6 +2067,31 @@ return Error::success(); } +static bool upgradeOldMemoryAttribute(MemoryEffects &ME, uint64_t EncodedKind) { + switch (EncodedKind) { + case bitc::ATTR_KIND_READ_NONE: + ME &= MemoryEffects::none(); + return true; + case bitc::ATTR_KIND_READ_ONLY: + ME &= MemoryEffects::readOnly(); + return true; + case bitc::ATTR_KIND_WRITEONLY: + ME &= MemoryEffects::writeOnly(); + return true; + case bitc::ATTR_KIND_ARGMEMONLY: + ME &= MemoryEffects::argMemOnly(); + return true; + case bitc::ATTR_KIND_INACCESSIBLEMEM_ONLY: + ME &= MemoryEffects::inaccessibleMemOnly(); + return true; + case bitc::ATTR_KIND_INACCESSIBLEMEM_OR_ARGMEMONLY: + ME &= MemoryEffects::inaccessibleOrArgMemOnly(); + return true; + default: + return false; + } +} + Error BitcodeReader::parseAttributeGroupBlock() { if (Error Err = Stream.EnterSubBlock(bitc::PARAMATTR_GROUP_BLOCK_ID)) return Err; @@ -2082,10 +2135,16 @@ uint64_t Idx = Record[1]; // Index of the object this attribute refers to. AttrBuilder B(Context); + MemoryEffects ME = MemoryEffects::unknown(); for (unsigned i = 2, e = Record.size(); i != e; ++i) { if (Record[i] == 0) { // Enum attribute Attribute::AttrKind Kind; - if (Error Err = parseAttrKind(Record[++i], &Kind)) + uint64_t EncodedKind = Record[++i]; + if (Idx == AttributeList::FunctionIndex && + upgradeOldMemoryAttribute(ME, EncodedKind)) + continue; + + if (Error Err = parseAttrKind(EncodedKind, &Kind)) return Err; // Upgrade old-style byval attribute to one with a type, even if it's @@ -2159,6 +2218,9 @@ } } + if (ME != MemoryEffects::unknown()) + B.addMemoryAttr(ME); + UpgradeAttributes(B); MAttributeGroups[GrpID] = AttributeList::get(Context, Idx, B); break; Index: llvm/lib/Bitcode/Writer/BitcodeWriter.cpp =================================================================== --- llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -620,8 +620,6 @@ return bitc::ATTR_KIND_ALLOC_SIZE; case Attribute::AlwaysInline: return bitc::ATTR_KIND_ALWAYS_INLINE; - case Attribute::ArgMemOnly: - return bitc::ATTR_KIND_ARGMEMONLY; case Attribute::Builtin: return bitc::ATTR_KIND_BUILTIN; case Attribute::ByVal: @@ -640,10 +638,6 @@ return bitc::ATTR_KIND_HOT; case Attribute::ElementType: return bitc::ATTR_KIND_ELEMENTTYPE; - case Attribute::InaccessibleMemOnly: - return bitc::ATTR_KIND_INACCESSIBLEMEM_ONLY; - case Attribute::InaccessibleMemOrArgMemOnly: - return bitc::ATTR_KIND_INACCESSIBLEMEM_OR_ARGMEMONLY; case Attribute::InlineHint: return bitc::ATTR_KIND_INLINE_HINT; case Attribute::InReg: Index: llvm/lib/CodeGen/MachineVerifier.cpp =================================================================== --- llvm/lib/CodeGen/MachineVerifier.cpp +++ llvm/lib/CodeGen/MachineVerifier.cpp @@ -61,6 +61,7 @@ #include "llvm/IR/Function.h" #include "llvm/IR/InlineAsm.h" #include "llvm/IR/Instructions.h" +#include "llvm/IR/ModRef.h" #include "llvm/InitializePasses.h" #include "llvm/MC/LaneBitmask.h" #include "llvm/MC/MCAsmInfo.h" @@ -1473,10 +1474,9 @@ bool NoSideEffects = MI->getOpcode() == TargetOpcode::G_INTRINSIC; unsigned IntrID = IntrIDOp.getIntrinsicID(); if (IntrID != 0 && IntrID < Intrinsic::num_intrinsics) { - AttributeList Attrs - = Intrinsic::getAttributes(MF->getFunction().getContext(), - static_cast(IntrID)); - bool DeclHasSideEffects = !Attrs.hasFnAttr(Attribute::ReadNone); + AttributeList Attrs = Intrinsic::getAttributes( + MF->getFunction().getContext(), static_cast(IntrID)); + bool DeclHasSideEffects = !Attrs.getMemoryEffects().doesNotAccessMemory(); if (NoSideEffects && DeclHasSideEffects) { report("G_INTRINSIC used with intrinsic that accesses memory", MI); break; Index: llvm/lib/IR/AttributeImpl.h =================================================================== --- llvm/lib/IR/AttributeImpl.h +++ llvm/lib/IR/AttributeImpl.h @@ -263,6 +263,7 @@ Optional getVScaleRangeMax() const; UWTableKind getUWTableKind() const; AllocFnKind getAllocKind() const; + MemoryEffects getMemoryEffects() const; std::string getAsString(bool InAttrGrp) const; Type *getAttributeType(Attribute::AttrKind Kind) const; Index: llvm/lib/IR/Attributes.cpp =================================================================== --- llvm/lib/IR/Attributes.cpp +++ llvm/lib/IR/Attributes.cpp @@ -211,6 +211,11 @@ return get(Context, UWTable, uint64_t(Kind)); } +Attribute Attribute::getWithMemoryEffects(LLVMContext &Context, + MemoryEffects ME) { + return get(Context, Memory, ME.toIntValue()); +} + Attribute Attribute::getWithAllocSizeArgs(LLVMContext &Context, unsigned ElemSizeArg, const Optional &NumElemsArg) { @@ -831,6 +836,10 @@ return SetNode ? SetNode->getAllocKind() : AllocFnKind::Unknown; } +MemoryEffects AttributeSet::getMemoryEffects() const { + return SetNode ? SetNode->getMemoryEffects() : MemoryEffects::unknown(); +} + std::string AttributeSet::getAsString(bool InAttrGrp) const { return SetNode ? SetNode->getAsString(InAttrGrp) : ""; } @@ -1009,6 +1018,12 @@ return AllocFnKind::Unknown; } +MemoryEffects AttributeSetNode::getMemoryEffects() const { + if (auto A = findEnumAttribute(Attribute::Memory)) + return A->getMemoryEffects(); + return MemoryEffects::unknown(); +} + std::string AttributeSetNode::getAsString(bool InAttrGrp) const { std::string Str; for (iterator I = begin(), E = end(); I != E; ++I) { @@ -1561,6 +1576,10 @@ return getFnAttrs().getAllocKind(); } +MemoryEffects AttributeList::getMemoryEffects() const { + return getFnAttrs().getMemoryEffects(); +} + std::string AttributeList::getAsString(unsigned Index, bool InAttrGrp) const { return getAttributes(Index).getAsString(InAttrGrp); } Index: llvm/lib/IR/Function.cpp =================================================================== --- llvm/lib/IR/Function.cpp +++ llvm/lib/IR/Function.cpp @@ -51,6 +51,7 @@ #include "llvm/IR/LLVMContext.h" #include "llvm/IR/MDBuilder.h" #include "llvm/IR/Metadata.h" +#include "llvm/IR/ModRef.h" #include "llvm/IR/Module.h" #include "llvm/IR/Operator.h" #include "llvm/IR/SymbolTableListTraits.h" @@ -727,6 +728,65 @@ setPrologueData(Src->getPrologueData()); } +MemoryEffects Function::getMemoryEffects() const { + return getAttributes().getMemoryEffects(); +} +void Function::setMemoryEffects(MemoryEffects ME) { + addFnAttr(Attribute::getWithMemoryEffects(getContext(), ME)); +} + +/// Determine if the function does not access memory. +bool Function::doesNotAccessMemory() const { + return getMemoryEffects().doesNotAccessMemory(); +} +void Function::setDoesNotAccessMemory() { + setMemoryEffects(MemoryEffects::none()); +} + +/// Determine if the function does not access or only reads memory. +bool Function::onlyReadsMemory() const { + return getMemoryEffects().onlyReadsMemory(); +} +void Function::setOnlyReadsMemory() { + setMemoryEffects(getMemoryEffects() & MemoryEffects::readOnly()); +} + +/// Determine if the function does not access or only writes memory. +bool Function::onlyWritesMemory() const { + return getMemoryEffects().onlyWritesMemory(); +} +void Function::setOnlyWritesMemory() { + setMemoryEffects(getMemoryEffects() & MemoryEffects::writeOnly()); +} + +/// Determine if the call can access memmory only using pointers based +/// on its arguments. +bool Function::onlyAccessesArgMemory() const { + return getMemoryEffects().onlyAccessesArgPointees(); +} +void Function::setOnlyAccessesArgMemory() { + setMemoryEffects(getMemoryEffects() & MemoryEffects::argMemOnly()); +} + +/// Determine if the function may only access memory that is +/// inaccessible from the IR. +bool Function::onlyAccessesInaccessibleMemory() const { + return getMemoryEffects().onlyAccessesInaccessibleMem(); +} +void Function::setOnlyAccessesInaccessibleMemory() { + setMemoryEffects(getMemoryEffects() & MemoryEffects::inaccessibleMemOnly()); +} + +/// Determine if the function may only access memory that is +/// either inaccessible from the IR or pointed to by its arguments. +bool Function::onlyAccessesInaccessibleMemOrArgMem() const { + return getMemoryEffects().onlyAccessesInaccessibleOrArgMem(); +} +void Function::setOnlyAccessesInaccessibleMemOrArgMem() { + setMemoryEffects(getMemoryEffects() & + MemoryEffects::inaccessibleOrArgMemOnly()); +} + /// Table of string intrinsic names indexed by enum value. static const char * const IntrinsicNameTable[] = { "not_intrinsic", Index: llvm/lib/IR/Instructions.cpp =================================================================== --- llvm/lib/IR/Instructions.cpp +++ llvm/lib/IR/Instructions.cpp @@ -30,6 +30,7 @@ #include "llvm/IR/LLVMContext.h" #include "llvm/IR/MDBuilder.h" #include "llvm/IR/Metadata.h" +#include "llvm/IR/ModRef.h" #include "llvm/IR/Module.h" #include "llvm/IR/Operator.h" #include "llvm/IR/Type.h" @@ -375,10 +376,12 @@ template Attribute CallBase::getFnAttrOnCalledFunction(AK Kind) const { - // Operand bundles override attributes on the called function, but don't - // override attributes directly present on the call instruction. - if (isFnAttrDisallowedByOpBundle(Kind)) - return Attribute(); + if constexpr (std::is_same_v) { + // getMemoryEffects() correctly combines memory effects from the call-site, + // operand bundles and function. + assert(Kind != Attribute::Memory && "Use getMemoryEffects() instead"); + } + Value *V = getCalledOperand(); if (auto *CE = dyn_cast(V)) if (CE->getOpcode() == BitCast) @@ -518,6 +521,77 @@ getIntrinsicID() != Intrinsic::assume; } +MemoryEffects CallBase::getMemoryEffects() const { + MemoryEffects ME = getAttributes().getMemoryEffects(); + if (auto *Fn = dyn_cast(getCalledOperand())) { + MemoryEffects FnME = Fn->getMemoryEffects(); + if (hasOperandBundles()) { + // TODO: Add a method to get memory effects for operand bundles instead. + if (hasReadingOperandBundles()) + FnME |= MemoryEffects::readOnly(); + if (hasClobberingOperandBundles()) + FnME |= MemoryEffects::writeOnly(); + } + ME &= FnME; + } + return ME; +} +void CallBase::setMemoryEffects(MemoryEffects ME) { + addFnAttr(Attribute::getWithMemoryEffects(getContext(), ME)); +} + +/// Determine if the function does not access memory. +bool CallBase::doesNotAccessMemory() const { + return getMemoryEffects().doesNotAccessMemory(); +} +void CallBase::setDoesNotAccessMemory() { + setMemoryEffects(MemoryEffects::none()); +} + +/// Determine if the function does not access or only reads memory. +bool CallBase::onlyReadsMemory() const { + return getMemoryEffects().onlyReadsMemory(); +} +void CallBase::setOnlyReadsMemory() { + setMemoryEffects(getMemoryEffects() & MemoryEffects::readOnly()); +} + +/// Determine if the function does not access or only writes memory. +bool CallBase::onlyWritesMemory() const { + return getMemoryEffects().onlyWritesMemory(); +} +void CallBase::setOnlyWritesMemory() { + setMemoryEffects(getMemoryEffects() & MemoryEffects::writeOnly()); +} + +/// Determine if the call can access memmory only using pointers based +/// on its arguments. +bool CallBase::onlyAccessesArgMemory() const { + return getMemoryEffects().onlyAccessesArgPointees(); +} +void CallBase::setOnlyAccessesArgMemory() { + setMemoryEffects(getMemoryEffects() & MemoryEffects::argMemOnly()); +} + +/// Determine if the function may only access memory that is +/// inaccessible from the IR. +bool CallBase::onlyAccessesInaccessibleMemory() const { + return getMemoryEffects().onlyAccessesInaccessibleMem(); +} +void CallBase::setOnlyAccessesInaccessibleMemory() { + setMemoryEffects(getMemoryEffects() & MemoryEffects::inaccessibleMemOnly()); +} + +/// Determine if the function may only access memory that is +/// either inaccessible from the IR or pointed to by its arguments. +bool CallBase::onlyAccessesInaccessibleMemOrArgMem() const { + return getMemoryEffects().onlyAccessesInaccessibleOrArgMem(); +} +void CallBase::setOnlyAccessesInaccessibleMemOrArgMem() { + setMemoryEffects(getMemoryEffects() & + MemoryEffects::inaccessibleOrArgMemOnly()); +} + //===----------------------------------------------------------------------===// // CallInst Implementation //===----------------------------------------------------------------------===// Index: llvm/lib/IR/Verifier.cpp =================================================================== --- llvm/lib/IR/Verifier.cpp +++ llvm/lib/IR/Verifier.cpp @@ -2021,28 +2021,6 @@ "' does not apply to functions!", V); - Check(!(Attrs.hasFnAttr(Attribute::ReadNone) && - Attrs.hasFnAttr(Attribute::ReadOnly)), - "Attributes 'readnone and readonly' are incompatible!", V); - - Check(!(Attrs.hasFnAttr(Attribute::ReadNone) && - Attrs.hasFnAttr(Attribute::WriteOnly)), - "Attributes 'readnone and writeonly' are incompatible!", V); - - Check(!(Attrs.hasFnAttr(Attribute::ReadOnly) && - Attrs.hasFnAttr(Attribute::WriteOnly)), - "Attributes 'readonly and writeonly' are incompatible!", V); - - Check(!(Attrs.hasFnAttr(Attribute::ReadNone) && - Attrs.hasFnAttr(Attribute::InaccessibleMemOrArgMemOnly)), - "Attributes 'readnone and inaccessiblemem_or_argmemonly' are " - "incompatible!", - V); - - Check(!(Attrs.hasFnAttr(Attribute::ReadNone) && - Attrs.hasFnAttr(Attribute::InaccessibleMemOnly)), - "Attributes 'readnone and inaccessiblememonly' are incompatible!", V); - Check(!(Attrs.hasFnAttr(Attribute::NoInline) && Attrs.hasFnAttr(Attribute::AlwaysInline)), "Attributes 'noinline and alwaysinline' are incompatible!", V); Index: llvm/lib/Target/AMDGPU/AMDGPULibFunc.cpp =================================================================== --- llvm/lib/Target/AMDGPU/AMDGPULibFunc.cpp +++ llvm/lib/Target/AMDGPU/AMDGPULibFunc.cpp @@ -17,6 +17,7 @@ #include "llvm/ADT/StringSwitch.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Function.h" +#include "llvm/IR/ModRef.h" #include "llvm/IR/Module.h" #include "llvm/IR/ValueSymbolTable.h" #include "llvm/Support/CommandLine.h" @@ -992,7 +993,8 @@ } else { AttributeList Attr; LLVMContext &Ctx = M->getContext(); - Attr = Attr.addFnAttribute(Ctx, Attribute::ReadOnly); + Attr = Attr.addFnAttribute( + Ctx, Attribute::getWithMemoryEffects(Ctx, MemoryEffects::readOnly())); Attr = Attr.addFnAttribute(Ctx, Attribute::NoUnwind); C = M->getOrInsertFunction(FuncName, FuncTy, Attr); } Index: llvm/lib/Target/AMDGPU/SIISelLowering.cpp =================================================================== --- llvm/lib/Target/AMDGPU/SIISelLowering.cpp +++ llvm/lib/Target/AMDGPU/SIISelLowering.cpp @@ -33,6 +33,7 @@ #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/IntrinsicsAMDGPU.h" #include "llvm/IR/IntrinsicsR600.h" +#include "llvm/IR/ModRef.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/KnownBits.h" @@ -958,7 +959,8 @@ AMDGPU::lookupRsrcIntrinsic(IntrID)) { AttributeList Attr = Intrinsic::getAttributes(CI.getContext(), (Intrinsic::ID)IntrID); - if (Attr.hasFnAttr(Attribute::ReadNone)) + MemoryEffects ME = Attr.getMemoryEffects(); + if (ME.doesNotAccessMemory()) return false; SIMachineFunctionInfo *MFI = MF.getInfo(); @@ -974,7 +976,7 @@ } Info.flags |= MachineMemOperand::MODereferenceable; - if (Attr.hasFnAttr(Attribute::ReadOnly)) { + if (ME.onlyReadsMemory()) { unsigned DMaskLanes = 4; if (RsrcIntr->IsImage) { @@ -998,7 +1000,7 @@ // FIXME: What does alignment mean for an image? Info.opc = ISD::INTRINSIC_W_CHAIN; Info.flags |= MachineMemOperand::MOLoad; - } else if (Attr.hasFnAttr(Attribute::WriteOnly)) { + } else if (ME.onlyWritesMemory()) { Info.opc = ISD::INTRINSIC_VOID; Type *DataTy = CI.getArgOperand(0)->getType(); Index: llvm/lib/Target/Mips/Mips16HardFloat.cpp =================================================================== --- llvm/lib/Target/Mips/Mips16HardFloat.cpp +++ llvm/lib/Target/Mips/Mips16HardFloat.cpp @@ -12,6 +12,7 @@ #include "MipsTargetMachine.h" #include "llvm/CodeGen/TargetPassConfig.h" +#include "llvm/IR/ModRef.h" #include "llvm/IR/Module.h" #include "llvm/IR/Value.h" #include "llvm/Support/Debug.h" @@ -409,7 +410,8 @@ // functions will take place. // A = A.addFnAttribute(C, "__Mips16RetHelper"); - A = A.addFnAttribute(C, Attribute::ReadNone); + A = A.addFnAttribute( + C, Attribute::getWithMemoryEffects(C, MemoryEffects::none())); A = A.addFnAttribute(C, Attribute::NoInline); FunctionCallee F = (M->getOrInsertFunction(Name, A, MyVoid, T)); CallInst::Create(F, Params, "", &I); Index: llvm/lib/Transforms/IPO/FunctionAttrs.cpp =================================================================== --- llvm/lib/Transforms/IPO/FunctionAttrs.cpp +++ llvm/lib/Transforms/IPO/FunctionAttrs.cpp @@ -69,10 +69,7 @@ #define DEBUG_TYPE "function-attrs" -STATISTIC(NumArgMemOnly, "Number of functions marked argmemonly"); -STATISTIC(NumReadNone, "Number of functions marked readnone"); -STATISTIC(NumReadOnly, "Number of functions marked readonly"); -STATISTIC(NumWriteOnly, "Number of functions marked writeonly"); +STATISTIC(NumMemoryAttr, "Number of functions with improved memory attribute"); STATISTIC(NumNoCapture, "Number of arguments marked nocapture"); STATISTIC(NumReturned, "Number of arguments marked returned"); STATISTIC(NumReadNoneArg, "Number of arguments marked readnone"); @@ -253,79 +250,14 @@ return; } - ModRefInfo MR = ME.getModRef(); - for (Function *F : SCCNodes) { - if (F->doesNotAccessMemory()) - // Already perfect! - continue; - - if (ME.doesNotAccessMemory()) { - // For readnone, remove all other memory attributes. - AttributeMask AttrsToRemove; - AttrsToRemove.addAttribute(Attribute::ReadOnly); - AttrsToRemove.addAttribute(Attribute::WriteOnly); - AttrsToRemove.addAttribute(Attribute::ArgMemOnly); - AttrsToRemove.addAttribute(Attribute::InaccessibleMemOnly); - AttrsToRemove.addAttribute(Attribute::InaccessibleMemOrArgMemOnly); - - ++NumReadNone; - F->removeFnAttrs(AttrsToRemove); - F->addFnAttr(Attribute::ReadNone); - Changed.insert(F); - continue; - } - - // Add argmemonly, inaccessiblememonly, or inaccessible_or_argmemonly - // attributes if possible. - AttributeMask AttrsToRemove; - AttrsToRemove.addAttribute(Attribute::ArgMemOnly); - AttrsToRemove.addAttribute(Attribute::InaccessibleMemOnly); - AttrsToRemove.addAttribute(Attribute::InaccessibleMemOrArgMemOnly); - if (ME.onlyAccessesArgPointees()) { - if (!F->onlyAccessesArgMemory()) { - NumArgMemOnly++; - F->removeFnAttrs(AttrsToRemove); - F->addFnAttr(Attribute::ArgMemOnly); - Changed.insert(F); - } - } else if (ME.onlyAccessesInaccessibleMem()) { - if (!F->onlyAccessesInaccessibleMemory()) { - F->removeFnAttrs(AttrsToRemove); - F->addFnAttr(Attribute::InaccessibleMemOnly); - Changed.insert(F); - } - } else if (ME.onlyAccessesInaccessibleOrArgMem() && - !F->onlyAccessesInaccessibleMemOrArgMem()) { - F->removeFnAttrs(AttrsToRemove); - F->addFnAttr(Attribute::InaccessibleMemOrArgMemOnly); + MemoryEffects OldME = F->getMemoryEffects(); + MemoryEffects NewME = ME & OldME; + if (NewME != OldME) { + ++NumMemoryAttr; + F->setMemoryEffects(NewME); Changed.insert(F); } - - // The SCC contains functions both writing and reading from memory. We - // cannot add readonly or writeonline attributes. - if (MR == ModRefInfo::ModRef) - continue; - - if (F->onlyReadsMemory() && MR == ModRefInfo::Ref) - continue; - - if (F->onlyWritesMemory() && MR == ModRefInfo::Mod) - continue; - - Changed.insert(F); - - // Add in the new attribute. - if (MR == ModRefInfo::Mod) { - ++NumWriteOnly; - F->removeFnAttr(Attribute::ReadOnly); - F->addFnAttr(Attribute::WriteOnly); - } else { - ++NumReadOnly; - assert(MR == ModRefInfo::Ref); - F->removeFnAttr(Attribute::WriteOnly); - F->addFnAttr(Attribute::ReadOnly); - } } } Index: llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp =================================================================== --- llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp +++ llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp @@ -1234,19 +1234,22 @@ // Initialize DataFlowSanitizer runtime functions and declare them in the module void DataFlowSanitizer::initializeRuntimeFunctions(Module &M) { + LLVMContext &C = M.getContext(); { AttributeList AL; - AL = AL.addFnAttribute(M.getContext(), Attribute::NoUnwind); - AL = AL.addFnAttribute(M.getContext(), Attribute::ReadOnly); - AL = AL.addRetAttribute(M.getContext(), Attribute::ZExt); + AL = AL.addFnAttribute(C, Attribute::NoUnwind); + AL = AL.addFnAttribute( + C, Attribute::getWithMemoryEffects(C, MemoryEffects::readOnly())); + AL = AL.addRetAttribute(C, Attribute::ZExt); DFSanUnionLoadFn = Mod->getOrInsertFunction("__dfsan_union_load", DFSanUnionLoadFnTy, AL); } { AttributeList AL; - AL = AL.addFnAttribute(M.getContext(), Attribute::NoUnwind); - AL = AL.addFnAttribute(M.getContext(), Attribute::ReadOnly); - AL = AL.addRetAttribute(M.getContext(), Attribute::ZExt); + AL = AL.addFnAttribute(C, Attribute::NoUnwind); + AL = AL.addFnAttribute( + C, Attribute::getWithMemoryEffects(C, MemoryEffects::readOnly())); + AL = AL.addRetAttribute(C, Attribute::ZExt); DFSanLoadLabelAndOriginFn = Mod->getOrInsertFunction( "__dfsan_load_label_and_origin", DFSanLoadLabelAndOriginFnTy, AL); } @@ -1470,8 +1473,7 @@ } } - ReadOnlyNoneAttrs.addAttribute(Attribute::ReadOnly) - .addAttribute(Attribute::ReadNone); + ReadOnlyNoneAttrs.addAttribute(Attribute::Memory); // First, change the ABI of every function in the module. ABI-listed // functions keep their original ABI and get a wrapper function. Index: llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp =================================================================== --- llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp +++ llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp @@ -4049,12 +4049,9 @@ // will become a non-readonly function after it is instrumented by us. To // prevent this code from being optimized out, mark that function // non-readonly in advance. + // TODO: We can likely do better than dropping memory() completely here. AttributeMask B; - B.addAttribute(Attribute::ReadOnly) - .addAttribute(Attribute::ReadNone) - .addAttribute(Attribute::WriteOnly) - .addAttribute(Attribute::ArgMemOnly) - .addAttribute(Attribute::Speculatable); + B.addAttribute(Attribute::Memory).addAttribute(Attribute::Speculatable); Call->removeFnAttrs(B); if (Function *Func = Call->getCalledFunction()) { @@ -5744,13 +5741,9 @@ MemorySanitizerVisitor Visitor(F, *this, TLI); - // Clear out readonly/readnone attributes. + // Clear out memory attributes. AttributeMask B; - B.addAttribute(Attribute::ReadOnly) - .addAttribute(Attribute::ReadNone) - .addAttribute(Attribute::WriteOnly) - .addAttribute(Attribute::ArgMemOnly) - .addAttribute(Attribute::Speculatable); + B.addAttribute(Attribute::Memory).addAttribute(Attribute::Speculatable); F.removeFnAttrs(B); return Visitor.runOnFunction(); Index: llvm/lib/Transforms/Scalar/PartiallyInlineLibCalls.cpp =================================================================== --- llvm/lib/Transforms/Scalar/PartiallyInlineLibCalls.cpp +++ llvm/lib/Transforms/Scalar/PartiallyInlineLibCalls.cpp @@ -80,10 +80,9 @@ Instruction *LibCall = Call->clone(); Builder.Insert(LibCall); - // Add attribute "readnone" so that backend can use a native sqrt instruction - // for this call. - Call->removeFnAttr(Attribute::WriteOnly); - Call->addFnAttr(Attribute::ReadNone); + // Add memory(none) attribute, so that the backend can use a native sqrt + // instruction for this call. + Call->setDoesNotAccessMemory(); // Insert a FP compare instruction and use it as the CurrBB branch condition. Builder.SetInsertPoint(CurrBBTerm); Index: llvm/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp =================================================================== --- llvm/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp +++ llvm/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp @@ -1430,10 +1430,7 @@ // machine model for purposes of optimization. We have to strip these on // both function declarations and call sites. static constexpr Attribute::AttrKind FnAttrsToStrip[] = - {Attribute::ReadNone, Attribute::ReadOnly, Attribute::WriteOnly, - Attribute::ArgMemOnly, Attribute::InaccessibleMemOnly, - Attribute::InaccessibleMemOrArgMemOnly, - Attribute::NoSync, Attribute::NoFree}; + {Attribute::Memory, Attribute::NoSync, Attribute::NoFree}; // Create new attribute set containing only attributes which can be transferred // from original call to the safepoint. Index: llvm/lib/Transforms/Scalar/SCCP.cpp =================================================================== --- llvm/lib/Transforms/Scalar/SCCP.cpp +++ llvm/lib/Transforms/Scalar/SCCP.cpp @@ -590,21 +590,27 @@ } } - // If we replaced an argument, the argmemonly and - // inaccessiblemem_or_argmemonly attributes do not hold any longer. Remove - // them from both the function and callsites. + // If we replaced an argument, we may not also access a global (currently + // classified as "other" memory). Update memory attribute to reflect this. if (ReplacedPointerArg) { - AttributeMask AttributesToRemove; - AttributesToRemove.addAttribute(Attribute::ArgMemOnly); - AttributesToRemove.addAttribute(Attribute::InaccessibleMemOrArgMemOnly); - F.removeFnAttrs(AttributesToRemove); - + auto UpdateAttrs = [&](AttributeList AL) { + MemoryEffects ME = AL.getMemoryEffects(); + if (ME == MemoryEffects::unknown()) + return AL; + + ME |= MemoryEffects(MemoryEffects::Other, ModRefInfo::ModRef); + return AL.addFnAttribute( + F.getContext(), + Attribute::getWithMemoryEffects(F.getContext(), ME)); + }; + + F.setAttributes(UpdateAttrs(F.getAttributes())); for (User *U : F.users()) { auto *CB = dyn_cast(U); if (!CB || CB->getCalledFunction() != &F) continue; - CB->removeFnAttrs(AttributesToRemove); + CB->setAttributes(UpdateAttrs(CB->getAttributes())); } } MadeChanges |= ReplacedPointerArg; Index: llvm/lib/Transforms/Utils/BuildLibCalls.cpp =================================================================== --- llvm/lib/Transforms/Utils/BuildLibCalls.cpp +++ llvm/lib/Transforms/Utils/BuildLibCalls.cpp @@ -75,11 +75,6 @@ static bool setOnlyWritesMemory(Function &F) { if (F.onlyWritesMemory()) // writeonly or readnone return false; - // Turn readonly and writeonly into readnone. - if (F.hasFnAttribute(Attribute::ReadOnly)) { - F.removeFnAttr(Attribute::ReadOnly); - return setDoesNotAccessMemory(F); - } ++NumWriteOnly; F.setOnlyWritesMemory(); return true; Index: llvm/test/Analysis/BasicAA/cs-cs.ll =================================================================== --- llvm/test/Analysis/BasicAA/cs-cs.ll +++ llvm/test/Analysis/BasicAA/cs-cs.ll @@ -429,19 +429,19 @@ } -; CHECK: attributes #0 = { argmemonly nocallback nofree nounwind willreturn writeonly } -; CHECK-NEXT: attributes #1 = { argmemonly nocallback nofree nounwind willreturn } -; CHECK-NEXT: attributes #2 = { argmemonly nosync nounwind willreturn } -; CHECK-NEXT: attributes #3 = { noinline nounwind readonly } -; CHECK-NEXT: attributes #4 = { noinline nounwind writeonly } +; CHECK: attributes #0 = { nocallback nofree nounwind willreturn memory(argmem: write) } +; CHECK-NEXT: attributes #1 = { nocallback nofree nounwind willreturn memory(argmem: readwrite) } +; CHECK-NEXT: attributes #2 = { nosync nounwind willreturn memory(argmem: readwrite) } +; CHECK-NEXT: attributes #3 = { noinline nounwind memory(read) } +; CHECK-NEXT: attributes #4 = { noinline nounwind memory(write) } ; CHECK-NEXT: attributes #5 = { nounwind ssp } -; CHECK-NEXT: attributes #6 = { inaccessiblememonly nounwind } -; CHECK-NEXT: attributes #7 = { inaccessiblemem_or_argmemonly nounwind } -; CHECK-NEXT: attributes #8 = { argmemonly nounwind } -; CHECK-NEXT: attributes #9 = { readonly } -; CHECK-NEXT: attributes #10 = { inaccessiblememonly } -; CHECK-NEXT: attributes #11 = { inaccessiblemem_or_argmemonly } -; CHECK-NEXT: attributes #12 = { argmemonly } +; CHECK-NEXT: attributes #6 = { nounwind memory(inaccessiblemem: readwrite) } +; CHECK-NEXT: attributes #7 = { nounwind memory(argmem: readwrite, inaccessiblemem: readwrite) } +; CHECK-NEXT: attributes #8 = { nounwind memory(argmem: readwrite) } +; CHECK-NEXT: attributes #9 = { memory(read) } +; CHECK-NEXT: attributes #10 = { memory(inaccessiblemem: readwrite) } +; CHECK-NEXT: attributes #11 = { memory(argmem: readwrite, inaccessiblemem: readwrite) } +; CHECK-NEXT: attributes #12 = { memory(argmem: readwrite) } attributes #0 = { argmemonly nounwind } attributes #1 = { noinline nounwind readonly } Index: llvm/test/Analysis/BasicAA/intrinsics.ll =================================================================== --- llvm/test/Analysis/BasicAA/intrinsics.ll +++ llvm/test/Analysis/BasicAA/intrinsics.ll @@ -22,6 +22,6 @@ declare <8 x i16> @llvm.masked.load.v8i16.p0v8i16(<8 x i16>*, i32, <8 x i1>, <8 x i16>) nounwind readonly declare void @llvm.masked.store.v8i16.p0v8i16(<8 x i16>, <8 x i16>*, i32, <8 x i1>) nounwind -; CHECK: attributes #0 = { argmemonly nocallback nofree nosync nounwind readonly willreturn } -; CHECK: attributes #1 = { argmemonly nocallback nofree nosync nounwind willreturn writeonly } +; CHECK: attributes #0 = { nocallback nofree nosync nounwind willreturn memory(argmem: read) } +; CHECK: attributes #1 = { nocallback nofree nosync nounwind willreturn memory(argmem: write) } ; CHECK: attributes [[ATTR]] = { nounwind } Index: llvm/test/Analysis/BasicAA/pure-const-dce.ll =================================================================== --- llvm/test/Analysis/BasicAA/pure-const-dce.ll +++ llvm/test/Analysis/BasicAA/pure-const-dce.ll @@ -50,5 +50,5 @@ declare i32 @TestNone(i32) -; CHECK: attributes [[READNONE]] = { readnone } -; CHECK: attributes [[READONLY]] = { readonly } +; CHECK: attributes [[READNONE]] = { memory(none) } +; CHECK: attributes [[READONLY]] = { memory(read) } Index: llvm/test/Analysis/TypeBasedAliasAnalysis/functionattrs.ll =================================================================== --- llvm/test/Analysis/TypeBasedAliasAnalysis/functionattrs.ll +++ llvm/test/Analysis/TypeBasedAliasAnalysis/functionattrs.ll @@ -72,14 +72,14 @@ declare void @callee(i32* %p) nounwind declare void @llvm.memcpy.p0i8.p0i8.i64(i8*, i8*, i64, i1) nounwind -; CHECK: attributes #0 = { mustprogress nofree norecurse nosync nounwind readnone willreturn } -; CHECK: attributes #1 = { argmemonly mustprogress nofree norecurse nosync nounwind willreturn writeonly } -; CHECK: attributes #2 = { nofree nosync nounwind readnone } +; CHECK: attributes #0 = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) } +; CHECK: attributes #1 = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write) } +; CHECK: attributes #2 = { nofree nosync nounwind memory(none) } ; CHECK: attributes #3 = { nounwind } -; CHECK: attributes #4 = { mustprogress nofree nosync nounwind readnone willreturn } -; CHECK: attributes #5 = { argmemonly mustprogress nofree nosync nounwind willreturn } -; CHECK: attributes #6 = { argmemonly mustprogress nofree norecurse nosync nounwind willreturn } -; CHECK: attributes #7 = { argmemonly nocallback nofree nounwind willreturn } +; CHECK: attributes #4 = { mustprogress nofree nosync nounwind willreturn memory(none) } +; CHECK: attributes #5 = { mustprogress nofree nosync nounwind willreturn memory(argmem: readwrite) } +; CHECK: attributes #6 = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite) } +; CHECK: attributes #7 = { nocallback nofree nounwind willreturn memory(argmem: readwrite) } ; Root note. !0 = !{ } Index: llvm/test/Analysis/TypeBasedAliasAnalysis/intrinsics.ll =================================================================== --- llvm/test/Analysis/TypeBasedAliasAnalysis/intrinsics.ll +++ llvm/test/Analysis/TypeBasedAliasAnalysis/intrinsics.ll @@ -22,8 +22,8 @@ declare <8 x i16> @llvm.masked.load.v8i16.p0v8i16(<8 x i16>*, i32, <8 x i1>, <8 x i16>) nounwind readonly declare void @llvm.masked.store.v8i16.p0v8i16(<8 x i16>, <8 x i16>*, i32, <8 x i1>) nounwind -; CHECK: attributes #0 = { argmemonly nocallback nofree nosync nounwind readonly willreturn } -; CHECK: attributes #1 = { argmemonly nocallback nofree nosync nounwind willreturn writeonly } +; CHECK: attributes #0 = { nocallback nofree nosync nounwind willreturn memory(argmem: read) } +; CHECK: attributes #1 = { nocallback nofree nosync nounwind willreturn memory(argmem: write) } ; CHECK: attributes [[NUW]] = { nounwind } !0 = !{!"tbaa root"} Index: llvm/test/Assembler/aarch64-intrinsics-attributes.ll =================================================================== --- llvm/test/Assembler/aarch64-intrinsics-attributes.ll +++ llvm/test/Assembler/aarch64-intrinsics-attributes.ll @@ -23,4 +23,4 @@ declare @llvm.aarch64.sve.dup.nxv4i32(, , i32) ; CHECK: attributes [[NOFREE_NOUNWIND_WILLRETURN]] = { nofree nounwind willreturn } -; CHECK: attributes [[NO_CALLBACK_NOFREE_NOSYNC_NOUNWIND_READNONE_WILLRETURN]] = { nocallback nofree nosync nounwind readnone willreturn } +; CHECK: attributes [[NO_CALLBACK_NOFREE_NOSYNC_NOUNWIND_READNONE_WILLRETURN]] = { nocallback nofree nosync nounwind willreturn memory(none) } Index: llvm/test/Bindings/llvm-c/debug_info.ll =================================================================== --- llvm/test/Bindings/llvm-c/debug_info.ll +++ llvm/test/Bindings/llvm-c/debug_info.ll @@ -12,13 +12,13 @@ ; CHECK-NEXT: call void @llvm.dbg.value(metadata i64 0, metadata !41, metadata !DIExpression(DW_OP_constu, 0, DW_OP_stack_value)), !dbg !44 ; CHECK-NEXT: } -; CHECK: ; Function Attrs: nocallback nofree nosync nounwind readnone speculatable willreturn +; CHECK: ; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none) ; CHECK-NEXT: declare void @llvm.dbg.declare(metadata, metadata, metadata) #0 -; CHECK: ; Function Attrs: nocallback nofree nosync nounwind readnone speculatable willreturn +; CHECK: ; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none) ; CHECK-NEXT: declare void @llvm.dbg.value(metadata, metadata, metadata) #0 -; CHECK: attributes #0 = { nocallback nofree nosync nounwind readnone speculatable willreturn } +; CHECK: attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) } ; CHECK: !llvm.dbg.cu = !{!0} ; CHECK-NEXT: !FooType = !{!28} Index: llvm/test/Bitcode/attributes-3.3.ll =================================================================== --- llvm/test/Bitcode/attributes-3.3.ll +++ llvm/test/Bitcode/attributes-3.3.ll @@ -213,8 +213,8 @@ ; CHECK: attributes #0 = { noreturn } ; CHECK: attributes #1 = { nounwind } -; CHECK: attributes #2 = { readnone } -; CHECK: attributes #3 = { readonly } +; CHECK: attributes #2 = { memory(none) } +; CHECK: attributes #3 = { memory(read) } ; CHECK: attributes #4 = { noinline } ; CHECK: attributes #5 = { alwaysinline } ; CHECK: attributes #6 = { optsize } Index: llvm/test/Bitcode/attributes.ll =================================================================== --- llvm/test/Bitcode/attributes.ll +++ llvm/test/Bitcode/attributes.ll @@ -540,8 +540,8 @@ ; CHECK: attributes #0 = { noreturn } ; CHECK: attributes #1 = { nounwind } -; CHECK: attributes #2 = { readnone } -; CHECK: attributes #3 = { readonly } +; CHECK: attributes #2 = { memory(none) } +; CHECK: attributes #3 = { memory(read) } ; CHECK: attributes #4 = { noinline } ; CHECK: attributes #5 = { alwaysinline } ; CHECK: attributes #6 = { optsize } @@ -564,13 +564,13 @@ ; CHECK: attributes #23 = { noinline optnone } ; CHECK: attributes #24 = { jumptable } ; CHECK: attributes #25 = { convergent } -; CHECK: attributes #26 = { argmemonly } +; CHECK: attributes #26 = { memory(argmem: readwrite) } ; CHECK: attributes #27 = { norecurse } -; CHECK: attributes #28 = { inaccessiblememonly } -; CHECK: attributes #29 = { inaccessiblemem_or_argmemonly } +; CHECK: attributes #28 = { memory(inaccessiblemem: readwrite) } +; CHECK: attributes #29 = { memory(argmem: readwrite, inaccessiblemem: readwrite) } ; CHECK: attributes #30 = { allocsize(0) } ; CHECK: attributes #31 = { allocsize(0,1) } -; CHECK: attributes #32 = { writeonly } +; CHECK: attributes #32 = { memory(write) } ; CHECK: attributes #33 = { speculatable } ; CHECK: attributes #34 = { sanitize_hwaddress } ; CHECK: attributes #35 = { shadowcallstack } Index: llvm/test/Bitcode/compatibility-3.6.ll =================================================================== --- llvm/test/Bitcode/compatibility-3.6.ll +++ llvm/test/Bitcode/compatibility-3.6.ll @@ -1168,8 +1168,8 @@ ; CHECK: attributes #15 = { nounwind } ; CHECK: attributes #16 = { noinline optnone } ; CHECK: attributes #17 = { optsize } -; CHECK: attributes #18 = { readnone } -; CHECK: attributes #19 = { readonly } +; CHECK: attributes #18 = { memory(none) } +; CHECK: attributes #19 = { memory(read) } ; CHECK: attributes #20 = { returns_twice } ; CHECK: attributes #21 = { sanitize_address } ; CHECK: attributes #22 = { sanitize_memory } @@ -1179,12 +1179,12 @@ ; CHECK: attributes #26 = { sspstrong } ; CHECK: attributes #27 = { uwtable } ; CHECK: attributes #28 = { "cpu"="cortex-a8" } -; CHECK: attributes #29 = { nocallback nofree nosync nounwind readnone willreturn } +; CHECK: attributes #29 = { nocallback nofree nosync nounwind willreturn memory(none) } ; CHECK: attributes #30 = { nocallback nofree nosync nounwind willreturn } -; CHECK: attributes #31 = { argmemonly nounwind readonly } -; CHECK: attributes #32 = { argmemonly nounwind } -; CHECK: attributes #33 = { nounwind readonly } -; CHECK: attributes #34 = { inaccessiblemem_or_argmemonly nocallback nofree nosync nounwind willreturn } +; CHECK: attributes #31 = { nounwind memory(argmem: read) } +; CHECK: attributes #32 = { nounwind memory(argmem: readwrite) } +; CHECK: attributes #33 = { nounwind memory(read) } +; CHECK: attributes #34 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite, inaccessiblemem: readwrite) } ; CHECK: attributes #35 = { builtin } ;; Metadata Index: llvm/test/Bitcode/compatibility-3.7.ll =================================================================== --- llvm/test/Bitcode/compatibility-3.7.ll +++ llvm/test/Bitcode/compatibility-3.7.ll @@ -1229,8 +1229,8 @@ ; CHECK: attributes #16 = { nounwind } ; CHECK: attributes #17 = { noinline optnone } ; CHECK: attributes #18 = { optsize } -; CHECK: attributes #19 = { readnone } -; CHECK: attributes #20 = { readonly } +; CHECK: attributes #19 = { memory(none) } +; CHECK: attributes #20 = { memory(read) } ; CHECK: attributes #21 = { returns_twice } ; CHECK: attributes #22 = { safestack } ; CHECK: attributes #23 = { sanitize_address } @@ -1242,12 +1242,12 @@ ; CHECK: attributes #29 = { "thunk" } ; CHECK: attributes #30 = { uwtable } ; CHECK: attributes #31 = { "cpu"="cortex-a8" } -; CHECK: attributes #32 = { nocallback nofree nosync nounwind readnone willreturn } +; CHECK: attributes #32 = { nocallback nofree nosync nounwind willreturn memory(none) } ; CHECK: attributes #33 = { nocallback nofree nosync nounwind willreturn } -; CHECK: attributes #34 = { argmemonly nounwind readonly } -; CHECK: attributes #35 = { argmemonly nounwind } -; CHECK: attributes #36 = { nounwind readonly } -; CHECK: attributes #37 = { inaccessiblemem_or_argmemonly nocallback nofree nosync nounwind willreturn } +; CHECK: attributes #34 = { nounwind memory(argmem: read) } +; CHECK: attributes #35 = { nounwind memory(argmem: readwrite) } +; CHECK: attributes #36 = { nounwind memory(read) } +; CHECK: attributes #37 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite, inaccessiblemem: readwrite) } ; CHECK: attributes #38 = { builtin } ;; Metadata Index: llvm/test/Bitcode/compatibility-3.8.ll =================================================================== --- llvm/test/Bitcode/compatibility-3.8.ll +++ llvm/test/Bitcode/compatibility-3.8.ll @@ -1536,8 +1536,8 @@ ; CHECK: attributes #16 = { nounwind } ; CHECK: attributes #17 = { noinline optnone } ; CHECK: attributes #18 = { optsize } -; CHECK: attributes #19 = { readnone } -; CHECK: attributes #20 = { readonly } +; CHECK: attributes #19 = { memory(none) } +; CHECK: attributes #20 = { memory(read) } ; CHECK: attributes #21 = { returns_twice } ; CHECK: attributes #22 = { safestack } ; CHECK: attributes #23 = { sanitize_address } @@ -1550,14 +1550,14 @@ ; CHECK: attributes #30 = { uwtable } ; CHECK: attributes #31 = { "cpu"="cortex-a8" } ; CHECK: attributes #32 = { norecurse } -; CHECK: attributes #33 = { inaccessiblememonly } -; CHECK: attributes #34 = { inaccessiblemem_or_argmemonly } -; CHECK: attributes #35 = { nocallback nofree nosync nounwind readnone willreturn } +; CHECK: attributes #33 = { memory(inaccessiblemem: readwrite) } +; CHECK: attributes #34 = { memory(argmem: readwrite, inaccessiblemem: readwrite) } +; CHECK: attributes #35 = { nocallback nofree nosync nounwind willreturn memory(none) } ; CHECK: attributes #36 = { nocallback nofree nosync nounwind willreturn } -; CHECK: attributes #37 = { argmemonly nounwind readonly } -; CHECK: attributes #38 = { argmemonly nounwind } -; CHECK: attributes #39 = { nounwind readonly } -; CHECK: attributes #40 = { inaccessiblemem_or_argmemonly nocallback nofree nosync nounwind willreturn } +; CHECK: attributes #37 = { nounwind memory(argmem: read) } +; CHECK: attributes #38 = { nounwind memory(argmem: readwrite) } +; CHECK: attributes #39 = { nounwind memory(read) } +; CHECK: attributes #40 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite, inaccessiblemem: readwrite) } ; CHECK: attributes #41 = { builtin } ;; Metadata Index: llvm/test/Bitcode/compatibility-3.9.ll =================================================================== --- llvm/test/Bitcode/compatibility-3.9.ll +++ llvm/test/Bitcode/compatibility-3.9.ll @@ -1609,8 +1609,8 @@ ; CHECK: attributes #16 = { nounwind } ; CHECK: attributes #17 = { noinline optnone } ; CHECK: attributes #18 = { optsize } -; CHECK: attributes #19 = { readnone } -; CHECK: attributes #20 = { readonly } +; CHECK: attributes #19 = { memory(none) } +; CHECK: attributes #20 = { memory(read) } ; CHECK: attributes #21 = { returns_twice } ; CHECK: attributes #22 = { safestack } ; CHECK: attributes #23 = { sanitize_address } @@ -1623,15 +1623,15 @@ ; CHECK: attributes #30 = { uwtable } ; CHECK: attributes #31 = { "cpu"="cortex-a8" } ; CHECK: attributes #32 = { norecurse } -; CHECK: attributes #33 = { inaccessiblememonly } -; CHECK: attributes #34 = { inaccessiblemem_or_argmemonly } -; CHECK: attributes #35 = { nocallback nofree nosync nounwind readnone willreturn } +; CHECK: attributes #33 = { memory(inaccessiblemem: readwrite) } +; CHECK: attributes #34 = { memory(argmem: readwrite, inaccessiblemem: readwrite) } +; CHECK: attributes #35 = { nocallback nofree nosync nounwind willreturn memory(none) } ; CHECK: attributes #36 = { nocallback nofree nosync nounwind willreturn } -; CHECK: attributes #37 = { argmemonly nounwind readonly } -; CHECK: attributes #38 = { argmemonly nounwind } -; CHECK: attributes #39 = { nounwind readonly } -; CHECK: attributes #40 = { writeonly } -; CHECK: attributes #41 = { inaccessiblemem_or_argmemonly nocallback nofree nosync nounwind willreturn } +; CHECK: attributes #37 = { nounwind memory(argmem: read) } +; CHECK: attributes #38 = { nounwind memory(argmem: readwrite) } +; CHECK: attributes #39 = { nounwind memory(read) } +; CHECK: attributes #40 = { memory(write) } +; CHECK: attributes #41 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite, inaccessiblemem: readwrite) } ; CHECK: attributes #42 = { builtin } ;; Metadata Index: llvm/test/Bitcode/compatibility-4.0.ll =================================================================== --- llvm/test/Bitcode/compatibility-4.0.ll +++ llvm/test/Bitcode/compatibility-4.0.ll @@ -1634,8 +1634,8 @@ ; CHECK: attributes #16 = { nounwind } ; CHECK: attributes #17 = { noinline optnone } ; CHECK: attributes #18 = { optsize } -; CHECK: attributes #19 = { readnone } -; CHECK: attributes #20 = { readonly } +; CHECK: attributes #19 = { memory(none) } +; CHECK: attributes #20 = { memory(read) } ; CHECK: attributes #21 = { returns_twice } ; CHECK: attributes #22 = { safestack } ; CHECK: attributes #23 = { sanitize_address } @@ -1648,15 +1648,15 @@ ; CHECK: attributes #30 = { uwtable } ; CHECK: attributes #31 = { "cpu"="cortex-a8" } ; CHECK: attributes #32 = { norecurse } -; CHECK: attributes #33 = { inaccessiblememonly } -; CHECK: attributes #34 = { inaccessiblemem_or_argmemonly } -; CHECK: attributes #35 = { nocallback nofree nosync nounwind readnone willreturn } +; CHECK: attributes #33 = { memory(inaccessiblemem: readwrite) } +; CHECK: attributes #34 = { memory(argmem: readwrite, inaccessiblemem: readwrite) } +; CHECK: attributes #35 = { nocallback nofree nosync nounwind willreturn memory(none) } ; CHECK: attributes #36 = { nocallback nofree nosync nounwind willreturn } -; CHECK: attributes #37 = { argmemonly nounwind readonly } -; CHECK: attributes #38 = { argmemonly nounwind } -; CHECK: attributes #39 = { nounwind readonly } -; CHECK: attributes #40 = { writeonly } -; CHECK: attributes #41 = { inaccessiblemem_or_argmemonly nocallback nofree nosync nounwind willreturn } +; CHECK: attributes #37 = { nounwind memory(argmem: read) } +; CHECK: attributes #38 = { nounwind memory(argmem: readwrite) } +; CHECK: attributes #39 = { nounwind memory(read) } +; CHECK: attributes #40 = { memory(write) } +; CHECK: attributes #41 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite, inaccessiblemem: readwrite) } ; CHECK: attributes #42 = { builtin } ;; Metadata Index: llvm/test/Bitcode/compatibility-5.0.ll =================================================================== --- llvm/test/Bitcode/compatibility-5.0.ll +++ llvm/test/Bitcode/compatibility-5.0.ll @@ -1649,8 +1649,8 @@ ; CHECK: attributes #16 = { nounwind } ; CHECK: attributes #17 = { noinline optnone } ; CHECK: attributes #18 = { optsize } -; CHECK: attributes #19 = { readnone } -; CHECK: attributes #20 = { readonly } +; CHECK: attributes #19 = { memory(none) } +; CHECK: attributes #20 = { memory(read) } ; CHECK: attributes #21 = { returns_twice } ; CHECK: attributes #22 = { safestack } ; CHECK: attributes #23 = { sanitize_address } @@ -1663,16 +1663,16 @@ ; CHECK: attributes #30 = { uwtable } ; CHECK: attributes #31 = { "cpu"="cortex-a8" } ; CHECK: attributes #32 = { norecurse } -; CHECK: attributes #33 = { inaccessiblememonly } -; CHECK: attributes #34 = { inaccessiblemem_or_argmemonly } -; CHECK: attributes #35 = { nocallback nofree nosync nounwind readnone willreturn } -; CHECK: attributes #36 = { nocallback nofree nosync nounwind willreturn } -; CHECK: attributes #37 = { argmemonly nounwind readonly } -; CHECK: attributes #38 = { argmemonly nounwind } -; CHECK: attributes #39 = { nounwind readonly } -; CHECK: attributes #40 = { writeonly } +; CHECK: attributes #33 = { memory(inaccessiblemem: readwrite) } +; CHECK: attributes #34 = { memory(argmem: readwrite, inaccessiblemem: readwrite) } +; CHECK: attributes #35 = { nocallback nofree nosync nounwind willreturn memory(none) } +; CHECK: attributes #36 = { nocallback nofree nosync nounwind willreturn } +; CHECK: attributes #37 = { nounwind memory(argmem: read) } +; CHECK: attributes #38 = { nounwind memory(argmem: readwrite) } +; CHECK: attributes #39 = { nounwind memory(read) } +; CHECK: attributes #40 = { memory(write) } ; CHECK: attributes #41 = { speculatable } -; CHECK: attributes #42 = { inaccessiblemem_or_argmemonly nocallback nofree nosync nounwind willreturn } +; CHECK: attributes #42 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite, inaccessiblemem: readwrite) } ; CHECK: attributes #43 = { builtin } ;; Metadata Index: llvm/test/Bitcode/compatibility-6.0.ll =================================================================== --- llvm/test/Bitcode/compatibility-6.0.ll +++ llvm/test/Bitcode/compatibility-6.0.ll @@ -1660,8 +1660,8 @@ ; CHECK: attributes #16 = { nounwind } ; CHECK: attributes #17 = { noinline optnone } ; CHECK: attributes #18 = { optsize } -; CHECK: attributes #19 = { readnone } -; CHECK: attributes #20 = { readonly } +; CHECK: attributes #19 = { memory(none) } +; CHECK: attributes #20 = { memory(read) } ; CHECK: attributes #21 = { returns_twice } ; CHECK: attributes #22 = { safestack } ; CHECK: attributes #23 = { sanitize_address } @@ -1674,16 +1674,16 @@ ; CHECK: attributes #30 = { uwtable } ; CHECK: attributes #31 = { "cpu"="cortex-a8" } ; CHECK: attributes #32 = { norecurse } -; CHECK: attributes #33 = { inaccessiblememonly } -; CHECK: attributes #34 = { inaccessiblemem_or_argmemonly } -; CHECK: attributes #35 = { nocallback nofree nosync nounwind readnone willreturn } +; CHECK: attributes #33 = { memory(inaccessiblemem: readwrite) } +; CHECK: attributes #34 = { memory(argmem: readwrite, inaccessiblemem: readwrite) } +; CHECK: attributes #35 = { nocallback nofree nosync nounwind willreturn memory(none) } ; CHECK: attributes #36 = { nocallback nofree nosync nounwind willreturn } -; CHECK: attributes #37 = { argmemonly nounwind readonly } -; CHECK: attributes #38 = { argmemonly nounwind } -; CHECK: attributes #39 = { nounwind readonly } -; CHECK: attributes #40 = { writeonly } +; CHECK: attributes #37 = { nounwind memory(argmem: read) } +; CHECK: attributes #38 = { nounwind memory(argmem: readwrite) } +; CHECK: attributes #39 = { nounwind memory(read) } +; CHECK: attributes #40 = { memory(write) } ; CHECK: attributes #41 = { speculatable } -; CHECK: attributes #42 = { inaccessiblemem_or_argmemonly nocallback nofree nosync nounwind willreturn } +; CHECK: attributes #42 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite, inaccessiblemem: readwrite) } ; CHECK: attributes #43 = { builtin } ;; Metadata Index: llvm/test/Bitcode/compatibility.ll =================================================================== --- llvm/test/Bitcode/compatibility.ll +++ llvm/test/Bitcode/compatibility.ll @@ -1985,8 +1985,8 @@ ; CHECK: attributes #16 = { nounwind } ; CHECK: attributes #17 = { noinline optnone } ; CHECK: attributes #18 = { optsize } -; CHECK: attributes #19 = { readnone } -; CHECK: attributes #20 = { readonly } +; CHECK: attributes #19 = { memory(none) } +; CHECK: attributes #20 = { memory(read) } ; CHECK: attributes #21 = { returns_twice } ; CHECK: attributes #22 = { safestack } ; CHECK: attributes #23 = { sanitize_address } @@ -1999,15 +1999,15 @@ ; CHECK: attributes #30 = { uwtable } ; CHECK: attributes #31 = { "cpu"="cortex-a8" } ; CHECK: attributes #32 = { norecurse } -; CHECK: attributes #33 = { inaccessiblememonly } -; CHECK: attributes #34 = { inaccessiblemem_or_argmemonly } -; CHECK: attributes #35 = { nocallback nofree nosync nounwind readnone willreturn } +; CHECK: attributes #33 = { memory(inaccessiblemem: readwrite) } +; CHECK: attributes #34 = { memory(argmem: readwrite, inaccessiblemem: readwrite) } +; CHECK: attributes #35 = { nocallback nofree nosync nounwind willreturn memory(none) } ; CHECK: attributes #36 = { nocallback nofree nosync nounwind willreturn } -; CHECK: attributes #37 = { argmemonly nounwind readonly } -; CHECK: attributes #38 = { argmemonly nounwind } -; CHECK: attributes #39 = { nounwind readonly } -; CHECK: attributes #40 = { inaccessiblemem_or_argmemonly nocallback nofree nosync nounwind willreturn } -; CHECK: attributes #41 = { writeonly } +; CHECK: attributes #37 = { nounwind memory(argmem: read) } +; CHECK: attributes #38 = { nounwind memory(argmem: readwrite) } +; CHECK: attributes #39 = { nounwind memory(read) } +; CHECK: attributes #40 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite, inaccessiblemem: readwrite) } +; CHECK: attributes #41 = { memory(write) } ; CHECK: attributes #42 = { speculatable } ; CHECK: attributes #43 = { strictfp } ; CHECK: attributes #44 = { nosanitize_coverage } Index: llvm/test/Bitcode/ptest-new.ll =================================================================== --- llvm/test/Bitcode/ptest-new.ll +++ llvm/test/Bitcode/ptest-new.ll @@ -23,4 +23,4 @@ declare i32 @llvm.x86.sse41.ptestnzc(<2 x i64>, <2 x i64>) nounwind readnone ; CHECK: attributes #0 = { nounwind } -; CHECK: attributes #1 = { nounwind readnone } +; CHECK: attributes #1 = { nounwind memory(none) } Index: llvm/test/Bitcode/ptest-old.ll =================================================================== --- llvm/test/Bitcode/ptest-old.ll +++ llvm/test/Bitcode/ptest-old.ll @@ -24,4 +24,4 @@ declare i32 @llvm.x86.sse41.ptestnzc(<4 x float>, <4 x float>) nounwind readnone ; CHECK: attributes #0 = { nounwind } -; CHECK: attributes #1 = { nounwind readnone } +; CHECK: attributes #1 = { nounwind memory(none) } Index: llvm/test/Bitcode/upgrade-frame-pointer.ll =================================================================== --- llvm/test/Bitcode/upgrade-frame-pointer.ll +++ llvm/test/Bitcode/upgrade-frame-pointer.ll @@ -27,7 +27,7 @@ ;; Other attributes (e.g. readnone) are unaffected. ; CHECK: attributes #0 = { "frame-pointer"="all" } -; CHECK: attributes #1 = { readnone "frame-pointer"="all" } +; CHECK: attributes #1 = { memory(none) "frame-pointer"="all" } ; CHECK: attributes #2 = { "frame-pointer"="non-leaf" } -; CHECK: attributes #3 = { readnone "frame-pointer"="non-leaf" } +; CHECK: attributes #3 = { memory(none) "frame-pointer"="non-leaf" } ; CHECK: attributes #4 = { "frame-pointer"="none" } Index: llvm/test/Bitcode/upgrade-invariant-group-barrier.ll =================================================================== --- llvm/test/Bitcode/upgrade-invariant-group-barrier.ll +++ llvm/test/Bitcode/upgrade-invariant-group-barrier.ll @@ -13,9 +13,9 @@ ret void } -; CHECK: Function Attrs: inaccessiblememonly nocallback nofree nosync nounwind speculatable willreturn +; CHECK: Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(inaccessiblemem: readwrite) ; CHECK: declare i8* @llvm.launder.invariant.group.p0i8(i8*) -; CHECK: Function Attrs: inaccessiblememonly nocallback nofree nosync nounwind speculatable willreturn +; CHECK: Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(inaccessiblemem: readwrite) ; CHECK: declare i16* @llvm.launder.invariant.group.p0i16(i16*) declare i8* @llvm.invariant.group.barrier(i8*) declare i8* @llvm.invariant.group.barrier.p0i8(i8*) Index: llvm/test/CodeGen/AMDGPU/addrspacecast-constantexpr.ll =================================================================== --- llvm/test/CodeGen/AMDGPU/addrspacecast-constantexpr.ll +++ llvm/test/CodeGen/AMDGPU/addrspacecast-constantexpr.ll @@ -226,10 +226,10 @@ attributes #0 = { argmemonly nounwind } attributes #1 = { nounwind } ;. -; AKF_HSA: attributes #[[ATTR0:[0-9]+]] = { argmemonly nocallback nofree nounwind willreturn } +; AKF_HSA: attributes #[[ATTR0:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: readwrite) } ; AKF_HSA: attributes #[[ATTR1]] = { nounwind } ;. -; ATTRIBUTOR_HSA: attributes #[[ATTR0:[0-9]+]] = { argmemonly nocallback nofree nounwind willreturn } +; ATTRIBUTOR_HSA: attributes #[[ATTR0:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: readwrite) } ; ATTRIBUTOR_HSA: attributes #[[ATTR1]] = { nounwind "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "uniform-work-group-size"="false" } ; ATTRIBUTOR_HSA: attributes #[[ATTR2]] = { nounwind "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "uniform-work-group-size"="false" } ;. Index: llvm/test/CodeGen/AMDGPU/annotate-kernel-features-hsa-call.ll =================================================================== --- llvm/test/CodeGen/AMDGPU/annotate-kernel-features-hsa-call.ll +++ llvm/test/CodeGen/AMDGPU/annotate-kernel-features-hsa-call.ll @@ -928,7 +928,7 @@ attributes #5 = { nounwind sanitize_address "amdgpu-no-implicitarg-ptr" } ;. -; AKF_HSA: attributes #[[ATTR0:[0-9]+]] = { nounwind readnone speculatable willreturn } +; AKF_HSA: attributes #[[ATTR0:[0-9]+]] = { nounwind speculatable willreturn memory(none) } ; AKF_HSA: attributes #[[ATTR1]] = { nounwind "target-cpu"="fiji" } ; AKF_HSA: attributes #[[ATTR2]] = { nounwind "target-cpu"="gfx900" } ; AKF_HSA: attributes #[[ATTR3]] = { nounwind } @@ -936,7 +936,7 @@ ; AKF_HSA: attributes #[[ATTR5]] = { nounwind sanitize_address } ; AKF_HSA: attributes #[[ATTR6:[0-9]+]] = { nounwind sanitize_address "amdgpu-no-implicitarg-ptr" } ;. -; ATTRIBUTOR_HSA: attributes #[[ATTR0:[0-9]+]] = { nounwind readnone speculatable willreturn } +; ATTRIBUTOR_HSA: attributes #[[ATTR0:[0-9]+]] = { nounwind speculatable willreturn memory(none) } ; ATTRIBUTOR_HSA: attributes #[[ATTR1]] = { nounwind "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "target-cpu"="fiji" "uniform-work-group-size"="false" } ; ATTRIBUTOR_HSA: attributes #[[ATTR2]] = { nounwind "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-z" "target-cpu"="fiji" "uniform-work-group-size"="false" } ; ATTRIBUTOR_HSA: attributes #[[ATTR3]] = { nounwind "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "target-cpu"="fiji" "uniform-work-group-size"="false" } Index: llvm/test/CodeGen/AMDGPU/annotate-kernel-features-hsa.ll =================================================================== --- llvm/test/CodeGen/AMDGPU/annotate-kernel-features-hsa.ll +++ llvm/test/CodeGen/AMDGPU/annotate-kernel-features-hsa.ll @@ -642,11 +642,11 @@ attributes #1 = { nounwind } ;. -; AKF_HSA: attributes #[[ATTR0:[0-9]+]] = { nounwind readnone speculatable willreturn } +; AKF_HSA: attributes #[[ATTR0:[0-9]+]] = { nounwind speculatable willreturn memory(none) } ; AKF_HSA: attributes #[[ATTR1]] = { nounwind } ; AKF_HSA: attributes #[[ATTR2]] = { nounwind "amdgpu-stack-objects" } ;. -; ATTRIBUTOR_HSA: attributes #[[ATTR0:[0-9]+]] = { nounwind readnone speculatable willreturn } +; ATTRIBUTOR_HSA: attributes #[[ATTR0:[0-9]+]] = { nounwind speculatable willreturn memory(none) } ; ATTRIBUTOR_HSA: attributes #[[ATTR1]] = { nounwind "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "uniform-work-group-size"="false" } ; ATTRIBUTOR_HSA: attributes #[[ATTR2]] = { nounwind "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "uniform-work-group-size"="false" } ; ATTRIBUTOR_HSA: attributes #[[ATTR3]] = { nounwind "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "uniform-work-group-size"="false" } Index: llvm/test/CodeGen/AMDGPU/annotate-kernel-features.ll =================================================================== --- llvm/test/CodeGen/AMDGPU/annotate-kernel-features.ll +++ llvm/test/CodeGen/AMDGPU/annotate-kernel-features.ll @@ -414,10 +414,10 @@ ; NOHSA: attributes #[[ATTR8]] = { nounwind "amdgpu-work-item-id-y" "amdgpu-work-item-id-z" "uniform-work-group-size"="false" } ; NOHSA: attributes #[[ATTR9]] = { nounwind "amdgpu-work-group-id-y" "amdgpu-work-group-id-z" "amdgpu-work-item-id-y" "amdgpu-work-item-id-z" "uniform-work-group-size"="false" } ;. -; AKF_CHECK: attributes #[[ATTR0:[0-9]+]] = { nounwind readnone speculatable willreturn } +; AKF_CHECK: attributes #[[ATTR0:[0-9]+]] = { nounwind speculatable willreturn memory(none) } ; AKF_CHECK: attributes #[[ATTR1]] = { nounwind } ;. -; ATTRIBUTOR_CHECK: attributes #[[ATTR0:[0-9]+]] = { nounwind readnone speculatable willreturn } +; ATTRIBUTOR_CHECK: attributes #[[ATTR0:[0-9]+]] = { nounwind speculatable willreturn memory(none) } ; ATTRIBUTOR_CHECK: attributes #[[ATTR1]] = { nounwind "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "uniform-work-group-size"="false" } ; ATTRIBUTOR_CHECK: attributes #[[ATTR2]] = { nounwind "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "uniform-work-group-size"="false" } ; ATTRIBUTOR_CHECK: attributes #[[ATTR3]] = { nounwind "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "uniform-work-group-size"="false" } Index: llvm/test/CodeGen/AMDGPU/inline-attr.ll =================================================================== --- llvm/test/CodeGen/AMDGPU/inline-attr.ll +++ llvm/test/CodeGen/AMDGPU/inline-attr.ll @@ -6,14 +6,14 @@ ; GCN: define amdgpu_kernel void @caller(float addrspace(1)* nocapture %p) local_unnamed_addr #1 { ; GCN: %mul.i = fmul float %load, 1.500000e+01 -; UNSAFE: attributes #0 = { mustprogress nofree norecurse nosync nounwind readnone willreturn "unsafe-fp-math"="true" } -; UNSAFE: attributes #1 = { argmemonly mustprogress nofree norecurse nosync nounwind willreturn "less-precise-fpmad"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "unsafe-fp-math"="true" } +; UNSAFE: attributes #0 = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) "unsafe-fp-math"="true" } +; UNSAFE: attributes #1 = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite) "less-precise-fpmad"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "unsafe-fp-math"="true" } -; NOINFS: attributes #0 = { mustprogress nofree norecurse nosync nounwind readnone willreturn "no-infs-fp-math"="true" } -; NOINFS: attributes #1 = { argmemonly mustprogress nofree norecurse nosync nounwind willreturn "less-precise-fpmad"="false" "no-infs-fp-math"="true" "no-nans-fp-math"="false" "unsafe-fp-math"="false" } +; NOINFS: attributes #0 = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) "no-infs-fp-math"="true" } +; NOINFS: attributes #1 = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite) "less-precise-fpmad"="false" "no-infs-fp-math"="true" "no-nans-fp-math"="false" "unsafe-fp-math"="false" } -; NONANS: attributes #0 = { mustprogress nofree norecurse nosync nounwind readnone willreturn "no-nans-fp-math"="true" } -; NONANS: attributes #1 = { argmemonly mustprogress nofree norecurse nosync nounwind willreturn "less-precise-fpmad"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="true" "unsafe-fp-math"="false" } +; NONANS: attributes #0 = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) "no-nans-fp-math"="true" } +; NONANS: attributes #1 = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite) "less-precise-fpmad"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="true" "unsafe-fp-math"="false" } define float @foo(float %x) #0 { entry: Index: llvm/test/CodeGen/AMDGPU/pal-simple-indirect-call.ll =================================================================== --- llvm/test/CodeGen/AMDGPU/pal-simple-indirect-call.ll +++ llvm/test/CodeGen/AMDGPU/pal-simple-indirect-call.ll @@ -69,8 +69,8 @@ attributes #0 = { nounwind readnone speculatable willreturn } ;. -; AKF_GCN: attributes #[[ATTR0:[0-9]+]] = { nounwind readnone speculatable willreturn } +; AKF_GCN: attributes #[[ATTR0:[0-9]+]] = { nounwind speculatable willreturn memory(none) } ;. ; ATTRIBUTOR_GCN: attributes #[[ATTR0]] = { "uniform-work-group-size"="false" } -; ATTRIBUTOR_GCN: attributes #[[ATTR1:[0-9]+]] = { nounwind readnone speculatable willreturn } +; ATTRIBUTOR_GCN: attributes #[[ATTR1:[0-9]+]] = { nounwind speculatable willreturn memory(none) } ;. Index: llvm/test/CodeGen/AMDGPU/simplify-libcalls.ll =================================================================== --- llvm/test/CodeGen/AMDGPU/simplify-libcalls.ll +++ llvm/test/CodeGen/AMDGPU/simplify-libcalls.ll @@ -791,5 +791,5 @@ ; GCN-PRELINK: declare float @_Z11native_sqrtf(float) local_unnamed_addr #[[$NOUNWIND_READONLY]] ; GCN-PRELINK: attributes #[[$NOUNWIND]] = { nounwind } -; GCN-PRELINK: attributes #[[$NOUNWIND_READONLY]] = { nofree nounwind readonly } +; GCN-PRELINK: attributes #[[$NOUNWIND_READONLY]] = { nofree nounwind memory(read) } attributes #0 = { nounwind } Index: llvm/test/CodeGen/AMDGPU/uniform-work-group-recursion-test.ll =================================================================== --- llvm/test/CodeGen/AMDGPU/uniform-work-group-recursion-test.ll +++ llvm/test/CodeGen/AMDGPU/uniform-work-group-recursion-test.ll @@ -101,7 +101,7 @@ attributes #0 = { nounwind readnone } attributes #1 = { "uniform-work-group-size"="true" } ;. -; CHECK: attributes #[[ATTR0]] = { nounwind readnone "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "uniform-work-group-size"="false" } -; CHECK: attributes #[[ATTR1]] = { nounwind readnone "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "uniform-work-group-size"="true" } +; CHECK: attributes #[[ATTR0]] = { nounwind memory(none) "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "uniform-work-group-size"="false" } +; CHECK: attributes #[[ATTR1]] = { nounwind memory(none) "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "uniform-work-group-size"="true" } ; CHECK: attributes #[[ATTR2]] = { "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "uniform-work-group-size"="true" } ;. Index: llvm/test/Feature/OperandBundles/function-attrs.ll =================================================================== --- llvm/test/Feature/OperandBundles/function-attrs.ll +++ llvm/test/Feature/OperandBundles/function-attrs.ll @@ -43,8 +43,8 @@ ret void } -; CHECK: attributes #0 = { nofree readonly } -; CHECK: attributes #1 = { nofree nosync readnone } -; CHECK: attributes #2 = { writeonly } +; CHECK: attributes #0 = { nofree memory(read) } +; CHECK: attributes #1 = { nofree nosync memory(none) } +; CHECK: attributes #2 = { memory(write) } ; CHECK: attributes #3 = { nofree } ; CHECK: attributes #4 = { nofree nosync } Index: llvm/test/Feature/intrinsics.ll =================================================================== --- llvm/test/Feature/intrinsics.ll +++ llvm/test/Feature/intrinsics.ll @@ -69,5 +69,5 @@ ret void } -; CHECK: attributes #0 = { nocallback nofree nosync nounwind readnone speculatable willreturn } +; CHECK: attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) } ; CHECK: attributes #1 = { cold noreturn nounwind } Index: llvm/test/Instrumentation/DataFlowSanitizer/basic.ll =================================================================== --- llvm/test/Instrumentation/DataFlowSanitizer/basic.ll +++ llvm/test/Instrumentation/DataFlowSanitizer/basic.ll @@ -35,10 +35,10 @@ ; CHECK: declare void @__dfsan_mem_transfer_callback(i[[#SBITS]]*, i64) ; CHECK: declare void @__dfsan_cmp_callback(i[[#SBITS]]) -; CHECK: ; Function Attrs: nounwind readonly +; CHECK: ; Function Attrs: nounwind memory(read) ; CHECK-NEXT: declare zeroext i[[#SBITS]] @__dfsan_union_load(i[[#SBITS]]*, i64) -; CHECK: ; Function Attrs: nounwind readonly +; CHECK: ; Function Attrs: nounwind memory(read) ; CHECK-NEXT: declare zeroext i64 @__dfsan_load_label_and_origin(i8*, i64) ; CHECK: declare void @__dfsan_unimplemented(i8*) Index: llvm/test/Instrumentation/MemorySanitizer/attributes.ll =================================================================== --- llvm/test/Instrumentation/MemorySanitizer/attributes.ll +++ llvm/test/Instrumentation/MemorySanitizer/attributes.ll @@ -44,11 +44,8 @@ ret void } -; CHECK-NOT: readnone -; CHECK-NOT: readonly -; CHECK-NOT: writeonly -; CHECK-NOT: argmemonly +; CHECK-NOT: memory( ; CHECK-NOT: speculatable -; CHECK: Function Attrs: nocallback nofree nosync nounwind readnone willreturn +; CHECK: Function Attrs: nocallback nofree nosync nounwind willreturn memory(none) ; CHECK-NEXT: declare void @llvm.donothing Index: llvm/test/Other/attribute-comment.ll =================================================================== --- llvm/test/Other/attribute-comment.ll +++ llvm/test/Other/attribute-comment.ll @@ -1,6 +1,6 @@ ; RUN: opt -S < %s | FileCheck %s -strict-whitespace -; CHECK: {{^}}; Function Attrs: nounwind readnone ssp uwtable{{$}} +; CHECK: {{^}}; Function Attrs: nounwind ssp memory(none) uwtable{{$}} ; CHECK-NEXT: define void @test1() #0 define void @test1() #0 { ret void Index: llvm/test/Other/cgscc-devirt-iteration.ll =================================================================== --- llvm/test/Other/cgscc-devirt-iteration.ll +++ llvm/test/Other/cgscc-devirt-iteration.ll @@ -15,7 +15,7 @@ ; RUN: opt -aa-pipeline=basic-aa -passes='default' -S < %s | FileCheck %s --check-prefix=CHECK --check-prefix=AFTER --check-prefix=AFTER2 declare void @readnone() readnone -; CHECK: Function Attrs: nofree nosync readnone +; CHECK: Function Attrs: nofree nosync memory(none) ; CHECK-NEXT: declare void @readnone() declare void @unknown() @@ -28,7 +28,7 @@ define void @test1() { ; BEFORE-NOT: Function Attrs -; AFTER: Function Attrs: nofree nosync readnone +; AFTER: Function Attrs: nofree nosync memory(none) ; CHECK-LABEL: define void @test1() entry: %fptr = alloca void ()* @@ -51,13 +51,13 @@ ; devirtualize again, and then deduce readnone. declare void @readnone_with_arg(void ()**) readnone -; CHECK: Function Attrs: nofree nosync readnone +; CHECK: Function Attrs: nofree nosync memory(none) ; CHECK-LABEL: declare void @readnone_with_arg(void ()**) define void @test2_a(void ()** %ignore) { ; BEFORE-NOT: Function Attrs -; AFTER1: Function Attrs: nofree readonly -; AFTER2: Function Attrs: nofree nosync readnone +; AFTER1: Function Attrs: nofree memory(read) +; AFTER2: Function Attrs: nofree nosync memory(none) ; BEFORE: define void @test2_a(void ()** %ignore) ; AFTER: define void @test2_a(void ()** readnone %ignore) entry: @@ -77,8 +77,8 @@ define void @test2_b() { ; BEFORE-NOT: Function Attrs -; AFTER1: Function Attrs: nofree readonly -; AFTER2: Function Attrs: nofree nosync readnone +; AFTER1: Function Attrs: nofree memory(read) +; AFTER2: Function Attrs: nofree nosync memory(none) ; CHECK-LABEL: define void @test2_b() entry: %f2ptr = alloca void ()* Index: llvm/test/Other/cgscc-iterate-function-mutation.ll =================================================================== --- llvm/test/Other/cgscc-iterate-function-mutation.ll +++ llvm/test/Other/cgscc-iterate-function-mutation.ll @@ -338,4 +338,4 @@ ret void } -; CHECK: attributes #0 = { nofree nosync readnone } +; CHECK: attributes #0 = { nofree nosync memory(none) } Index: llvm/test/Other/invariant.group.ll =================================================================== --- llvm/test/Other/invariant.group.ll +++ llvm/test/Other/invariant.group.ll @@ -91,11 +91,11 @@ declare void @useBool(i1) declare void @clobber(i8*) -; CHECK: Function Attrs: inaccessiblememonly nocallback nofree nosync nounwind speculatable willreturn{{$}} +; CHECK: Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(inaccessiblemem: readwrite){{$}} ; CHECK-NEXT: declare i8* @llvm.launder.invariant.group.p0i8(i8*) declare i8* @llvm.launder.invariant.group.p0i8(i8*) -; CHECK: Function Attrs: nocallback nofree nosync nounwind readnone speculatable willreturn{{$}} +; CHECK: Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none){{$}} ; CHECK-NEXT: declare i8* @llvm.strip.invariant.group.p0i8(i8*) declare i8* @llvm.strip.invariant.group.p0i8(i8*) Index: llvm/test/Other/opt-override-mcpu-mattr.ll =================================================================== --- llvm/test/Other/opt-override-mcpu-mattr.ll +++ llvm/test/Other/opt-override-mcpu-mattr.ll @@ -4,8 +4,8 @@ ; target-cpu and target-features using command line options -mcpu and ; -mattr. -; CHECK: attributes #0 = { nounwind readnone ssp uwtable "target-cpu"="broadwell" "target-features"="+ssse3,+cx16,+sse,+sse2,+sse3,+avx2" "use-soft-float"="false" } -; CHECK: attributes #1 = { nounwind readnone ssp uwtable "target-cpu"="core2" "target-features"="+ssse3,+cx16,+sse,+sse2,+sse3,+avx2" "use-soft-float"="false" } +; CHECK: attributes #0 = { nounwind ssp memory(none) uwtable "target-cpu"="broadwell" "target-features"="+ssse3,+cx16,+sse,+sse2,+sse3,+avx2" "use-soft-float"="false" } +; CHECK: attributes #1 = { nounwind ssp memory(none) uwtable "target-cpu"="core2" "target-features"="+ssse3,+cx16,+sse,+sse2,+sse3,+avx2" "use-soft-float"="false" } define i32 @no_target_cpu() #0 { entry: Index: llvm/test/Other/print-module-scope.ll =================================================================== --- llvm/test/Other/print-module-scope.ll +++ llvm/test/Other/print-module-scope.ll @@ -30,7 +30,7 @@ ; FOO: define void @foo ; FOO: Function Attrs: nounwind ; FOO: define void @bar -; FOO: Function Attrs: nounwind readnone ssp +; FOO: Function Attrs: nounwind ssp memory(none) ; FOO: declare void @baz define void @foo() nounwind ssp { @@ -49,6 +49,6 @@ attributes #1 = { nounwind readnone ssp "use-soft-float"="false" } ; FOO: attributes #{{[0-9]}} = { nounwind "frame-pointer"="all" } -; FOO: attributes #{{[0-9]}} = { nounwind readnone ssp "use-soft-float"="false" } +; FOO: attributes #{{[0-9]}} = { nounwind ssp memory(none) "use-soft-float"="false" } ; FOO-NOT: IR Dump After {{Simplify the CFG|SimplifyCFGPass}} Index: llvm/test/Transforms/Coroutines/coro-readnone-02.ll =================================================================== --- llvm/test/Transforms/Coroutines/coro-readnone-02.ll +++ llvm/test/Transforms/Coroutines/coro-readnone-02.ll @@ -50,7 +50,7 @@ ; CHECK_SPLITTED-NEXT: call void @nop() ; CHECK_SPLITTED-NEXT: call void @print_same() ; -; CHECK_SPLITTED: attributes #[[ATTR_NUM]] = { readnone } +; CHECK_SPLITTED: attributes #[[ATTR_NUM]] = { memory(none) } ; ; CHECK_UNSPLITTED-LABEL: @f( ; CHECK_UNSPLITTED: br i1 %cmp, label %same, label %diff Index: llvm/test/Transforms/DeadArgElim/2010-04-30-DbgInfo.ll =================================================================== --- llvm/test/Transforms/DeadArgElim/2010-04-30-DbgInfo.ll +++ llvm/test/Transforms/DeadArgElim/2010-04-30-DbgInfo.ll @@ -45,7 +45,7 @@ declare void @llvm.dbg.value(metadata, metadata, metadata) nounwind readnone ; CHECK: attributes #0 = { nounwind ssp } -; CHECK: attributes #1 = { nocallback nofree nosync nounwind readnone speculatable willreturn } +; CHECK: attributes #1 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) } ; CHECK: attributes #2 = { noinline nounwind ssp } ; CHECK: attributes [[NUW]] = { nounwind } Index: llvm/test/Transforms/FunctionAttrs/2008-09-03-Mutual.ll =================================================================== --- llvm/test/Transforms/FunctionAttrs/2008-09-03-Mutual.ll +++ llvm/test/Transforms/FunctionAttrs/2008-09-03-Mutual.ll @@ -2,7 +2,7 @@ ; RUN: opt < %s -passes=function-attrs -S | FileCheck %s define i32 @a() { -; CHECK: Function Attrs: nofree nosync nounwind readnone +; CHECK: Function Attrs: nofree nosync nounwind memory(none) ; CHECK-LABEL: define {{[^@]+}}@a ; CHECK-SAME: () #[[ATTR0:[0-9]+]] { ; CHECK-NEXT: [[TMP:%.*]] = call i32 @b() @@ -13,7 +13,7 @@ } define i32 @b() { -; CHECK: Function Attrs: nofree nosync nounwind readnone +; CHECK: Function Attrs: nofree nosync nounwind memory(none) ; CHECK-LABEL: define {{[^@]+}}@b ; CHECK-SAME: () #[[ATTR0]] { ; CHECK-NEXT: [[TMP:%.*]] = call i32 @a() Index: llvm/test/Transforms/FunctionAttrs/2008-09-03-ReadNone.ll =================================================================== --- llvm/test/Transforms/FunctionAttrs/2008-09-03-ReadNone.ll +++ llvm/test/Transforms/FunctionAttrs/2008-09-03-ReadNone.ll @@ -6,7 +6,7 @@ declare i32 @e() readnone define i32 @f() { -; CHECK: Function Attrs: nofree nosync readnone +; CHECK: Function Attrs: nofree nosync memory(none) ; CHECK-LABEL: @f( ; CHECK-NEXT: [[TMP:%.*]] = call i32 @e() ; CHECK-NEXT: ret i32 [[TMP]] @@ -16,7 +16,7 @@ } define i32 @g() readonly { -; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind readnone willreturn +; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: @g( ; CHECK-NEXT: ret i32 0 ; @@ -24,7 +24,7 @@ } define i32 @h() readnone { -; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind readnone willreturn +; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: @h( ; CHECK-NEXT: [[TMP:%.*]] = load i32, ptr @x, align 4 ; CHECK-NEXT: ret i32 [[TMP]] Index: llvm/test/Transforms/FunctionAttrs/2008-09-03-ReadOnly.ll =================================================================== --- llvm/test/Transforms/FunctionAttrs/2008-09-03-ReadOnly.ll +++ llvm/test/Transforms/FunctionAttrs/2008-09-03-ReadOnly.ll @@ -2,7 +2,7 @@ ; RUN: opt < %s -passes=function-attrs -S | FileCheck %s define i32 @f() { -; CHECK: Function Attrs: nofree readonly +; CHECK: Function Attrs: nofree memory(read) ; CHECK-LABEL: @f( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[TMP:%.*]] = call i32 @e() Index: llvm/test/Transforms/FunctionAttrs/2008-12-29-Constant.ll =================================================================== --- llvm/test/Transforms/FunctionAttrs/2008-12-29-Constant.ll +++ llvm/test/Transforms/FunctionAttrs/2008-12-29-Constant.ll @@ -4,7 +4,7 @@ @s = external constant i8 define i8 @f() { -; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind readnone willreturn +; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: @f( ; CHECK-NEXT: [[TMP:%.*]] = load i8, ptr @s, align 1 ; CHECK-NEXT: ret i8 [[TMP]] Index: llvm/test/Transforms/FunctionAttrs/argmemonly.ll =================================================================== --- llvm/test/Transforms/FunctionAttrs/argmemonly.ll +++ llvm/test/Transforms/FunctionAttrs/argmemonly.ll @@ -4,7 +4,7 @@ @g = global i32 20 define void @test_no_read_or_write() { -; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind readnone willreturn +; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: @test_no_read_or_write( ; CHECK-NEXT: entry: ; CHECK-NEXT: ret void @@ -14,7 +14,7 @@ } define i32 @test_only_read_arg(ptr %ptr) { -; CHECK: Function Attrs: argmemonly mustprogress nofree norecurse nosync nounwind readonly willreturn +; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read) ; CHECK-LABEL: @test_only_read_arg( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[L:%.*]] = load i32, ptr [[PTR:%.*]], align 4 @@ -26,7 +26,7 @@ } define i32 @test_only_read_arg_already_has_argmemonly(ptr %ptr) argmemonly { -; CHECK: Function Attrs: argmemonly mustprogress nofree norecurse nosync nounwind readonly willreturn +; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read) ; CHECK-LABEL: @test_only_read_arg_already_has_argmemonly( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[L:%.*]] = load i32, ptr [[PTR:%.*]], align 4 @@ -38,7 +38,7 @@ } define i32 @test_read_global() { -; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind readonly willreturn +; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(read, argmem: none, inaccessiblemem: none) ; CHECK-LABEL: @test_read_global( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[L:%.*]] = load i32, ptr @g, align 4 @@ -50,7 +50,7 @@ } define i32 @test_read_loaded_ptr(ptr %ptr) { -; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind readonly willreturn +; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(read, inaccessiblemem: none) ; CHECK-LABEL: @test_read_loaded_ptr( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[L:%.*]] = load ptr, ptr [[PTR:%.*]], align 8 @@ -64,7 +64,7 @@ } define void @test_only_write_arg(ptr %ptr) { -; CHECK: Function Attrs: argmemonly mustprogress nofree norecurse nosync nounwind willreturn writeonly +; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write) ; CHECK-LABEL: @test_only_write_arg( ; CHECK-NEXT: entry: ; CHECK-NEXT: store i32 0, ptr [[PTR:%.*]], align 4 @@ -76,7 +76,7 @@ } define void @test_write_global() { -; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn writeonly +; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write, argmem: none, inaccessiblemem: none) ; CHECK-LABEL: @test_write_global( ; CHECK-NEXT: entry: ; CHECK-NEXT: store i32 0, ptr @g, align 4 @@ -103,7 +103,7 @@ declare i32 @fn_readnone() readnone define void @test_call_readnone(ptr %ptr) { -; CHECK: Function Attrs: argmemonly writeonly +; CHECK: Function Attrs: memory(argmem: write) ; CHECK-LABEL: @test_call_readnone( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[C:%.*]] = call i32 @fn_readnone() @@ -119,7 +119,7 @@ declare i32 @fn_argmemonly(ptr) argmemonly define i32 @test_call_argmemonly(ptr %ptr) { -; CHECK: Function Attrs: argmemonly +; CHECK: Function Attrs: memory(argmem: readwrite) ; CHECK-LABEL: @test_call_argmemonly( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[C:%.*]] = call i32 @fn_argmemonly(ptr [[PTR:%.*]]) @@ -131,7 +131,7 @@ } define i32 @test_call_fn_where_argmemonly_can_be_inferred(ptr %ptr) { -; CHECK: Function Attrs: argmemonly mustprogress nofree norecurse nosync nounwind readonly willreturn +; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read) ; CHECK-LABEL: @test_call_fn_where_argmemonly_can_be_inferred( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[C:%.*]] = call i32 @test_only_read_arg(ptr [[PTR:%.*]]) @@ -143,7 +143,7 @@ } define void @test_memcpy_argonly(ptr %dst, ptr %src) { -; CHECK: Function Attrs: argmemonly mustprogress nofree nosync nounwind willreturn +; CHECK: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(argmem: readwrite) ; CHECK-LABEL: @test_memcpy_argonly( ; CHECK-NEXT: entry: ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr [[DST:%.*]], ptr [[SRC:%.*]], i64 32, i1 false) @@ -159,7 +159,7 @@ @arr = global [32 x i8] zeroinitializer define void @test_memcpy_src_global(ptr %dst) { -; CHECK: Function Attrs: mustprogress nofree nosync nounwind willreturn +; CHECK: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(readwrite, inaccessiblemem: none) ; CHECK-LABEL: @test_memcpy_src_global( ; CHECK-NEXT: entry: ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr [[DST:%.*]], ptr @arr, i64 32, i1 false) @@ -171,7 +171,7 @@ } define void @test_memcpy_dst_global(ptr %src) { -; CHECK: Function Attrs: mustprogress nofree nosync nounwind willreturn +; CHECK: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(readwrite, inaccessiblemem: none) ; CHECK-LABEL: @test_memcpy_dst_global( ; CHECK-NEXT: entry: ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr @arr, ptr [[SRC:%.*]], i64 32, i1 false) @@ -183,7 +183,7 @@ } define i32 @test_read_arg_access_alloca(ptr %ptr) { -; CHECK: Function Attrs: argmemonly mustprogress nofree norecurse nosync nounwind readonly willreturn +; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read) ; CHECK-LABEL: @test_read_arg_access_alloca( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 @@ -203,7 +203,7 @@ declare void @fn_inaccessiblememonly() inaccessiblememonly define void @test_inaccessiblememonly() { -; CHECK: Function Attrs: inaccessiblememonly +; CHECK: Function Attrs: memory(inaccessiblemem: readwrite) ; CHECK-LABEL: @test_inaccessiblememonly( ; CHECK-NEXT: call void @fn_inaccessiblememonly() ; CHECK-NEXT: ret void @@ -213,9 +213,9 @@ } define void @test_inaccessiblememonly_readonly() { -; CHECK: Function Attrs: inaccessiblememonly nofree readonly +; CHECK: Function Attrs: nofree memory(inaccessiblemem: read) ; CHECK-LABEL: @test_inaccessiblememonly_readonly( -; CHECK-NEXT: call void @fn_inaccessiblememonly() #[[ATTR15:[0-9]+]] +; CHECK-NEXT: call void @fn_inaccessiblememonly() #[[ATTR16:[0-9]+]] ; CHECK-NEXT: ret void ; call void @fn_inaccessiblememonly() readonly @@ -223,10 +223,10 @@ } define void @test_inaccessibleorargmemonly_readonly(ptr %arg) { -; CHECK: Function Attrs: inaccessiblemem_or_argmemonly nofree readonly +; CHECK: Function Attrs: nofree memory(argmem: read, inaccessiblemem: read) ; CHECK-LABEL: @test_inaccessibleorargmemonly_readonly( ; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[ARG:%.*]], align 4 -; CHECK-NEXT: call void @fn_inaccessiblememonly() #[[ATTR15]] +; CHECK-NEXT: call void @fn_inaccessiblememonly() #[[ATTR16]] ; CHECK-NEXT: ret void ; load i32, ptr %arg @@ -235,10 +235,10 @@ } define void @test_inaccessibleorargmemonly_readwrite(ptr %arg) { -; CHECK: Function Attrs: inaccessiblemem_or_argmemonly +; CHECK: Function Attrs: memory(argmem: write, inaccessiblemem: read) ; CHECK-LABEL: @test_inaccessibleorargmemonly_readwrite( ; CHECK-NEXT: store i32 0, ptr [[ARG:%.*]], align 4 -; CHECK-NEXT: call void @fn_inaccessiblememonly() #[[ATTR15]] +; CHECK-NEXT: call void @fn_inaccessiblememonly() #[[ATTR16]] ; CHECK-NEXT: ret void ; store i32 0, ptr %arg Index: llvm/test/Transforms/FunctionAttrs/atomic.ll =================================================================== --- llvm/test/Transforms/FunctionAttrs/atomic.ll +++ llvm/test/Transforms/FunctionAttrs/atomic.ll @@ -4,7 +4,7 @@ ; Atomic load/store to local doesn't affect whether a function is ; readnone/readonly. define i32 @test1(i32 %x) uwtable ssp { -; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind readnone ssp willreturn uwtable +; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind ssp willreturn memory(none) uwtable ; CHECK-LABEL: @test1( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[X_ADDR:%.*]] = alloca i32, align 4 @@ -21,7 +21,7 @@ ; A function with an Acquire load is not readonly. define i32 @test2(ptr %x) uwtable ssp { -; CHECK: Function Attrs: argmemonly mustprogress nofree norecurse nounwind ssp willreturn uwtable +; CHECK: Function Attrs: mustprogress nofree norecurse nounwind ssp willreturn memory(argmem: readwrite) uwtable ; CHECK-LABEL: @test2( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[R:%.*]] = load atomic i32, ptr [[X:%.*]] seq_cst, align 4 Index: llvm/test/Transforms/FunctionAttrs/convergent.ll =================================================================== --- llvm/test/Transforms/FunctionAttrs/convergent.ll +++ llvm/test/Transforms/FunctionAttrs/convergent.ll @@ -2,7 +2,7 @@ ; RUN: opt -passes=function-attrs -S < %s | FileCheck %s define i32 @nonleaf() convergent { -; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind readnone willreturn +; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define {{[^@]+}}@nonleaf ; CHECK-SAME: () #[[ATTR0:[0-9]+]] { ; CHECK-NEXT: [[A:%.*]] = call i32 @leaf() @@ -13,7 +13,7 @@ } define i32 @leaf() convergent { -; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind readnone willreturn +; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define {{[^@]+}}@leaf ; CHECK-SAME: () #[[ATTR0]] { ; CHECK-NEXT: ret i32 0 @@ -85,7 +85,7 @@ } define i32 @recursive1() convergent { -; CHECK: Function Attrs: nofree nosync nounwind readnone +; CHECK: Function Attrs: nofree nosync nounwind memory(none) ; CHECK-LABEL: define {{[^@]+}}@recursive1 ; CHECK-SAME: () #[[ATTR5:[0-9]+]] { ; CHECK-NEXT: [[A:%.*]] = call i32 @recursive2() #[[ATTR1]] @@ -96,7 +96,7 @@ } define i32 @recursive2() convergent { -; CHECK: Function Attrs: nofree nosync nounwind readnone +; CHECK: Function Attrs: nofree nosync nounwind memory(none) ; CHECK-LABEL: define {{[^@]+}}@recursive2 ; CHECK-SAME: () #[[ATTR5]] { ; CHECK-NEXT: [[A:%.*]] = call i32 @recursive1() #[[ATTR1]] Index: llvm/test/Transforms/FunctionAttrs/incompatible_fn_attrs.ll =================================================================== --- llvm/test/Transforms/FunctionAttrs/incompatible_fn_attrs.ll +++ llvm/test/Transforms/FunctionAttrs/incompatible_fn_attrs.ll @@ -5,7 +5,7 @@ ; function attributes when we derive readnone. define ptr @given_argmem_infer_readnone(ptr %p) #0 { -; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind readnone willreturn +; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: @given_argmem_infer_readnone( ; CHECK-NEXT: entry: ; CHECK-NEXT: ret ptr [[P:%.*]] @@ -15,7 +15,7 @@ } define ptr @given_inaccessible_infer_readnone(ptr %p) #1 { -; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind readnone willreturn +; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: @given_inaccessible_infer_readnone( ; CHECK-NEXT: entry: ; CHECK-NEXT: ret ptr [[P:%.*]] @@ -25,7 +25,7 @@ } define ptr @given_inaccessible_or_argmem_infer_readnone(ptr %p) #2 { -; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind readnone willreturn +; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: @given_inaccessible_or_argmem_infer_readnone( ; CHECK-NEXT: entry: ; CHECK-NEXT: ret ptr [[P:%.*]] Index: llvm/test/Transforms/FunctionAttrs/int_sideeffect.ll =================================================================== --- llvm/test/Transforms/FunctionAttrs/int_sideeffect.ll +++ llvm/test/Transforms/FunctionAttrs/int_sideeffect.ll @@ -7,7 +7,7 @@ ; is present. define void @test() { -; CHECK: Function Attrs: inaccessiblememonly mustprogress nofree nosync nounwind willreturn +; CHECK: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(inaccessiblemem: readwrite) ; CHECK-LABEL: @test( ; CHECK-NEXT: call void @llvm.sideeffect() ; CHECK-NEXT: ret void @@ -17,7 +17,7 @@ } define void @loop() { -; CHECK: Function Attrs: inaccessiblememonly nofree noreturn nosync nounwind +; CHECK: Function Attrs: nofree noreturn nosync nounwind memory(inaccessiblemem: readwrite) ; CHECK-LABEL: @loop( ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: Index: llvm/test/Transforms/FunctionAttrs/nofree-attributor.ll =================================================================== --- llvm/test/Transforms/FunctionAttrs/nofree-attributor.ll +++ llvm/test/Transforms/FunctionAttrs/nofree-attributor.ll @@ -14,7 +14,7 @@ ; TEST 1 (positive case) define void @only_return() #0 { -; FNATTR: Function Attrs: mustprogress nofree noinline norecurse nosync nounwind readnone willreturn uwtable +; FNATTR: Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(none) uwtable ; FNATTR-LABEL: define {{[^@]+}}@only_return ; FNATTR-SAME: () #[[ATTR3:[0-9]+]] { ; FNATTR-NEXT: ret void @@ -101,7 +101,7 @@ define void @mutual_recursion1() #0 { -; FNATTR: Function Attrs: nofree noinline nosync nounwind readnone uwtable +; FNATTR: Function Attrs: nofree noinline nosync nounwind memory(none) uwtable ; FNATTR-LABEL: define {{[^@]+}}@mutual_recursion1 ; FNATTR-SAME: () #[[ATTR4:[0-9]+]] { ; FNATTR-NEXT: call void @mutual_recursion2() @@ -112,7 +112,7 @@ } define void @mutual_recursion2() #0 { -; FNATTR: Function Attrs: nofree noinline nosync nounwind readnone uwtable +; FNATTR: Function Attrs: nofree noinline nosync nounwind memory(none) uwtable ; FNATTR-LABEL: define {{[^@]+}}@mutual_recursion2 ; FNATTR-SAME: () #[[ATTR4]] { ; FNATTR-NEXT: call void @mutual_recursion1() @@ -174,7 +174,7 @@ declare void @nofree_function() nofree readnone #0 define void @call_nofree_function() #0 { -; FNATTR: Function Attrs: nofree noinline nosync nounwind readnone uwtable +; FNATTR: Function Attrs: nofree noinline nosync nounwind memory(none) uwtable ; FNATTR-LABEL: define {{[^@]+}}@call_nofree_function ; FNATTR-SAME: () #[[ATTR4]] { ; FNATTR-NEXT: tail call void @nofree_function() @@ -225,7 +225,7 @@ declare float @llvm.floor.f32(float) define void @call_floor(float %a) #0 { -; FNATTR: Function Attrs: mustprogress nofree noinline nosync nounwind readnone willreturn uwtable +; FNATTR: Function Attrs: mustprogress nofree noinline nosync nounwind willreturn memory(none) uwtable ; FNATTR-LABEL: define {{[^@]+}}@call_floor ; FNATTR-SAME: (float [[A:%.*]]) #[[ATTR7:[0-9]+]] { ; FNATTR-NEXT: [[TMP1:%.*]] = tail call float @llvm.floor.f32(float [[A]]) @@ -239,7 +239,7 @@ ; Check propagation. define void @f1() #0 { -; FNATTR: Function Attrs: nofree noinline nosync nounwind readnone uwtable +; FNATTR: Function Attrs: nofree noinline nosync nounwind memory(none) uwtable ; FNATTR-LABEL: define {{[^@]+}}@f1 ; FNATTR-SAME: () #[[ATTR4]] { ; FNATTR-NEXT: tail call void @nofree_function() @@ -250,7 +250,7 @@ } define void @f2() #0 { -; FNATTR: Function Attrs: nofree noinline nosync nounwind readnone uwtable +; FNATTR: Function Attrs: nofree noinline nosync nounwind memory(none) uwtable ; FNATTR-LABEL: define {{[^@]+}}@f2 ; FNATTR-SAME: () #[[ATTR4]] { ; FNATTR-NEXT: tail call void @f1() Index: llvm/test/Transforms/FunctionAttrs/nofree.ll =================================================================== --- llvm/test/Transforms/FunctionAttrs/nofree.ll +++ llvm/test/Transforms/FunctionAttrs/nofree.ll @@ -34,7 +34,7 @@ declare void @free(ptr nocapture) local_unnamed_addr #2 define i32 @_Z4foo3Pi(ptr nocapture readonly %a) local_unnamed_addr #3 { -; CHECK: Function Attrs: argmemonly mustprogress nofree norecurse nosync nounwind readonly willreturn uwtable +; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read) uwtable ; CHECK-LABEL: @_Z4foo3Pi( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A:%.*]], align 4 @@ -81,8 +81,8 @@ ; CHECK: Function Attrs: nounwind uwtable ; CHECK-LABEL: @_Z4foo6Pm( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[TMP1:%.*]] = load i64, ptr [[A:%.*]], align 8 -; CHECK-NEXT: [[CALL:%.*]] = tail call ptr @realloc(ptr [[A]], i64 [[TMP1]]) #[[ATTR2]] +; CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr [[A:%.*]], align 8 +; CHECK-NEXT: [[CALL:%.*]] = tail call ptr @realloc(ptr [[A]], i64 [[TMP0]]) #[[ATTR2]] ; CHECK-NEXT: ret ptr [[CALL]] ; entry: Index: llvm/test/Transforms/FunctionAttrs/norecurse.ll =================================================================== --- llvm/test/Transforms/FunctionAttrs/norecurse.ll +++ llvm/test/Transforms/FunctionAttrs/norecurse.ll @@ -2,7 +2,7 @@ ; RUN: opt < %s -aa-pipeline=basic-aa -passes='cgscc(function-attrs),rpo-function-attrs' -S | FileCheck %s define i32 @leaf() { -; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind readnone willreturn +; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define {{[^@]+}}@leaf ; CHECK-SAME: () #[[ATTR0:[0-9]+]] { ; CHECK-NEXT: ret i32 1 @@ -11,7 +11,7 @@ } define i32 @self_rec() { -; CHECK: Function Attrs: nofree nosync nounwind readnone +; CHECK: Function Attrs: nofree nosync nounwind memory(none) ; CHECK-LABEL: define {{[^@]+}}@self_rec ; CHECK-SAME: () #[[ATTR1:[0-9]+]] { ; CHECK-NEXT: [[A:%.*]] = call i32 @self_rec() @@ -22,7 +22,7 @@ } define i32 @indirect_rec() { -; CHECK: Function Attrs: nofree nosync nounwind readnone +; CHECK: Function Attrs: nofree nosync nounwind memory(none) ; CHECK-LABEL: define {{[^@]+}}@indirect_rec ; CHECK-SAME: () #[[ATTR1]] { ; CHECK-NEXT: [[A:%.*]] = call i32 @indirect_rec2() @@ -33,7 +33,7 @@ } define i32 @indirect_rec2() { -; CHECK: Function Attrs: nofree nosync nounwind readnone +; CHECK: Function Attrs: nofree nosync nounwind memory(none) ; CHECK-LABEL: define {{[^@]+}}@indirect_rec2 ; CHECK-SAME: () #[[ATTR1]] { ; CHECK-NEXT: [[A:%.*]] = call i32 @indirect_rec() @@ -44,7 +44,7 @@ } define i32 @extern() { -; CHECK: Function Attrs: nofree nosync readnone +; CHECK: Function Attrs: nofree nosync memory(none) ; CHECK-LABEL: define {{[^@]+}}@extern ; CHECK-SAME: () #[[ATTR2:[0-9]+]] { ; CHECK-NEXT: [[A:%.*]] = call i32 @k() @@ -57,7 +57,7 @@ declare i32 @k() readnone define void @intrinsic(ptr %dest, ptr %src, i32 %len) { -; CHECK: Function Attrs: argmemonly mustprogress nofree nosync nounwind willreturn +; CHECK: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(argmem: readwrite) ; CHECK-LABEL: define {{[^@]+}}@intrinsic ; CHECK-SAME: (ptr nocapture writeonly [[DEST:%.*]], ptr nocapture readonly [[SRC:%.*]], i32 [[LEN:%.*]]) #[[ATTR4:[0-9]+]] { ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr [[DEST]], ptr [[SRC]], i32 [[LEN]], i1 false) @@ -70,7 +70,7 @@ declare void @llvm.memcpy.p0.p0.i32(ptr, ptr, i32, i1) define internal i32 @called_by_norecurse() { -; CHECK: Function Attrs: nofree norecurse nosync readnone +; CHECK: Function Attrs: nofree norecurse nosync memory(none) ; CHECK-LABEL: define {{[^@]+}}@called_by_norecurse ; CHECK-SAME: () #[[ATTR6:[0-9]+]] { ; CHECK-NEXT: [[A:%.*]] = call i32 @k() @@ -81,7 +81,7 @@ } define void @m() norecurse { -; CHECK: Function Attrs: nofree norecurse nosync readnone +; CHECK: Function Attrs: nofree norecurse nosync memory(none) ; CHECK-LABEL: define {{[^@]+}}@m ; CHECK-SAME: () #[[ATTR6]] { ; CHECK-NEXT: [[A:%.*]] = call i32 @called_by_norecurse() @@ -92,7 +92,7 @@ } define internal i32 @called_by_norecurse_indirectly() { -; CHECK: Function Attrs: nofree norecurse nosync readnone +; CHECK: Function Attrs: nofree norecurse nosync memory(none) ; CHECK-LABEL: define {{[^@]+}}@called_by_norecurse_indirectly ; CHECK-SAME: () #[[ATTR6]] { ; CHECK-NEXT: [[A:%.*]] = call i32 @k() @@ -103,7 +103,7 @@ } define internal void @o() { -; CHECK: Function Attrs: nofree norecurse nosync readnone +; CHECK: Function Attrs: nofree norecurse nosync memory(none) ; CHECK-LABEL: define {{[^@]+}}@o ; CHECK-SAME: () #[[ATTR6]] { ; CHECK-NEXT: [[A:%.*]] = call i32 @called_by_norecurse_indirectly() @@ -114,7 +114,7 @@ } define void @p() norecurse { -; CHECK: Function Attrs: nofree norecurse nosync readnone +; CHECK: Function Attrs: nofree norecurse nosync memory(none) ; CHECK-LABEL: define {{[^@]+}}@p ; CHECK-SAME: () #[[ATTR6]] { ; CHECK-NEXT: call void @o() @@ -125,7 +125,7 @@ } define internal i32 @escapes_as_parameter(ptr %p) { -; CHECK: Function Attrs: nofree nosync readnone +; CHECK: Function Attrs: nofree nosync memory(none) ; CHECK-LABEL: define {{[^@]+}}@escapes_as_parameter ; CHECK-SAME: (ptr nocapture readnone [[P:%.*]]) #[[ATTR2]] { ; CHECK-NEXT: [[A:%.*]] = call i32 @k() @@ -136,7 +136,7 @@ } define internal void @q() { -; CHECK: Function Attrs: nofree norecurse nosync readnone +; CHECK: Function Attrs: nofree norecurse nosync memory(none) ; CHECK-LABEL: define {{[^@]+}}@q ; CHECK-SAME: () #[[ATTR6]] { ; CHECK-NEXT: [[A:%.*]] = call i32 @escapes_as_parameter(ptr @escapes_as_parameter) @@ -147,7 +147,7 @@ } define void @r() norecurse { -; CHECK: Function Attrs: nofree norecurse nosync readnone +; CHECK: Function Attrs: nofree norecurse nosync memory(none) ; CHECK-LABEL: define {{[^@]+}}@r ; CHECK-SAME: () #[[ATTR6]] { ; CHECK-NEXT: call void @q() Index: llvm/test/Transforms/FunctionAttrs/nosync.ll =================================================================== --- llvm/test/Transforms/FunctionAttrs/nosync.ll +++ llvm/test/Transforms/FunctionAttrs/nosync.ll @@ -6,7 +6,7 @@ ; Base case, empty function define void @test1() { -; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind readnone willreturn +; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: @test1( ; CHECK-NEXT: ret void ; @@ -15,7 +15,7 @@ ; Show the bottom up walk define void @test2() { -; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind readnone willreturn +; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: @test2( ; CHECK-NEXT: call void @test1() ; CHECK-NEXT: ret void @@ -38,7 +38,7 @@ } define i32 @test4(i32 %a, i32 %b) { -; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind readnone willreturn +; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: @test4( ; CHECK-NEXT: [[ADD:%.*]] = add i32 [[A:%.*]], [[B:%.*]] ; CHECK-NEXT: ret i32 [[A]] @@ -49,7 +49,7 @@ ; negative case - explicit sync define void @test5(ptr %p) { -; CHECK: Function Attrs: argmemonly mustprogress nofree norecurse nounwind willreturn +; CHECK: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite) ; CHECK-LABEL: @test5( ; CHECK-NEXT: store atomic i8 0, ptr [[P:%.*]] seq_cst, align 1 ; CHECK-NEXT: ret void @@ -60,7 +60,7 @@ ; negative case - explicit sync define i8 @test6(ptr %p) { -; CHECK: Function Attrs: argmemonly mustprogress nofree norecurse nounwind willreturn +; CHECK: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite) ; CHECK-LABEL: @test6( ; CHECK-NEXT: [[V:%.*]] = load atomic i8, ptr [[P:%.*]] seq_cst, align 1 ; CHECK-NEXT: ret i8 [[V]] @@ -71,7 +71,7 @@ ; negative case - explicit sync define void @test7(ptr %p) { -; CHECK: Function Attrs: argmemonly mustprogress nofree norecurse nounwind willreturn +; CHECK: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite) ; CHECK-LABEL: @test7( ; CHECK-NEXT: [[TMP1:%.*]] = atomicrmw add ptr [[P:%.*]], i8 0 seq_cst, align 1 ; CHECK-NEXT: ret void @@ -104,7 +104,7 @@ ; atomic load with monotonic ordering define i32 @load_monotonic(ptr nocapture readonly %0) norecurse nounwind uwtable { -; CHECK: Function Attrs: argmemonly mustprogress nofree norecurse nounwind willreturn uwtable +; CHECK: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite) uwtable ; CHECK-LABEL: @load_monotonic( ; CHECK-NEXT: [[TMP2:%.*]] = load atomic i32, ptr [[TMP0:%.*]] monotonic, align 4 ; CHECK-NEXT: ret i32 [[TMP2]] @@ -115,7 +115,7 @@ ; atomic store with monotonic ordering. define void @store_monotonic(ptr nocapture %0) norecurse nounwind uwtable { -; CHECK: Function Attrs: argmemonly mustprogress nofree norecurse nounwind willreturn uwtable +; CHECK: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite) uwtable ; CHECK-LABEL: @store_monotonic( ; CHECK-NEXT: store atomic i32 10, ptr [[TMP0:%.*]] monotonic, align 4 ; CHECK-NEXT: ret void @@ -127,7 +127,7 @@ ; negative, should not deduce nosync ; atomic load with acquire ordering. define i32 @load_acquire(ptr nocapture readonly %0) norecurse nounwind uwtable { -; CHECK: Function Attrs: argmemonly mustprogress nofree norecurse nounwind willreturn uwtable +; CHECK: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite) uwtable ; CHECK-LABEL: @load_acquire( ; CHECK-NEXT: [[TMP2:%.*]] = load atomic i32, ptr [[TMP0:%.*]] acquire, align 4 ; CHECK-NEXT: ret i32 [[TMP2]] @@ -137,7 +137,7 @@ } define i32 @load_unordered(ptr nocapture readonly %0) norecurse nounwind uwtable { -; CHECK: Function Attrs: argmemonly mustprogress nofree norecurse nosync nounwind readonly willreturn uwtable +; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read) uwtable ; CHECK-LABEL: @load_unordered( ; CHECK-NEXT: [[TMP2:%.*]] = load atomic i32, ptr [[TMP0:%.*]] unordered, align 4 ; CHECK-NEXT: ret i32 [[TMP2]] @@ -148,7 +148,7 @@ ; atomic store with unordered ordering. define void @store_unordered(ptr nocapture %0) norecurse nounwind uwtable { -; CHECK: Function Attrs: argmemonly mustprogress nofree norecurse nosync nounwind willreturn writeonly uwtable +; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write) uwtable ; CHECK-LABEL: @store_unordered( ; CHECK-NEXT: store atomic i32 10, ptr [[TMP0:%.*]] unordered, align 4 ; CHECK-NEXT: ret void @@ -161,7 +161,7 @@ ; negative, should not deduce nosync ; atomic load with release ordering define void @load_release(ptr nocapture %0) norecurse nounwind uwtable { -; CHECK: Function Attrs: inaccessiblemem_or_argmemonly nofree norecurse nounwind uwtable +; CHECK: Function Attrs: nofree norecurse nounwind memory(argmem: readwrite, inaccessiblemem: readwrite) uwtable ; CHECK-LABEL: @load_release( ; CHECK-NEXT: store atomic volatile i32 10, ptr [[TMP0:%.*]] release, align 4 ; CHECK-NEXT: ret void @@ -172,7 +172,7 @@ ; negative volatile, relaxed atomic define void @load_volatile_release(ptr nocapture %0) norecurse nounwind uwtable { -; CHECK: Function Attrs: inaccessiblemem_or_argmemonly nofree norecurse nounwind uwtable +; CHECK: Function Attrs: nofree norecurse nounwind memory(argmem: readwrite, inaccessiblemem: readwrite) uwtable ; CHECK-LABEL: @load_volatile_release( ; CHECK-NEXT: store atomic volatile i32 10, ptr [[TMP0:%.*]] release, align 4 ; CHECK-NEXT: ret void @@ -183,7 +183,7 @@ ; volatile store. define void @volatile_store(ptr %0) norecurse nounwind uwtable { -; CHECK: Function Attrs: inaccessiblemem_or_argmemonly nofree norecurse nounwind uwtable +; CHECK: Function Attrs: nofree norecurse nounwind memory(argmem: readwrite, inaccessiblemem: readwrite) uwtable ; CHECK-LABEL: @volatile_store( ; CHECK-NEXT: store volatile i32 14, ptr [[TMP0:%.*]], align 4 ; CHECK-NEXT: ret void @@ -195,7 +195,7 @@ ; negative, should not deduce nosync ; volatile load. define i32 @volatile_load(ptr %0) norecurse nounwind uwtable { -; CHECK: Function Attrs: inaccessiblemem_or_argmemonly mustprogress nofree norecurse nounwind willreturn uwtable +; CHECK: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite, inaccessiblemem: readwrite) uwtable ; CHECK-LABEL: @volatile_load( ; CHECK-NEXT: [[TMP2:%.*]] = load volatile i32, ptr [[TMP0:%.*]], align 4 ; CHECK-NEXT: ret i32 [[TMP2]] @@ -237,7 +237,7 @@ ; negative, checking volatile intrinsics. define i32 @memcpy_volatile(ptr %ptr1, ptr %ptr2) { -; CHECK: Function Attrs: argmemonly mustprogress nofree nounwind willreturn +; CHECK: Function Attrs: mustprogress nofree nounwind willreturn memory(argmem: readwrite) ; CHECK-LABEL: @memcpy_volatile( ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr [[PTR1:%.*]], ptr [[PTR2:%.*]], i32 8, i1 true) ; CHECK-NEXT: ret i32 4 @@ -248,7 +248,7 @@ ; positive, non-volatile intrinsic. define i32 @memset_non_volatile(ptr %ptr1, i8 %val) { -; CHECK: Function Attrs: argmemonly mustprogress nofree nosync nounwind willreturn writeonly +; CHECK: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(argmem: write) ; CHECK-LABEL: @memset_non_volatile( ; CHECK-NEXT: call void @llvm.memset.p0.i32(ptr [[PTR1:%.*]], i8 [[VAL:%.*]], i32 8, i1 false) ; CHECK-NEXT: ret i32 4 @@ -271,7 +271,7 @@ ; negative. Convergent define void @convergent_readnone(){ -; CHECK: Function Attrs: nofree nosync readnone +; CHECK: Function Attrs: nofree nosync memory(none) ; CHECK-LABEL: @convergent_readnone( ; CHECK-NEXT: call void @readnone_test() ; CHECK-NEXT: ret void @@ -299,7 +299,7 @@ declare float @llvm.cos(float %val) readnone define float @cos_test(float %x) { -; CHECK: Function Attrs: mustprogress nofree nosync nounwind readnone willreturn +; CHECK: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none) ; CHECK-LABEL: @cos_test( ; CHECK-NEXT: [[C:%.*]] = call float @llvm.cos.f32(float [[X:%.*]]) ; CHECK-NEXT: ret float [[C]] Index: llvm/test/Transforms/FunctionAttrs/nounwind.ll =================================================================== --- llvm/test/Transforms/FunctionAttrs/nounwind.ll +++ llvm/test/Transforms/FunctionAttrs/nounwind.ll @@ -3,7 +3,7 @@ ; TEST 1 define i32 @foo1() { -; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind readnone willreturn +; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define {{[^@]+}}@foo1 ; CHECK-SAME: () #[[ATTR0:[0-9]+]] { ; CHECK-NEXT: ret i32 1 @@ -13,7 +13,7 @@ ; TEST 2 define i32 @scc1_foo() { -; CHECK: Function Attrs: nofree nosync nounwind readnone +; CHECK: Function Attrs: nofree nosync nounwind memory(none) ; CHECK-LABEL: define {{[^@]+}}@scc1_foo ; CHECK-SAME: () #[[ATTR1:[0-9]+]] { ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @scc1_bar() @@ -26,7 +26,7 @@ ; TEST 3 define i32 @scc1_bar() { -; CHECK: Function Attrs: nofree nosync nounwind readnone +; CHECK: Function Attrs: nofree nosync nounwind memory(none) ; CHECK-LABEL: define {{[^@]+}}@scc1_bar ; CHECK-SAME: () #[[ATTR1]] { ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @scc1_foo() Index: llvm/test/Transforms/FunctionAttrs/optnone.ll =================================================================== --- llvm/test/Transforms/FunctionAttrs/optnone.ll +++ llvm/test/Transforms/FunctionAttrs/optnone.ll @@ -20,6 +20,6 @@ ; CHECK: (ptr) #1 ; CHECK-LABEL: attributes #0 -; CHECK: = { mustprogress nofree norecurse nosync nounwind readnone willreturn } +; CHECK: = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) } ; CHECK-LABEL: attributes #1 ; CHECK: = { noinline optnone } Index: llvm/test/Transforms/FunctionAttrs/readattrs.ll =================================================================== --- llvm/test/Transforms/FunctionAttrs/readattrs.ll +++ llvm/test/Transforms/FunctionAttrs/readattrs.ll @@ -18,7 +18,7 @@ } define ptr @test2(ptr %p) { -; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn writeonly +; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write, argmem: none, inaccessiblemem: none) ; CHECK-LABEL: define {{[^@]+}}@test2 ; CHECK-SAME: (ptr readnone returned [[P:%.*]]) #[[ATTR0:[0-9]+]] { ; CHECK-NEXT: store i32 0, ptr @x, align 4 @@ -29,7 +29,7 @@ } define i1 @test3(ptr %p, ptr %q) { -; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind readnone willreturn +; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define {{[^@]+}}@test3 ; CHECK-SAME: (ptr readnone [[P:%.*]], ptr readnone [[Q:%.*]]) #[[ATTR1:[0-9]+]] { ; CHECK-NEXT: [[A:%.*]] = icmp ult ptr [[P]], [[Q]] @@ -42,7 +42,7 @@ declare void @test4_1(ptr nocapture) readonly define void @test4_2(ptr %p) { -; CHECK: Function Attrs: nofree readonly +; CHECK: Function Attrs: nofree memory(read) ; CHECK-LABEL: define {{[^@]+}}@test4_2 ; CHECK-SAME: (ptr nocapture readonly [[P:%.*]]) #[[ATTR3:[0-9]+]] { ; CHECK-NEXT: call void @test4_1(ptr [[P]]) @@ -54,7 +54,7 @@ ; Missed optz'n: we could make %q readnone, but don't break test6! define void @test5(ptr %p, ptr %q) { -; CHECK: Function Attrs: argmemonly mustprogress nofree norecurse nosync nounwind willreturn writeonly +; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write) ; CHECK-LABEL: define {{[^@]+}}@test5 ; CHECK-SAME: (ptr nocapture writeonly [[P:%.*]], ptr [[Q:%.*]]) #[[ATTR4:[0-9]+]] { ; CHECK-NEXT: store ptr [[Q]], ptr [[P]], align 8 @@ -81,7 +81,7 @@ ; inalloca parameters are always considered written define void @test7_1(ptr inalloca(i32) %a) { -; CHECK: Function Attrs: argmemonly mustprogress nofree norecurse nosync nounwind willreturn +; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite) ; CHECK-LABEL: define {{[^@]+}}@test7_1 ; CHECK-SAME: (ptr nocapture inalloca(i32) [[A:%.*]]) #[[ATTR5:[0-9]+]] { ; CHECK-NEXT: ret void @@ -91,7 +91,7 @@ ; preallocated parameters are always considered written define void @test7_2(ptr preallocated(i32) %a) { -; CHECK: Function Attrs: argmemonly mustprogress nofree norecurse nosync nounwind willreturn +; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite) ; CHECK-LABEL: define {{[^@]+}}@test7_2 ; CHECK-SAME: (ptr nocapture preallocated(i32) [[A:%.*]]) #[[ATTR5]] { ; CHECK-NEXT: ret void @@ -100,7 +100,7 @@ } define ptr @test8_1(ptr %p) { -; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind readnone willreturn +; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define {{[^@]+}}@test8_1 ; CHECK-SAME: (ptr readnone returned [[P:%.*]]) #[[ATTR1]] { ; CHECK-NEXT: entry: @@ -111,7 +111,7 @@ } define void @test8_2(ptr %p) { -; CHECK: Function Attrs: argmemonly mustprogress nofree norecurse nosync nounwind willreturn writeonly +; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write) ; CHECK-LABEL: define {{[^@]+}}@test8_2 ; CHECK-SAME: (ptr writeonly [[P:%.*]]) #[[ATTR4]] { ; CHECK-NEXT: entry: @@ -128,7 +128,7 @@ declare void @llvm.masked.scatter.v4i32.v4p0(<4 x i32>%val, <4 x ptr>, i32, <4 x i1>) define void @test9(<4 x ptr> %ptrs, <4 x i32>%val) { -; CHECK: Function Attrs: mustprogress nofree nosync nounwind willreturn writeonly +; CHECK: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(write) ; CHECK-LABEL: define {{[^@]+}}@test9 ; CHECK-SAME: (<4 x ptr> [[PTRS:%.*]], <4 x i32> [[VAL:%.*]]) #[[ATTR7:[0-9]+]] { ; CHECK-NEXT: call void @llvm.masked.scatter.v4i32.v4p0(<4 x i32> [[VAL]], <4 x ptr> [[PTRS]], i32 4, <4 x i1> ) @@ -140,7 +140,7 @@ declare <4 x i32> @llvm.masked.gather.v4i32.v4p0(<4 x ptr>, i32, <4 x i1>, <4 x i32>) define <4 x i32> @test10(<4 x ptr> %ptrs) { -; CHECK: Function Attrs: mustprogress nofree nosync nounwind readonly willreturn +; CHECK: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(read) ; CHECK-LABEL: define {{[^@]+}}@test10 ; CHECK-SAME: (<4 x ptr> [[PTRS:%.*]]) #[[ATTR9:[0-9]+]] { ; CHECK-NEXT: [[RES:%.*]] = call <4 x i32> @llvm.masked.gather.v4i32.v4p0(<4 x ptr> [[PTRS]], i32 4, <4 x i1> , <4 x i32> undef) @@ -152,7 +152,7 @@ declare <4 x i32> @test11_1(<4 x ptr>) argmemonly nounwind readonly define <4 x i32> @test11_2(<4 x ptr> %ptrs) { -; CHECK: Function Attrs: argmemonly nofree nounwind readonly +; CHECK: Function Attrs: nofree nounwind memory(argmem: read) ; CHECK-LABEL: define {{[^@]+}}@test11_2 ; CHECK-SAME: (<4 x ptr> [[PTRS:%.*]]) #[[ATTR11:[0-9]+]] { ; CHECK-NEXT: [[RES:%.*]] = call <4 x i32> @test11_1(<4 x ptr> [[PTRS]]) @@ -164,7 +164,7 @@ declare <4 x i32> @test12_1(<4 x ptr>) argmemonly nounwind define <4 x i32> @test12_2(<4 x ptr> %ptrs) { -; CHECK: Function Attrs: argmemonly nounwind +; CHECK: Function Attrs: nounwind memory(argmem: readwrite) ; CHECK-LABEL: define {{[^@]+}}@test12_2 ; CHECK-SAME: (<4 x ptr> [[PTRS:%.*]]) #[[ATTR12:[0-9]+]] { ; CHECK-NEXT: [[RES:%.*]] = call <4 x i32> @test12_1(<4 x ptr> [[PTRS]]) @@ -175,7 +175,7 @@ } define i32 @volatile_load(ptr %p) { -; CHECK: Function Attrs: inaccessiblemem_or_argmemonly mustprogress nofree norecurse nounwind willreturn +; CHECK: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite, inaccessiblemem: readwrite) ; CHECK-LABEL: define {{[^@]+}}@volatile_load ; CHECK-SAME: (ptr [[P:%.*]]) #[[ATTR13:[0-9]+]] { ; CHECK-NEXT: [[LOAD:%.*]] = load volatile i32, ptr [[P]], align 4 @@ -246,7 +246,7 @@ } define void @fptr_test1c(ptr %p, ptr %f) { -; CHECK: Function Attrs: nofree readonly +; CHECK: Function Attrs: nofree memory(read) ; CHECK-LABEL: define {{[^@]+}}@fptr_test1c ; CHECK-SAME: (ptr readnone [[P:%.*]], ptr nocapture readonly [[F:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: call void [[F]](ptr readnone [[P]]) #[[ATTR2:[0-9]+]] @@ -278,7 +278,7 @@ } define void @fptr_test2c(ptr %p, ptr %f) { -; CHECK: Function Attrs: nofree readonly +; CHECK: Function Attrs: nofree memory(read) ; CHECK-LABEL: define {{[^@]+}}@fptr_test2c ; CHECK-SAME: (ptr readonly [[P:%.*]], ptr nocapture readonly [[F:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: call void [[F]](ptr readonly [[P]]) #[[ATTR2]] @@ -289,7 +289,7 @@ } define void @alloca_recphi() { -; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone +; CHECK: Function Attrs: nofree norecurse nosync nounwind memory(none) ; CHECK-LABEL: define {{[^@]+}}@alloca_recphi ; CHECK-SAME: () #[[ATTR14:[0-9]+]] { ; CHECK-NEXT: entry: Index: llvm/test/Transforms/FunctionAttrs/stats.ll =================================================================== --- llvm/test/Transforms/FunctionAttrs/stats.ll +++ llvm/test/Transforms/FunctionAttrs/stats.ll @@ -16,13 +16,11 @@ ret void } -; CHECK: 1 function-attrs - Number of functions marked argmemonly +; CHECK: 2 function-attrs - Number of functions with improved memory attribute ; CHECK-NEXT: 1 function-attrs - Number of arguments marked nocapture ; CHECK-NEXT: 1 function-attrs - Number of functions marked as nofree ; CHECK-NEXT: 2 function-attrs - Number of functions marked as norecurse ; CHECK-NEXT: 2 function-attrs - Number of functions marked as nosync ; CHECK-NEXT: 2 function-attrs - Number of functions marked as nounwind -; CHECK-NEXT: 1 function-attrs - Number of functions marked readonly ; CHECK-NEXT: 1 function-attrs - Number of arguments marked readonly ; CHECK-NEXT: 2 function-attrs - Number of functions marked as willreturn -; CHECK-NEXT: 1 function-attrs - Number of functions marked writeonly Index: llvm/test/Transforms/FunctionAttrs/willreturn-callsites.ll =================================================================== --- llvm/test/Transforms/FunctionAttrs/willreturn-callsites.ll +++ llvm/test/Transforms/FunctionAttrs/willreturn-callsites.ll @@ -38,7 +38,7 @@ } define void @test_fn_mustprogress_readonly_calls(ptr %ptr) mustprogress { -; CHECK: Function Attrs: mustprogress nofree readonly willreturn +; CHECK: Function Attrs: mustprogress nofree willreturn memory(read) ; CHECK-LABEL: @test_fn_mustprogress_readonly_calls( ; CHECK-NOT: call void @decl_readonly() # ; CHECK-NOT: call void @decl_readnone() # Index: llvm/test/Transforms/FunctionAttrs/willreturn.ll =================================================================== --- llvm/test/Transforms/FunctionAttrs/willreturn.ll +++ llvm/test/Transforms/FunctionAttrs/willreturn.ll @@ -2,7 +2,7 @@ ; RUN: opt -function-attrs -S %s | FileCheck %s define void @mustprogress_readnone() mustprogress { -; CHECK: Function Attrs: mustprogress nofree norecurse noreturn nosync nounwind readnone willreturn +; CHECK: Function Attrs: mustprogress nofree norecurse noreturn nosync nounwind willreturn memory(none) ; CHECK-LABEL: @mustprogress_readnone( ; CHECK-NEXT: entry: ; CHECK-NEXT: br label [[WHILE_BODY:%.*]] @@ -17,7 +17,7 @@ } define i32 @mustprogress_load(ptr %ptr) mustprogress { -; CHECK: Function Attrs: argmemonly mustprogress nofree norecurse noreturn nosync nounwind readonly willreturn +; CHECK: Function Attrs: mustprogress nofree norecurse noreturn nosync nounwind willreturn memory(argmem: read) ; CHECK-LABEL: @mustprogress_load( ; CHECK-NEXT: entry: ; CHECK-NEXT: br label [[WHILE_BODY:%.*]] @@ -34,7 +34,7 @@ } define void @mustprogress_store(ptr %ptr) mustprogress { -; CHECK: Function Attrs: argmemonly mustprogress nofree norecurse noreturn nosync nounwind writeonly +; CHECK: Function Attrs: mustprogress nofree norecurse noreturn nosync nounwind memory(argmem: write) ; CHECK-LABEL: @mustprogress_store( ; CHECK-NEXT: entry: ; CHECK-NEXT: br label [[WHILE_BODY:%.*]] @@ -63,7 +63,7 @@ } define i32 @mustprogress_call_known_functions(ptr %ptr) mustprogress { -; CHECK: Function Attrs: argmemonly mustprogress nofree norecurse noreturn nosync nounwind readonly willreturn +; CHECK: Function Attrs: mustprogress nofree norecurse noreturn nosync nounwind willreturn memory(argmem: read) ; CHECK-LABEL: @mustprogress_call_known_functions( ; CHECK-NEXT: call void @mustprogress_readnone() ; CHECK-NEXT: [[R:%.*]] = call i32 @mustprogress_load(ptr [[PTR:%.*]]) @@ -77,7 +77,7 @@ declare i32 @__gxx_personality_v0(...) define i64 @mustprogress_mayunwind() mustprogress personality ptr @__gxx_personality_v0 { -; CHECK: Function Attrs: mustprogress nofree nosync nounwind readnone willreturn +; CHECK: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none) ; CHECK-LABEL: @mustprogress_mayunwind( ; CHECK-NEXT: [[A:%.*]] = invoke i64 @fn_noread() ; CHECK-NEXT: to label [[A:%.*]] unwind label [[B:%.*]] @@ -141,7 +141,7 @@ ; Infinite loop without mustprogress, will not return. define void @willreturn_loop() { -; CHECK: Function Attrs: nofree norecurse noreturn nosync nounwind readnone +; CHECK: Function Attrs: nofree norecurse noreturn nosync nounwind memory(none) ; CHECK-LABEL: @willreturn_loop( ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: @@ -156,7 +156,7 @@ ; Finite loop. Could be willreturn but not detected. ; FIXME define void @willreturn_finite_loop() { -; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone +; CHECK: Function Attrs: nofree norecurse nosync nounwind memory(none) ; CHECK-LABEL: @willreturn_finite_loop( ; CHECK-NEXT: entry: ; CHECK-NEXT: br label [[LOOP:%.*]] @@ -183,7 +183,7 @@ ; Infinite recursion without mustprogress, will not return. define void @willreturn_recursion() { -; CHECK: Function Attrs: nofree nosync nounwind readnone +; CHECK: Function Attrs: nofree nosync nounwind memory(none) ; CHECK-LABEL: @willreturn_recursion( ; CHECK-NEXT: tail call void @willreturn_recursion() ; CHECK-NEXT: ret void @@ -194,7 +194,7 @@ ; Irreducible infinite loop, will not return. define void @willreturn_irreducible(i1 %c) { -; CHECK: Function Attrs: nofree norecurse noreturn nosync nounwind readnone +; CHECK: Function Attrs: nofree norecurse noreturn nosync nounwind memory(none) ; CHECK-LABEL: @willreturn_irreducible( ; CHECK-NEXT: br i1 [[C:%.*]], label [[BB1:%.*]], label [[BB2:%.*]] ; CHECK: bb1: Index: llvm/test/Transforms/FunctionAttrs/writeonly.ll =================================================================== --- llvm/test/Transforms/FunctionAttrs/writeonly.ll +++ llvm/test/Transforms/FunctionAttrs/writeonly.ll @@ -2,7 +2,7 @@ ; RUN: opt < %s -passes=function-attrs -S | FileCheck %s define void @nouses-argworn-funrn(ptr writeonly %.aaa) { -; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind readnone willreturn +; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define {{[^@]+}}@nouses-argworn-funrn ; CHECK-SAME: (ptr nocapture readnone [[DOTAAA:%.*]]) #[[ATTR0:[0-9]+]] { ; CHECK-NEXT: nouses-argworn-funrn_entry: @@ -13,7 +13,7 @@ } define void @nouses-argworn-funro(ptr writeonly %.aaa, ptr %.bbb) { -; CHECK: Function Attrs: argmemonly mustprogress nofree norecurse nosync nounwind readonly willreturn +; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read) ; CHECK-LABEL: define {{[^@]+}}@nouses-argworn-funro ; CHECK-SAME: (ptr nocapture readnone [[DOTAAA:%.*]], ptr nocapture readonly [[DOTBBB:%.*]]) #[[ATTR1:[0-9]+]] { ; CHECK-NEXT: nouses-argworn-funro_entry: @@ -30,7 +30,7 @@ @d-ccc = internal global %_type_of_d-ccc <{ ptr null, i8 1, i8 13, i8 0, i8 -127 }>, align 8 define void @nouses-argworn-funwo(ptr writeonly %.aaa) { -; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn writeonly +; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write, argmem: none, inaccessiblemem: none) ; CHECK-LABEL: define {{[^@]+}}@nouses-argworn-funwo ; CHECK-SAME: (ptr nocapture readnone [[DOTAAA:%.*]]) #[[ATTR2:[0-9]+]] { ; CHECK-NEXT: nouses-argworn-funwo_entry: @@ -43,7 +43,7 @@ } define void @test_store(ptr %p) { -; CHECK: Function Attrs: argmemonly mustprogress nofree norecurse nosync nounwind willreturn writeonly +; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write) ; CHECK-LABEL: define {{[^@]+}}@test_store ; CHECK-SAME: (ptr nocapture writeonly [[P:%.*]]) #[[ATTR3:[0-9]+]] { ; CHECK-NEXT: store i8 0, ptr [[P]], align 1 @@ -55,7 +55,7 @@ @G = external global ptr define i8 @test_store_capture(ptr %p) { -; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn +; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(readwrite, argmem: read, inaccessiblemem: none) ; CHECK-LABEL: define {{[^@]+}}@test_store_capture ; CHECK-SAME: (ptr [[P:%.*]]) #[[ATTR4:[0-9]+]] { ; CHECK-NEXT: store ptr [[P]], ptr @G, align 8 @@ -70,7 +70,7 @@ } define void @test_addressing(ptr %p) { -; CHECK: Function Attrs: argmemonly mustprogress nofree norecurse nosync nounwind willreturn writeonly +; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write) ; CHECK-LABEL: define {{[^@]+}}@test_addressing ; CHECK-SAME: (ptr nocapture writeonly [[P:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[GEP:%.*]] = getelementptr i8, ptr [[P]], i64 8 @@ -83,7 +83,7 @@ } define void @test_readwrite(ptr %p) { -; CHECK: Function Attrs: argmemonly mustprogress nofree norecurse nosync nounwind willreturn +; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite) ; CHECK-LABEL: define {{[^@]+}}@test_readwrite ; CHECK-SAME: (ptr nocapture [[P:%.*]]) #[[ATTR5:[0-9]+]] { ; CHECK-NEXT: [[V:%.*]] = load i8, ptr [[P]], align 1 @@ -96,7 +96,7 @@ } define void @test_volatile(ptr %p) { -; CHECK: Function Attrs: inaccessiblemem_or_argmemonly nofree norecurse nounwind +; CHECK: Function Attrs: nofree norecurse nounwind memory(argmem: readwrite, inaccessiblemem: readwrite) ; CHECK-LABEL: define {{[^@]+}}@test_volatile ; CHECK-SAME: (ptr [[P:%.*]]) #[[ATTR6:[0-9]+]] { ; CHECK-NEXT: store volatile i8 0, ptr [[P]], align 1 @@ -107,7 +107,7 @@ } define void @test_atomicrmw(ptr %p) { -; CHECK: Function Attrs: argmemonly mustprogress nofree norecurse nounwind willreturn +; CHECK: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite) ; CHECK-LABEL: define {{[^@]+}}@test_atomicrmw ; CHECK-SAME: (ptr nocapture [[P:%.*]]) #[[ATTR7:[0-9]+]] { ; CHECK-NEXT: [[TMP1:%.*]] = atomicrmw add ptr [[P]], i8 0 seq_cst, align 1 @@ -134,7 +134,7 @@ ; writeonly w/o nocapture is not enough define void @direct2(ptr %p) { -; CHECK: Function Attrs: writeonly +; CHECK: Function Attrs: memory(write) ; CHECK-LABEL: define {{[^@]+}}@direct2 ; CHECK-SAME: (ptr [[P:%.*]]) #[[ATTR8:[0-9]+]] { ; CHECK-NEXT: call void @direct2_callee(ptr [[P]]) @@ -146,9 +146,9 @@ } define void @direct2b(ptr %p) { -; CHECK: Function Attrs: writeonly +; CHECK: Function Attrs: memory(write) ; CHECK-LABEL: define {{[^@]+}}@direct2b -; CHECK-SAME: (ptr nocapture writeonly [[P:%.*]]) #[[ATTR8]] { +; CHECK-SAME: (ptr nocapture [[P:%.*]]) #[[ATTR8]] { ; CHECK-NEXT: call void @direct2_callee(ptr nocapture [[P]]) ; CHECK-NEXT: ret void ; @@ -199,9 +199,9 @@ } define void @fptr_test3(ptr %p, ptr %f) { -; CHECK: Function Attrs: writeonly +; CHECK: Function Attrs: memory(write) ; CHECK-LABEL: define {{[^@]+}}@fptr_test3 -; CHECK-SAME: (ptr nocapture writeonly [[P:%.*]], ptr nocapture readonly [[F:%.*]]) #[[ATTR8]] { +; CHECK-SAME: (ptr nocapture [[P:%.*]], ptr nocapture readonly [[F:%.*]]) #[[ATTR8]] { ; CHECK-NEXT: call void [[F]](ptr nocapture [[P]]) #[[ATTR8]] ; CHECK-NEXT: ret void ; Index: llvm/test/Transforms/GlobalOpt/ctor-memset.ll =================================================================== --- llvm/test/Transforms/GlobalOpt/ctor-memset.ll +++ llvm/test/Transforms/GlobalOpt/ctor-memset.ll @@ -115,5 +115,5 @@ declare void @llvm.memset.p0.i64(ptr, i8, i64, i1) ;. -; CHECK: attributes #[[ATTR0:[0-9]+]] = { argmemonly nocallback nofree nounwind willreturn writeonly } +; CHECK: attributes #[[ATTR0:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: write) } ;. Index: llvm/test/Transforms/GlobalOpt/pr54572.ll =================================================================== --- llvm/test/Transforms/GlobalOpt/pr54572.ll +++ llvm/test/Transforms/GlobalOpt/pr54572.ll @@ -19,5 +19,5 @@ ret void } ;. -; CHECK: attributes #[[ATTR0:[0-9]+]] = { argmemonly nocallback nofree nounwind willreturn } +; CHECK: attributes #[[ATTR0:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: readwrite) } ;. Index: llvm/test/Transforms/InferFunctionAttrs/annotate.ll =================================================================== --- llvm/test/Transforms/InferFunctionAttrs/annotate.ll +++ llvm/test/Transforms/InferFunctionAttrs/annotate.ll @@ -1081,25 +1081,25 @@ declare void @memset_pattern16(i8*, i8*, i64) ; CHECK-DAG: attributes [[NOFREE_NOUNWIND_WILLRETURN]] = { mustprogress nofree nounwind willreturn } -; CHECK-DAG: attributes [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]] = { mustprogress nofree nounwind willreturn writeonly } +; CHECK-DAG: attributes [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]] = { mustprogress nofree nounwind willreturn memory(write) } ; CHECK-DAG: attributes [[NOFREE_NOUNWIND]] = { nofree nounwind } -; CHECK-DAG: attributes [[INACCESSIBLEMEMONLY_NOFREE_NOUNWIND_WILLRETURN_ALLOCKIND_ALLOCUNINIT_ALLOCSIZE1_FAMILY_MALLOC]] = { inaccessiblememonly mustprogress nofree nounwind willreturn allockind("alloc,uninitialized,aligned") allocsize(1) "alloc-family"="malloc" } -; CHECK-DAG: attributes [[INACCESSIBLEMEMONLY_NOFREE_NOUNWIND_WILLRETURN_ALLOCKIND_ALLOCZEROED_ALLOCSIZE01_FAMILY_MALLOC]] = { inaccessiblememonly mustprogress nofree nounwind willreturn allockind("alloc,zeroed") allocsize(0,1) "alloc-family"="malloc" } -; CHECK-DAG: attributes [[NOFREE_NOUNWIND_READONLY_WILLRETURN]] = { mustprogress nofree nounwind readonly willreturn } -; CHECK-DAG: attributes [[ARGMEMONLY_NOFREE_NOUNWIND_WILLRETURN]] = { argmemonly mustprogress nofree nounwind willreturn } -; CHECK-DAG: attributes [[NOFREE_NOUNWIND_READONLY]] = { nofree nounwind readonly } -; CHECK-DAG: attributes [[INACCESSIBLEMEMORARGMEMONLY_NOUNWIND_WILLRETURN_ALLOCKIND_FREE_FAMILY_MALLOC]] = { inaccessiblemem_or_argmemonly mustprogress nounwind willreturn allockind("free") "alloc-family"="malloc" } +; CHECK-DAG: attributes [[INACCESSIBLEMEMONLY_NOFREE_NOUNWIND_WILLRETURN_ALLOCKIND_ALLOCUNINIT_ALLOCSIZE1_FAMILY_MALLOC]] = { mustprogress nofree nounwind willreturn allockind("alloc,uninitialized,aligned") allocsize(1) memory(inaccessiblemem: readwrite) "alloc-family"="malloc" } +; CHECK-DAG: attributes [[INACCESSIBLEMEMONLY_NOFREE_NOUNWIND_WILLRETURN_ALLOCKIND_ALLOCZEROED_ALLOCSIZE01_FAMILY_MALLOC]] = { mustprogress nofree nounwind willreturn allockind("alloc,zeroed") allocsize(0,1) memory(inaccessiblemem: readwrite) "alloc-family"="malloc" } +; CHECK-DAG: attributes [[NOFREE_NOUNWIND_READONLY_WILLRETURN]] = { mustprogress nofree nounwind willreturn memory(read) } +; CHECK-DAG: attributes [[ARGMEMONLY_NOFREE_NOUNWIND_WILLRETURN]] = { mustprogress nofree nounwind willreturn memory(argmem: readwrite) } +; CHECK-DAG: attributes [[NOFREE_NOUNWIND_READONLY]] = { nofree nounwind memory(read) } +; CHECK-DAG: attributes [[INACCESSIBLEMEMORARGMEMONLY_NOUNWIND_WILLRETURN_ALLOCKIND_FREE_FAMILY_MALLOC]] = { mustprogress nounwind willreturn allockind("free") memory(argmem: readwrite, inaccessiblemem: readwrite) "alloc-family"="malloc" } ; CHECK-DAG: attributes [[NOFREE_WILLRETURN]] = { mustprogress nofree willreturn } -; CHECK-DAG: attributes [[INACCESSIBLEMEMONLY_NOFREE_NOUNWIND_WILLRETURN_ALLOCKIND_ALLOCUNINIT_ALLOCSIZE0_FAMILY_MALLOC]] = { inaccessiblememonly mustprogress nofree nounwind willreturn allockind("alloc,uninitialized") allocsize(0) "alloc-family"="malloc" } -; CHECK-DAG: attributes [[ARGMEMONLY_NOFREE_NOUNWIND_READONLY_WILLRETURN]] = { argmemonly mustprogress nofree nounwind readonly willreturn } +; CHECK-DAG: attributes [[INACCESSIBLEMEMONLY_NOFREE_NOUNWIND_WILLRETURN_ALLOCKIND_ALLOCUNINIT_ALLOCSIZE0_FAMILY_MALLOC]] = { mustprogress nofree nounwind willreturn allockind("alloc,uninitialized") allocsize(0) memory(inaccessiblemem: readwrite) "alloc-family"="malloc" } +; CHECK-DAG: attributes [[ARGMEMONLY_NOFREE_NOUNWIND_READONLY_WILLRETURN]] = { mustprogress nofree nounwind willreturn memory(argmem: read) } ; CHECK-DAG: attributes [[NOFREE]] = { nofree } -; CHECK-DAG: attributes [[ARGMEMONLY_NOFREE_NOUNWIND]] = { argmemonly nofree nounwind } -; CHECK-DAG: attributes [[INACCESSIBLEMEMORARGMEMONLY_NOUNWIND_WILLRETURN_ALLOCKIND_REALLOC_ALLOCSIZE1_FAMILY_MALLOC]] = { inaccessiblemem_or_argmemonly mustprogress nounwind willreturn allockind("realloc") allocsize(1) "alloc-family"="malloc" } -; CHECK-DAG: attributes [[INACCESSIBLEMEMORARGONLY_NOFREE_NOUNWIND_WILLRETURN_FAMILY_MALLOC]] = { inaccessiblemem_or_argmemonly mustprogress nofree nounwind willreturn "alloc-family"="malloc" } +; CHECK-DAG: attributes [[ARGMEMONLY_NOFREE_NOUNWIND]] = { nofree nounwind memory(argmem: readwrite) } +; CHECK-DAG: attributes [[INACCESSIBLEMEMORARGMEMONLY_NOUNWIND_WILLRETURN_ALLOCKIND_REALLOC_ALLOCSIZE1_FAMILY_MALLOC]] = { mustprogress nounwind willreturn allockind("realloc") allocsize(1) memory(argmem: readwrite, inaccessiblemem: readwrite) "alloc-family"="malloc" } +; CHECK-DAG: attributes [[INACCESSIBLEMEMORARGONLY_NOFREE_NOUNWIND_WILLRETURN_FAMILY_MALLOC]] = { mustprogress nofree nounwind willreturn memory(argmem: readwrite, inaccessiblemem: readwrite) "alloc-family"="malloc" } -; CHECK-NVPTX-DAG: attributes [[NOFREE_NOUNWIND_READNONE]] = { nofree nosync nounwind readnone } +; CHECK-NVPTX-DAG: attributes [[NOFREE_NOUNWIND_READNONE]] = { nofree nosync nounwind memory(none) } -; CHECK-AIX-DAG: attributes [[INACCESSIBLEMEMONLY_NOFREE_NOUNWIND_WILLRETURN_ALLOCSIZE0_FAMILY_VEC_MALLOC]] = { inaccessiblememonly mustprogress nofree nounwind willreturn allockind("alloc,uninitialized") allocsize(0) "alloc-family"="vec_malloc" } -; CHECK-AIX-DAG: attributes [[INACCESSIBLEMEMORARGMEMONLY_NOUNWIND_WILLRETURN_FAMILY_VEC_MALLOC]] = { inaccessiblemem_or_argmemonly mustprogress nounwind willreturn allockind("free") "alloc-family"="vec_malloc" } -; CHECK-AIX-DAG: attributes [[INACCESSIBLEMEMORARGMEMONLY_NOUNWIND_WILLRETURN_ALLOCSIZE_FAMILY_VEC_MALLOC]] = { inaccessiblemem_or_argmemonly mustprogress nounwind willreturn allockind("realloc") allocsize(1) "alloc-family"="vec_malloc" } -; CHECK-AIX-DAG: attributes [[INACCESSIBLEMEMONLY_NOFREE_NOUNWIND_WILLRETURN_ALLOCSIZE01_FAMILY_VEC_MALLOC]] = { inaccessiblememonly mustprogress nofree nounwind willreturn allockind("alloc,zeroed") allocsize(0,1) "alloc-family"="vec_malloc" } +; CHECK-AIX-DAG: attributes [[INACCESSIBLEMEMONLY_NOFREE_NOUNWIND_WILLRETURN_ALLOCSIZE0_FAMILY_VEC_MALLOC]] = { mustprogress nofree nounwind willreturn allockind("alloc,uninitialized") allocsize(0) memory(inaccessiblemem: readwrite) "alloc-family"="vec_malloc" } +; CHECK-AIX-DAG: attributes [[INACCESSIBLEMEMORARGMEMONLY_NOUNWIND_WILLRETURN_FAMILY_VEC_MALLOC]] = { mustprogress nounwind willreturn allockind("free") memory(argmem: readwrite, inaccessiblemem: readwrite) "alloc-family"="vec_malloc" } +; CHECK-AIX-DAG: attributes [[INACCESSIBLEMEMORARGMEMONLY_NOUNWIND_WILLRETURN_ALLOCSIZE_FAMILY_VEC_MALLOC]] = { mustprogress nounwind willreturn allockind("realloc") allocsize(1) memory(argmem: readwrite, inaccessiblemem: readwrite) "alloc-family"="vec_malloc" } +; CHECK-AIX-DAG: attributes [[INACCESSIBLEMEMONLY_NOFREE_NOUNWIND_WILLRETURN_ALLOCSIZE01_FAMILY_VEC_MALLOC]] = { mustprogress nofree nounwind willreturn allockind("alloc,zeroed") allocsize(0,1) memory(inaccessiblemem: readwrite) "alloc-family"="vec_malloc" } Index: llvm/test/Transforms/InferFunctionAttrs/norecurse_debug.ll =================================================================== --- llvm/test/Transforms/InferFunctionAttrs/norecurse_debug.ll +++ llvm/test/Transforms/InferFunctionAttrs/norecurse_debug.ll @@ -52,5 +52,5 @@ !28 = !DILocation(line: 9, column: 18, scope: !2) !29 = !DILocation(line: 10, column: 1, scope: !2) -; CHECK: attributes #0 = { mustprogress nofree norecurse nosync nounwind willreturn } +; CHECK: attributes #0 = { mustprogress nofree norecurse nosync nounwind willreturn memory(readwrite, argmem: write, inaccessiblemem: none) } ; CHECK-NOT: foo.coefficient1 Index: llvm/test/Transforms/InferFunctionAttrs/readonly_and_writeonly.ll =================================================================== --- llvm/test/Transforms/InferFunctionAttrs/readonly_and_writeonly.ll +++ llvm/test/Transforms/InferFunctionAttrs/readonly_and_writeonly.ll @@ -5,4 +5,4 @@ ; CHECK: declare double @acos(double) [[NOFREE_NOUNWIND_WILLRETURN_READNONE:#[0-9]+]] declare double @acos(double) readonly -; CHECK-DAG: attributes [[NOFREE_NOUNWIND_WILLRETURN_READNONE]] = { mustprogress nofree nosync nounwind readnone willreturn } +; CHECK-DAG: attributes [[NOFREE_NOUNWIND_WILLRETURN_READNONE]] = { mustprogress nofree nosync nounwind willreturn memory(none) } Index: llvm/test/Transforms/Inline/cgscc-update.ll =================================================================== --- llvm/test/Transforms/Inline/cgscc-update.ll +++ llvm/test/Transforms/Inline/cgscc-update.ll @@ -9,8 +9,8 @@ ; CHECK: declare void @unknown() declare void @unknown() -; Basic correctness check: this should get annotated as readnone. -; CHECK: Function Attrs: nounwind readnone +; Basic correctness check: this should get annotated as memory(none). +; CHECK: Function Attrs: nounwind memory(none) ; CHECK-NEXT: declare void @readnone() declare void @readnone() readnone nounwind @@ -26,8 +26,8 @@ ret void } -; This function should have had 'readnone' deduced for its SCC. -; CHECK: Function Attrs: nofree noinline nosync nounwind readnone +; This function should have had 'memory(none)' deduced for its SCC. +; CHECK: Function Attrs: nofree noinline nosync nounwind memory(none) ; CHECK-NEXT: define void @test1_g() define void @test1_g() noinline { entry: @@ -35,8 +35,8 @@ ret void } -; This function should have had 'readnone' deduced for its SCC. -; CHECK: Function Attrs: nofree noinline nosync nounwind readnone +; This function should have had 'memory(none)' deduced for its SCC. +; CHECK: Function Attrs: nofree noinline nosync nounwind memory(none) ; CHECK-NEXT: define void @test1_h() define void @test1_h() noinline { entry: @@ -58,8 +58,8 @@ ret void()* @test2_h } -; This function should have had 'readnone' deduced for its SCC. -; CHECK: Function Attrs: nofree noinline nosync nounwind readnone +; This function should have had 'memory(none)' deduced for its SCC. +; CHECK: Function Attrs: nofree noinline nosync nounwind memory(none) ; CHECK-NEXT: define void @test2_g() define void @test2_g() noinline { entry: @@ -68,8 +68,8 @@ ret void } -; This function should have had 'readnone' deduced for its SCC. -; CHECK: Function Attrs: nofree noinline nosync nounwind readnone +; This function should have had 'memory(none)' deduced for its SCC. +; CHECK: Function Attrs: nofree noinline nosync nounwind memory(none) ; CHECK-NEXT: define void @test2_h() define void @test2_h() noinline { entry: @@ -151,8 +151,8 @@ ; interesting call graph update for the new call edge. Eventually, we still ; form a new SCC and should use that can deduce precise function attrs. -; This function should have had 'readnone' deduced for its SCC. -; CHECK: Function Attrs: nofree noinline nosync nounwind readnone +; This function should have had 'memory(none)' deduced for its SCC. +; CHECK: Function Attrs: nofree noinline nosync nounwind memory(none) ; CHECK-NEXT: define void @test4_f1() define void @test4_f1() noinline { entry: @@ -174,8 +174,8 @@ ret void } -; This function should have had 'readnone' deduced for its SCC. -; CHECK: Function Attrs: nofree noinline nosync nounwind readnone +; This function should have had 'memory(none)' deduced for its SCC. +; CHECK: Function Attrs: nofree noinline nosync nounwind memory(none) ; CHECK-NEXT: define void @test4_h() define void @test4_h() noinline { entry: Index: llvm/test/Transforms/Inline/inline_invoke.ll =================================================================== --- llvm/test/Transforms/Inline/inline_invoke.ll +++ llvm/test/Transforms/Inline/inline_invoke.ll @@ -343,7 +343,7 @@ ; CHECK-NEXT: call void @_ZSt9terminatev() ; CHECK: attributes [[NUW]] = { nounwind } -; CHECK: attributes #1 = { nounwind readnone } +; CHECK: attributes #1 = { nounwind memory(none) } ; CHECK: attributes #2 = { ssp uwtable } -; CHECK: attributes #3 = { argmemonly nocallback nofree nosync nounwind willreturn } +; CHECK: attributes #3 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) } ; CHECK: attributes #4 = { noreturn nounwind } Index: llvm/test/Transforms/InstCombine/AArch64/2012-04-23-Neon-Intrinsics.ll =================================================================== --- llvm/test/Transforms/InstCombine/AArch64/2012-04-23-Neon-Intrinsics.ll +++ llvm/test/Transforms/InstCombine/AArch64/2012-04-23-Neon-Intrinsics.ll @@ -65,6 +65,6 @@ declare <4 x i32> @llvm.aarch64.neon.smull.v4i32(<4 x i16>, <4 x i16>) nounwind readnone declare <4 x i32> @llvm.aarch64.neon.umull.v4i32(<4 x i16>, <4 x i16>) nounwind readnone -; CHECK: attributes #0 = { nounwind readnone ssp } -; CHECK: attributes #1 = { nocallback nofree nosync nounwind readnone willreturn } +; CHECK: attributes #0 = { nounwind ssp memory(none) } +; CHECK: attributes #1 = { nocallback nofree nosync nounwind willreturn memory(none) } ; CHECK: attributes [[NUW]] = { nounwind } Index: llvm/test/Transforms/InstCombine/stpncpy-1.ll =================================================================== --- llvm/test/Transforms/InstCombine/stpncpy-1.ll +++ llvm/test/Transforms/InstCombine/stpncpy-1.ll @@ -463,6 +463,6 @@ ret void } ;. -; ANY: attributes #[[ATTR0:[0-9]+]] = { argmemonly nocallback nofree nounwind willreturn writeonly } -; ANY: attributes #[[ATTR1:[0-9]+]] = { argmemonly nocallback nofree nounwind willreturn } +; ANY: attributes #[[ATTR0:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: write) } +; ANY: attributes #[[ATTR1:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: readwrite) } ;. Index: llvm/test/Transforms/LICM/scalar-promote.ll =================================================================== --- llvm/test/Transforms/LICM/scalar-promote.ll +++ llvm/test/Transforms/LICM/scalar-promote.ll @@ -600,7 +600,7 @@ } define i8 @test_hoistable_existing_load_sinkable_store_writeonly(ptr dereferenceable(8) %ptr, i8 %start) writeonly { -; CHECK: Function Attrs: writeonly +; CHECK: Function Attrs: memory(write) ; CHECK-LABEL: @test_hoistable_existing_load_sinkable_store_writeonly( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[PTR_PROMOTED:%.*]] = load i8, ptr [[PTR:%.*]], align 1 @@ -641,7 +641,7 @@ ; Test case for PR51248. define void @test_sink_store_only() writeonly { -; CHECK: Function Attrs: writeonly +; CHECK: Function Attrs: memory(write) ; CHECK-LABEL: @test_sink_store_only( ; CHECK-NEXT: entry: ; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] @@ -678,7 +678,7 @@ } define void @test_sink_store_to_local_object_only_loop_must_execute() writeonly { -; CHECK: Function Attrs: writeonly +; CHECK: Function Attrs: memory(write) ; CHECK-LABEL: @test_sink_store_to_local_object_only_loop_must_execute( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[A:%.*]] = alloca i8, align 1 @@ -719,7 +719,7 @@ ; The store in the loop may not execute, so we need to introduce a load in the ; pre-header. Make sure the writeonly attribute is dropped. define void @test_sink_store_to_local_object_only_loop_may_not_execute(i8 %n) writeonly { -; CHECK: Function Attrs: writeonly +; CHECK: Function Attrs: memory(write) ; CHECK-LABEL: @test_sink_store_to_local_object_only_loop_may_not_execute( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[A:%.*]] = alloca i8, align 1 @@ -761,7 +761,7 @@ declare dereferenceable(8) noalias ptr @alloc_writeonly() writeonly define void @test_sink_store_to_noalias_call_object_only_loop_may_not_execute1(i8 %n) writeonly { -; CHECK: Function Attrs: writeonly +; CHECK: Function Attrs: memory(write) ; CHECK-LABEL: @test_sink_store_to_noalias_call_object_only_loop_may_not_execute1( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[A:%.*]] = call noalias dereferenceable(8) ptr @alloc_writeonly() @@ -801,7 +801,7 @@ } define void @test_sink_store_only_no_phi_needed() writeonly { -; CHECK: Function Attrs: writeonly +; CHECK: Function Attrs: memory(write) ; CHECK-LABEL: @test_sink_store_only_no_phi_needed( ; CHECK-NEXT: entry: ; CHECK-NEXT: br label [[LOOP:%.*]] Index: llvm/test/Transforms/LICM/strlen.ll =================================================================== --- llvm/test/Transforms/LICM/strlen.ll +++ llvm/test/Transforms/LICM/strlen.ll @@ -13,7 +13,7 @@ } ; CHECK: declare i64 @strlen(ptr nocapture) #0 -; CHECK: attributes #0 = { argmemonly mustprogress nofree nounwind readonly willreturn } +; CHECK: attributes #0 = { mustprogress nofree nounwind willreturn memory(argmem: read) } declare i64 @strlen(ptr) Index: llvm/test/Transforms/LowerMatrixIntrinsics/strided-store-double.ll =================================================================== --- llvm/test/Transforms/LowerMatrixIntrinsics/strided-store-double.ll +++ llvm/test/Transforms/LowerMatrixIntrinsics/strided-store-double.ll @@ -85,4 +85,4 @@ ; CHECK: declare void @llvm.matrix.column.major.store.v6f64.i64(<6 x double>, double* nocapture writeonly, i64, i1 immarg, i32 immarg, i32 immarg) #0 ; CHECK: declare void @llvm.matrix.column.major.store.v10f64.i64(<10 x double>, double* nocapture writeonly, i64, i1 immarg, i32 immarg, i32 immarg) #0 -; CHECK: attributes #0 = { argmemonly nocallback nofree nosync nounwind willreturn writeonly } +; CHECK: attributes #0 = { nocallback nofree nosync nounwind willreturn memory(argmem: write) } Index: llvm/test/Transforms/ObjCARC/basic.ll =================================================================== --- llvm/test/Transforms/ObjCARC/basic.ll +++ llvm/test/Transforms/ObjCARC/basic.ll @@ -3073,5 +3073,5 @@ !5 = !{i32 2, !"Debug Info Version", i32 3} ; CHECK: attributes [[NUW]] = { nounwind } -; CHECK: attributes #1 = { nocallback nofree nosync nounwind readnone speculatable willreturn } +; CHECK: attributes #1 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) } ; CHECK: ![[RELEASE]] = !{} Index: llvm/test/Transforms/ObjCARC/ensure-that-exception-unwind-path-is-visited.ll =================================================================== --- llvm/test/Transforms/ObjCARC/ensure-that-exception-unwind-path-is-visited.ll +++ llvm/test/Transforms/ObjCARC/ensure-that-exception-unwind-path-is-visited.ll @@ -105,7 +105,7 @@ declare void @llvm.dbg.value(metadata, metadata, metadata) nounwind readnone ; CHECK: attributes #0 = { ssp uwtable } -; CHECK: attributes #1 = { nocallback nofree nosync nounwind readnone speculatable willreturn } +; CHECK: attributes #1 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) } ; CHECK: attributes #2 = { nonlazybind } ; CHECK: attributes [[NUW]] = { nounwind } ; CHECK: attributes #4 = { noinline ssp uwtable } Index: llvm/test/Transforms/ObjCARC/nested.ll =================================================================== --- llvm/test/Transforms/ObjCARC/nested.ll +++ llvm/test/Transforms/ObjCARC/nested.ll @@ -821,5 +821,5 @@ ; CHECK: attributes [[NUW]] = { nounwind } -; CHECK: attributes #1 = { argmemonly nocallback nofree nounwind willreturn writeonly } +; CHECK: attributes #1 = { nocallback nofree nounwind willreturn memory(argmem: write) } ; CHECK: attributes #2 = { nonlazybind } Index: llvm/test/Transforms/ObjCARC/rle-s2l.ll =================================================================== --- llvm/test/Transforms/ObjCARC/rle-s2l.ll +++ llvm/test/Transforms/ObjCARC/rle-s2l.ll @@ -135,4 +135,4 @@ } ; CHECK: attributes #0 = { nounwind } -; CHECK: attributes [[RO]] = { readonly } +; CHECK: attributes [[RO]] = { memory(read) } Index: llvm/test/Transforms/RewriteStatepointsForGC/X86/intrinsic-attributes.ll =================================================================== --- llvm/test/Transforms/RewriteStatepointsForGC/X86/intrinsic-attributes.ll +++ llvm/test/Transforms/RewriteStatepointsForGC/X86/intrinsic-attributes.ll @@ -1,6 +1,6 @@ ; RUN: opt < %s -S -rewrite-statepoints-for-gc | FileCheck %s -; CHECK: Function Attrs: nounwind readnone +; CHECK: Function Attrs: nounwind memory(none) ; CHECK: declare i64 @llvm.x86.sse2.cvttsd2si64(<2 x double>) declare i64 @llvm.x86.sse2.cvttsd2si64(<2 x double>) Index: llvm/test/Transforms/RewriteStatepointsForGC/statepoint-attrs.ll =================================================================== --- llvm/test/Transforms/RewriteStatepointsForGC/statepoint-attrs.ll +++ llvm/test/Transforms/RewriteStatepointsForGC/statepoint-attrs.ll @@ -20,6 +20,6 @@ attributes #1 = { norecurse noimplicitfloat } ;. -; CHECK: attributes #[[ATTR0:[0-9]+]] = { nounwind readnone } +; CHECK: attributes #[[ATTR0:[0-9]+]] = { nounwind memory(none) } ; CHECK: attributes #[[ATTR1]] = { noimplicitfloat norecurse } ;. Index: llvm/test/Transforms/SCCP/ipscp-drop-argmemonly.ll =================================================================== --- llvm/test/Transforms/SCCP/ipscp-drop-argmemonly.ll +++ llvm/test/Transforms/SCCP/ipscp-drop-argmemonly.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-attributes --check-globals ; RUN: opt -passes=ipsccp -S %s | FileCheck %s ; Test cases to ensure argmemonly/inaccessiblemem_or_argmemonly attributes are @@ -10,8 +10,11 @@ ; Here the pointer argument %arg will be replaced by a constant. We need to ; drop argmemonly. +;. +; CHECK: @[[G:[a-zA-Z0-9_$"\\.-]+]] = internal global i32 0 +;. define internal void @ptrarg.1(i32* %arg, i32 %val) argmemonly nounwind { -; CHECK: Function Attrs: nounwind +; CHECK: Function Attrs: nounwind memory(readwrite, inaccessiblemem: none) ; CHECK-LABEL: @ptrarg.1( ; CHECK-NEXT: store i32 10, i32* @g, align 4 ; CHECK-NEXT: ret void @@ -37,7 +40,7 @@ ; Here only the non-pointer argument %val is replaced, no need ; to drop the argmemonly attribute. define internal void @ptrarg.2(i32* %arg, i32 %val) argmemonly nounwind { -; CHECK: Function Attrs: argmemonly nounwind +; CHECK: Function Attrs: nounwind memory(argmem: readwrite) ; CHECK-LABEL: @ptrarg.2( ; CHECK-NEXT: store i32 10, i32* [[ARG:%.*]], align 4 ; CHECK-NEXT: ret void @@ -59,7 +62,7 @@ ; Here the pointer argument %arg will be replaced by a constant. We need to ; drop inaccessiblemem_or_argmemonly. define internal void @ptrarg.3(i32* %arg, i32 %val) inaccessiblemem_or_argmemonly nounwind { -; CHECK: Function Attrs: nounwind +; CHECK: Function Attrs: nounwind memory(readwrite) ; CHECK-LABEL: @ptrarg.3( ; CHECK-NEXT: store i32 10, i32* @g, align 4 ; CHECK-NEXT: ret void @@ -85,7 +88,7 @@ ; Here only the non-pointer argument %val is replaced, no need ; to drop the inaccessiblemem_or_argmemonly attribute. define internal void @ptrarg.4(i32* %arg, i32 %val) inaccessiblemem_or_argmemonly nounwind { -; CHECK: Function Attrs: inaccessiblemem_or_argmemonly nounwind +; CHECK: Function Attrs: nounwind memory(argmem: readwrite, inaccessiblemem: readwrite) ; CHECK-LABEL: @ptrarg.4( ; CHECK-NEXT: store i32 10, i32* [[ARG:%.*]], align 4 ; CHECK-NEXT: ret void @@ -107,7 +110,7 @@ ; Here the pointer argument %arg will be replaced by a constant. We need to ; drop inaccessiblemem_or_argmemonly. define internal void @ptrarg.5(i32* %arg, i32 %val) argmemonly inaccessiblemem_or_argmemonly nounwind { -; CHECK: Function Attrs: nounwind +; CHECK: Function Attrs: nounwind memory(readwrite, inaccessiblemem: none) ; CHECK-LABEL: @ptrarg.5( ; CHECK-NEXT: store i32 10, i32* @g, align 4 ; CHECK-NEXT: ret void @@ -143,10 +146,10 @@ define i32 @caller.6.cs.attributes(i32 %n) { ; CHECK-LABEL: @caller.6.cs.attributes( ; CHECK-NEXT: store i32 1, i32* @g, align 4 -; CHECK-NEXT: tail call void @ptrarg.5(i32* @g, i32 10) [[NOUNWIND:#[0-9]+]] -; CHECK-NEXT: tail call void @ptrarg.5(i32* @g, i32 10) [[NOUNWIND:#[0-9]+]] -; CHECK-NEXT: tail call void @ptrarg.5(i32* @g, i32 10) [[NOUNWIND:#[0-9]+]] -; CHECK-NEXT: tail call void @ptrarg.5(i32* @g, i32 10) [[NOUNWIND:#[0-9]+]] +; CHECK-NEXT: tail call void @ptrarg.5(i32* @g, i32 10) #[[ATTR0:[0-9]+]] +; CHECK-NEXT: tail call void @ptrarg.5(i32* @g, i32 10) #[[ATTR2:[0-9]+]] +; CHECK-NEXT: tail call void @ptrarg.5(i32* @g, i32 10) #[[ATTR0]] +; CHECK-NEXT: tail call void @ptrarg.5(i32* @g, i32 10) #[[ATTR4:[0-9]+]] ; CHECK-NEXT: [[G_VAL:%.*]] = load i32, i32* @g, align 4 ; CHECK-NEXT: ret i32 [[G_VAL]] ; @@ -159,4 +162,10 @@ ret i32 %g.val } -; CHECK: [[NOUNWIND]] = { nounwind } +;. +; CHECK: attributes #[[ATTR0]] = { nounwind memory(readwrite, inaccessiblemem: none) } +; CHECK: attributes #[[ATTR1:[0-9]+]] = { nounwind memory(argmem: readwrite) } +; CHECK: attributes #[[ATTR2]] = { nounwind memory(readwrite) } +; CHECK: attributes #[[ATTR3:[0-9]+]] = { nounwind memory(argmem: readwrite, inaccessiblemem: readwrite) } +; CHECK: attributes #[[ATTR4]] = { nounwind } +;. Index: llvm/test/Transforms/SCCP/remove-call-inst.ll =================================================================== --- llvm/test/Transforms/SCCP/remove-call-inst.ll +++ llvm/test/Transforms/SCCP/remove-call-inst.ll @@ -36,4 +36,4 @@ } ; CHECK: attributes #0 = { noreturn nounwind } -; CHECK: attributes #1 = { nounwind readnone willreturn } +; CHECK: attributes #1 = { nounwind willreturn memory(none) } Index: llvm/test/Transforms/SampleProfile/pseudo-probe-emit.ll =================================================================== --- llvm/test/Transforms/SampleProfile/pseudo-probe-emit.ll +++ llvm/test/Transforms/SampleProfile/pseudo-probe-emit.ll @@ -64,7 +64,7 @@ ret void } -; CHECK-IL: Function Attrs: inaccessiblememonly nocallback nofree nosync nounwind willreturn +; CHECK-IL: Function Attrs: nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: readwrite) ; CHECK-IL-NEXT: declare void @llvm.pseudoprobe(i64, i64, i32, i64) ; CHECK-IL: ![[#FOO:]] = distinct !DISubprogram(name: "foo" Index: llvm/test/Transforms/SimplifyCFG/X86/merge-compatible-invokes-of-landingpad-debuginfo.ll =================================================================== --- llvm/test/Transforms/SimplifyCFG/X86/merge-compatible-invokes-of-landingpad-debuginfo.ll +++ llvm/test/Transforms/SimplifyCFG/X86/merge-compatible-invokes-of-landingpad-debuginfo.ll @@ -68,7 +68,7 @@ declare dso_local i32 @__gxx_personality_v0(...) ;. ; CHECK: attributes #[[ATTR0:[0-9]+]] = { noreturn } -; CHECK: attributes #[[ATTR1:[0-9]+]] = { nocallback nofree nosync nounwind readnone speculatable willreturn } +; CHECK: attributes #[[ATTR1:[0-9]+]] = { nocallback nofree nosync nounwind speculatable willreturn memory(none) } ;. ; CHECK: [[META0:![0-9]+]] = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug) ; CHECK: [[META1:![0-9]+]] = !DIFile(filename: "", directory: "/") Index: llvm/test/Transforms/SimplifyCFG/X86/merge-compatible-invokes-of-landingpad.ll =================================================================== --- llvm/test/Transforms/SimplifyCFG/X86/merge-compatible-invokes-of-landingpad.ll +++ llvm/test/Transforms/SimplifyCFG/X86/merge-compatible-invokes-of-landingpad.ll @@ -2475,5 +2475,5 @@ ;. ; CHECK: attributes #[[ATTR0:[0-9]+]] = { noreturn } ; CHECK: attributes #[[ATTR1]] = { nomerge } -; CHECK: attributes #[[ATTR2]] = { readnone } +; CHECK: attributes #[[ATTR2]] = { memory(none) } ;. Index: llvm/test/Transforms/SimplifyCFG/preserve-branchweights.ll =================================================================== --- llvm/test/Transforms/SimplifyCFG/preserve-branchweights.ll +++ llvm/test/Transforms/SimplifyCFG/preserve-branchweights.ll @@ -1133,7 +1133,7 @@ ;. ; CHECK: attributes #[[ATTR0:[0-9]+]] = { nounwind uwtable } ; CHECK: attributes #[[ATTR1]] = { nounwind } -; CHECK: attributes #[[ATTR2:[0-9]+]] = { noredzone nounwind readnone ssp } +; CHECK: attributes #[[ATTR2:[0-9]+]] = { noredzone nounwind ssp memory(none) } ;. ; CHECK: [[PROF0]] = !{!"branch_weights", i32 5, i32 11} ; CHECK: [[PROF1]] = !{!"branch_weights", i32 1, i32 3} Index: llvm/test/Verifier/fp-intrinsics.ll =================================================================== --- llvm/test/Verifier/fp-intrinsics.ll +++ llvm/test/Verifier/fp-intrinsics.ll @@ -12,7 +12,7 @@ ; attached to the FP intrinsic. ; CHECK1: declare double @llvm.experimental.constrained.fadd.f64(double, double, metadata, metadata) #[[ATTR:[0-9]+]] ; CHECK1: declare double @llvm.experimental.constrained.sqrt.f64(double, metadata, metadata) #[[ATTR]] -; CHECK1: attributes #[[ATTR]] = { inaccessiblememonly nocallback nofree nosync nounwind willreturn } +; CHECK1: attributes #[[ATTR]] = { nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: readwrite) } ; Note: FP exceptions aren't usually caught through normal unwind mechanisms, ; but we may want to revisit this for asynchronous exception handling. define double @f1(double %a, double %b) #0 { Index: llvm/test/Verifier/writeonly.ll =================================================================== --- llvm/test/Verifier/writeonly.ll +++ /dev/null @@ -1,13 +0,0 @@ -; RUN: not llvm-as %s -o /dev/null 2>&1 | FileCheck %s - -declare void @a() readnone writeonly -; CHECK: Attributes {{.*}} are incompatible - -declare void @b() readonly writeonly -; CHECK: Attributes {{.*}} are incompatible - -declare void @c(i32* readnone writeonly %p) -; CHECK: Attributes {{.*}} are incompatible - -declare void @d(i32* readonly writeonly %p) -; CHECK: Attributes {{.*}} are incompatible Index: llvm/test/tools/llvm-reduce/remove-attributes-from-intrinsics.ll =================================================================== --- llvm/test/tools/llvm-reduce/remove-attributes-from-intrinsics.ll +++ llvm/test/tools/llvm-reduce/remove-attributes-from-intrinsics.ll @@ -26,7 +26,7 @@ ; CHECK-ALL: declare i32 @llvm.uadd.sat.i32(i32, i32) #0 declare i32 @llvm.uadd.sat.i32(i32, i32) #0 -; CHECK-ALL: attributes #0 = { nocallback nofree nosync nounwind readnone speculatable willreturn } +; CHECK-ALL: attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) } ; CHECK-INTERESTINGNESS: attributes #1 = { ; CHECK-INTERESTINGNESS-SAME: "arg4" Index: llvm/unittests/IR/InstructionsTest.cpp =================================================================== --- llvm/unittests/IR/InstructionsTest.cpp +++ llvm/unittests/IR/InstructionsTest.cpp @@ -731,11 +731,11 @@ // Test cloning an attribute. { AttrBuilder AB(C); - AB.addAttribute(Attribute::ReadOnly); + AB.addAttribute(Attribute::NoUnwind); Call->setAttributes( AttributeList::get(C, AttributeList::FunctionIndex, AB)); std::unique_ptr Clone(cast(Call->clone())); - EXPECT_TRUE(Clone->onlyReadsMemory()); + EXPECT_TRUE(Clone->doesNotThrow()); } } Index: llvm/utils/TableGen/IntrinsicEmitter.cpp =================================================================== --- llvm/utils/TableGen/IntrinsicEmitter.cpp +++ llvm/utils/TableGen/IntrinsicEmitter.cpp @@ -776,49 +776,53 @@ case CodeGenIntrinsic::NoMem: if (Intrinsic.hasSideEffects) break; - OS << " Attribute::get(C, Attribute::ReadNone),\n"; + OS << " Attribute::getWithMemoryEffects(C, " + << "MemoryEffects::none()),\n"; break; case CodeGenIntrinsic::ReadArgMem: - OS << " Attribute::get(C, Attribute::ReadOnly),\n"; - OS << " Attribute::get(C, Attribute::ArgMemOnly),\n"; + OS << " Attribute::getWithMemoryEffects(C, " + << "MemoryEffects::argMemOnly(ModRefInfo::Ref)),\n"; break; case CodeGenIntrinsic::ReadMem: - OS << " Attribute::get(C, Attribute::ReadOnly),\n"; + OS << " Attribute::getWithMemoryEffects(C, " + << "MemoryEffects::readOnly()),\n"; break; case CodeGenIntrinsic::ReadInaccessibleMem: - OS << " Attribute::get(C, Attribute::ReadOnly),\n"; - OS << " Attribute::get(C, Attribute::InaccessibleMemOnly),\n"; + OS << " Attribute::getWithMemoryEffects(C, " + << "MemoryEffects::inaccessibleMemOnly(ModRefInfo::Ref)),\n"; break; case CodeGenIntrinsic::ReadInaccessibleMemOrArgMem: - OS << " Attribute::get(C, Attribute::ReadOnly),\n"; - OS << " Attribute::get(C, " - << "Attribute::InaccessibleMemOrArgMemOnly),\n"; + OS << " Attribute::getWithMemoryEffects(C, " + << "MemoryEffects::inaccessibleOrArgMemOnly(ModRefInfo::Ref)),\n"; + break; break; case CodeGenIntrinsic::WriteArgMem: - OS << " Attribute::get(C, Attribute::WriteOnly),\n"; - OS << " Attribute::get(C, Attribute::ArgMemOnly),\n"; + OS << " Attribute::getWithMemoryEffects(C, " + << "MemoryEffects::argMemOnly(ModRefInfo::Mod)),\n"; break; case CodeGenIntrinsic::WriteMem: - OS << " Attribute::get(C, Attribute::WriteOnly),\n"; + OS << " Attribute::getWithMemoryEffects(C, " + << "MemoryEffects::writeOnly()),\n"; break; case CodeGenIntrinsic::WriteInaccessibleMem: - OS << " Attribute::get(C, Attribute::WriteOnly),\n"; - OS << " Attribute::get(C, Attribute::InaccessibleMemOnly),\n"; + OS << " Attribute::getWithMemoryEffects(C, " + << "MemoryEffects::inaccessibleMemOnly(ModRefInfo::Mod)),\n"; break; case CodeGenIntrinsic::WriteInaccessibleMemOrArgMem: - OS << " Attribute::get(C, Attribute::WriteOnly),\n"; - OS << " Attribute::get(C, " - << "Attribute::InaccessibleMemOrArgMemOnly),\n"; + OS << " Attribute::getWithMemoryEffects(C, " + << "MemoryEffects::inaccessibleOrArgMemOnly(ModRefInfo::Mod)),\n"; break; case CodeGenIntrinsic::ReadWriteArgMem: - OS << " Attribute::get(C, Attribute::ArgMemOnly),\n"; + OS << " Attribute::getWithMemoryEffects(C, " + << "MemoryEffects::argMemOnly(ModRefInfo::ModRef)),\n"; break; case CodeGenIntrinsic::ReadWriteInaccessibleMem: - OS << " Attribute::get(C, Attribute::InaccessibleMemOnly),\n"; + OS << " Attribute::getWithMemoryEffects(C, " + << "MemoryEffects::inaccessibleMemOnly(ModRefInfo::ModRef)),\n"; break; case CodeGenIntrinsic::ReadWriteInaccessibleMemOrArgMem: - OS << " Attribute::get(C, " - << "Attribute::InaccessibleMemOrArgMemOnly),\n"; + OS << " Attribute::getWithMemoryEffects(C, " + << "MemoryEffects::inaccessibleOrArgMemOnly(ModRefInfo::ModRef)),\n"; break; case CodeGenIntrinsic::ReadWriteMem: break; Index: llvm/utils/UpdateTestChecks/common.py =================================================================== --- llvm/utils/UpdateTestChecks/common.py +++ llvm/utils/UpdateTestChecks/common.py @@ -327,7 +327,7 @@ UNUSED_NOTE = 'NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:' OPT_FUNCTION_RE = re.compile( - r'^(\s*;\s*Function\sAttrs:\s(?P[\w\s]+?))?\s*define\s+(?:internal\s+)?[^@]*@(?P[\w.$-]+?)\s*' + r'^(\s*;\s*Function\sAttrs:\s(?P[\w\s():,]+?))?\s*define\s+(?:internal\s+)?[^@]*@(?P[\w.$-]+?)\s*' r'(?P\((\)|(.*?[\w.-]+?)\))[^{]*\{)\n(?P.*?)^\}$', flags=(re.M | re.S)) Index: mlir/test/Target/LLVMIR/llvmir.mlir =================================================================== --- mlir/test/Target/LLVMIR/llvmir.mlir +++ mlir/test/Target/LLVMIR/llvmir.mlir @@ -1948,5 +1948,5 @@ // Function attributes: readnone // CHECK: declare void @readnone_function() #[[ATTR:[0-9]+]] -// CHECK: attributes #[[ATTR]] = { readnone } +// CHECK: attributes #[[ATTR]] = { memory(none) } llvm.func @readnone_function() attributes {llvm.readnone}