Skip to content

Commit

Permalink
COWArrayOpt: ensure that we can hoist all address projections that we…
Browse files Browse the repository at this point in the history
… stripped.

This change is needed because we new consider index_addr as address projection in Projection.h
  • Loading branch information
eeckstein committed Jan 27, 2016
1 parent ae28353 commit 905fd37
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 6 deletions.
11 changes: 6 additions & 5 deletions include/swift/SIL/InstructionUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,14 @@ SILValue stripUpCasts(SILValue V);
/// upcasts and downcasts.
SILValue stripClassCasts(SILValue V);

/// Return the underlying SILValue after stripping off all casts and
/// address projection instructions.
///
/// An address projection instruction is one of one of ref_element_addr,
/// struct_element_addr, tuple_element_addr.
/// Return the underlying SILValue after stripping off all address projection
/// instructions.
SILValue stripAddressProjections(SILValue V);

/// Return the underlying SILValue after stripping off all address projection
/// instructions which have a single operand.
SILValue stripUnaryAddressProjections(SILValue V);

/// Return the underlying SILValue after stripping off all aggregate projection
/// instructions.
///
Expand Down
12 changes: 12 additions & 0 deletions lib/SIL/InstructionUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,18 @@ SILValue swift::stripAddressProjections(SILValue V) {
}
}

SILValue swift::stripUnaryAddressProjections(SILValue V) {
while (true) {
V = stripSinglePredecessorArgs(V);
if (!NewProjection::isAddressProjection(V))
return V;
auto *Inst = cast<SILInstruction>(V);
if (Inst->getNumOperands() > 1)
return V;
V = Inst->getOperand(0);
}
}

SILValue swift::stripValueProjections(SILValue V) {
while (true) {
V = stripSinglePredecessorArgs(V);
Expand Down
2 changes: 1 addition & 1 deletion lib/SILOptimizer/LoopTransforms/COWArrayOpt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1433,7 +1433,7 @@ bool COWArrayOpt::hoistMakeMutable(ArraySemanticsCall MakeMutable) {

// We can hoist address projections (even if they are only conditionally
// executed).
auto ArrayAddrBase = stripAddressProjections(CurrentArrayAddr);
auto ArrayAddrBase = stripUnaryAddressProjections(CurrentArrayAddr);
SILBasicBlock *ArrayAddrBaseBB = ArrayAddrBase->getParentBB();

if (ArrayAddrBaseBB && !DomTree->dominates(ArrayAddrBaseBB, Preheader)) {
Expand Down
27 changes: 27 additions & 0 deletions test/SILOptimizer/cowarray_opt.sil
Original file line number Diff line number Diff line change
Expand Up @@ -1051,6 +1051,33 @@ bb2:
return %7 : $()
}

// We don't support hoisting non-unary projections yet.

// CHECK-LABEL: sil @dont_hoist_non_unary_projections
// CHECK-NOT: index_addr
// CHECK: bb2({{.*}}):
// CHECK: index_addr
sil @dont_hoist_non_unary_projections : $@convention(thin) (@inout ContainerContainer, @inout Builtin.Int1) -> () {
bb0(%0 : $*ContainerContainer, %1 : $*Builtin.Int1):
br bb1

bb1:
%2 = struct_element_addr %0 : $*ContainerContainer, #ContainerContainer.container
br bb2(%2 : $*Container)

bb2(%3: $*Container):
%i = integer_literal $Builtin.Int32, 0
%3i = index_addr %3 : $*Container, %i : $Builtin.Int32
%4 = struct_element_addr %3i : $*Container, #Container.array
%5 = function_ref @array_make_mutable : $@convention(method) (@inout MyArray<MyStruct>) -> ()
%6 = apply %5(%4) : $@convention(method) (@inout MyArray<MyStruct>) -> ()
cond_br undef, bb1, bb3

bb3:
%7 = tuple()
return %7 : $()
}

// CHECK-LABEL: sil @hoist_projections2
// CHECK: bb0([[CONTAINER:%[0-9]+]]
// CHECK: [[CONTAINER2:%.*]] = struct_element_addr [[CONTAINER]] : $*ContainerContainer
Expand Down

0 comments on commit 905fd37

Please sign in to comment.