Skip to content

Commit 67ce72c

Browse files
committed
MemBehavior: fix minor bugs for begin_access and end_access.
* ``begin_access [modify]`` returned MayWrite, but "modify" means, it can be a read as well. Instead, return MayReadWrite. Only for ``begin_access [init]`` return MayWrite. This is more or less cosmetic - probably this bug had no real impact on any optimization. * ``begin_access [deinit]`` needs to return MayReadWrite for the same reason ``destroy_addr`` returns MayReadWrite (see SILInstruction::MemoryBehavior).
1 parent 8828d8e commit 67ce72c

File tree

2 files changed

+57
-20
lines changed

2 files changed

+57
-20
lines changed

lib/SILOptimizer/Analysis/MemoryBehavior.cpp

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -136,37 +136,38 @@ class MemoryBehaviorVisitor
136136
}
137137

138138
MemBehavior visitBeginAccessInst(BeginAccessInst *beginAccess) {
139+
if (!mayAlias(beginAccess->getSource()))
140+
return MemBehavior::None;
141+
142+
// begin_access does not physically read or write memory. But we model it
143+
// as a memory read and/or write to prevent optimizations to move other
144+
// aliased loads/stores across begin_access into the access scope.
139145
switch (beginAccess->getAccessKind()) {
140146
case SILAccessKind::Deinit:
141-
// A [deinit] only directly reads from the object. The fact that it frees
142-
// memory is modeled more precisely by the release operations within the
143-
// deinit scope. Therefore, handle it like a [read] here...
144-
LLVM_FALLTHROUGH;
147+
// For the same reason we treat a ``load [take]`` or a ``destroy_addr``
148+
// as a memory write, we do that for a ``begin_access [deinit]`` as well.
149+
// See SILInstruction::MemoryBehavior.
150+
return MemBehavior::MayReadWrite;
145151
case SILAccessKind::Read:
146-
if (!mayAlias(beginAccess->getSource()))
147-
return MemBehavior::None;
148-
149152
return MemBehavior::MayRead;
150-
151153
case SILAccessKind::Modify:
152154
if (isLetValue()) {
153155
assert(getAccessBase(beginAccess) != getValueAddress()
154156
&& "let modification not allowed");
155157
return MemBehavior::None;
156158
}
157-
// [modify] has a special case for ignoring 'let's, but otherwise is
158-
// identical to an [init]...
159-
LLVM_FALLTHROUGH;
159+
return MemBehavior::MayReadWrite;
160160
case SILAccessKind::Init:
161-
if (!mayAlias(beginAccess->getSource()))
162-
return MemBehavior::None;
163-
164161
return MemBehavior::MayWrite;
165162
}
166163
llvm_unreachable("invalid access kind");
167164
}
168165

169166
MemBehavior visitEndAccessInst(EndAccessInst *endAccess) {
167+
// end_access does not physically read or write memory. But, similar to
168+
// begin_access, we model it as a memory read and/or write to prevent
169+
// optimizations to move other aliased loads/stores across end_access into
170+
// the access scope.
170171
return visitBeginAccessInst(endAccess->getBeginAccess());
171172
}
172173

test/SILOptimizer/mem-behavior.sil

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -491,23 +491,23 @@ bb0(%0 : @owned $Parent, %1 : $*Builtin.Int32):
491491
// CHECK: PAIR #8.
492492
// CHECK-NEXT: %{{.*}} = begin_access [modify] [static] %0 : $*Builtin.Int32
493493
// CHECK-NEXT: %0 = argument of bb0 : $*Builtin.Int32
494-
// CHECK-NEXT: r=0,w=1
494+
// CHECK-NEXT: r=1,w=1
495495
// CHECK: PAIR #9.
496496
// CHECK-NEXT: %{{.*}} = begin_access [modify] [static] %0 : $*Builtin.Int32
497497
// CHECK-NEXT: %{{.*}} = begin_access [read] [static] %0 : $*Builtin.Int32
498-
// CHECK-NEXT: r=0,w=1
498+
// CHECK-NEXT: r=1,w=1
499499
// CHECK: PAIR #13.
500500
// CHECK-NEXT: end_access %{{.*}} : $*Builtin.Int32
501501
// CHECK-NEXT: %0 = argument of bb0 : $*Builtin.Int32
502-
// CHECK-NEXT: r=0,w=1
502+
// CHECK-NEXT: r=1,w=1
503503
// CHECK: PAIR #14.
504504
// CHECK-NEXT: end_access %{{.*}} : $*Builtin.Int32
505505
// CHECK-NEXT: %{{.*}} = begin_access [read] [static] %0 : $*Builtin.Int32
506-
// CHECK-NEXT: r=0,w=1
506+
// CHECK-NEXT: r=1,w=1
507507
// CHECK: PAIR #15.
508508
// CHECK-NEXT: end_access %{{.*}} : $*Builtin.Int32
509509
// CHECK-NEXT: %{{.*}} = begin_access [modify] [static] %0 : $*Builtin.Int32
510-
// CHECK-NEXT: r=0,w=1
510+
// CHECK-NEXT: r=1,w=1
511511
sil [ossa] @testReadWriteAccess : $@convention(thin) (@inout Builtin.Int32) -> Builtin.Int32 {
512512
bb0(%0 : $*Builtin.Int32):
513513
%read = begin_access [read] [static] %0 : $*Builtin.Int32
@@ -520,6 +520,42 @@ bb0(%0 : $*Builtin.Int32):
520520
return %val : $Builtin.Int32
521521
}
522522

523+
// CHECK-LABEL: @testDeinitAccess
524+
// CHECK: PAIR #0.
525+
// CHECK-NEXT: %1 = begin_access [deinit] [static] %0 : $*Builtin.Int32
526+
// CHECK-NEXT: %0 = argument of bb0 : $*Builtin.Int32
527+
// CHECK-NEXT: r=1,w=1
528+
// CHECK: PAIR #1.
529+
// CHECK-NEXT: end_access %1 : $*Builtin.Int32
530+
// CHECK-NEXT: %0 = argument of bb0 : $*Builtin.Int32
531+
// CHECK-NEXT: r=1,w=1
532+
sil [ossa] @testDeinitAccess : $@convention(thin) (@in Builtin.Int32) -> () {
533+
bb0(%0 : $*Builtin.Int32):
534+
%1 = begin_access [deinit] [static] %0 : $*Builtin.Int32
535+
end_access %1 : $*Builtin.Int32
536+
%r = tuple ()
537+
return %r : $()
538+
}
539+
540+
// CHECK-LABEL: @testInitAccess
541+
// CHECK: PAIR #0.
542+
// CHECK-NEXT: %{{.*}} = begin_access [init] [static] %0 : $*Builtin.Int32
543+
// CHECK-NEXT: %0 = argument of bb0 : $*Builtin.Int32
544+
// CHECK-NEXT: r=0,w=1
545+
// CHECK: PAIR #3.
546+
// CHECK-NEXT: end_access %{{.*}} : $*Builtin.Int32
547+
// CHECK-NEXT: %0 = argument of bb0 : $*Builtin.Int32
548+
// CHECK-NEXT: r=0,w=1
549+
sil [ossa] @testInitAccess : $@convention(thin) (Builtin.Int32) -> @out Builtin.Int32 {
550+
bb0(%0 : $*Builtin.Int32, %1 : $Builtin.Int32):
551+
%init = begin_access [init] [static] %0 : $*Builtin.Int32
552+
store %1 to [trivial] %init : $*Builtin.Int32
553+
end_access %init : $*Builtin.Int32
554+
%val = load [trivial] %0 : $*Builtin.Int32
555+
%r = tuple ()
556+
return %r : $()
557+
}
558+
523559
// CHECK-LABEL: @testLoadTake
524560
// CHECK: PAIR #0.
525561
// CHECK-NEXT: %2 = load [take] %0 : $*C
@@ -572,7 +608,7 @@ struct Int64Wrapper {
572608
// CHECK: PAIR #2.
573609
// CHECK: %1 = begin_access [modify] [static] %0 : $*Int64Wrapper // users: %7, %2
574610
// CHECK: %3 = begin_access [read] [static] %2 : $*Int64 // users: %6, %4
575-
// CHECK: r=0,w=1
611+
// CHECK: r=1,w=1
576612
// CHECK: PAIR #3.
577613
sil @testNestedAccessWithInterposedProjection : $@convention(thin) (@inout Int64Wrapper) -> () {
578614
bb0(%0 : $*Int64Wrapper):

0 commit comments

Comments
 (0)