Index: llvm/docs/LangRef.rst =================================================================== --- llvm/docs/LangRef.rst +++ llvm/docs/LangRef.rst @@ -1907,6 +1907,10 @@ If an argmemonly function reads or writes memory other than the pointer arguments, or has other side-effects, the behavior is undefined. +``globalmemonly`` + This attribute indicates that the only memory accessed inside a function, + that is visible to the callee, is global memory. If the function reads or + writes other memory that is visible to the callee, the behavior is undefined. ``returns_twice`` This attribute indicates that this function can return twice. The C ``setjmp`` is an example of such a function. The compiler disables Index: llvm/include/llvm/AsmParser/LLToken.h =================================================================== --- llvm/include/llvm/AsmParser/LLToken.h +++ llvm/include/llvm/AsmParser/LLToken.h @@ -252,6 +252,7 @@ kw_immarg, kw_byref, kw_mustprogress, + kw_globalmemonly, kw_type, kw_opaque, Index: llvm/include/llvm/Bitcode/LLVMBitCodes.h =================================================================== --- llvm/include/llvm/Bitcode/LLVMBitCodes.h +++ llvm/include/llvm/Bitcode/LLVMBitCodes.h @@ -672,6 +672,7 @@ ATTR_KIND_NO_SANITIZE_COVERAGE = 76, ATTR_KIND_ELEMENTTYPE = 77, ATTR_KIND_DISABLE_SANITIZER_INSTRUMENTATION = 78, + ATTR_KIND_GLOBALMEMONLY = 79 }; enum ComdatSelectionKindCodes { Index: llvm/include/llvm/IR/Attributes.td =================================================================== --- llvm/include/llvm/IR/Attributes.td +++ llvm/include/llvm/IR/Attributes.td @@ -92,6 +92,9 @@ /// Provide pointer element type to intrinsic. def ElementType : TypeAttr<"elementtype", [ParamAttr]>; +/// Function can only access or modify global variables +def GlobalMemOnly : EnumAttr<"globalmemonly", [FnAttr]>; + /// Function may only access memory that is inaccessible from IR. def InaccessibleMemOnly : EnumAttr<"inaccessiblememonly", [FnAttr]>; Index: llvm/lib/AsmParser/LLLexer.cpp =================================================================== --- llvm/lib/AsmParser/LLLexer.cpp +++ llvm/lib/AsmParser/LLLexer.cpp @@ -708,6 +708,7 @@ KEYWORD(immarg); KEYWORD(byref); KEYWORD(mustprogress); + KEYWORD(globalmemonly); KEYWORD(type); KEYWORD(opaque); Index: llvm/lib/Bitcode/Reader/BitcodeReader.cpp =================================================================== --- llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -1533,6 +1533,8 @@ return Attribute::MustProgress; case bitc::ATTR_KIND_HOT: return Attribute::Hot; + case bitc::ATTR_KIND_GLOBALMEMONLY: + return Attribute::GlobalMemOnly; } } Index: llvm/lib/Bitcode/Writer/BitcodeWriter.cpp =================================================================== --- llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -764,6 +764,8 @@ return bitc::ATTR_KIND_BYREF; case Attribute::MustProgress: return bitc::ATTR_KIND_MUSTPROGRESS; + case Attribute::GlobalMemOnly: + return bitc::ATTR_KIND_GLOBALMEMONLY; case Attribute::EndAttrKinds: llvm_unreachable("Can not encode end-attribute kinds marker."); case Attribute::None: Index: llvm/lib/Transforms/Utils/CodeExtractor.cpp =================================================================== --- llvm/lib/Transforms/Utils/CodeExtractor.cpp +++ llvm/lib/Transforms/Utils/CodeExtractor.cpp @@ -904,6 +904,7 @@ case Attribute::Dereferenceable: case Attribute::DereferenceableOrNull: case Attribute::ElementType: + case Attribute::GlobalMemOnly: case Attribute::InAlloca: case Attribute::InReg: case Attribute::InaccessibleMemOnly: Index: llvm/test/Bitcode/attributes.ll =================================================================== --- llvm/test/Bitcode/attributes.ll +++ llvm/test/Bitcode/attributes.ll @@ -478,6 +478,12 @@ ret void; } +; CHECK: define void @f81() #51 +define void @f81() globalmemonly +{ + ret void; +} + ; CHECK: attributes #0 = { noreturn } ; CHECK: attributes #1 = { nounwind } ; CHECK: attributes #2 = { readnone } @@ -529,4 +535,5 @@ ; CHECK: attributes #48 = { nosanitize_coverage } ; CHECK: attributes #49 = { noprofile } ; CHECK: attributes #50 = { disable_sanitizer_instrumentation } +; CHECK: attributes #51 = { globalmemonly } ; CHECK: attributes #[[NOBUILTIN]] = { nobuiltin }