For the purposes of alias analysis, we should only consider provenance captures, not address captures. To support this, change (or add) CaptureTracking APIs to accept a Mask and StopFn argument. The Mask determines which components we are interested in (for AA that would be Provenance). The StopFn determines when we can abort the walk early. Currently, we want to do this as soon as any of the components in the Mask is captured. The purpose of making this a separate predicate is that in the future we will also want to distinguish between capturing full provenance and read-only provenance. In that case, we can only stop early once full provenance is captured. The earliest escape analysis does not get a StopFn, because it must always inspect all captures.
66 lines
2.5 KiB
LLVM
66 lines
2.5 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
|
|
; RUN: opt -S -passes=dse < %s | FileCheck %s
|
|
|
|
declare ptr @passthrough(ptr)
|
|
|
|
define i16 @ret_only() {
|
|
; CHECK-LABEL: define i16 @ret_only() {
|
|
; CHECK-NEXT: [[A:%.*]] = alloca i16, align 1
|
|
; CHECK-NEXT: store i16 1, ptr [[A]], align 1
|
|
; CHECK-NEXT: [[CALL:%.*]] = call ptr @passthrough(ptr readnone captures(ret: address, provenance) [[A]])
|
|
; CHECK-NEXT: [[V:%.*]] = load i16, ptr [[CALL]], align 1
|
|
; CHECK-NEXT: ret i16 [[V]]
|
|
;
|
|
%a = alloca i16, align 1
|
|
store i16 1, ptr %a, align 1
|
|
%call = call ptr @passthrough(ptr readnone captures(ret: address, provenance) %a)
|
|
%v = load i16, ptr %call, align 1
|
|
ret i16 %v
|
|
}
|
|
|
|
define i16 @ret_has_more_components() {
|
|
; CHECK-LABEL: define i16 @ret_has_more_components() {
|
|
; CHECK-NEXT: [[A:%.*]] = alloca i16, align 1
|
|
; CHECK-NEXT: store i16 1, ptr [[A]], align 1
|
|
; CHECK-NEXT: [[CALL:%.*]] = call ptr @passthrough(ptr readnone captures(address, ret: address, provenance) [[A]])
|
|
; CHECK-NEXT: [[V:%.*]] = load i16, ptr [[CALL]], align 1
|
|
; CHECK-NEXT: ret i16 [[V]]
|
|
;
|
|
%a = alloca i16, align 1
|
|
store i16 1, ptr %a, align 1
|
|
%call = call ptr @passthrough(ptr readnone captures(address, ret: address, provenance) %a)
|
|
%v = load i16, ptr %call, align 1
|
|
ret i16 %v
|
|
}
|
|
|
|
; Okay to drop the store as only the address of %a is captured, so the load
|
|
; cannot be accessing %a.
|
|
define i16 @address_capture() {
|
|
; CHECK-LABEL: define i16 @address_capture() {
|
|
; CHECK-NEXT: [[A:%.*]] = alloca i16, align 1
|
|
; CHECK-NEXT: [[CALL:%.*]] = call ptr @passthrough(ptr readnone captures(address) [[A]])
|
|
; CHECK-NEXT: [[V:%.*]] = load i16, ptr [[CALL]], align 1
|
|
; CHECK-NEXT: ret i16 [[V]]
|
|
;
|
|
%a = alloca i16, align 1
|
|
store i16 1, ptr %a, align 1
|
|
%call = call ptr @passthrough(ptr readnone captures(address) %a)
|
|
%v = load i16, ptr %call, align 1
|
|
ret i16 %v
|
|
}
|
|
|
|
define i16 @read_only_capture() {
|
|
; CHECK-LABEL: define i16 @read_only_capture() {
|
|
; CHECK-NEXT: [[A:%.*]] = alloca i16, align 1
|
|
; CHECK-NEXT: store i16 1, ptr [[A]], align 1
|
|
; CHECK-NEXT: [[CALL:%.*]] = call ptr @passthrough(ptr readnone captures(address, read_provenance) [[A]])
|
|
; CHECK-NEXT: [[V:%.*]] = load i16, ptr [[CALL]], align 1
|
|
; CHECK-NEXT: ret i16 [[V]]
|
|
;
|
|
%a = alloca i16, align 1
|
|
store i16 1, ptr %a, align 1
|
|
%call = call ptr @passthrough(ptr readnone captures(address, read_provenance) %a)
|
|
%v = load i16, ptr %call, align 1
|
|
ret i16 %v
|
|
}
|