Skip to content

Commit ac4e704

Browse files
authored
Merge pull request #2438 from swiftwasm/main
[pull] swiftwasm from main
2 parents 70596be + e45dd64 commit ac4e704

File tree

4 files changed

+146
-39
lines changed

4 files changed

+146
-39
lines changed

include/swift/SILOptimizer/Analysis/AliasAnalysis.h

Lines changed: 9 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -113,19 +113,12 @@ class AliasAnalysis : public SILAnalysis {
113113
/// The computeMemoryBehavior() method uses this map to cache queries.
114114
llvm::DenseMap<MemBehaviorKeyTy, MemoryBehavior> MemoryBehaviorCache;
115115

116-
/// The AliasAnalysis cache can't directly map a pair of ValueBase pointers
117-
/// to alias results because we'd like to be able to remove deleted pointers
118-
/// without having to scan the whole map. So, instead of storing pointers we
119-
/// map pointers to indices and store the indices.
120-
ValueEnumerator<ValueBase*> AliasValueBaseToIndex;
121-
122-
/// Same as AliasValueBaseToIndex, map a pointer to the indices for
123-
/// MemoryBehaviorCache.
124-
///
125-
/// NOTE: we do not use the same ValueEnumerator for the alias cache,
126-
/// as when either cache is cleared, we can not clear the ValueEnumerator
127-
/// because doing so could give rise to collisions in the other cache.
128-
ValueEnumerator<SILNode*> MemoryBehaviorNodeToIndex;
116+
/// The caches can't directly map a pair of value/instruction pointers
117+
/// to results because we'd like to be able to remove deleted instruction
118+
/// pointers without having to scan the whole map. So, instead of storing
119+
/// pointers we map pointers to indices and store the indices.
120+
ValueEnumerator<ValueBase *> ValueToIndex;
121+
ValueEnumerator<SILInstruction *> InstructionToIndex;
129122

130123
AliasResult aliasAddressProjection(SILValue V1, SILValue V2,
131124
SILValue O1, SILValue O2);
@@ -138,18 +131,7 @@ class AliasAnalysis : public SILAnalysis {
138131
/// Returns True if memory of type \p T1 and \p T2 may alias.
139132
bool typesMayAlias(SILType T1, SILType T2, const SILFunction &F);
140133

141-
virtual void handleDeleteNotification(SILNode *node) override {
142-
assert(node->isRepresentativeSILNodeInObject());
143-
144-
// The pointer 'node' is going away. We can't scan the whole cache
145-
// and remove all of the occurrences of the pointer. Instead we remove
146-
// the pointer from the cache that translates pointers to indices.
147-
auto value = dyn_cast<ValueBase>(node);
148-
if (!value) return;
149-
150-
AliasValueBaseToIndex.invalidateValue(value);
151-
MemoryBehaviorNodeToIndex.invalidateValue(node);
152-
}
134+
virtual void handleDeleteNotification(SILNode *node) override;
153135

154136
virtual bool needsNotifications() override { return true; }
155137

@@ -262,6 +244,8 @@ class AliasAnalysis : public SILAnalysis {
262244
virtual void invalidate() override {
263245
AliasCache.clear();
264246
MemoryBehaviorCache.clear();
247+
InstructionToIndex.clear();
248+
ValueToIndex.clear();
265249
}
266250

267251
virtual void invalidate(SILFunction *,

lib/SILOptimizer/Analysis/AliasAnalysis.cpp

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -538,6 +538,29 @@ bool AliasAnalysis::typesMayAlias(SILType T1, SILType T2,
538538
return MA;
539539
}
540540

541+
void AliasAnalysis::handleDeleteNotification(SILNode *node) {
542+
assert(node->isRepresentativeSILNodeInObject());
543+
544+
// The pointer 'node' is going away. We can't scan the whole cache
545+
// and remove all of the occurrences of the pointer. Instead we remove
546+
// the pointer from the index caches.
547+
548+
if (auto *value = dyn_cast<ValueBase>(node))
549+
ValueToIndex.invalidateValue(value);
550+
551+
if (auto *inst = dyn_cast<SILInstruction>(node)) {
552+
InstructionToIndex.invalidateValue(inst);
553+
554+
// When a MultipleValueInstruction is deleted, we have to invalidate all
555+
// the instruction results.
556+
if (auto *mvi = dyn_cast<MultipleValueInstruction>(inst)) {
557+
for (unsigned idx = 0, end = mvi->getNumResults(); idx < end; ++idx) {
558+
ValueToIndex.invalidateValue(mvi->getResult(idx));
559+
}
560+
}
561+
}
562+
}
563+
541564
//===----------------------------------------------------------------------===//
542565
// Entry Points
543566
//===----------------------------------------------------------------------===//
@@ -557,10 +580,6 @@ AliasResult AliasAnalysis::alias(SILValue V1, SILValue V2,
557580
// Flush the cache if the size of the cache is too large.
558581
if (AliasCache.size() > AliasAnalysisMaxCacheSize) {
559582
AliasCache.clear();
560-
AliasValueBaseToIndex.clear();
561-
562-
// Key is no longer valid as we cleared the AliasValueBaseToIndex.
563-
Key = toAliasKey(V1, V2, TBAAType1, TBAAType2);
564583
}
565584

566585
// Calculate the aliasing result and store it in the cache.
@@ -785,10 +804,10 @@ SILAnalysis *swift::createAliasAnalysis(SILModule *M) {
785804

786805
AliasKeyTy AliasAnalysis::toAliasKey(SILValue V1, SILValue V2,
787806
SILType Type1, SILType Type2) {
788-
size_t idx1 = AliasValueBaseToIndex.getIndex(V1);
807+
size_t idx1 = ValueToIndex.getIndex(V1);
789808
assert(idx1 != std::numeric_limits<size_t>::max() &&
790809
"~0 index reserved for empty/tombstone keys");
791-
size_t idx2 = AliasValueBaseToIndex.getIndex(V2);
810+
size_t idx2 = ValueToIndex.getIndex(V2);
792811
assert(idx2 != std::numeric_limits<size_t>::max() &&
793812
"~0 index reserved for empty/tombstone keys");
794813
void *t1 = Type1.getOpaqueValue();

lib/SILOptimizer/Analysis/MemoryBehavior.cpp

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -527,10 +527,6 @@ AliasAnalysis::computeMemoryBehavior(SILInstruction *Inst, SILValue V) {
527527
// Flush the cache if the size of the cache is too large.
528528
if (MemoryBehaviorCache.size() > MemoryBehaviorAnalysisMaxCacheSize) {
529529
MemoryBehaviorCache.clear();
530-
MemoryBehaviorNodeToIndex.clear();
531-
532-
// Key is no longer valid as we cleared the MemoryBehaviorNodeToIndex.
533-
Key = toMemoryBehaviorKey(Inst, V);
534530
}
535531

536532
// Calculate the aliasing result and store it in the cache.
@@ -549,12 +545,10 @@ AliasAnalysis::computeMemoryBehaviorInner(SILInstruction *Inst, SILValue V) {
549545

550546
MemBehaviorKeyTy AliasAnalysis::toMemoryBehaviorKey(SILInstruction *V1,
551547
SILValue V2) {
552-
size_t idx1 =
553-
MemoryBehaviorNodeToIndex.getIndex(V1->getRepresentativeSILNodeInObject());
548+
size_t idx1 = InstructionToIndex.getIndex(V1);
554549
assert(idx1 != std::numeric_limits<size_t>::max() &&
555550
"~0 index reserved for empty/tombstone keys");
556-
size_t idx2 = MemoryBehaviorNodeToIndex.getIndex(
557-
V2->getRepresentativeSILNodeInObject());
551+
size_t idx2 = ValueToIndex.getIndex(V2);
558552
assert(idx2 != std::numeric_limits<size_t>::max() &&
559553
"~0 index reserved for empty/tombstone keys");
560554
return {idx1, idx2};
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
// RUN: %sil-opt -temp-rvalue-opt %s -o /dev/null
2+
3+
// This test exposes a bug in the MemBehavior cache invalidation mechanism.
4+
// With this bug, the optimizer aborts with a SIL memory lifetime failure
5+
// (only on linux).
6+
7+
sil_stage canonical
8+
9+
import Builtin
10+
import Swift
11+
import SwiftShims
12+
13+
public struct Complex<RealType> where RealType : FloatingPoint {
14+
@usableFromInline
15+
@_hasStorage internal var x: RealType { get set }
16+
@usableFromInline
17+
@_hasStorage internal var y: RealType { get set }
18+
init(_ real: RealType, _ imaginary: RealType)
19+
}
20+
21+
extension Complex {
22+
var phase: RealType { get }
23+
}
24+
25+
extension Complex {
26+
public static func log(_ z: Complex<RealType>, _ b: Bool) -> Complex<RealType>
27+
}
28+
29+
sil [ossa] @callee : $@convention(method) <RealType where RealType : FloatingPoint> (@in_guaranteed Complex<RealType>) -> @out RealType
30+
31+
sil [ossa] @test : $@convention(method) <RealType where RealType : FloatingPoint> (@in_guaranteed Complex<RealType>, Bool, @thin Complex<RealType>.Type) -> @out Complex<RealType> {
32+
bb0(%0 : $*Complex<RealType>, %1 : $*Complex<RealType>, %2 : $Bool, %3 : $@thin Complex<RealType>.Type):
33+
debug_value_addr %1 : $*Complex<RealType>, let, name "z", argno 1
34+
debug_value %2 : $Bool, let, name "b", argno 2
35+
debug_value %3 : $@thin Complex<RealType>.Type, let, name "self", argno 3
36+
%7 = alloc_stack $RealType, let, name "θ"
37+
%8 = alloc_stack $Complex<RealType>
38+
copy_addr %1 to [initialization] %8 : $*Complex<RealType>
39+
%10 = function_ref @callee : $@convention(method) <τ_0_0 where τ_0_0 : FloatingPoint> (@in_guaranteed Complex<τ_0_0>) -> @out τ_0_0
40+
%11 = apply %10<RealType>(%7, %8) : $@convention(method) <τ_0_0 where τ_0_0 : FloatingPoint> (@in_guaranteed Complex<τ_0_0>) -> @out τ_0_0
41+
destroy_addr %8 : $*Complex<RealType>
42+
dealloc_stack %8 : $*Complex<RealType>
43+
%14 = integer_literal $Builtin.Int1, -1
44+
%15 = struct_extract %2 : $Bool, #Bool._value
45+
%16 = builtin "cmp_eq_Int1"(%15 : $Builtin.Int1, %14 : $Builtin.Int1) : $Builtin.Int1
46+
cond_br %16, bb1, bb2
47+
48+
bb1:
49+
%18 = metatype $@thick RealType.Type
50+
%19 = alloc_stack $RealType
51+
%20 = witness_method $RealType, #FloatingPoint.infinity!getter : <Self where Self : FloatingPoint> (Self.Type) -> () -> Self : $@convention(witness_method: FloatingPoint) <τ_0_0 where τ_0_0 : FloatingPoint> (@thick τ_0_0.Type) -> @out τ_0_0
52+
%21 = apply %20<RealType>(%19, %18) : $@convention(witness_method: FloatingPoint) <τ_0_0 where τ_0_0 : FloatingPoint> (@thick τ_0_0.Type) -> @out τ_0_0
53+
%22 = alloc_stack $RealType
54+
copy_addr [take] %7 to [initialization] %22 : $*RealType
55+
%24 = alloc_stack $Complex<RealType>
56+
%25 = alloc_stack $RealType
57+
copy_addr [take] %19 to [initialization] %25 : $*RealType
58+
%27 = struct_element_addr %24 : $*Complex<RealType>, #Complex.x
59+
copy_addr [take] %25 to [initialization] %27 : $*RealType
60+
dealloc_stack %25 : $*RealType
61+
%30 = alloc_stack $RealType
62+
copy_addr [take] %22 to [initialization] %30 : $*RealType
63+
%32 = struct_element_addr %24 : $*Complex<RealType>, #Complex.y
64+
copy_addr [take] %30 to [initialization] %32 : $*RealType
65+
dealloc_stack %30 : $*RealType
66+
copy_addr %24 to [initialization] %0 : $*Complex<RealType>
67+
destroy_addr %24 : $*Complex<RealType>
68+
dealloc_stack %24 : $*Complex<RealType>
69+
%38 = tuple ()
70+
dealloc_stack %22 : $*RealType
71+
dealloc_stack %19 : $*RealType
72+
dealloc_stack %7 : $*RealType
73+
br bb3
74+
75+
bb2:
76+
%43 = metatype $@thick RealType.Type
77+
%44 = alloc_stack $RealType
78+
%45 = witness_method $RealType, #FloatingPoint.infinity!getter : <Self where Self : FloatingPoint> (Self.Type) -> () -> Self : $@convention(witness_method: FloatingPoint) <τ_0_0 where τ_0_0 : FloatingPoint> (@thick τ_0_0.Type) -> @out τ_0_0
79+
%46 = apply %45<RealType>(%44, %43) : $@convention(witness_method: FloatingPoint) <τ_0_0 where τ_0_0 : FloatingPoint> (@thick τ_0_0.Type) -> @out τ_0_0
80+
%47 = alloc_stack $RealType
81+
copy_addr [take] %7 to [initialization] %47 : $*RealType
82+
%49 = alloc_stack $Complex<RealType>
83+
%50 = alloc_stack $RealType
84+
copy_addr [take] %44 to [initialization] %50 : $*RealType
85+
%52 = struct_element_addr %49 : $*Complex<RealType>, #Complex.x
86+
copy_addr [take] %50 to [initialization] %52 : $*RealType
87+
dealloc_stack %50 : $*RealType
88+
%55 = alloc_stack $RealType
89+
copy_addr [take] %47 to [initialization] %55 : $*RealType
90+
%57 = struct_element_addr %49 : $*Complex<RealType>, #Complex.y
91+
copy_addr [take] %55 to [initialization] %57 : $*RealType
92+
dealloc_stack %55 : $*RealType
93+
copy_addr %49 to [initialization] %0 : $*Complex<RealType>
94+
destroy_addr %49 : $*Complex<RealType>
95+
dealloc_stack %49 : $*Complex<RealType>
96+
%63 = tuple ()
97+
dealloc_stack %47 : $*RealType
98+
dealloc_stack %44 : $*RealType
99+
dealloc_stack %7 : $*RealType
100+
br bb3
101+
102+
bb3:
103+
%68 = tuple ()
104+
return %68 : $()
105+
}
106+
107+
sil_property #Complex.x<τ_0_0 where τ_0_0 : FloatingPoint> ()
108+
sil_property #Complex.y<τ_0_0 where τ_0_0 : FloatingPoint> ()
109+
110+

0 commit comments

Comments
 (0)