declare void @dummy()
+declare void @foo(ptr)
+
; FIXME: This could be NoModRef
; CHECK-LABEL: Function: basic
; CHECK: Just Ref: Ptr: i32* @c <-> call void @dummy()
exit:
ret void
}
+
+; Tests that readonly noalias doesn't imply !Mod yet.
+;
+; CHECK-LABEL: Function: readonly_noalias
+; CHECK: Both ModRef: Ptr: i32* %p <-> call void @foo(ptr %p)
+define void @readonly_noalias(ptr readonly noalias %p) {
+ call void @foo(ptr %p)
+ load i32, ptr %p
+ ret void
+}
+
+; Tests that readnone noalias doesn't imply !Mod yet.
+;
+; CHECK-LABEL: Function: readnone_noalias
+; CHECK: Both ModRef: Ptr: i32* %p <-> call void @foo(ptr %p)
+define void @readnone_noalias(ptr readnone noalias %p) {
+ call void @foo(ptr %p)
+ load i32, ptr %p
+ ret void
+}
+
+; Tests that writeonly noalias doesn't imply !Ref (since it's still possible
+; to read from the object through other pointers if the pointer wasn't
+; written).
+;
+; CHECK-LABEL: Function: writeonly_noalias
+; CHECK: Both ModRef: Ptr: i32* %p <-> call void @foo(ptr %p)
+define void @writeonly_noalias(ptr writeonly noalias %p) {
+ call void @foo(ptr %p)
+ load i32, ptr %p
+ ret void
+}
+
+; Tests that readonly doesn't imply !Mod without noalias.
+;
+; CHECK-LABEL: Function: just_readonly
+; CHECK: Both ModRef: Ptr: i32* %p <-> call void @foo(ptr %p)
+define void @just_readonly(ptr readonly %p) {
+ call void @foo(ptr %p)
+ load i32, ptr %p
+ ret void
+}
+
+; Tests that readnone doesn't imply !Mod without noalias.
+;
+; CHECK-LABEL: Function: just_readnone
+; CHECK: Both ModRef: Ptr: i32* %p <-> call void @foo(ptr %p)
+define void @just_readnone(ptr readnone %p) {
+ call void @foo(ptr %p)
+ load i32, ptr %p
+ ret void
+}
+
+; Tests that writeonly doesn't imply !Ref.
+;
+; CHECK-LABEL: Function: just_writeonly
+; CHECK: Both ModRef: Ptr: i32* %p <-> call void @foo(ptr %p)
+define void @just_writeonly(ptr writeonly %p) {
+ call void @foo(ptr %p)
+ load i32, ptr %p
+ ret void
+}
ret float %r
}
+; Tests that we can't eliminate allocas copied from readonly noalias pointers yet.
+define void @memcpy_from_readonly_noalias(ptr readonly noalias align 8 dereferenceable(124) %arg) {
+; CHECK-LABEL: @memcpy_from_readonly_noalias(
+; CHECK-NEXT: [[ALLOCA:%.*]] = alloca [[T:%.*]], align 8
+; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 8 dereferenceable(124) [[ALLOCA]], ptr noundef nonnull align 8 dereferenceable(124) [[ARG:%.*]], i64 124, i1 false)
+; CHECK-NEXT: call void @bar(ptr nonnull [[ALLOCA]]) #[[ATTR3]]
+; CHECK-NEXT: ret void
+;
+ %alloca = alloca %T, align 8
+ call void @llvm.memcpy.p0.p0.i64(ptr %alloca, ptr %arg, i64 124, i1 false)
+ call void @bar(ptr %alloca) readonly
+ ret void
+}
+
+; Tests that we don't eliminate allocas copied from readonly pointers without noalias.
+define void @memcpy_from_just_readonly(ptr readonly align 8 dereferenceable(124) %arg) {
+; CHECK-LABEL: @memcpy_from_just_readonly(
+; CHECK-NEXT: [[ALLOCA:%.*]] = alloca [[T:%.*]], align 8
+; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 8 dereferenceable(124) [[ALLOCA]], ptr noundef nonnull align 8 dereferenceable(124) [[ARG:%.*]], i64 124, i1 false)
+; CHECK-NEXT: call void @bar(ptr nonnull [[ALLOCA]]) #[[ATTR3]]
+; CHECK-NEXT: ret void
+;
+ %alloca = alloca %T, align 8
+ call void @llvm.memcpy.p0.p0.i64(ptr %alloca, ptr %arg, i64 124, i1 false)
+ call void @bar(ptr %alloca) readonly
+ ret void
+}
+
attributes #0 = { null_pointer_is_valid }
ret void
}
+; We can't delete stores to readonly noalias pointers yet.
+define void @store_to_readonly_noalias(ptr readonly noalias %0) {
+; CHECK-LABEL: @store_to_readonly_noalias(
+; CHECK-NEXT: store i32 3, ptr [[TMP0:%.*]], align 4
+; CHECK-NEXT: ret void
+;
+ store i32 3, ptr %0, align 4
+ ret void
+}
+
!0 = !{!4, !4, i64 0}
!1 = !{!"omnipotent char", !2}
!2 = !{!"Simple C/C++ TBAA"}