
Update the AA CaptureAnalysis providers to return CaptureComponents, so we can distinguish between full provenance and read-only provenance captures. Use this to restrict "other" memory effects on call from ModRef to Ref. Ideally we would also apply the same reasoning for escape sources, but the current API cannot actually convey the necessary information (we can only say NoAlias or MayAlias, not MayAlias but only via Ref).
93 lines
3.0 KiB
LLVM
93 lines
3.0 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
|
|
; RUN: opt -S -passes=gvn < %s | FileCheck %s
|
|
|
|
declare void @capture(ptr)
|
|
declare void @unknown_call()
|
|
|
|
define i32 @full_capture() {
|
|
; CHECK-LABEL: define i32 @full_capture() {
|
|
; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
|
|
; CHECK-NEXT: call void @capture(ptr [[A]])
|
|
; CHECK-NEXT: store i32 1, ptr [[A]], align 4
|
|
; CHECK-NEXT: call void @unknown_call()
|
|
; CHECK-NEXT: [[V:%.*]] = load i32, ptr [[A]], align 4
|
|
; CHECK-NEXT: ret i32 [[V]]
|
|
;
|
|
%a = alloca i32
|
|
call void @capture(ptr %a)
|
|
store i32 1, ptr %a
|
|
call void @unknown_call()
|
|
%v = load i32, ptr %a
|
|
ret i32 %v
|
|
}
|
|
|
|
define i32 @address_capture() {
|
|
; CHECK-LABEL: define i32 @address_capture() {
|
|
; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
|
|
; CHECK-NEXT: call void @capture(ptr captures(address) [[A]])
|
|
; CHECK-NEXT: store i32 1, ptr [[A]], align 4
|
|
; CHECK-NEXT: call void @unknown_call()
|
|
; CHECK-NEXT: ret i32 1
|
|
;
|
|
%a = alloca i32
|
|
call void @capture(ptr captures(address) %a)
|
|
store i32 1, ptr %a
|
|
call void @unknown_call()
|
|
%v = load i32, ptr %a
|
|
ret i32 %v
|
|
}
|
|
|
|
define i32 @read_provenance_capture() {
|
|
; CHECK-LABEL: define i32 @read_provenance_capture() {
|
|
; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
|
|
; CHECK-NEXT: call void @capture(ptr captures(address, read_provenance) [[A]])
|
|
; CHECK-NEXT: store i32 1, ptr [[A]], align 4
|
|
; CHECK-NEXT: call void @unknown_call()
|
|
; CHECK-NEXT: ret i32 1
|
|
;
|
|
%a = alloca i32
|
|
call void @capture(ptr captures(address, read_provenance) %a)
|
|
store i32 1, ptr %a
|
|
call void @unknown_call()
|
|
%v = load i32, ptr %a
|
|
ret i32 %v
|
|
}
|
|
|
|
define i32 @read_provenance_capture_and_full_capture() {
|
|
; CHECK-LABEL: define i32 @read_provenance_capture_and_full_capture() {
|
|
; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
|
|
; CHECK-NEXT: call void @capture(ptr captures(address, read_provenance) [[A]])
|
|
; CHECK-NEXT: call void @capture(ptr [[A]])
|
|
; CHECK-NEXT: store i32 1, ptr [[A]], align 4
|
|
; CHECK-NEXT: call void @unknown_call()
|
|
; CHECK-NEXT: [[V:%.*]] = load i32, ptr [[A]], align 4
|
|
; CHECK-NEXT: ret i32 [[V]]
|
|
;
|
|
%a = alloca i32
|
|
call void @capture(ptr captures(address, read_provenance) %a)
|
|
call void @capture(ptr %a)
|
|
store i32 1, ptr %a
|
|
call void @unknown_call()
|
|
%v = load i32, ptr %a
|
|
ret i32 %v
|
|
}
|
|
|
|
define i32 @read_provenance_capture_and_full_capture_commuted() {
|
|
; CHECK-LABEL: define i32 @read_provenance_capture_and_full_capture_commuted() {
|
|
; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
|
|
; CHECK-NEXT: call void @capture(ptr [[A]])
|
|
; CHECK-NEXT: call void @capture(ptr captures(address, read_provenance) [[A]])
|
|
; CHECK-NEXT: store i32 1, ptr [[A]], align 4
|
|
; CHECK-NEXT: call void @unknown_call()
|
|
; CHECK-NEXT: [[V:%.*]] = load i32, ptr [[A]], align 4
|
|
; CHECK-NEXT: ret i32 [[V]]
|
|
;
|
|
%a = alloca i32
|
|
call void @capture(ptr %a)
|
|
call void @capture(ptr captures(address, read_provenance) %a)
|
|
store i32 1, ptr %a
|
|
call void @unknown_call()
|
|
%v = load i32, ptr %a
|
|
ret i32 %v
|
|
}
|