diff --git a/llvm/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp b/llvm/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp --- a/llvm/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp +++ b/llvm/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp @@ -1333,6 +1333,27 @@ return Ret; } +// List of all function attributes which must be stripped when lowering from +// abstract machine model to physical machine model. Essentially, these are +// all the effects a safepoint might have which we ignored in the abstract +// 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}; + +// List of all parameter and return attributes which must be stripped when +// lowering from the abstract machine model. Note that we list attributes +// here which aren't valid as return attributes, that is okay. There are +// also some additional attributes with arguments which are handled +// explicitly and are not in this list. +static constexpr Attribute::AttrKind ParamAttrsToStrip[] = + {Attribute::ReadNone, Attribute::ReadOnly, Attribute::WriteOnly, + Attribute::NoAlias, Attribute::NoFree}; + + // Create new attribute set containing only attributes which can be transferred // from original call to the safepoint. static AttributeList legalizeCallAttributes(LLVMContext &Ctx, @@ -1342,8 +1363,7 @@ // Remove the readonly, readnone, and statepoint function attributes. AttrBuilder FnAttrs = AL.getFnAttributes(); - for (auto Attr : {Attribute::ReadNone, Attribute::ReadOnly, - Attribute::NoSync, Attribute::NoFree}) + for (auto Attr : FnAttrsToStrip) FnAttrs.removeAttribute(Attr); for (Attribute A : AL.getFnAttributes()) { @@ -2583,7 +2603,7 @@ if (AH.getDereferenceableOrNullBytes(Index)) R.addAttribute(Attribute::get(Ctx, Attribute::DereferenceableOrNull, AH.getDereferenceableOrNullBytes(Index))); - for (auto Attr : {Attribute::NoAlias, Attribute::NoFree}) + for (auto Attr : ParamAttrsToStrip) if (AH.getAttributes().hasAttribute(Index, Attr)) R.addAttribute(Attr); @@ -2612,7 +2632,7 @@ if (isa(F.getReturnType())) RemoveNonValidAttrAtIndex(Ctx, F, AttributeList::ReturnIndex); - for (auto Attr : {Attribute::NoSync, Attribute::NoFree}) + for (auto Attr : FnAttrsToStrip) F.removeFnAttr(Attr); } diff --git a/llvm/test/Transforms/RewriteStatepointsForGC/strip-invalid-attributes.ll b/llvm/test/Transforms/RewriteStatepointsForGC/strip-invalid-attributes.ll --- a/llvm/test/Transforms/RewriteStatepointsForGC/strip-invalid-attributes.ll +++ b/llvm/test/Transforms/RewriteStatepointsForGC/strip-invalid-attributes.ll @@ -55,3 +55,39 @@ ret i8 addrspace(1)* %arg } +define i8 addrspace(1)* @readnone(i8 addrspace(1)* readnone %arg) readnone gc "statepoint-example" { +; CHECK: define i8 addrspace(1)* @readnone(i8 addrspace(1)* %arg) gc "statepoint-example" { + call void @f() + ret i8 addrspace(1)* %arg +} + +define i8 addrspace(1)* @readonly(i8 addrspace(1)* readonly %arg) readonly gc "statepoint-example" { +; CHECK: define i8 addrspace(1)* @readonly(i8 addrspace(1)* %arg) gc "statepoint-example" { + call void @f() + ret i8 addrspace(1)* %arg +} + +define i8 addrspace(1)* @writeonly(i8 addrspace(1)* writeonly %arg) writeonly gc "statepoint-example" { +; CHECK: define i8 addrspace(1)* @writeonly(i8 addrspace(1)* %arg) gc "statepoint-example" { + call void @f() + ret i8 addrspace(1)* %arg +} + +define i8 addrspace(1)* @argmemonly(i8 addrspace(1)* %arg) argmemonly gc "statepoint-example" { +; CHECK: define i8 addrspace(1)* @argmemonly(i8 addrspace(1)* %arg) gc "statepoint-example" { + call void @f() + ret i8 addrspace(1)* %arg +} + +define i8 addrspace(1)* @inaccessiblememonly(i8 addrspace(1)* %arg) inaccessiblememonly gc "statepoint-example" { +; CHECK: define i8 addrspace(1)* @inaccessiblememonly(i8 addrspace(1)* %arg) gc "statepoint-example" { + call void @f() + ret i8 addrspace(1)* %arg +} + +define i8 addrspace(1)* @inaccessiblemem_or_argmemonly(i8 addrspace(1)* %arg) inaccessiblemem_or_argmemonly gc "statepoint-example" { +; CHECK: define i8 addrspace(1)* @inaccessiblemem_or_argmemonly(i8 addrspace(1)* %arg) gc "statepoint-example" { + call void @f() + ret i8 addrspace(1)* %arg +} +