Skip to content

Commit c15f489

Browse files
committed
SILMem2Reg: Allow uncheck_addr_cast 'projections'
1 parent 7989d3f commit c15f489

File tree

2 files changed

+30
-7
lines changed

2 files changed

+30
-7
lines changed

lib/SILOptimizer/Transforms/SILMem2Reg.cpp

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,8 @@ static bool isAddressForLoad(SILInstruction *I, SILBasicBlock *&singleBlock) {
188188
if (isa<LoadInst>(I))
189189
return true;
190190

191-
if (!isa<StructElementAddrInst>(I) && !isa<TupleElementAddrInst>(I))
191+
if (!isa<UncheckedAddrCastInst>(I) && !isa<StructElementAddrInst>(I) &&
192+
!isa<TupleElementAddrInst>(I))
192193
return false;
193194

194195
// Recursively search for other (non-)loads in the instruction's uses.
@@ -205,7 +206,8 @@ static bool isAddressForLoad(SILInstruction *I, SILBasicBlock *&singleBlock) {
205206

206207
/// Returns true if \p I is a dead struct_element_addr or tuple_element_addr.
207208
static bool isDeadAddrProjection(SILInstruction *I) {
208-
if (!isa<StructElementAddrInst>(I) && !isa<TupleElementAddrInst>(I))
209+
if (!isa<UncheckedAddrCastInst>(I) && !isa<StructElementAddrInst>(I) &&
210+
!isa<TupleElementAddrInst>(I))
209211
return false;
210212

211213
// Recursively search for uses which are dead themselves.
@@ -311,7 +313,8 @@ static bool isLoadFromStack(SILInstruction *I, AllocStackInst *ASI) {
311313
// Skip struct and tuple address projections.
312314
ValueBase *op = I->getOperand(0);
313315
while (op != ASI) {
314-
if (!isa<StructElementAddrInst>(op) && !isa<TupleElementAddrInst>(op))
316+
if (!isa<UncheckedAddrCastInst>(op) && !isa<StructElementAddrInst>(op) &&
317+
!isa<TupleElementAddrInst>(op))
315318
return false;
316319

317320
op = cast<SingleValueInstruction>(op)->getOperand(0);
@@ -325,7 +328,8 @@ static void collectLoads(SILInstruction *I, SmallVectorImpl<LoadInst *> &Loads)
325328
Loads.push_back(load);
326329
return;
327330
}
328-
if (!isa<StructElementAddrInst>(I) && !isa<TupleElementAddrInst>(I))
331+
if (!isa<UncheckedAddrCastInst>(I) && !isa<StructElementAddrInst>(I) &&
332+
!isa<TupleElementAddrInst>(I))
329333
return;
330334

331335
// Recursively search for other loads in the instruction's uses.
@@ -339,7 +343,8 @@ static void replaceLoad(LoadInst *LI, SILValue val, AllocStackInst *ASI) {
339343
ProjectionPath projections(val->getType());
340344
SILValue op = LI->getOperand();
341345
while (op != ASI) {
342-
assert(isa<StructElementAddrInst>(op) || isa<TupleElementAddrInst>(op));
346+
assert(isa<UncheckedAddrCastInst>(op) || isa<StructElementAddrInst>(op) ||
347+
isa<TupleElementAddrInst>(op));
343348
auto *Inst = cast<SingleValueInstruction>(op);
344349
projections.push_back(Projection(Inst));
345350
op = Inst->getOperand(0);
@@ -353,7 +358,8 @@ static void replaceLoad(LoadInst *LI, SILValue val, AllocStackInst *ASI) {
353358
LI->replaceAllUsesWith(val);
354359
LI->eraseFromParent();
355360
while (op != ASI && op->use_empty()) {
356-
assert(isa<StructElementAddrInst>(op) || isa<TupleElementAddrInst>(op));
361+
assert(isa<UncheckedAddrCastInst>(op) || isa<StructElementAddrInst>(op) ||
362+
isa<TupleElementAddrInst>(op));
357363
auto *Inst = cast<SingleValueInstruction>(op);
358364
SILValue next = Inst->getOperand(0);
359365
Inst->eraseFromParent();
@@ -541,7 +547,8 @@ void MemoryToRegisters::removeSingleBlockAllocation(AllocStackInst *ASI) {
541547
// Remove dead address instructions that may be uses of the allocation.
542548
SILNode *Node = Inst;
543549
while (isa<StructElementAddrInst>(Node) ||
544-
isa<TupleElementAddrInst>(Node)) {
550+
isa<TupleElementAddrInst>(Node) ||
551+
isa<UncheckedAddrCastInst>(Node)) {
545552
auto *I = cast<SingleValueInstruction>(Node);
546553
if (!I->use_empty()) break;
547554
Node = I->getOperand(0);

test/SILOptimizer/mem2reg.sil

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -449,3 +449,19 @@ bb0:
449449
return %16 : $((), ())
450450
}
451451

452+
// CHECK-LABEL: sil @unchecked_ref_cast
453+
// CHECK-NOT: alloc_stack
454+
// CHECK: [[CAST:%.*]] = unchecked_bitwise_cast %0 : $Optional<Klass> to $Klass
455+
// CHECK: release_value [[CAST]]
456+
// CHECK: return
457+
sil @unchecked_ref_cast : $@convention(thin) (@owned Optional<Klass>) -> () {
458+
bb0(%0 : $Optional<Klass>):
459+
%1 = alloc_stack $Optional<Klass>
460+
store %0 to %1 : $*Optional<Klass>
461+
%2 = unchecked_addr_cast %1 : $*Optional<Klass> to $*Klass
462+
%3 = load %2 : $*Klass
463+
release_value %3 : $Klass
464+
dealloc_stack %1 : $*Optional<Klass>
465+
%4 = tuple()
466+
return %4 : $()
467+
}

0 commit comments

Comments
 (0)