Skip to content

Commit 2767b51

Browse files
committed
Change Projection to support signed indices.
Change ProjectionIndex for ref_tail_addr to std::numeric_limits<int>::max(); This is necessary to disambiguate the tail elements from ref_element_addr field zero.
1 parent 7774f06 commit 2767b51

File tree

5 files changed

+51
-51
lines changed

5 files changed

+51
-51
lines changed

include/swift/SIL/Projection.h

Lines changed: 18 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,9 @@ inline bool isStrictSubSeqRelation(SubSeqRelation_t Seq) {
6767

6868
/// Extract an integer index from a SILValue.
6969
///
70-
/// Return true if IndexVal is a constant index representable as unsigned
70+
/// Return true if IndexVal is a constant index representable as an
7171
/// int. We do not support symbolic projections yet.
72-
bool getIntegerIndex(SILValue IndexVal, unsigned &IndexConst);
72+
bool getIntegerIndex(SILValue IndexVal, int &IndexConst);
7373

7474
/// The kind of projection that we are representing.
7575
///
@@ -136,11 +136,18 @@ static inline bool isCastProjectionKind(ProjectionKind Kind) {
136136
/// that immediately contains it.
137137
///
138138
/// This lightweight utility maps a SIL address projection to an index.
139+
///
140+
/// project_box does not have a projection index. At the SIL level, the box
141+
/// storage is considered part of the same object as the. The box projection is
142+
/// does not affect access path so that box projections can occur on distinct
143+
/// phi paths in the address def-use chain.
139144
struct ProjectionIndex {
145+
static constexpr int TailIndex = std::numeric_limits<int>::max();
146+
140147
SILValue Aggregate;
141-
unsigned Index;
148+
int Index = std::numeric_limits<int>::min();
142149

143-
explicit ProjectionIndex(SILValue V) : Index(~0U) {
150+
explicit ProjectionIndex(SILValue V) {
144151
switch (V->getKind()) {
145152
default:
146153
break;
@@ -163,16 +170,9 @@ struct ProjectionIndex {
163170
break;
164171
}
165172
case ValueKind::RefTailAddrInst: {
166-
RefTailAddrInst *REA = cast<RefTailAddrInst>(V);
167-
Index = 0;
168-
Aggregate = REA->getOperand();
169-
break;
170-
}
171-
case ValueKind::ProjectBoxInst: {
172-
ProjectBoxInst *PBI = cast<ProjectBoxInst>(V);
173-
// A box has only a single payload.
174-
Index = 0;
175-
Aggregate = PBI->getOperand();
173+
RefTailAddrInst *RTA = cast<RefTailAddrInst>(V);
174+
Index = TailIndex;
175+
Aggregate = RTA->getOperand();
176176
break;
177177
}
178178
case ValueKind::TupleElementAddrInst: {
@@ -233,8 +233,7 @@ class Projection {
233233
: Projection(dyn_cast<SingleValueInstruction>(I)) {}
234234
explicit Projection(SingleValueInstruction *I);
235235

236-
Projection(ProjectionKind Kind, unsigned NewIndex)
237-
: Value(Kind, NewIndex) {}
236+
Projection(ProjectionKind Kind, int NewIndex) : Value(Kind, NewIndex) {}
238237

239238
Projection(ProjectionKind Kind, TypeBase *Ptr)
240239
: Value(Kind, Ptr) {}
@@ -252,10 +251,8 @@ class Projection {
252251

253252
/// Convenience method for getting the underlying index. Assumes that this
254253
/// projection is valid. Otherwise it asserts.
255-
unsigned getIndex() const {
256-
return Value.getIndex();
257-
}
258-
254+
int getIndex() const { return Value.getIndex(); }
255+
259256
unsigned getHash() const { return (unsigned)Value.getStorage(); }
260257

261258
/// Determine if I is a value projection instruction whose corresponding
@@ -359,7 +356,7 @@ class Projection {
359356
return nullptr;
360357
case ValueKind::IndexAddrInst: {
361358
auto *i = cast<IndexAddrInst>(v);
362-
unsigned scalar;
359+
int scalar;
363360
if (getIntegerIndex(i->getIndex(), scalar))
364361
return i;
365362
return nullptr;

lib/SIL/Utils/Projection.cpp

Lines changed: 28 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,11 @@
1212

1313
#define DEBUG_TYPE "sil-projection"
1414
#include "swift/SIL/Projection.h"
15+
#include "swift/Basic/IndexTrie.h"
1516
#include "swift/Basic/NullablePtr.h"
16-
#include "swift/SIL/SILBuilder.h"
17-
#include "swift/SIL/InstructionUtils.h"
1817
#include "swift/SIL/DebugUtils.h"
18+
#include "swift/SIL/InstructionUtils.h"
19+
#include "swift/SIL/SILBuilder.h"
1920
#include "swift/SIL/SILUndef.h"
2021
#include "llvm/ADT/None.h"
2122
#include "llvm/Support/Debug.h"
@@ -42,22 +43,27 @@ static_assert(std::is_standard_layout<Projection>::value,
4243
/// Return true if IndexVal is a constant index representable as unsigned
4344
/// int. We do not support symbolic projections yet, only 32-bit unsigned
4445
/// integers.
45-
bool swift::getIntegerIndex(SILValue IndexVal, unsigned &IndexConst) {
46-
if (auto *IndexLiteral = dyn_cast<IntegerLiteralInst>(IndexVal)) {
47-
APInt ConstInt = IndexLiteral->getValue();
48-
// IntegerLiterals are signed.
49-
if (ConstInt.isIntN(32) && ConstInt.isNonNegative()) {
50-
IndexConst = (unsigned)ConstInt.getSExtValue();
51-
return true;
52-
}
53-
}
54-
return false;
46+
bool swift::getIntegerIndex(SILValue IndexVal, int &IndexConst) {
47+
auto *IndexLiteral = dyn_cast<IntegerLiteralInst>(IndexVal);
48+
if (!IndexLiteral)
49+
return false;
50+
51+
APInt ConstInt = IndexLiteral->getValue();
52+
// Reserve 1 bit for encoding. See AccessPath::Index.
53+
if (!ConstInt.isSignedIntN(31))
54+
return false;
55+
56+
IndexConst = ConstInt.getSExtValue();
57+
assert(((IndexConst << 1) >> 1) == IndexConst);
58+
return true;
5559
}
5660

5761
//===----------------------------------------------------------------------===//
5862
// Projection
5963
//===----------------------------------------------------------------------===//
6064

65+
constexpr int ProjectionIndex::TailIndex;
66+
6167
Projection::Projection(SingleValueInstruction *I) : Value() {
6268
if (!I)
6369
return;
@@ -72,21 +78,21 @@ Projection::Projection(SingleValueInstruction *I) : Value() {
7278
auto *SEAI = cast<StructElementAddrInst>(I);
7379
Value = ValueTy(ProjectionKind::Struct, SEAI->getFieldIndex());
7480
assert(getKind() == ProjectionKind::Struct);
75-
assert(getIndex() == SEAI->getFieldIndex());
81+
assert(getIndex() == int(SEAI->getFieldIndex()));
7682
break;
7783
}
7884
case SILInstructionKind::StructExtractInst: {
7985
auto *SEI = cast<StructExtractInst>(I);
8086
Value = ValueTy(ProjectionKind::Struct, SEI->getFieldIndex());
8187
assert(getKind() == ProjectionKind::Struct);
82-
assert(getIndex() == SEI->getFieldIndex());
88+
assert(getIndex() == int(SEI->getFieldIndex()));
8389
break;
8490
}
8591
case SILInstructionKind::RefElementAddrInst: {
8692
auto *REAI = cast<RefElementAddrInst>(I);
8793
Value = ValueTy(ProjectionKind::Class, REAI->getFieldIndex());
8894
assert(getKind() == ProjectionKind::Class);
89-
assert(getIndex() == REAI->getFieldIndex());
95+
assert(getIndex() == int(REAI->getFieldIndex()));
9096
break;
9197
}
9298
case SILInstructionKind::RefTailAddrInst: {
@@ -108,28 +114,28 @@ Projection::Projection(SingleValueInstruction *I) : Value() {
108114
auto *TEI = cast<TupleExtractInst>(I);
109115
Value = ValueTy(ProjectionKind::Tuple, TEI->getFieldIndex());
110116
assert(getKind() == ProjectionKind::Tuple);
111-
assert(getIndex() == TEI->getFieldIndex());
117+
assert(getIndex() == int(TEI->getFieldIndex()));
112118
break;
113119
}
114120
case SILInstructionKind::TupleElementAddrInst: {
115121
auto *TEAI = cast<TupleElementAddrInst>(I);
116122
Value = ValueTy(ProjectionKind::Tuple, TEAI->getFieldIndex());
117123
assert(getKind() == ProjectionKind::Tuple);
118-
assert(getIndex() == TEAI->getFieldIndex());
124+
assert(getIndex() == int(TEAI->getFieldIndex()));
119125
break;
120126
}
121127
case SILInstructionKind::UncheckedEnumDataInst: {
122128
auto *UEDI = cast<UncheckedEnumDataInst>(I);
123129
Value = ValueTy(ProjectionKind::Enum, UEDI->getElementNo());
124130
assert(getKind() == ProjectionKind::Enum);
125-
assert(getIndex() == UEDI->getElementNo());
131+
assert(getIndex() == int(UEDI->getElementNo()));
126132
break;
127133
}
128134
case SILInstructionKind::UncheckedTakeEnumDataAddrInst: {
129135
auto *UTEDAI = cast<UncheckedTakeEnumDataAddrInst>(I);
130136
Value = ValueTy(ProjectionKind::Enum, UTEDAI->getElementNo());
131137
assert(getKind() == ProjectionKind::Enum);
132-
assert(getIndex() == UTEDAI->getElementNo());
138+
assert(getIndex() == int(UTEDAI->getElementNo()));
133139
break;
134140
}
135141
case SILInstructionKind::IndexAddrInst: {
@@ -138,9 +144,10 @@ Projection::Projection(SingleValueInstruction *I) : Value() {
138144
// updated and a MaxLargeIndex will need to be used here. Currently we
139145
// represent large Indexes using a 64 bit integer, so we don't need to mess
140146
// with anything.
141-
unsigned NewIndex = 0;
147+
int NewIndex = 0;
142148
auto *IAI = cast<IndexAddrInst>(I);
143-
if (getIntegerIndex(IAI->getIndex(), NewIndex)) {
149+
// TODO: handle negative indices
150+
if (getIntegerIndex(IAI->getIndex(), NewIndex) && NewIndex >= 0) {
144151
Value = ValueTy(ProjectionKind::Index, NewIndex);
145152
assert(getKind() == ProjectionKind::Index);
146153
assert(getIndex() == NewIndex);
@@ -321,10 +328,6 @@ void Projection::getFirstLevelProjections(
321328

322329
if (auto *C = Ty.getClassOrBoundGenericClass()) {
323330
unsigned Count = 0;
324-
for (auto *superDecl = C->getSuperclassDecl(); superDecl != nullptr;
325-
superDecl = superDecl->getSuperclassDecl()) {
326-
Count += superDecl->getStoredProperties().size();
327-
}
328331
for (auto *VDecl : C->getStoredProperties()) {
329332
(void) VDecl;
330333
Projection P(ProjectionKind::Class, Count++);

lib/SILOptimizer/LoopTransforms/ArrayOpt.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ class StructUseCollector {
6363
/// Do not form a path with an IndexAddrInst because we have no way to
6464
/// distinguish between indexing and subelement access. The same index could
6565
/// either refer to the next element (indexed) or a subelement.
66-
static SILValue getAccessPath(SILValue V, SmallVectorImpl<unsigned>& Path) {
66+
static SILValue getAccessPath(SILValue V, SmallVectorImpl<int> &Path) {
6767
V = stripCasts(V);
6868
if (auto *IA = dyn_cast<IndexAddrInst>(V)) {
6969
// Don't include index_addr projections in the access path. We could if
@@ -89,7 +89,7 @@ class StructUseCollector {
8989
VisitedSet Visited;
9090

9191
/// Collect all uses of the value at the given address.
92-
void collectUses(ValueBase *V, ArrayRef<unsigned> AccessPath) {
92+
void collectUses(ValueBase *V, ArrayRef<int> AccessPath) {
9393
// Save our old indent and increment.
9494
// Collect all users of the address and loads.
9595
collectAddressUses(V, AccessPath, nullptr);
@@ -142,7 +142,7 @@ class StructUseCollector {
142142
/// StructVal is invalid, then the value is the address of the Struct. If
143143
/// StructVal is valid, the value is the address of an element within the
144144
/// Struct.
145-
void collectAddressUses(ValueBase *V, ArrayRef<unsigned> AccessPathSuffix,
145+
void collectAddressUses(ValueBase *V, ArrayRef<int> AccessPathSuffix,
146146
Operand *StructVal) {
147147
for (auto *UI : V->getUses()) {
148148
// Keep the operand, not the instruction in the visited set. The same

lib/SILOptimizer/LoopTransforms/ArrayPropertyOpt.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -402,7 +402,7 @@ class ArrayPropertiesAnalysis {
402402
if (!Call.canHoist(Preheader->getTerminator(), DomTree))
403403
return false;
404404

405-
SmallVector<unsigned, 4> AccessPath;
405+
SmallVector<int, 4> AccessPath;
406406
SILValue ArrayContainer =
407407
StructUseCollector::getAccessPath(Arr, AccessPath);
408408

lib/SILOptimizer/LoopTransforms/COWArrayOpt.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -843,7 +843,7 @@ bool COWArrayOpt::hoistMakeMutable(ArraySemanticsCall MakeMutable,
843843
return false;
844844
}
845845

846-
SmallVector<unsigned, 4> AccessPath;
846+
SmallVector<int, 4> AccessPath;
847847
SILValue ArrayContainer =
848848
StructUseCollector::getAccessPath(CurrentArrayAddr, AccessPath);
849849
bool arrayContainerIsUnique = checkUniqueArrayContainer(ArrayContainer);

0 commit comments

Comments
 (0)