[IR] Take operand bundles into account for call argument readonly/writeonly
We currently only take operand bundle effects into account when querying the function-level memory attributes. However, I believe that we also need to do the same for parameter attributes. For example, a call with deopt bundle to a function with readnone parameter attribute cannot treat that parameter as readnone, because the deopt bundle may read it. Differential Revision: https://reviews.llvm.org/D136834
This commit is contained in:
parent
bcedeefa40
commit
6aa672f141
|
@ -344,9 +344,25 @@ bool CallBase::paramHasAttr(unsigned ArgNo, Attribute::AttrKind Kind) const {
|
|||
|
||||
if (Attrs.hasParamAttr(ArgNo, Kind))
|
||||
return true;
|
||||
if (const Function *F = getCalledFunction())
|
||||
return F->getAttributes().hasParamAttr(ArgNo, Kind);
|
||||
return false;
|
||||
|
||||
const Function *F = getCalledFunction();
|
||||
if (!F)
|
||||
return false;
|
||||
|
||||
if (!F->getAttributes().hasParamAttr(ArgNo, Kind))
|
||||
return false;
|
||||
|
||||
// Take into account mod/ref by operand bundles.
|
||||
switch (Kind) {
|
||||
case Attribute::ReadNone:
|
||||
return !hasReadingOperandBundles() && !hasClobberingOperandBundles();
|
||||
case Attribute::ReadOnly:
|
||||
return !hasClobberingOperandBundles();
|
||||
case Attribute::WriteOnly:
|
||||
return !hasReadingOperandBundles();
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool CallBase::hasFnAttrOnCalledFunction(Attribute::AttrKind Kind) const {
|
||||
|
|
|
@ -21,7 +21,7 @@ define void @test1(i8* %p) {
|
|||
; Check that global G1 is reported as Ref by memcpy/memmove calls.
|
||||
define i32 @test_memcpy_with_deopt() {
|
||||
; CHECK-LABEL: Function: test_memcpy_with_deopt:
|
||||
; CHECK: Just Mod: Ptr: i8* %A <-> call void @llvm.memcpy.p0i8.p0i8.i64(i8* %A, i8* %B, i64 -1, i1 false) [ "deopt"() ]
|
||||
; CHECK: Both ModRef: Ptr: i8* %A <-> call void @llvm.memcpy.p0i8.p0i8.i64(i8* %A, i8* %B, i64 -1, i1 false) [ "deopt"() ]
|
||||
; CHECK: Just Ref: Ptr: i8* %B <-> call void @llvm.memcpy.p0i8.p0i8.i64(i8* %A, i8* %B, i64 -1, i1 false) [ "deopt"() ]
|
||||
; CHECK: Just Ref: Ptr: i32* @G1 <-> call void @llvm.memcpy.p0i8.p0i8.i64(i8* %A, i8* %B, i64 -1, i1 false) [ "deopt"() ]
|
||||
|
||||
|
@ -40,7 +40,7 @@ define i32 @test_memcpy_with_deopt() {
|
|||
|
||||
define i32 @test_memmove_with_deopt() {
|
||||
; CHECK-LABEL: Function: test_memmove_with_deopt:
|
||||
; CHECK: Just Mod: Ptr: i8* %A <-> call void @llvm.memmove.p0i8.p0i8.i64(i8* %A, i8* %B, i64 -1, i1 false) [ "deopt"() ]
|
||||
; CHECK: Both ModRef: Ptr: i8* %A <-> call void @llvm.memmove.p0i8.p0i8.i64(i8* %A, i8* %B, i64 -1, i1 false) [ "deopt"() ]
|
||||
; CHECK: Just Ref: Ptr: i8* %B <-> call void @llvm.memmove.p0i8.p0i8.i64(i8* %A, i8* %B, i64 -1, i1 false) [ "deopt"() ]
|
||||
; CHECK: Just Ref: Ptr: i32* @G1 <-> call void @llvm.memmove.p0i8.p0i8.i64(i8* %A, i8* %B, i64 -1, i1 false) [ "deopt"() ]
|
||||
|
||||
|
|
|
@ -326,9 +326,10 @@ exit:
|
|||
declare void @readnone_param(ptr nocapture readnone %p)
|
||||
declare void @readonly_param(ptr nocapture readonly %p)
|
||||
|
||||
; FIXME: While this can't be readnone, this could be readonly.
|
||||
define void @op_bundle_readnone_deopt(ptr %p) {
|
||||
; CHECK-LABEL: define {{[^@]+}}@op_bundle_readnone_deopt
|
||||
; CHECK-SAME: (ptr nocapture readnone [[P:%.*]]) {
|
||||
; CHECK-SAME: (ptr nocapture [[P:%.*]]) {
|
||||
; CHECK-NEXT: call void @readnone_param(ptr [[P]]) [ "deopt"() ]
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
|
@ -338,7 +339,7 @@ define void @op_bundle_readnone_deopt(ptr %p) {
|
|||
|
||||
define void @op_bundle_readnone_unknown(ptr %p) {
|
||||
; CHECK-LABEL: define {{[^@]+}}@op_bundle_readnone_unknown
|
||||
; CHECK-SAME: (ptr nocapture readnone [[P:%.*]]) {
|
||||
; CHECK-SAME: (ptr nocapture [[P:%.*]]) {
|
||||
; CHECK-NEXT: call void @readnone_param(ptr [[P]]) [ "unknown"() ]
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
|
@ -358,7 +359,7 @@ define void @op_bundle_readonly_deopt(ptr %p) {
|
|||
|
||||
define void @op_bundle_readonly_unknown(ptr %p) {
|
||||
; CHECK-LABEL: define {{[^@]+}}@op_bundle_readonly_unknown
|
||||
; CHECK-SAME: (ptr nocapture readonly [[P:%.*]]) {
|
||||
; CHECK-SAME: (ptr nocapture [[P:%.*]]) {
|
||||
; CHECK-NEXT: call void @readonly_param(ptr [[P]]) [ "unknown"() ]
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
|
|
|
@ -180,7 +180,7 @@ define void @direct3b(ptr %p) {
|
|||
|
||||
define void @direct3c(ptr %p) {
|
||||
; CHECK-LABEL: define {{[^@]+}}@direct3c
|
||||
; CHECK-SAME: (ptr nocapture writeonly [[P:%.*]]) {
|
||||
; CHECK-SAME: (ptr nocapture [[P:%.*]]) {
|
||||
; CHECK-NEXT: call void @direct3_callee(ptr [[P]]) [ "may-read"() ]
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
|
|
Loading…
Reference in New Issue