Skip to content

Commit 3f54a46

Browse files
authored
Merge pull request #22506 from gottesmm/pr-1976b9749f89a8476a3c2744d1c8e2a758c40fdf
2 parents fc58ad4 + 89a447a commit 3f54a46

File tree

3 files changed

+71
-15
lines changed

3 files changed

+71
-15
lines changed

lib/SILOptimizer/Transforms/OwnershipModelEliminator.cpp

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,9 @@
2727
#include "swift/SIL/SILBuilder.h"
2828
#include "swift/SIL/SILFunction.h"
2929
#include "swift/SIL/SILVisitor.h"
30+
#include "swift/SILOptimizer/Analysis/SimplifyInstruction.h"
3031
#include "swift/SILOptimizer/PassManager/Transforms.h"
32+
#include "swift/SILOptimizer/Utils/Local.h"
3133
#include "llvm/Support/CommandLine.h"
3234

3335
using namespace swift;
@@ -248,6 +250,9 @@ static void splitDestructure(SILBuilder &B, SILInstruction *I, SILValue Op) {
248250
assert((isa<DestructureStructInst>(I) || isa<DestructureTupleInst>(I)) &&
249251
"Only destructure operations can be passed to splitDestructure");
250252

253+
// First before we destructure anything, see if we can simplify any of our
254+
// instruction operands.
255+
251256
SILModule &M = I->getModule();
252257
SILLocation Loc = I->getLoc();
253258
SILType OpType = Op->getType();
@@ -256,16 +261,33 @@ static void splitDestructure(SILBuilder &B, SILInstruction *I, SILValue Op) {
256261
Projection::getFirstLevelProjections(OpType, M, Projections);
257262
assert(Projections.size() == I->getNumResults());
258263

259-
llvm::SmallVector<SILValue, 8> NewValues;
260-
for (unsigned i : indices(Projections)) {
261-
const auto &Proj = Projections[i];
262-
NewValues.push_back(Proj.createObjectProjection(B, Loc, Op).get());
263-
assert(NewValues.back()->getType() == I->getResults()[i]->getType() &&
264-
"Expected created projections and results to be the same types");
264+
auto Results = I->getResults();
265+
for (unsigned Index : indices(Results)) {
266+
SILValue Result = Results[Index];
267+
268+
// If our result doesnt have any uses, do not emit instructions, just skip
269+
// it.
270+
if (Result->use_empty())
271+
continue;
272+
273+
// Otherwise, create a projection.
274+
const auto &Proj = Projections[Index];
275+
SingleValueInstruction *ProjInst =
276+
Proj.createObjectProjection(B, Loc, Op).get();
277+
278+
// If we can simplify, do so.
279+
if (SILValue NewV = simplifyInstruction(ProjInst)) {
280+
Result->replaceAllUsesWith(NewV);
281+
ProjInst->eraseFromParent();
282+
continue;
283+
}
284+
285+
Result->replaceAllUsesWith(ProjInst);
265286
}
266287

267-
I->replaceAllUsesPairwiseWith(NewValues);
268-
I->eraseFromParent();
288+
// We may have exposed trivially dead instructions due to
289+
// simplifyInstruction... delete I and any such instructions!
290+
recursivelyDeleteTriviallyDeadInstructions(I, true);
269291
}
270292

271293
bool OwnershipModelEliminatorVisitor::visitDestructureStructInst(

test/SILOptimizer/ownership_model_eliminator.sil

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,3 +299,33 @@ bb0(%0 : @owned $(Builtin.NativeObject, Builtin.Int32), %1 : @owned $TestArray2)
299299
%7 = tuple(%2 : $Builtin.NativeObject, %3 : $Builtin.Int32, %4 : $TestArrayStorage, %5 : $Builtin.Int32, %6 : $TestArrayStorage)
300300
return %7 : $(Builtin.NativeObject, Builtin.Int32, TestArrayStorage, Builtin.Int32, TestArrayStorage)
301301
}
302+
303+
// In the following test, the trivial parts do not have any actual uses... do
304+
// not emit any value projections for them!
305+
//
306+
// CHECK-LABEL: sil [canonical] @test_destructure_with_only_some_uses : $@convention(thin) (@owned (Builtin.NativeObject, Builtin.Int32), @owned TestArray2) -> @owned (Builtin.NativeObject, TestArrayStorage, TestArrayStorage) {
307+
// CHECK: bb0([[ARG0:%.*]] : $(Builtin.NativeObject, Builtin.Int32), [[ARG1:%.*]] : $TestArray2):
308+
// CHECK-NEXT: [[ARG0_0:%.*]] = tuple_extract [[ARG0]]
309+
// CHECK-NEXT: [[STORAGE:%.*]] = struct_extract [[ARG1]] : $TestArray2, #TestArray2.storage
310+
// CHECK-NEXT: [[STORAGE2:%.*]] = struct_extract [[ARG1]] : $TestArray2, #TestArray2.storage2
311+
// CHECK-NEXT: [[RESULT:%.*]] = tuple ([[ARG0_0]] : ${{.*}}, [[STORAGE]] : ${{.*}}, [[STORAGE2]] : ${{.*}})
312+
// CHECK-NEXT: return [[RESULT]]
313+
// CHECK: } // end sil function 'test_destructure_with_only_some_uses'
314+
sil [canonical] [ossa] @test_destructure_with_only_some_uses : $@convention(thin) (@owned (Builtin.NativeObject, Builtin.Int32), @owned TestArray2) -> @owned (Builtin.NativeObject, TestArrayStorage, TestArrayStorage) {
315+
bb0(%0 : @owned $(Builtin.NativeObject, Builtin.Int32), %1 : @owned $TestArray2):
316+
(%2, %3) = destructure_tuple %0 : $(Builtin.NativeObject, Builtin.Int32)
317+
(%4, %5, %6) = destructure_struct %1 : $TestArray2
318+
%7 = tuple (%2 : $Builtin.NativeObject, %4 : $TestArrayStorage, %6 : $TestArrayStorage)
319+
return %7 : $(Builtin.NativeObject, TestArrayStorage, TestArrayStorage)
320+
}
321+
322+
// CHECK-LABEL: sil [canonical] @test_simplify_instruction : $@convention(thin) (@owned Builtin.NativeObject, Builtin.Int32) -> @owned Builtin.NativeObject {
323+
// CHECK: bb0([[ARG:%.*]] : $Builtin.NativeObject,
324+
// CHECK-NEXT: return [[ARG]]
325+
// CHECK: } // end sil function 'test_simplify_instruction'
326+
sil [canonical] [ossa] @test_simplify_instruction : $@convention(thin) (@owned Builtin.NativeObject, Builtin.Int32) -> @owned Builtin.NativeObject {
327+
bb0(%0 : @owned $Builtin.NativeObject, %1 : $Builtin.Int32):
328+
%2 = tuple(%0 : $Builtin.NativeObject, %1 : $Builtin.Int32)
329+
(%3, %4) = destructure_tuple %2 : $(Builtin.NativeObject, Builtin.Int32)
330+
return %3 : $Builtin.NativeObject
331+
}

test/Serialization/transparent-std.swift

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,17 @@ func test_foo(x: Builtin.Int1, y: Builtin.Int1) -> Builtin.Int1 {
1616
}
1717

1818
// SIL-LABEL: sil public_external [transparent] [serialized] [canonical] @$s19def_transparent_std12assign_tuple1x1yyBi64__Bot_BptF : $@convention(thin) (Builtin.Int64, @guaranteed Builtin.NativeObject, Builtin.RawPointer) -> () {
19-
// SIL: = tuple (%0 : $Builtin.Int64, %1 : $Builtin.NativeObject)
20-
// SIL: retain_value
21-
// SIL: = tuple_extract
22-
// SIL: = tuple_extract
23-
// SIL: = pointer_to_address
24-
// SIL: = tuple
25-
// SIL: = load
19+
// SIL: bb0([[ARG0:%.*]] : ${{.*}}, [[ARG1:%.*]] : ${{.*}}, [[ARG2:%.*]] :
20+
// SIL: [[TUP:%.*]] = tuple ([[ARG0]] : $Builtin.Int64, [[ARG1]] : $Builtin.NativeObject)
21+
// SIL: retain_value [[TUP]]
22+
// SIL: [[CASTED_PTR:%.*]] = pointer_to_address [[ARG2]]
23+
// SIL: [[CASTED_PTR_0:%.*]] = tuple_element_addr [[CASTED_PTR]] : $*(Builtin.Int64, Builtin.NativeObject), 0
24+
// SIL: store [[ARG0]] to [[CASTED_PTR_0]]
25+
// SIL: [[CASTED_PTR_1:%.*]] = tuple_element_addr [[CASTED_PTR]] : $*(Builtin.Int64, Builtin.NativeObject), 1
26+
// SIL: [[OLD_VALUE:%.*]] = load [[CASTED_PTR_1]]
27+
// SIL: store [[ARG1]] to [[CASTED_PTR_1]]
28+
// SIL: strong_release [[OLD_VALUE]]
29+
// SIL: } // end sil function '$s19def_transparent_std12assign_tuple1x1yyBi64__Bot_BptF'
2630
func test_tuple(x: (Builtin.Int64, Builtin.NativeObject),
2731
y: Builtin.RawPointer) {
2832
assign_tuple(x: x, y: y)

0 commit comments

Comments
 (0)