Skip to content

Commit 2cbc13a

Browse files
committed
[CanonInst] Process "at" load after rewriting.
When a load/load_borrow is canonicalized, canonicalization should continue from where the load was before rather than the first instruction that was after it. Enables narrowing the load through a sequence of projections.
1 parent 9c3d941 commit 2cbc13a

File tree

2 files changed

+60
-1
lines changed

2 files changed

+60
-1
lines changed

lib/SILOptimizer/Utils/CanonicalizeInstruction.cpp

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,8 @@ static void replaceUsesOfExtract(SingleValueInstruction *extract,
141141
// (load (struct_element_addr %base, #field)
142142
static SILBasicBlock::iterator
143143
splitAggregateLoad(LoadOperation loadInst, CanonicalizeInstruction &pass) {
144+
auto *block = loadInst->getParentBlock();
145+
auto *instBeforeLoad = loadInst->getPreviousInstruction();
144146
// Keep track of the next iterator after any newly added or to-be-deleted
145147
// instructions. This must be valid regardless of whether the pass immediately
146148
// deletes the instructions or simply records them for later deletion.
@@ -336,7 +338,22 @@ splitAggregateLoad(LoadOperation loadInst, CanonicalizeInstruction &pass) {
336338
++nextII;
337339
}
338340
deleteAllDebugUses(*loadInst, pass.getCallbacks());
339-
return killInstAndIncidentalUses(*loadInst, nextII, pass);
341+
nextII = killInstAndIncidentalUses(*loadInst, nextII, pass);
342+
/// A change has been made; and the load instruction is deleted. The caller
343+
/// should now process the instruction where the load was before.
344+
///
345+
/// BEFORE TRANSFORM | AFTER TRANSFORM
346+
/// prequel_2 | prequel_2
347+
/// prequel_1 | prequel_1
348+
/// load | +-> ???
349+
/// sequel_1 | | ???
350+
/// sequel_2 | | ???
351+
/// |
352+
/// The instruction the caller should process next.
353+
if (instBeforeLoad)
354+
return instBeforeLoad->getNextInstruction()->getIterator();
355+
else
356+
return block->begin();
340357
}
341358

342359
// Given a store within a single property struct, recursively form the parent

test/SILOptimizer/silgen_cleanup.sil

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,3 +362,45 @@ bb9(%0 : @owned $Klass):
362362
destroy_value %0 : $Klass
363363
return %v : $Builtin.Int64
364364
}
365+
366+
struct Outer {
367+
var middle: Middle
368+
}
369+
370+
struct Middle {
371+
var inner: Inner
372+
}
373+
374+
struct Inner {
375+
var guts: Builtin.AnyObject
376+
}
377+
378+
sil @getOuter : $@convention(thin) () -> @owned Outer
379+
sil @takeInner : $@convention(thin) (@owned Inner) -> ()
380+
381+
// CHECK-LABEL: sil [ossa] @narrowLoadThroughProjectionSequence : {{.*}} {
382+
// CHECK: [[OUTER_ADDR:%[^,]+]] = project_box
383+
// CHECK: [[MIDDLE_ADDR:%[^,]+]] = struct_element_addr [[OUTER_ADDR]]
384+
// CHECK: [[INNER_ADDR:%[^,]+]] = struct_element_addr [[MIDDLE_ADDR]]
385+
// CHECK: [[INNER_BORROW:%[^,]+]] = load_borrow [[INNER_ADDR]]
386+
// CHECK: copy_value [[INNER_BORROW]]
387+
// CHECK-LABEL: } // end sil function 'narrowLoadThroughProjectionSequence'
388+
sil [ossa] @narrowLoadThroughProjectionSequence : $@convention(thin) () -> () {
389+
%box = alloc_box ${ let Outer }
390+
%box_borrow = begin_borrow [lexical] [var_decl] %box : ${ let Outer }
391+
%outer_addr = project_box %box_borrow : ${ let Outer }, 0
392+
%getOuter = function_ref @getOuter : $@convention(thin) () -> @owned Outer
393+
%outer = apply %getOuter() : $@convention(thin) () -> @owned Outer
394+
store %outer to [init] %outer_addr : $*Outer
395+
%outer_borrow = load_borrow %outer_addr : $*Outer
396+
%middle = struct_extract %outer_borrow : $Outer, #Outer.middle
397+
%inner = struct_extract %middle : $Middle, #Middle.inner
398+
%inner_copy = copy_value %inner : $Inner
399+
%takeInner = function_ref @takeInner : $@convention(thin) (@owned Inner) -> ()
400+
apply %takeInner(%inner_copy) : $@convention(thin) (@owned Inner) -> ()
401+
end_borrow %outer_borrow : $Outer
402+
end_borrow %box_borrow : ${ let Outer }
403+
dealloc_box %box : ${ let Outer }
404+
%retval = tuple ()
405+
return %retval : $()
406+
}

0 commit comments

Comments
 (0)