From 12d652e39fc0cc35c5e9894e960299cec091acdf Mon Sep 17 00:00:00 2001 From: zoecarver Date: Fri, 10 Apr 2020 15:10:09 -0700 Subject: [PATCH] [ownership] Update SROA to support OSSA. Use destructure to chop up allocations. Other than that, just add correct load/store qualifiers. --- lib/SILOptimizer/Transforms/SILSROA.cpp | 46 +-- test/SILOptimizer/sroa.sil | 42 +- test/SILOptimizer/sroa_ossa.sil | 498 ++++++++++++++++++++++++ 3 files changed, 532 insertions(+), 54 deletions(-) create mode 100644 test/SILOptimizer/sroa_ossa.sil diff --git a/lib/SILOptimizer/Transforms/SILSROA.cpp b/lib/SILOptimizer/Transforms/SILSROA.cpp index 4164b365ce8..b931a3c1567 100644 --- a/lib/SILOptimizer/Transforms/SILSROA.cpp +++ b/lib/SILOptimizer/Transforms/SILSROA.cpp @@ -67,8 +67,6 @@ public: private: SILValue createAgg(SILBuilder &B, SILLocation Loc, SILType Ty, ArrayRef Elements); - SILValue createAggProjection(SILBuilder &B, SILLocation Loc, - SILValue Operand, unsigned EltNo); unsigned getEltNoForProjection(SILInstruction *Inst); void createAllocas(llvm::SmallVector &NewAllocations); }; @@ -87,24 +85,6 @@ SROAMemoryUseAnalyzer::createAgg(SILBuilder &B, SILLocation Loc, return B.createStruct(Loc, Ty, Elements); } -SILValue -SROAMemoryUseAnalyzer::createAggProjection(SILBuilder &B, SILLocation Loc, - SILValue Operand, - unsigned EltNo) { - if (TT) - return B.createTupleExtract(Loc, Operand, EltNo); - - assert(SD && "SD should not be null since either it or TT must be set at " - "this point."); - - auto Properties = SD->getStoredProperties(); - unsigned Counter = 0; - for (auto *D : Properties) - if (Counter++ == EltNo) - return B.createStructExtract(Loc, Operand, D); - llvm_unreachable("Unknown field."); -} - unsigned SROAMemoryUseAnalyzer::getEltNoForProjection(SILInstruction *Inst) { if (TT) return cast(Inst)->getFieldNo(); @@ -249,9 +229,10 @@ void SROAMemoryUseAnalyzer::chopUpAlloca(std::vector &Worklist for (auto *LI : Loads) { SILBuilderWithScope B(LI); llvm::SmallVector Elements; - for (auto *NewAI : NewAllocations) - Elements.push_back(B.createLoad(LI->getLoc(), NewAI, - LoadOwnershipQualifier::Unqualified)); + for (auto *NewAI : NewAllocations) { + Elements.push_back(B.emitLoadValueOperation(LI->getLoc(), NewAI, + LI->getOwnershipQualifier())); + } SILValue Agg = createAgg(B, LI->getLoc(), LI->getType().getObjectType(), Elements); LI->replaceAllUsesWith(Agg); @@ -260,12 +241,15 @@ void SROAMemoryUseAnalyzer::chopUpAlloca(std::vector &Worklist // Change any aggregate stores into extracts + field stores. for (auto *SI : Stores) { - SILBuilderWithScope B(SI); - for (unsigned EltNo : indices(NewAllocations)) - B.createStore(SI->getLoc(), - createAggProjection(B, SI->getLoc(), SI->getSrc(), EltNo), - NewAllocations[EltNo], - StoreOwnershipQualifier::Unqualified); + SILBuilderWithScope builder(SI); + SmallVector destructured; + builder.emitDestructureValueOperation(SI->getLoc(), SI->getSrc(), + destructured); + for (unsigned eltNo : indices(NewAllocations)) { + builder.emitStoreValueOperation(SI->getLoc(), destructured[eltNo], + NewAllocations[eltNo], + StoreOwnershipQualifier::Init); + } SI->eraseFromParent(); } @@ -356,10 +340,6 @@ public: void run() override { SILFunction *F = getFunction(); - // FIXME: We should be able to handle ownership. - if (F->hasOwnership()) - return; - LLVM_DEBUG(llvm::dbgs() << "***** SROA on function: " << F->getName() << " *****\n"); diff --git a/test/SILOptimizer/sroa.sil b/test/SILOptimizer/sroa.sil index 59183292bec..b08b874a06b 100644 --- a/test/SILOptimizer/sroa.sil +++ b/test/SILOptimizer/sroa.sil @@ -23,10 +23,10 @@ sil @use_int32 : $@convention(thin) (Builtin.Int32) -> () // CHECK: [[VAR_2:%[0-9]+]] = alloc_stack $Builtin.Int32 // CHECK: [[VAR_3:%[0-9]+]] = alloc_stack $Builtin.Int64 // CHECK: [[VAR_4:%[0-9]+]] = struct_extract [[VAR_0]] : $S1, #S1.x -// CHECK: store [[VAR_4]] to [[VAR_1]] : $*Builtin.Int1 // CHECK: [[VAR_6:%[0-9]+]] = struct_extract [[VAR_0]] : $S1, #S1.y -// CHECK: store [[VAR_6]] to [[VAR_2]] : $*Builtin.Int32 // CHECK: [[VAR_8:%[0-9]+]] = struct_extract [[VAR_0]] : $S1, #S1.z +// CHECK: store [[VAR_4]] to [[VAR_1]] : $*Builtin.Int1 +// CHECK: store [[VAR_6]] to [[VAR_2]] : $*Builtin.Int32 // CHECK: store [[VAR_8]] to [[VAR_3]] : $*Builtin.Int64 // CHECK: [[VAR_10:%[0-9]+]] = function_ref @use_int32 : $@convention(thin) (Builtin.Int32) -> () // CHECK: [[VAR_11:%[0-9]+]] = load [[VAR_2]] : $*Builtin.Int32 @@ -91,13 +91,13 @@ struct S2 { // CHECK: [[VAR_4:%[0-9]+]] = alloc_stack $Builtin.Int32 // CHECK: [[VAR_5:%[0-9]+]] = alloc_stack $Builtin.Int64 // CHECK: [[VAR_6:%[0-9]+]] = struct_extract [[VAR_0]] : $S2, #S2.alpha -// CHECK: store [[VAR_6]] to [[VAR_2]] : $*Builtin.FPIEEE32 // CHECK: [[VAR_8:%[0-9]+]] = struct_extract [[VAR_0]] : $S2, #S2.beta +// CHECK: store [[VAR_6]] to [[VAR_2]] : $*Builtin.FPIEEE32 // CHECK: [[VAR_9:%[0-9]+]] = struct_extract [[VAR_8]] : $S1, #S1.x -// CHECK: store [[VAR_9]] to [[VAR_3]] : $*Builtin.Int1 // CHECK: [[VAR_11:%[0-9]+]] = struct_extract [[VAR_8]] : $S1, #S1.y -// CHECK: store [[VAR_11]] to [[VAR_4]] : $*Builtin.Int32 // CHECK: [[VAR_13:%[0-9]+]] = struct_extract [[VAR_8]] : $S1, #S1.z +// CHECK: store [[VAR_9]] to [[VAR_3]] : $*Builtin.Int1 +// CHECK: store [[VAR_11]] to [[VAR_4]] : $*Builtin.Int32 // CHECK: store [[VAR_13]] to [[VAR_5]] : $*Builtin.Int64 // CHECK: [[VAR_15:%[0-9]+]] = load [[VAR_3]] : $*Builtin.Int1 // CHECK: [[VAR_16:%[0-9]+]] = load [[VAR_4]] : $*Builtin.Int32 @@ -159,13 +159,13 @@ struct S3 { // CHECK: [[VAR_4:%[0-9]+]] = alloc_stack $Builtin.Int16 // CHECK: [[VAR_5:%[0-9]+]] = alloc_stack $Builtin.FPIEEE32 // CHECK: [[VAR_6:%[0-9]+]] = struct_extract [[VAR_0]] : $S3, #S3.gamma -// CHECK: [[VAR_7:%[0-9]+]] = tuple_extract [[VAR_6]] : $(Builtin.Int32, Builtin.Int64, Builtin.Int16), 0 -// CHECK: store [[VAR_7]] to [[VAR_2]] : $*Builtin.Int32 -// CHECK: [[VAR_9:%[0-9]+]] = tuple_extract [[VAR_6]] : $(Builtin.Int32, Builtin.Int64, Builtin.Int16), 1 -// CHECK: store [[VAR_9]] to [[VAR_3]] : $*Builtin.Int64 -// CHECK: [[VAR_11:%[0-9]+]] = tuple_extract [[VAR_6]] : $(Builtin.Int32, Builtin.Int64, Builtin.Int16), 2 -// CHECK: store [[VAR_11]] to [[VAR_4]] : $*Builtin.Int16 // CHECK: [[VAR_13:%[0-9]+]] = struct_extract [[VAR_0]] : $S3, #S3.delta +// CHECK: [[VAR_7:%[0-9]+]] = tuple_extract [[VAR_6]] : $(Builtin.Int32, Builtin.Int64, Builtin.Int16), 0 +// CHECK: [[VAR_9:%[0-9]+]] = tuple_extract [[VAR_6]] : $(Builtin.Int32, Builtin.Int64, Builtin.Int16), 1 +// CHECK: [[VAR_11:%[0-9]+]] = tuple_extract [[VAR_6]] : $(Builtin.Int32, Builtin.Int64, Builtin.Int16), 2 +// CHECK: store [[VAR_7]] to [[VAR_2]] : $*Builtin.Int32 +// CHECK: store [[VAR_9]] to [[VAR_3]] : $*Builtin.Int64 +// CHECK: store [[VAR_11]] to [[VAR_4]] : $*Builtin.Int16 // CHECK: store [[VAR_13]] to [[VAR_5]] : $*Builtin.FPIEEE32 // CHECK: [[VAR_15:%[0-9]+]] = function_ref @use_tup : $@convention(thin) ((Builtin.Int32, Builtin.Int64, Builtin.Int16)) -> () // CHECK: [[VAR_16:%[0-9]+]] = load [[VAR_2]] : $*Builtin.Int32 @@ -219,10 +219,10 @@ bb0(%0 : $S3, %1 : $Builtin.Int64): // CHECK: [[VAR_2:%[0-9]+]] = alloc_stack $Builtin.Int32 // CHECK: [[VAR_3:%[0-9]+]] = alloc_stack $Builtin.Int64 // CHECK: [[VAR_4:%[0-9]+]] = tuple_extract [[VAR_0]] : $(Builtin.Int1, Builtin.Int32, Builtin.Int64), 0 -// CHECK: store [[VAR_4]] to [[VAR_1]] : $*Builtin.Int1 // CHECK: [[VAR_6:%[0-9]+]] = tuple_extract [[VAR_0]] : $(Builtin.Int1, Builtin.Int32, Builtin.Int64), 1 -// CHECK: store [[VAR_6]] to [[VAR_2]] : $*Builtin.Int32 // CHECK: [[VAR_8:%[0-9]+]] = tuple_extract [[VAR_0]] : $(Builtin.Int1, Builtin.Int32, Builtin.Int64), 2 +// CHECK: store [[VAR_4]] to [[VAR_1]] : $*Builtin.Int1 +// CHECK: store [[VAR_6]] to [[VAR_2]] : $*Builtin.Int32 // CHECK: store [[VAR_8]] to [[VAR_3]] : $*Builtin.Int64 // CHECK: [[VAR_10:%[0-9]+]] = function_ref @use_int32 : $@convention(thin) (Builtin.Int32) -> () // CHECK: [[VAR_11:%[0-9]+]] = load [[VAR_2]] : $*Builtin.Int32 @@ -267,11 +267,11 @@ sil @use_str4 : $@convention(thin) (S4) -> () // CHECK: [[VAR_3:%[0-9]+]] = alloc_stack $Builtin.Int32 // CHECK: [[VAR_4:%[0-9]+]] = alloc_stack $Builtin.Int16 // CHECK: [[VAR_5:%[0-9]+]] = tuple_extract [[VAR_0]] : $(S4, Builtin.Int16), 0 -// CHECK: [[VAR_6:%[0-9]+]] = struct_extract [[VAR_5]] : $S4, #S4.aleph -// CHECK: store [[VAR_6]] to [[VAR_2]] : $*Builtin.Int64 -// CHECK: [[VAR_8:%[0-9]+]] = struct_extract [[VAR_5]] : $S4, #S4.bet -// CHECK: store [[VAR_8]] to [[VAR_3]] : $*Builtin.Int32 // CHECK: [[VAR_10:%[0-9]+]] = tuple_extract [[VAR_0]] : $(S4, Builtin.Int16), 1 +// CHECK: [[VAR_6:%[0-9]+]] = struct_extract [[VAR_5]] : $S4, #S4.aleph +// CHECK: [[VAR_8:%[0-9]+]] = struct_extract [[VAR_5]] : $S4, #S4.bet +// CHECK: store [[VAR_6]] to [[VAR_2]] : $*Builtin.Int64 +// CHECK: store [[VAR_8]] to [[VAR_3]] : $*Builtin.Int32 // CHECK: store [[VAR_10]] to [[VAR_4]] : $*Builtin.Int16 // CHECK: [[VAR_12:%[0-9]+]] = function_ref @use_str4 : $@convention(thin) (S4) -> () // CHECK: [[VAR_13:%[0-9]+]] = load [[VAR_2]] : $*Builtin.Int64 @@ -325,11 +325,11 @@ sil @use_int16 : $@convention(thin) (Builtin.Int16) -> () // CHECK: [[VAR_3:%[0-9]+]] = alloc_stack $Builtin.Int32 // CHECK: [[VAR_4:%[0-9]+]] = alloc_stack $Builtin.Int16 // CHECK: [[VAR_5:%[0-9]+]] = tuple_extract [[VAR_0]] : $((Builtin.Int64, Builtin.Int32), Builtin.Int16), 0 -// CHECK: [[VAR_6:%[0-9]+]] = tuple_extract [[VAR_5]] : $(Builtin.Int64, Builtin.Int32), 0 -// CHECK: store [[VAR_6]] to [[VAR_2]] : $*Builtin.Int64 -// CHECK: [[VAR_8:%[0-9]+]] = tuple_extract [[VAR_5]] : $(Builtin.Int64, Builtin.Int32), 1 -// CHECK: store [[VAR_8]] to [[VAR_3]] : $*Builtin.Int32 // CHECK: [[VAR_10:%[0-9]+]] = tuple_extract [[VAR_0]] : $((Builtin.Int64, Builtin.Int32), Builtin.Int16), 1 +// CHECK: [[VAR_6:%[0-9]+]] = tuple_extract [[VAR_5]] : $(Builtin.Int64, Builtin.Int32), 0 +// CHECK: [[VAR_8:%[0-9]+]] = tuple_extract [[VAR_5]] : $(Builtin.Int64, Builtin.Int32), 1 +// CHECK: store [[VAR_6]] to [[VAR_2]] : $*Builtin.Int64 +// CHECK: store [[VAR_8]] to [[VAR_3]] : $*Builtin.Int32 // CHECK: store [[VAR_10]] to [[VAR_4]] : $*Builtin.Int16 // CHECK: [[VAR_12:%[0-9]+]] = load [[VAR_2]] : $*Builtin.Int64 // CHECK: [[VAR_13:%[0-9]+]] = load [[VAR_3]] : $*Builtin.Int32 diff --git a/test/SILOptimizer/sroa_ossa.sil b/test/SILOptimizer/sroa_ossa.sil new file mode 100644 index 00000000000..8a88a90200f --- /dev/null +++ b/test/SILOptimizer/sroa_ossa.sil @@ -0,0 +1,498 @@ +// RUN: %target-sil-opt -enable-sil-verify-all -sroa %s | %FileCheck %s + +sil_stage canonical + +import Builtin +import Swift + +/////////////////////////////// +// Struct with Scalar Fields // +/////////////////////////////// + +struct S1 { + var x : Builtin.Int1 + var y : Builtin.Int32 + var z : Builtin.Int64 +} + +sil [ossa] @use_int32 : $@convention(thin) (Builtin.Int32) -> () + +// CHECK-LABEL: sil [ossa] @struct_with_scalar_fields : $@convention(thin) (S1) -> () +// CHECK: bb0([[VAR_0:%[0-9]+]] : $S1): + +// CHECK-NEXT: [[VAR_1:%[0-9]+]] = alloc_stack $Builtin.Int1 +// CHECK-NEXT: [[VAR_2:%[0-9]+]] = alloc_stack $Builtin.Int32 +// CHECK-NEXT: [[VAR_3:%[0-9]+]] = alloc_stack $Builtin.Int64 +// CHECK-NEXT: ([[VAR_4:%[0-9]+]], [[VAR_6:%[0-9]+]], [[VAR_8:%[0-9]+]]) = destructure_struct [[VAR_0]] +// CHECK-NEXT: store [[VAR_4]] to [trivial] [[VAR_1]] : $*Builtin.Int1 +// CHECK-NEXT: store [[VAR_6]] to [trivial] [[VAR_2]] : $*Builtin.Int32 +// CHECK-NEXT: store [[VAR_8]] to [trivial] [[VAR_3]] : $*Builtin.Int64 + +// CHECK-NEXT: function_ref +// CHECK-NEXT: [[VAR_10:%[0-9]+]] = function_ref @use_int32 : $@convention(thin) (Builtin.Int32) -> () +// CHECK-NEXT: [[VAR_11:%[0-9]+]] = load [trivial] [[VAR_2]] : $*Builtin.Int32 +// CHECK-NEXT: [[VAR_12:%[0-9]+]] = apply [[VAR_10]]([[VAR_11]]) : $@convention(thin) (Builtin.Int32) -> () +// CHECK-NEXT: [[VAR_13:%[0-9]+]] = load [trivial] [[VAR_1]] : $*Builtin.Int1 +// CHECK-NEXT: [[VAR_14:%[0-9]+]] = load [trivial] [[VAR_2]] : $*Builtin.Int32 +// CHECK-NEXT: [[VAR_15:%[0-9]+]] = load [trivial] [[VAR_3]] : $*Builtin.Int64 +// CHECK-NEXT: [[VAR_16:%[0-9]+]] = struct $S1 ([[VAR_13]] : $Builtin.Int1, [[VAR_14]] : $Builtin.Int32, [[VAR_15]] : $Builtin.Int64) + +// CHECK: dealloc_stack [[VAR_3]] : $*Builtin.Int64 +// CHECK: dealloc_stack [[VAR_2]] : $*Builtin.Int32 +// CHECK: dealloc_stack [[VAR_1]] : $*Builtin.Int1 + +// CHECK: [[VAR_20:%[0-9]+]] = tuple () +// CHECK: return [[VAR_20]] : $() +sil [ossa] @struct_with_scalar_fields : $@convention(thin) (S1) -> () { +bb0(%0 : $S1): + %1 = alloc_stack $S1 + debug_value %1 : $*S1 // should not prevent the optimization + debug_value %1 : $*S1 // should not prevent the optimization + store %0 to [trivial] %1 : $*S1 + %2 = function_ref @use_int32 : $@convention(thin) (Builtin.Int32) -> () + %3 = struct_element_addr %1 : $*S1, #S1.y + %4 = load [trivial] %3 : $*Builtin.Int32 + apply %2(%4) : $@convention(thin) (Builtin.Int32) -> () + %5 = load [trivial] %1 : $*S1 + dealloc_stack %1 : $*S1 + %6 = tuple () + return %6 : $() +} + +// CHECK-LABEL: sil [ossa] @dont_sroa_without_benefit : $@convention(thin) (S1) -> S1 +// CHECK: bb0 +// CHECK-NEXT: alloc_stack $S1 +// CHECK-NEXT: store %0 to [trivial] %1 : $*S1 +// CHECK-NEXT: load [trivial] %1 : $*S1 +// CHECK-NEXT: dealloc_stack %1 : $*S1 +// CHECK-NEXT: return +sil [ossa] @dont_sroa_without_benefit : $@convention(thin) (S1) -> S1 { +bb0(%0 : $S1): + %1 = alloc_stack $S1 + store %0 to [trivial] %1 : $*S1 + %3 = load [trivial] %1 : $*S1 + dealloc_stack %1 : $*S1 + return %3 : $S1 +} + + +/////////////////////////////// +// Struct With Struct Fields // +/////////////////////////////// + +sil [ossa] @use_s1 : $@convention(thin) (S1) -> () + +struct S2 { + var alpha : Builtin.FPIEEE32 + var beta : S1 +} + +// CHECK-LABEL: sil [ossa] @struct_with_struct_fields : $@convention(thin) (S2, Builtin.Int64) -> () +// CHECK: bb0([[VAR_0:%[0-9]+]] : $S2, [[VAR_1:%[0-9]+]] : $Builtin.Int64): + +// CHECK-NEXT: [[VAR_2:%[0-9]+]] = alloc_stack $Builtin.FPIEEE32 +// CHECK-NEXT: [[VAR_3:%[0-9]+]] = alloc_stack $Builtin.Int1 +// CHECK-NEXT: [[VAR_4:%[0-9]+]] = alloc_stack $Builtin.Int32 +// CHECK-NEXT: [[VAR_5:%[0-9]+]] = alloc_stack $Builtin.Int64 + +// CHECK-NEXT: ([[VAR_6:%[0-9]+]], [[VAR_8:%[0-9]+]]) = destructure_struct [[VAR_0]] +// CHECK-NEXT: store [[VAR_6]] to [trivial] [[VAR_2]] : $*Builtin.FPIEEE32 + +// CHECK-NEXT: ([[VAR_9:%[0-9]+]], [[VAR_11:%[0-9]+]], [[VAR_13:%[0-9]+]]) = destructure_struct [[VAR_8]] +// CHECK-NEXT: store [[VAR_9]] to [trivial] [[VAR_3]] : $*Builtin.Int1 +// CHECK-NEXT: store [[VAR_11]] to [trivial] [[VAR_4]] : $*Builtin.Int32 +// CHECK-NEXT: store [[VAR_13]] to [trivial] [[VAR_5]] : $*Builtin.Int64 + +// CHECK-NEXT: [[VAR_15:%[0-9]+]] = load [trivial] [[VAR_3]] : $*Builtin.Int1 +// CHECK-NEXT: [[VAR_16:%[0-9]+]] = load [trivial] [[VAR_4]] : $*Builtin.Int32 +// CHECK-NEXT: [[VAR_17:%[0-9]+]] = load [trivial] [[VAR_5]] : $*Builtin.Int64 +// CHECK-NEXT: [[VAR_18:%[0-9]+]] = struct $S1 ([[VAR_15]] : $Builtin.Int1, [[VAR_16]] : $Builtin.Int32, [[VAR_17]] : $Builtin.Int64) +// CHECK-NEXT: function_ref +// CHECK-NEXT: [[VAR_19:%[0-9]+]] = function_ref @use_s1 : $@convention(thin) (S1) -> () +// CHECK-NEXT: [[VAR_20:%[0-9]+]] = apply [[VAR_19]]([[VAR_18]]) : $@convention(thin) (S1) -> () +// CHECK-NEXT: function_ref +// CHECK-NEXT: [[VAR_21:%[0-9]+]] = function_ref @use_int32 : $@convention(thin) (Builtin.Int32) -> () +// CHECK-NEXT: [[VAR_22:%[0-9]+]] = load [trivial] [[VAR_4]] : $*Builtin.Int32 +// CHECK-NEXT: [[VAR_23:%[0-9]+]] = apply [[VAR_21]]([[VAR_22]]) : $@convention(thin) (Builtin.Int32) -> () +// CHECK-NEXT: [[VAR_24:%[0-9]+]] = load [trivial] [[VAR_2]] : $*Builtin.FPIEEE32 +// CHECK-NEXT: [[VAR_25:%[0-9]+]] = load [trivial] [[VAR_3]] : $*Builtin.Int1 +// CHECK-NEXT: [[VAR_26:%[0-9]+]] = load [trivial] [[VAR_4]] : $*Builtin.Int32 +// CHECK-NEXT: [[VAR_27:%[0-9]+]] = load [trivial] [[VAR_5]] : $*Builtin.Int64 +// CHECK-NEXT: [[VAR_28:%[0-9]+]] = struct $S1 ([[VAR_25]] : $Builtin.Int1, [[VAR_26]] : $Builtin.Int32, [[VAR_27]] : $Builtin.Int64) +// CHECK-NEXT: [[VAR_29:%[0-9]+]] = struct $S2 ([[VAR_24]] : $Builtin.FPIEEE32, [[VAR_28]] : $S1) +// CHECK-NEXT: store [[VAR_1]] to [trivial] [[VAR_5]] : $*Builtin.Int64 +// CHECK-NEXT: dealloc_stack [[VAR_5]] : $*Builtin.Int64 +// CHECK-NEXT: dealloc_stack [[VAR_4]] : $*Builtin.Int32 +// CHECK-NEXT: dealloc_stack [[VAR_3]] : $*Builtin.Int1 +// CHECK-NEXT: dealloc_stack [[VAR_2]] : $*Builtin.FPIEEE32 +// CHECK-NEXT: [[VAR_35:%[0-9]+]] = tuple () +// CHECK-NEXT: return [[VAR_35]] : $() +sil [ossa] @struct_with_struct_fields : $@convention(thin) (S2, Builtin.Int64) -> () { +bb0(%0 : $S2, %1 : $Builtin.Int64): + %2 = alloc_stack $S2 + store %0 to [trivial] %2 : $*S2 + %3 = struct_element_addr %2 : $*S2, #S2.beta + %4 = load [trivial] %3 : $*S1 + %5 = function_ref @use_s1 : $@convention(thin) (S1) -> () + apply %5(%4) : $@convention(thin) (S1) -> () + %6 = struct_element_addr %3 : $*S1, #S1.y + %7 = function_ref @use_int32 : $@convention(thin) (Builtin.Int32) -> () + %8 = load [trivial] %6 : $*Builtin.Int32 + apply %7(%8) : $@convention(thin) (Builtin.Int32) -> () + %9 = load [trivial] %2 : $*S2 + %10 = struct_element_addr %3 : $*S1, #S1.z + store %1 to [trivial] %10 : $*Builtin.Int64 + dealloc_stack %2 : $*S2 + %11 = tuple() + return %11 : $() +} + +////////////////////////////// +// Struct with Tuple Fields // +////////////////////////////// + +sil [ossa] @use_tup : $@convention(thin) ((Builtin.Int32, Builtin.Int64, Builtin.Int16)) -> () + +struct S3 { + var gamma : (Builtin.Int32, Builtin.Int64, Builtin.Int16) + var delta : Builtin.FPIEEE32 +} + +// CHECK-LABEL: sil [ossa] @struct_with_tuple_fields : $@convention(thin) (S3, Builtin.Int64) -> () +// CHECK: bb0([[VAR_0:%[0-9]+]] : $S3, [[VAR_1:%[0-9]+]] : $Builtin.Int64): +// CHECK-NEXT: [[VAR_2:%[0-9]+]] = alloc_stack $Builtin.Int32 +// CHECK-NEXT: [[VAR_3:%[0-9]+]] = alloc_stack $Builtin.Int64 +// CHECK-NEXT: [[VAR_4:%[0-9]+]] = alloc_stack $Builtin.Int16 +// CHECK-NEXT: [[VAR_5:%[0-9]+]] = alloc_stack $Builtin.FPIEEE32 +// CHECK-NEXT: ([[VAR_6:%[0-9]+]], [[VAR_13:%[0-9]+]]) = destructure_struct [[VAR_0]] +// CHECK-NEXT: ([[VAR_7:%[0-9]+]], [[VAR_9:%[0-9]+]], [[VAR_11:%[0-9]+]]) = destructure_tuple [[VAR_6]] +// CHECK-NEXT: store [[VAR_7]] to [trivial] [[VAR_2]] : $*Builtin.Int32 +// CHECK-NEXT: store [[VAR_9]] to [trivial] [[VAR_3]] : $*Builtin.Int64 +// CHECK-NEXT: store [[VAR_11]] to [trivial] [[VAR_4]] : $*Builtin.Int16 +// CHECK-NEXT: store [[VAR_13]] to [trivial] [[VAR_5]] : $*Builtin.FPIEEE32 +// CHECK-NEXT: function_ref +// CHECK-NEXT: [[VAR_15:%[0-9]+]] = function_ref @use_tup : $@convention(thin) ((Builtin.Int32, Builtin.Int64, Builtin.Int16)) -> () +// CHECK-NEXT: [[VAR_16:%[0-9]+]] = load [trivial] [[VAR_2]] : $*Builtin.Int32 +// CHECK-NEXT: [[VAR_17:%[0-9]+]] = load [trivial] [[VAR_3]] : $*Builtin.Int64 +// CHECK-NEXT: [[VAR_18:%[0-9]+]] = load [trivial] [[VAR_4]] : $*Builtin.Int16 +// CHECK-NEXT: [[VAR_19:%[0-9]+]] = tuple ([[VAR_16]] : $Builtin.Int32, [[VAR_17]] : $Builtin.Int64, [[VAR_18]] : $Builtin.Int16) +// CHECK-NEXT: [[VAR_20:%[0-9]+]] = apply [[VAR_15]]([[VAR_19]]) : $@convention(thin) ((Builtin.Int32, Builtin.Int64, Builtin.Int16)) -> () +// CHECK-NEXT: [[VAR_21:%[0-9]+]] = load [trivial] [[VAR_2]] : $*Builtin.Int32 +// CHECK-NEXT: function_ref +// CHECK-NEXT: [[VAR_22:%[0-9]+]] = function_ref @use_int32 : $@convention(thin) (Builtin.Int32) -> () +// CHECK-NEXT: [[VAR_23:%[0-9]+]] = apply [[VAR_22]]([[VAR_21]]) : $@convention(thin) (Builtin.Int32) -> () +// CHECK-NEXT: [[VAR_24:%[0-9]+]] = load [trivial] [[VAR_2]] : $*Builtin.Int32 +// CHECK-NEXT: [[VAR_25:%[0-9]+]] = load [trivial] [[VAR_3]] : $*Builtin.Int64 +// CHECK-NEXT: [[VAR_26:%[0-9]+]] = load [trivial] [[VAR_4]] : $*Builtin.Int16 +// CHECK-NEXT: [[VAR_27:%[0-9]+]] = tuple ([[VAR_24]] : $Builtin.Int32, [[VAR_25]] : $Builtin.Int64, [[VAR_26]] : $Builtin.Int16) +// CHECK-NEXT: [[VAR_28:%[0-9]+]] = load [trivial] [[VAR_5]] : $*Builtin.FPIEEE32 +// CHECK-NEXT: [[VAR_29:%[0-9]+]] = struct $S3 ([[VAR_27]] : $(Builtin.Int32, Builtin.Int64, Builtin.Int16), [[VAR_28]] : $Builtin.FPIEEE32) +// CHECK-NEXT: store [[VAR_1]] to [trivial] [[VAR_3]] : $*Builtin.Int64 +// CHECK-NEXT: dealloc_stack [[VAR_5]] : $*Builtin.FPIEEE32 +// CHECK-NEXT: dealloc_stack [[VAR_4]] : $*Builtin.Int16 +// CHECK-NEXT: dealloc_stack [[VAR_3]] : $*Builtin.Int64 +// CHECK-NEXT: dealloc_stack [[VAR_2]] : $*Builtin.Int32 +// CHECK-NEXT: [[VAR_35:%[0-9]+]] = tuple () +// CHECK-NEXT: return [[VAR_35]] : $() +sil [ossa] @struct_with_tuple_fields : $@convention(thin) (S3, Builtin.Int64) -> () { +bb0(%0 : $S3, %1 : $Builtin.Int64): + %2 = alloc_stack $S3 + store %0 to [trivial] %2 : $*S3 + %3 = function_ref @use_tup : $@convention(thin) ((Builtin.Int32, Builtin.Int64, Builtin.Int16)) -> () + %4 = struct_element_addr %2 : $*S3, #S3.gamma + %5 = load [trivial] %4 : $*(Builtin.Int32, Builtin.Int64, Builtin.Int16) + apply %3(%5) : $@convention(thin) ((Builtin.Int32, Builtin.Int64, Builtin.Int16)) -> () + %6 = tuple_element_addr %4 : $*(Builtin.Int32, Builtin.Int64, Builtin.Int16), 0 + %7 = load [trivial] %6 : $*Builtin.Int32 + %8 = function_ref @use_int32 : $@convention(thin) (Builtin.Int32) -> () + apply %8(%7) : $@convention(thin) (Builtin.Int32) -> () + %9 = load [trivial] %2 : $*S3 + %10 = tuple_element_addr %4 : $*(Builtin.Int32, Builtin.Int64, Builtin.Int16), 1 + store %1 to [trivial] %10 : $*Builtin.Int64 + dealloc_stack %2 : $*S3 + %11 = tuple () + return %11 : $() +} + +////////////////////////////// +// Tuple with Scalar Fields // +////////////////////////////// + +// CHECK-LABEL: sil [ossa] @tuple_with_scalar_fields : $@convention(thin) ((Builtin.Int1, Builtin.Int32, Builtin.Int64)) -> () +// CHECK: bb0([[VAR_0:%[0-9]+]] : $(Builtin.Int1, Builtin.Int32, Builtin.Int64)): +// CHECK-NEXT: [[VAR_1:%[0-9]+]] = alloc_stack $Builtin.Int1 +// CHECK-NEXT: [[VAR_2:%[0-9]+]] = alloc_stack $Builtin.Int32 +// CHECK-NEXT: [[VAR_3:%[0-9]+]] = alloc_stack $Builtin.Int64 +// CHECK-NEXT: ([[VAR_4:%[0-9]+]], [[VAR_6:%[0-9]+]], [[VAR_8:%[0-9]+]]) = destructure_tuple [[VAR_0]] +// CHECK-NEXT: store [[VAR_4]] to [trivial] [[VAR_1]] : $*Builtin.Int1 +// CHECK-NEXT: store [[VAR_6]] to [trivial] [[VAR_2]] : $*Builtin.Int32 +// CHECK-NEXT: store [[VAR_8]] to [trivial] [[VAR_3]] : $*Builtin.Int64 +// CHECK-NEXT: function_ref +// CHECK-NEXT: [[VAR_10:%[0-9]+]] = function_ref @use_int32 : $@convention(thin) (Builtin.Int32) -> () +// CHECK-NEXT: [[VAR_11:%[0-9]+]] = load [trivial] [[VAR_2]] : $*Builtin.Int32 +// CHECK-NEXT: [[VAR_12:%[0-9]+]] = apply [[VAR_10]]([[VAR_11]]) : $@convention(thin) (Builtin.Int32) -> () +// CHECK-NEXT: [[VAR_13:%[0-9]+]] = load [trivial] [[VAR_1]] : $*Builtin.Int1 +// CHECK-NEXT: [[VAR_14:%[0-9]+]] = load [trivial] [[VAR_2]] : $*Builtin.Int32 +// CHECK-NEXT: [[VAR_15:%[0-9]+]] = load [trivial] [[VAR_3]] : $*Builtin.Int64 +// CHECK-NEXT: [[VAR_16:%[0-9]+]] = tuple ([[VAR_13]] : $Builtin.Int1, [[VAR_14]] : $Builtin.Int32, [[VAR_15]] : $Builtin.Int64) +// CHECK-NEXT: dealloc_stack [[VAR_3]] : $*Builtin.Int64 +// CHECK-NEXT: dealloc_stack [[VAR_2]] : $*Builtin.Int32 +// CHECK-NEXT: dealloc_stack [[VAR_1]] : $*Builtin.Int1 +// CHECK-NEXT: [[VAR_20:%[0-9]+]] = tuple () +// CHECK-NEXT: return [[VAR_20]] : $() +sil [ossa] @tuple_with_scalar_fields : $@convention(thin) ((Builtin.Int1, Builtin.Int32, Builtin.Int64)) -> () { +bb0(%0 : $(Builtin.Int1, Builtin.Int32, Builtin.Int64)): + %1 = alloc_stack $(Builtin.Int1, Builtin.Int32, Builtin.Int64) + store %0 to [trivial] %1 : $*(Builtin.Int1, Builtin.Int32, Builtin.Int64) + %2 = function_ref @use_int32 : $@convention(thin) (Builtin.Int32) -> () + %3 = tuple_element_addr %1 : $*(Builtin.Int1, Builtin.Int32, Builtin.Int64), 1 + %4 = load [trivial] %3 : $*Builtin.Int32 + apply %2(%4) : $@convention(thin) (Builtin.Int32) -> () + %5 = load [trivial] %1 : $*(Builtin.Int1, Builtin.Int32, Builtin.Int64) + dealloc_stack %1 : $*(Builtin.Int1, Builtin.Int32, Builtin.Int64) + %6 = tuple() + return %6 : $() +} + +////////////////////////////// +// Tuple With Struct Fields // +////////////////////////////// + +struct S4 { + var aleph : Builtin.Int64 + var bet : Builtin.Int32 +} + +sil [ossa] @use_str4 : $@convention(thin) (S4) -> () + +// CHECK-LABEL: sil [ossa] @tuple_with_struct_fields : $@convention(thin) ((S4, Builtin.Int16), Builtin.Int16) -> () +// CHECK: bb0([[VAR_0:%[0-9]+]] : $(S4, Builtin.Int16), [[VAR_1:%[0-9]+]] : $Builtin.Int16): +// CHECK-NEXT: [[VAR_2:%[0-9]+]] = alloc_stack $Builtin.Int64 +// CHECK-NEXT: [[VAR_3:%[0-9]+]] = alloc_stack $Builtin.Int32 +// CHECK-NEXT: [[VAR_4:%[0-9]+]] = alloc_stack $Builtin.Int16 +// CHECK-NEXT: ([[VAR_5:%[0-9]+]], [[VAR_10:%[0-9]+]]) = destructure_tuple [[VAR_0]] +// CHECK-NEXT: ([[VAR_6:%[0-9]+]], [[VAR_8:%[0-9]+]]) = destructure_struct [[VAR_5]] +// CHECK-NEXT: store [[VAR_6]] to [trivial] [[VAR_2]] : $*Builtin.Int64 +// CHECK-NEXT: store [[VAR_8]] to [trivial] [[VAR_3]] : $*Builtin.Int32 +// CHECK-NEXT: store [[VAR_10]] to [trivial] [[VAR_4]] : $*Builtin.Int16 +// CHECK-NEXT: function_ref +// CHECK-NEXT: [[VAR_12:%[0-9]+]] = function_ref @use_str4 : $@convention(thin) (S4) -> () +// CHECK-NEXT: [[VAR_13:%[0-9]+]] = load [trivial] [[VAR_2]] : $*Builtin.Int64 +// CHECK-NEXT: [[VAR_14:%[0-9]+]] = load [trivial] [[VAR_3]] : $*Builtin.Int32 +// CHECK-NEXT: [[VAR_15:%[0-9]+]] = struct $S4 ([[VAR_13]] : $Builtin.Int64, [[VAR_14]] : $Builtin.Int32) +// CHECK-NEXT: [[VAR_16:%[0-9]+]] = apply [[VAR_12]]([[VAR_15]]) : $@convention(thin) (S4) -> () +// CHECK-NEXT: [[VAR_17:%[0-9]+]] = load [trivial] [[VAR_3]] : $*Builtin.Int32 +// CHECK-NEXT: function_ref +// CHECK-NEXT: [[VAR_18:%[0-9]+]] = function_ref @use_int32 : $@convention(thin) (Builtin.Int32) -> () +// CHECK-NEXT: [[VAR_19:%[0-9]+]] = apply [[VAR_18]]([[VAR_17]]) : $@convention(thin) (Builtin.Int32) -> () +// CHECK-NEXT: [[VAR_20:%[0-9]+]] = load [trivial] [[VAR_2]] : $*Builtin.Int64 +// CHECK-NEXT: [[VAR_21:%[0-9]+]] = load [trivial] [[VAR_3]] : $*Builtin.Int32 +// CHECK-NEXT: [[VAR_22:%[0-9]+]] = struct $S4 ([[VAR_20]] : $Builtin.Int64, [[VAR_21]] : $Builtin.Int32) +// CHECK-NEXT: [[VAR_23:%[0-9]+]] = load [trivial] [[VAR_4]] : $*Builtin.Int16 +// CHECK-NEXT: [[VAR_24:%[0-9]+]] = tuple ([[VAR_22]] : $S4, [[VAR_23]] : $Builtin.Int16) +// CHECK-NEXT: store [[VAR_1]] to [trivial] [[VAR_4]] : $*Builtin.Int16 +// CHECK-NEXT: dealloc_stack [[VAR_4]] : $*Builtin.Int16 +// CHECK-NEXT: dealloc_stack [[VAR_3]] : $*Builtin.Int32 +// CHECK-NEXT: dealloc_stack [[VAR_2]] : $*Builtin.Int64 +// CHECK-NEXT: [[VAR_29:%[0-9]+]] = tuple () +// CHECK-NEXT: return [[VAR_29]] : $() +sil [ossa] @tuple_with_struct_fields : $@convention(thin) ((S4, Builtin.Int16), Builtin.Int16) -> () { +bb0(%0 : $(S4, Builtin.Int16), %1 : $Builtin.Int16): + %2 = alloc_stack $(S4, Builtin.Int16) + store %0 to [trivial] %2 : $*(S4, Builtin.Int16) + %3 = function_ref @use_str4 : $@convention(thin) (S4) -> () + %4 = tuple_element_addr %2 : $*(S4, Builtin.Int16), 0 + %5 = load [trivial] %4 : $*S4 + apply %3(%5) : $@convention(thin) (S4) -> () + %6 = struct_element_addr %4 : $*S4, #S4.bet + %7 = load [trivial] %6 : $*Builtin.Int32 + %8 = function_ref @use_int32 : $@convention(thin) (Builtin.Int32) -> () + apply %8(%7) : $@convention(thin) (Builtin.Int32) -> () + %9 = load [trivial] %2 : $*(S4, Builtin.Int16) + %10 = tuple_element_addr %2 : $*(S4, Builtin.Int16), 1 + store %1 to [trivial] %10 : $*Builtin.Int16 + dealloc_stack %2 : $*(S4, Builtin.Int16) + %11 = tuple() + return %11 : $() +} + +///////////////////////////////// +// Tuple with Tuple Field Test // +///////////////////////////////// + +sil [ossa] @use_tup2 : $@convention(thin) ((Builtin.Int64, Builtin.Int32)) -> () +sil [ossa] @use_int16 : $@convention(thin) (Builtin.Int16) -> () + +// CHECK-LABEL: sil [ossa] @tuple_with_tuple_fields : $@convention(thin) (((Builtin.Int64, Builtin.Int32), Builtin.Int16), Builtin.Int16) -> () +// CHECK: bb0([[VAR_0:%[0-9]+]] : $((Builtin.Int64, Builtin.Int32), Builtin.Int16), [[VAR_1:%[0-9]+]] : $Builtin.Int16): +// CHECK-NEXT: [[VAR_2:%[0-9]+]] = alloc_stack $Builtin.Int64 +// CHECK-NEXT: [[VAR_3:%[0-9]+]] = alloc_stack $Builtin.Int32 +// CHECK-NEXT: [[VAR_4:%[0-9]+]] = alloc_stack $Builtin.Int16 +// CHECK-NEXT: ([[VAR_5:%[0-9]+]], [[VAR_10:%[0-9]+]]) = destructure_tuple [[VAR_0]] +// CHECK-NEXT: ([[VAR_6:%[0-9]+]], [[VAR_8:%[0-9]+]]) = destructure_tuple [[VAR_5]] +// CHECK-NEXT: store [[VAR_6]] to [trivial] [[VAR_2]] : $*Builtin.Int64 +// CHECK-NEXT: store [[VAR_8]] to [trivial] [[VAR_3]] : $*Builtin.Int32 +// CHECK-NEXT: store [[VAR_10]] to [trivial] [[VAR_4]] : $*Builtin.Int16 +// CHECK-NEXT: [[VAR_12:%[0-9]+]] = load [trivial] [[VAR_2]] : $*Builtin.Int64 +// CHECK-NEXT: [[VAR_13:%[0-9]+]] = load [trivial] [[VAR_3]] : $*Builtin.Int32 +// CHECK-NEXT: [[VAR_14:%[0-9]+]] = tuple ([[VAR_12]] : $Builtin.Int64, [[VAR_13]] : $Builtin.Int32) +// CHECK-NEXT: function_ref +// CHECK-NEXT: [[VAR_15:%[0-9]+]] = function_ref @use_tup2 : $@convention(thin) ((Builtin.Int64, Builtin.Int32)) -> () +// CHECK-NEXT: [[VAR_16:%[0-9]+]] = apply [[VAR_15]]([[VAR_14]]) : $@convention(thin) ((Builtin.Int64, Builtin.Int32)) -> () +// CHECK-NEXT: function_ref +// CHECK-NEXT: [[VAR_17:%[0-9]+]] = function_ref @use_int32 : $@convention(thin) (Builtin.Int32) -> () +// CHECK-NEXT: [[VAR_18:%[0-9]+]] = load [trivial] [[VAR_3]] : $*Builtin.Int32 +// CHECK-NEXT: [[VAR_19:%[0-9]+]] = apply [[VAR_17]]([[VAR_18]]) : $@convention(thin) (Builtin.Int32) -> () +// CHECK-NEXT: [[VAR_20:%[0-9]+]] = load [trivial] [[VAR_2]] : $*Builtin.Int64 +// CHECK-NEXT: [[VAR_21:%[0-9]+]] = load [trivial] [[VAR_3]] : $*Builtin.Int32 +// CHECK-NEXT: [[VAR_22:%[0-9]+]] = tuple ([[VAR_20]] : $Builtin.Int64, [[VAR_21]] : $Builtin.Int32) +// CHECK-NEXT: [[VAR_23:%[0-9]+]] = load [trivial] [[VAR_4]] : $*Builtin.Int16 +// CHECK-NEXT: [[VAR_24:%[0-9]+]] = tuple ([[VAR_22]] : $(Builtin.Int64, Builtin.Int32), [[VAR_23]] : $Builtin.Int16) +// CHECK-NEXT: store [[VAR_1]] to [trivial] [[VAR_4]] : $*Builtin.Int16 +// CHECK-NEXT: dealloc_stack [[VAR_4]] : $*Builtin.Int16 +// CHECK-NEXT: dealloc_stack [[VAR_3]] : $*Builtin.Int32 +// CHECK-NEXT: dealloc_stack [[VAR_2]] : $*Builtin.Int64 +// CHECK-NEXT: [[VAR_29:%[0-9]+]] = tuple () +// CHECK-NEXT: return [[VAR_29]] : $() +sil [ossa] @tuple_with_tuple_fields : $@convention(thin) (((Builtin.Int64, Builtin.Int32), Builtin.Int16), Builtin.Int16) -> () { +bb0(%0 : $((Builtin.Int64, Builtin.Int32), Builtin.Int16), %1 : $Builtin.Int16): + %2 = alloc_stack $((Builtin.Int64, Builtin.Int32), Builtin.Int16) + store %0 to [trivial] %2 : $*((Builtin.Int64, Builtin.Int32), Builtin.Int16) + %3 = tuple_element_addr %2 : $*((Builtin.Int64, Builtin.Int32), Builtin.Int16), 0 + %4 = load [trivial] %3 : $*(Builtin.Int64, Builtin.Int32) + %5 = function_ref @use_tup2 : $@convention(thin) ((Builtin.Int64, Builtin.Int32)) -> () + apply %5(%4) : $@convention(thin) ((Builtin.Int64, Builtin.Int32)) -> () + %6 = tuple_element_addr %3 : $*(Builtin.Int64, Builtin.Int32), 1 + %7 = function_ref @use_int32 : $@convention(thin) (Builtin.Int32) -> () + %8 = load [trivial] %6 : $*Builtin.Int32 + apply %7(%8) : $@convention(thin) (Builtin.Int32) -> () + %9 = load [trivial] %2 : $*((Builtin.Int64, Builtin.Int32), Builtin.Int16) + %10 = tuple_element_addr %2 : $*((Builtin.Int64, Builtin.Int32), Builtin.Int16), 1 + store %1 to [trivial] %10 : $*Builtin.Int16 + dealloc_stack %2 : $*((Builtin.Int64, Builtin.Int32), Builtin.Int16) + %11 = tuple() + return %11 : $() +} + +///////////////////////// +// Capture Struct Test // +///////////////////////// + +struct CapturedS { + var x : Builtin.Int32 +} + +sil [ossa] @use_capturedstruct : $@convention(thin) (@inout CapturedS) -> () + +// CHECK-LABEL: sil [ossa] @captured_struct : $@convention(thin) (CapturedS) -> () +// CHECK: bb0([[VAR_0:%[0-9]+]] : $CapturedS): +// CHECK-NEXT: [[VAR_1:%[0-9]+]] = alloc_stack $CapturedS +// CHECK-NEXT: store [[VAR_0]] to [trivial] [[VAR_1]] : $*CapturedS +// CHECK-NEXT: [[VAR_3:%[0-9]+]] = struct_element_addr [[VAR_1]] : $*CapturedS, #CapturedS.x +// CHECK-NEXT: [[VAR_4:%[0-9]+]] = load [trivial] [[VAR_3]] : $*Builtin.Int32 +// CHECK-NEXT: function_ref +// CHECK-NEXT: [[VAR_5:%[0-9]+]] = function_ref @use_capturedstruct : $@convention(thin) (@inout CapturedS) -> () +// CHECK-NEXT: [[VAR_6:%[0-9]+]] = apply [[VAR_5]]([[VAR_1]]) : $@convention(thin) (@inout CapturedS) -> () +// CHECK-NEXT: [[VAR_7:%[0-9]+]] = load [trivial] [[VAR_3]] : $*Builtin.Int32 +// CHECK-NEXT: dealloc_stack [[VAR_1]] : $*CapturedS +// CHECK-NEXT: [[VAR_9:%[0-9]+]] = tuple () +// CHECK-NEXT: return [[VAR_9]] : $() +sil [ossa] @captured_struct : $@convention(thin) (CapturedS) -> () { +bb0(%0 : $CapturedS): + %1 = alloc_stack $CapturedS + store %0 to [trivial] %1 : $*CapturedS + %3 = struct_element_addr %1 : $*CapturedS, #CapturedS.x + %4 = load [trivial] %3 : $*Builtin.Int32 + %5 = function_ref @use_capturedstruct : $@convention(thin) (@inout CapturedS) -> () + %6 = apply %5(%1) : $@convention(thin) (@inout CapturedS) -> () + %7 = load [trivial] %3 : $*Builtin.Int32 + dealloc_stack %1 : $*CapturedS + %9 = tuple () + return %9 : $() +} + +///////////////////////// +// Captured Tuple Test // +///////////////////////// + +sil [ossa] @use_capturedtuple : $@convention(thin) (@inout (Builtin.Int32, Builtin.Int64)) -> () + +// CHECK-LABEL: sil [ossa] @captured_tuple : $@convention(thin) ((Builtin.Int32, Builtin.Int64)) -> () +// CHECK: bb0([[VAR_0:%[0-9]+]] : $(Builtin.Int32, Builtin.Int64)): +// CHECK-NEXT: [[VAR_1:%[0-9]+]] = alloc_stack $(Builtin.Int32, Builtin.Int64) +// CHECK-NEXT: store [[VAR_0]] to [trivial] [[VAR_1]] : $*(Builtin.Int32, Builtin.Int64) +// CHECK-NEXT: [[VAR_3:%[0-9]+]] = tuple_element_addr [[VAR_1]] : $*(Builtin.Int32, Builtin.Int64), 0 +// CHECK-NEXT: [[VAR_4:%[0-9]+]] = load [trivial] [[VAR_3]] : $*Builtin.Int32 +// CHECK-NEXT: function_ref +// CHECK-NEXT: [[VAR_5:%[0-9]+]] = function_ref @use_capturedtuple : $@convention(thin) (@inout (Builtin.Int32, Builtin.Int64)) -> () +// CHECK-NEXT: [[VAR_6:%[0-9]+]] = apply [[VAR_5]]([[VAR_1]]) : $@convention(thin) (@inout (Builtin.Int32, Builtin.Int64)) -> () +// CHECK-NEXT: [[VAR_7:%[0-9]+]] = load [trivial] [[VAR_3]] : $*Builtin.Int32 +// CHECK-NEXT: dealloc_stack [[VAR_1]] : $*(Builtin.Int32, Builtin.Int64) +// CHECK-NEXT: [[VAR_9:%[0-9]+]] = tuple () +// CHECK-NEXT: return [[VAR_9]] : $() +sil [ossa] @captured_tuple : $@convention(thin) ((Builtin.Int32, Builtin.Int64)) -> () { +bb0(%0 : $(Builtin.Int32, Builtin.Int64)): + %1 = alloc_stack $(Builtin.Int32, Builtin.Int64) + store %0 to [trivial] %1 : $*(Builtin.Int32, Builtin.Int64) + %3 = tuple_element_addr %1 : $*(Builtin.Int32, Builtin.Int64), 0 + %4 = load [trivial] %3 : $*Builtin.Int32 + %5 = function_ref @use_capturedtuple : $@convention(thin) (@inout (Builtin.Int32, Builtin.Int64)) -> () + %6 = apply %5(%1) : $@convention(thin) (@inout (Builtin.Int32, Builtin.Int64)) -> () + %7 = load [trivial] %3 : $*Builtin.Int32 + dealloc_stack %1 : $*(Builtin.Int32, Builtin.Int64) + %9 = tuple () + return %9 : $() +} + +/////////////////////// +// Non-trivial Tests // +/////////////////////// + +class Obj { } + +struct NotTrivial { + var x : Obj + var y : Obj +} + +sil [ossa] @use_obj : $@convention(thin) (@owned Obj) -> () + +// CHECK-LABEL: sil [ossa] @struct_with_obj_fields : $@convention(thin) (@owned NotTrivial) -> () +// CHECK: bb0([[VAR_0:%[0-9]+]] : @owned $NotTrivial): + +// CHECK-NEXT: [[VAR_1:%[0-9]+]] = alloc_stack $Obj +// CHECK-NEXT: [[VAR_2:%[0-9]+]] = alloc_stack $Obj +// CHECK-NEXT: ([[VAR_4:%[0-9]+]], [[VAR_6:%[0-9]+]]) = destructure_struct [[VAR_0]] +// CHECK-NEXT: store [[VAR_4]] to [init] [[VAR_1]] : $*Obj +// CHECK-NEXT: store [[VAR_6]] to [init] [[VAR_2]] : $*Obj + +// CHECK-NEXT: function_ref +// CHECK-NEXT: [[VAR_10:%[0-9]+]] = function_ref @use_obj : $@convention(thin) (@owned Obj) -> () +// Make sure we use [copy] here ▼▼▼▼▼▼ +// CHECK-NEXT: [[VAR_11:%[0-9]+]] = load [copy] [[VAR_2]] : $*Obj +// CHECK-NEXT: [[VAR_12:%[0-9]+]] = apply [[VAR_10]]([[VAR_11]]) : $@convention(thin) (@owned Obj) -> () +// CHECK-NEXT: [[VAR_13:%[0-9]+]] = load [take] [[VAR_1]] : $*Obj +// CHECK-NEXT: [[VAR_14:%[0-9]+]] = load [take] [[VAR_2]] : $*Obj +// CHECK-NEXT: [[VAR_16:%[0-9]+]] = struct $NotTrivial ([[VAR_13]] : $Obj, [[VAR_14]] : $Obj) + +// CHECK: dealloc_stack [[VAR_2]] : $*Obj +// CHECK: dealloc_stack [[VAR_1]] : $*Obj + +// CHECK: [[VAR_20:%[0-9]+]] = tuple () +// CHECK: return [[VAR_20]] : $() +sil [ossa] @struct_with_obj_fields : $@convention(thin) (@owned NotTrivial) -> () { +bb0(%0 : @owned $NotTrivial): + %1 = alloc_stack $NotTrivial + debug_value %1 : $*NotTrivial // should not prevent the optimization + store %0 to [init] %1 : $*NotTrivial + %2 = function_ref @use_obj : $@convention(thin) (@owned Obj) -> () + %3 = struct_element_addr %1 : $*NotTrivial, #NotTrivial.y + // Make sure that SROA respects the [copy] qual. + %4 = load [copy] %3 : $*Obj + apply %2(%4) : $@convention(thin) (@owned Obj) -> () + %5 = load [take] %1 : $*NotTrivial + destroy_value %5 : $NotTrivial + dealloc_stack %1 : $*NotTrivial + %6 = tuple () + return %6 : $() +}