Skip to content

Commit 74a7026

Browse files
committed
AliasAnalysis: fix a bug where an index_addr with zero offset can result in a false no-alias result
When building a projection path we _must_ ignore zero-indexing projections so that alias analysis recognizes an "alias" between two addresses where one has such an `index_addr 0` instruction and the other doesn't.
1 parent c3cd243 commit 74a7026

File tree

2 files changed

+50
-9
lines changed

2 files changed

+50
-9
lines changed

Diff for: lib/SIL/Utils/Projection.cpp

+5-1
Original file line numberDiff line numberDiff line change
@@ -389,7 +389,11 @@ Optional<ProjectionPath> ProjectionPath::getProjectionPath(SILValue Start,
389389
Projection AP(Iter);
390390
if (!AP.isValid())
391391
break;
392-
P.Path.push_back(AP);
392+
// We _must_ ignore zero-indexing projections so that alias analysis
393+
// recognizes an "alias" between two addresses where one has such an
394+
// `index_addr 0` instruction and the other doesn't.
395+
if (AP.getKind() != ProjectionKind::Index || AP.getIndex() != 0)
396+
P.Path.push_back(AP);
393397
}
394398
Iter = cast<SingleValueInstruction>(*Iter).getOperand(0);
395399
}

Diff for: test/SILOptimizer/alias-analysis.sil

+45-8
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,10 @@ struct OuterStruct {
2222

2323
// Test overlaping access on a different path; the user has misused an index offset
2424
// CHECK-LABEL: @testOffsetBehindProjection
25-
// CHECK: PAIR #28.
26-
// CHECK: %4 = load %3 : $*Int64
27-
// CHECK: %6 = load %5 : $*Int64
28-
// CHECK: MayAlias
25+
// CHECK: PAIR #23.
26+
// CHECK: %3 = index_addr %1 : $*Int64, %2 : $Builtin.Word
27+
// CHECK: %5 = struct_element_addr %0 : $*MyStruct, #MyStruct.j
28+
// CHECK: NoAlias
2929
sil shared @testOffsetBehindProjection : $@convention(thin) (@inout MyStruct) -> () {
3030
bb0(%0 : $*MyStruct):
3131
%1 = struct_element_addr %0 : $*MyStruct, #MyStruct.i
@@ -40,10 +40,10 @@ bb0(%0 : $*MyStruct):
4040
}
4141

4242
// CHECK-LABEL: @testOffsetsBehindProjectionOverlap
43-
// CHECK: PAIR #28.
44-
// CHECK: %3 = load %2 : $*Int64
45-
// CHECK: %7 = load %6 : $*Int64
46-
// CHECK: MayAlias
43+
// CHECK: PAIR #21.
44+
// CHECK: %2 = struct_element_addr %1 : $*MyStruct, #MyStruct.i
45+
// CHECK: %6 = struct_element_addr %5 : $*MyStruct, #MyStruct.i
46+
// CHECK: NoAlias
4747
sil shared @testOffsetsBehindProjectionOverlap : $@convention(thin) (@inout OuterStruct) -> () {
4848
bb0(%0 : $*OuterStruct):
4949
%1 = struct_element_addr %0 : $*OuterStruct, #OuterStruct.s
@@ -58,3 +58,40 @@ bb0(%0 : $*OuterStruct):
5858
%99 = tuple ()
5959
return %99 : $()
6060
}
61+
62+
// CHECK-LABEL: @testIndexOf0
63+
// CHECK: PAIR #8.
64+
// CHECK: %1 = struct_element_addr %0 : $*MyStruct, #MyStruct.i
65+
// CHECK: %3 = index_addr %0 : $*MyStruct, %2 : $Builtin.Word
66+
// CHECK: MayAlias
67+
// CHECK: PAIR #9.
68+
// CHECK: %1 = struct_element_addr %0 : $*MyStruct, #MyStruct.i
69+
// CHECK: %4 = struct_element_addr %3 : $*MyStruct, #MyStruct.i
70+
// CHECK: MustAlias
71+
sil @testIndexOf0 : $@convention(thin) (@inout MyStruct) -> () {
72+
bb0(%0 : $*MyStruct):
73+
%1 = struct_element_addr %0 : $*MyStruct, #MyStruct.i
74+
%2 = integer_literal $Builtin.Word, 0
75+
%3 = index_addr %0 : $*MyStruct, %2 : $Builtin.Word
76+
%4 = struct_element_addr %3 : $*MyStruct, #MyStruct.i
77+
%99 = tuple ()
78+
return %99 : $()
79+
}
80+
81+
// CHECK-LABEL: @testUnknownIndex
82+
// CHECK: PAIR #12.
83+
// CHECK: %2 = struct_element_addr %0 : $*MyStruct, #MyStruct.i
84+
// CHECK: %3 = index_addr %0 : $*MyStruct, %1 : $Builtin.Word
85+
// CHECK: MayAlias
86+
// CHECK: PAIR #13.
87+
// CHECK: %2 = struct_element_addr %0 : $*MyStruct, #MyStruct.i
88+
// CHECK: %4 = struct_element_addr %3 : $*MyStruct, #MyStruct.i
89+
// CHECK: MayAlias
90+
sil @testUnknownIndex : $@convention(thin) (@inout MyStruct, Builtin.Word) -> () {
91+
bb0(%0 : $*MyStruct, %1 : $Builtin.Word):
92+
%2 = struct_element_addr %0 : $*MyStruct, #MyStruct.i
93+
%3 = index_addr %0 : $*MyStruct, %1 : $Builtin.Word
94+
%4 = struct_element_addr %3 : $*MyStruct, #MyStruct.i
95+
%99 = tuple ()
96+
return %99 : $()
97+
}

0 commit comments

Comments
 (0)