diff --git a/llvm/include/llvm/IR/Intrinsics.td b/llvm/include/llvm/IR/Intrinsics.td --- a/llvm/include/llvm/IR/Intrinsics.td +++ b/llvm/include/llvm/IR/Intrinsics.td @@ -1165,7 +1165,10 @@ // might change in the future. def int_launder_invariant_group : DefaultAttrsIntrinsic<[llvm_anyptr_ty], [LLVMMatchType<0>], - [IntrInaccessibleMemOnly, IntrSpeculatable, IntrWillReturn]>; + [IntrInaccessibleMemOnly, + IntrSpeculatable, + IntrWillReturn, + WriteOnly]>; def int_strip_invariant_group : DefaultAttrsIntrinsic<[llvm_anyptr_ty], diff --git a/llvm/test/Other/invariant.group.ll b/llvm/test/Other/invariant.group.ll --- a/llvm/test/Other/invariant.group.ll +++ b/llvm/test/Other/invariant.group.ll @@ -91,7 +91,7 @@ declare void @useBool(i1) declare void @clobber(i8*) -; CHECK: Function Attrs: inaccessiblememonly nofree nosync nounwind speculatable willreturn{{$}} +; CHECK: Function Attrs: inaccessiblememonly nofree nosync nounwind speculatable willreturn writeonly{{$}} ; CHECK-NEXT: declare i8* @llvm.launder.invariant.group.p0i8(i8*) declare i8* @llvm.launder.invariant.group.p0i8(i8*) diff --git a/llvm/test/Transforms/Attributor/nocapture-1.ll b/llvm/test/Transforms/Attributor/nocapture-1.ll --- a/llvm/test/Transforms/Attributor/nocapture-1.ll +++ b/llvm/test/Transforms/Attributor/nocapture-1.ll @@ -54,7 +54,7 @@ ; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind willreturn writeonly ; IS__CGSCC____-LABEL: define {{[^@]+}}@c3 ; IS__CGSCC____-SAME: (i32* nofree writeonly [[Q:%.*]]) #[[ATTR1]] { -; IS__CGSCC____-NEXT: call void @c2(i32* nofree writeonly [[Q]]) #[[ATTR19:[0-9]+]] +; IS__CGSCC____-NEXT: call void @c2(i32* nofree writeonly [[Q]]) #[[ATTR18:[0-9]+]] ; IS__CGSCC____-NEXT: ret void ; call void @c2(i32* %q) @@ -228,7 +228,7 @@ ; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readonly willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@c7 ; IS__CGSCC____-SAME: (i32* nofree readonly [[Q:%.*]], i32 [[BITNO:%.*]]) #[[ATTR2]] { -; IS__CGSCC____-NEXT: [[PTR:%.*]] = call i1* @lookup_bit(i32* noalias nofree readnone [[Q]], i32 [[BITNO]]) #[[ATTR20:[0-9]+]] +; IS__CGSCC____-NEXT: [[PTR:%.*]] = call i1* @lookup_bit(i32* noalias nofree readnone [[Q]], i32 [[BITNO]]) #[[ATTR19:[0-9]+]] ; IS__CGSCC____-NEXT: [[VAL:%.*]] = load i1, i1* [[PTR]], align 1 ; IS__CGSCC____-NEXT: ret i1 [[VAL]] ; @@ -332,7 +332,7 @@ ; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@nc2 ; IS__CGSCC____-SAME: (i32* nocapture nofree align 4 [[P:%.*]], i32* nofree [[Q:%.*]]) #[[ATTR5]] { -; IS__CGSCC____-NEXT: [[TMP1:%.*]] = call i32 @nc1(i32* nofree [[Q]], i32* nocapture nofree align 4 [[P]], i1 noundef false) #[[ATTR16:[0-9]+]] +; IS__CGSCC____-NEXT: [[TMP1:%.*]] = call i32 @nc1(i32* nofree [[Q]], i32* nocapture nofree align 4 [[P]], i1 noundef false) #[[ATTR15:[0-9]+]] ; IS__CGSCC____-NEXT: ret void ; %1 = call i32 @nc1(i32* %q, i32* %p, i1 0) ; [#uses=0] @@ -363,7 +363,7 @@ ; IS__CGSCC____: Function Attrs: argmemonly nounwind ; IS__CGSCC____-LABEL: define {{[^@]+}}@nc4 ; IS__CGSCC____-SAME: (i8* [[P:%.*]]) #[[ATTR6:[0-9]+]] { -; IS__CGSCC____-NEXT: call void @external(i8* readonly [[P]]) #[[ATTR21:[0-9]+]] +; IS__CGSCC____-NEXT: call void @external(i8* readonly [[P]]) #[[ATTR20:[0-9]+]] ; IS__CGSCC____-NEXT: ret void ; call void @external(i8* %p) @@ -607,19 +607,19 @@ } define void @nocaptureLaunder(i8* %p) { -; IS__TUNIT____: Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn +; IS__TUNIT____: Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn writeonly ; IS__TUNIT____-LABEL: define {{[^@]+}}@nocaptureLaunder -; IS__TUNIT____-SAME: (i8* nocapture nofree [[P:%.*]]) #[[ATTR10:[0-9]+]] { +; IS__TUNIT____-SAME: (i8* nocapture nofree writeonly [[P:%.*]]) #[[ATTR10:[0-9]+]] { ; IS__TUNIT____-NEXT: entry: -; IS__TUNIT____-NEXT: [[B:%.*]] = call i8* @llvm.launder.invariant.group.p0i8(i8* nofree [[P]]) #[[ATTR19:[0-9]+]] +; IS__TUNIT____-NEXT: [[B:%.*]] = call i8* @llvm.launder.invariant.group.p0i8(i8* nofree writeonly [[P]]) #[[ATTR19:[0-9]+]] ; IS__TUNIT____-NEXT: store i8 42, i8* [[B]], align 1 ; IS__TUNIT____-NEXT: ret void ; -; IS__CGSCC____: Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn +; IS__CGSCC____: Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn writeonly ; IS__CGSCC____-LABEL: define {{[^@]+}}@nocaptureLaunder -; IS__CGSCC____-SAME: (i8* nocapture nofree [[P:%.*]]) #[[ATTR10:[0-9]+]] { +; IS__CGSCC____-SAME: (i8* nocapture nofree writeonly [[P:%.*]]) #[[ATTR10:[0-9]+]] { ; IS__CGSCC____-NEXT: entry: -; IS__CGSCC____-NEXT: [[B:%.*]] = call i8* @llvm.launder.invariant.group.p0i8(i8* nofree [[P]]) #[[ATTR22:[0-9]+]] +; IS__CGSCC____-NEXT: [[B:%.*]] = call i8* @llvm.launder.invariant.group.p0i8(i8* nofree writeonly [[P]]) #[[ATTR21:[0-9]+]] ; IS__CGSCC____-NEXT: store i8 42, i8* [[B]], align 1 ; IS__CGSCC____-NEXT: ret void ; @@ -631,17 +631,17 @@ @g2 = global i8* null define void @captureLaunder(i8* %p) { -; IS__TUNIT____: Function Attrs: nofree nosync nounwind willreturn +; IS__TUNIT____: Function Attrs: nofree nosync nounwind willreturn writeonly ; IS__TUNIT____-LABEL: define {{[^@]+}}@captureLaunder -; IS__TUNIT____-SAME: (i8* nofree [[P:%.*]]) #[[ATTR5]] { -; IS__TUNIT____-NEXT: [[B:%.*]] = call i8* @llvm.launder.invariant.group.p0i8(i8* nofree [[P]]) #[[ATTR19]] +; IS__TUNIT____-SAME: (i8* nofree writeonly [[P:%.*]]) #[[ATTR1]] { +; IS__TUNIT____-NEXT: [[B:%.*]] = call i8* @llvm.launder.invariant.group.p0i8(i8* nofree writeonly [[P]]) #[[ATTR19]] ; IS__TUNIT____-NEXT: store i8* [[B]], i8** @g2, align 8 ; IS__TUNIT____-NEXT: ret void ; -; IS__CGSCC____: Function Attrs: nofree nosync nounwind willreturn +; IS__CGSCC____: Function Attrs: nofree nosync nounwind willreturn writeonly ; IS__CGSCC____-LABEL: define {{[^@]+}}@captureLaunder -; IS__CGSCC____-SAME: (i8* nofree [[P:%.*]]) #[[ATTR11:[0-9]+]] { -; IS__CGSCC____-NEXT: [[B:%.*]] = call i8* @llvm.launder.invariant.group.p0i8(i8* nofree [[P]]) #[[ATTR22]] +; IS__CGSCC____-SAME: (i8* nofree writeonly [[P:%.*]]) #[[ATTR11:[0-9]+]] { +; IS__CGSCC____-NEXT: [[B:%.*]] = call i8* @llvm.launder.invariant.group.p0i8(i8* nofree writeonly [[P]]) #[[ATTR21]] ; IS__CGSCC____-NEXT: store i8* [[B]], i8** @g2, align 8 ; IS__CGSCC____-NEXT: ret void ; @@ -663,7 +663,7 @@ ; IS__CGSCC____-LABEL: define {{[^@]+}}@nocaptureStrip ; IS__CGSCC____-SAME: (i8* nocapture nofree writeonly [[P:%.*]]) #[[ATTR12:[0-9]+]] { ; IS__CGSCC____-NEXT: entry: -; IS__CGSCC____-NEXT: [[B:%.*]] = call i8* @llvm.strip.invariant.group.p0i8(i8* noalias nofree readnone [[P]]) #[[ATTR20]] +; IS__CGSCC____-NEXT: [[B:%.*]] = call i8* @llvm.strip.invariant.group.p0i8(i8* noalias nofree readnone [[P]]) #[[ATTR19]] ; IS__CGSCC____-NEXT: store i8 42, i8* [[B]], align 1 ; IS__CGSCC____-NEXT: ret void ; @@ -684,8 +684,8 @@ ; ; IS__CGSCC____: Function Attrs: nofree nosync nounwind willreturn writeonly ; IS__CGSCC____-LABEL: define {{[^@]+}}@captureStrip -; IS__CGSCC____-SAME: (i8* nofree writeonly [[P:%.*]]) #[[ATTR13:[0-9]+]] { -; IS__CGSCC____-NEXT: [[B:%.*]] = call i8* @llvm.strip.invariant.group.p0i8(i8* noalias nofree readnone [[P]]) #[[ATTR20]] +; IS__CGSCC____-SAME: (i8* nofree writeonly [[P:%.*]]) #[[ATTR11]] { +; IS__CGSCC____-NEXT: [[B:%.*]] = call i8* @llvm.strip.invariant.group.p0i8(i8* noalias nofree readnone [[P]]) #[[ATTR19]] ; IS__CGSCC____-NEXT: store i8* [[B]], i8** @g3, align 8 ; IS__CGSCC____-NEXT: ret void ; @@ -792,7 +792,7 @@ ; ; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind null_pointer_is_valid readnone willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@captureDereferenceableOrNullICmp -; IS__CGSCC____-SAME: (i32* nofree readnone dereferenceable_or_null(4) [[X:%.*]]) #[[ATTR14:[0-9]+]] { +; IS__CGSCC____-SAME: (i32* nofree readnone dereferenceable_or_null(4) [[X:%.*]]) #[[ATTR13:[0-9]+]] { ; IS__CGSCC____-NEXT: [[TMP1:%.*]] = bitcast i32* [[X]] to i8* ; IS__CGSCC____-NEXT: [[TMP2:%.*]] = icmp eq i8* [[TMP1]], null ; IS__CGSCC____-NEXT: ret i1 [[TMP2]] @@ -856,7 +856,7 @@ ; ; IS__CGSCC____: Function Attrs: nounwind willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@ptr_uses -; IS__CGSCC____-SAME: (i8* [[PTR:%.*]], i8* nocapture nofree noundef nonnull writeonly dereferenceable(1) [[WPTR:%.*]]) #[[ATTR16]] { +; IS__CGSCC____-SAME: (i8* [[PTR:%.*]], i8* nocapture nofree noundef nonnull writeonly dereferenceable(1) [[WPTR:%.*]]) #[[ATTR15]] { ; IS__CGSCC____-NEXT: store i8 0, i8* [[WPTR]], align 1 ; IS__CGSCC____-NEXT: ret void ; @@ -880,16 +880,16 @@ ; IS__TUNIT____: attributes #[[ATTR7]] = { nofree nosync nounwind writeonly } ; IS__TUNIT____: attributes #[[ATTR8]] = { nofree noreturn nosync nounwind readnone willreturn } ; IS__TUNIT____: attributes #[[ATTR9]] = { argmemonly nofree nounwind willreturn } -; IS__TUNIT____: attributes #[[ATTR10]] = { inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn } +; IS__TUNIT____: attributes #[[ATTR10]] = { inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn writeonly } ; IS__TUNIT____: attributes #[[ATTR11]] = { argmemonly nofree nosync nounwind willreturn writeonly } ; IS__TUNIT____: attributes #[[ATTR12]] = { nofree nosync nounwind null_pointer_is_valid readnone willreturn } ; IS__TUNIT____: attributes #[[ATTR13:[0-9]+]] = { nounwind readonly willreturn } ; IS__TUNIT____: attributes #[[ATTR14]] = { nounwind willreturn } -; IS__TUNIT____: attributes #[[ATTR15:[0-9]+]] = { inaccessiblememonly nofree nosync nounwind speculatable willreturn } +; IS__TUNIT____: attributes #[[ATTR15:[0-9]+]] = { inaccessiblememonly nofree nosync nounwind speculatable willreturn writeonly } ; IS__TUNIT____: attributes #[[ATTR16:[0-9]+]] = { nofree nosync nounwind readnone speculatable willreturn } ; IS__TUNIT____: attributes #[[ATTR17]] = { nofree nounwind readnone willreturn } ; IS__TUNIT____: attributes #[[ATTR18]] = { nounwind } -; IS__TUNIT____: attributes #[[ATTR19]] = { willreturn } +; IS__TUNIT____: attributes #[[ATTR19]] = { willreturn writeonly } ; IS__TUNIT____: attributes #[[ATTR20]] = { readnone willreturn } ;. ; IS__CGSCC____: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind readnone willreturn } @@ -902,17 +902,16 @@ ; IS__CGSCC____: attributes #[[ATTR7]] = { nofree nosync nounwind writeonly } ; IS__CGSCC____: attributes #[[ATTR8]] = { nofree norecurse noreturn nosync nounwind readnone willreturn } ; IS__CGSCC____: attributes #[[ATTR9]] = { argmemonly nofree norecurse nounwind willreturn } -; IS__CGSCC____: attributes #[[ATTR10]] = { inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn } -; IS__CGSCC____: attributes #[[ATTR11]] = { nofree nosync nounwind willreturn } +; IS__CGSCC____: attributes #[[ATTR10]] = { inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn writeonly } +; IS__CGSCC____: attributes #[[ATTR11]] = { nofree nosync nounwind willreturn writeonly } ; IS__CGSCC____: attributes #[[ATTR12]] = { argmemonly nofree nosync nounwind willreturn writeonly } -; IS__CGSCC____: attributes #[[ATTR13]] = { nofree nosync nounwind willreturn writeonly } -; IS__CGSCC____: attributes #[[ATTR14]] = { nofree norecurse nosync nounwind null_pointer_is_valid readnone willreturn } -; IS__CGSCC____: attributes #[[ATTR15:[0-9]+]] = { nounwind readonly willreturn } -; IS__CGSCC____: attributes #[[ATTR16]] = { nounwind willreturn } -; IS__CGSCC____: attributes #[[ATTR17:[0-9]+]] = { inaccessiblememonly nofree nosync nounwind speculatable willreturn } -; IS__CGSCC____: attributes #[[ATTR18:[0-9]+]] = { nofree nosync nounwind readnone speculatable willreturn } -; IS__CGSCC____: attributes #[[ATTR19]] = { nounwind willreturn writeonly } -; IS__CGSCC____: attributes #[[ATTR20]] = { readnone willreturn } -; IS__CGSCC____: attributes #[[ATTR21]] = { nounwind } -; IS__CGSCC____: attributes #[[ATTR22]] = { willreturn } +; IS__CGSCC____: attributes #[[ATTR13]] = { nofree norecurse nosync nounwind null_pointer_is_valid readnone willreturn } +; IS__CGSCC____: attributes #[[ATTR14:[0-9]+]] = { nounwind readonly willreturn } +; IS__CGSCC____: attributes #[[ATTR15]] = { nounwind willreturn } +; IS__CGSCC____: attributes #[[ATTR16:[0-9]+]] = { inaccessiblememonly nofree nosync nounwind speculatable willreturn writeonly } +; IS__CGSCC____: attributes #[[ATTR17:[0-9]+]] = { nofree nosync nounwind readnone speculatable willreturn } +; IS__CGSCC____: attributes #[[ATTR18]] = { nounwind willreturn writeonly } +; IS__CGSCC____: attributes #[[ATTR19]] = { readnone willreturn } +; IS__CGSCC____: attributes #[[ATTR20]] = { nounwind } +; IS__CGSCC____: attributes #[[ATTR21]] = { willreturn writeonly } ;. diff --git a/llvm/test/Transforms/FunctionAttrs/launder.ll b/llvm/test/Transforms/FunctionAttrs/launder.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/FunctionAttrs/launder.ll @@ -0,0 +1,11 @@ +; RUN: opt -passes=function-attrs < %s -S | FileCheck %s + +; CHECK: Function Attrs: {{.*}} writeonly +; CHECK-NEXT: define void @f +define void @f(i8* %a) { + %b = call i8* @llvm.launder.invariant.group.p0i8(i8* %a) + store i8 9, i8* %b + ret void +} + +declare i8* @llvm.launder.invariant.group.p0i8(i8*)