Skip to content

Commit 0e1d3f1

Browse files
committed
Add for case support and tests
1 parent e9cab1f commit 0e1d3f1

File tree

4 files changed

+119
-57
lines changed

4 files changed

+119
-57
lines changed

lib/SILGen/SILGenFunction.h

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2724,26 +2724,24 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
27242724
///
27252725
/// This function will be called within a cleanups scope and with
27262726
/// InnermostPackExpansion set up properly for the context.
2727-
void emitDynamicPackLoop(SILLocation loc,
2728-
CanPackType formalPackType,
2729-
unsigned componentIndex,
2730-
SILValue startingAfterIndexWithinComponent,
2731-
SILValue limitWithinComponent,
2732-
GenericEnvironment *openedElementEnv,
2733-
bool reverse,
2734-
llvm::function_ref<void(SILValue indexWithinComponent,
2735-
SILValue packExpansionIndex,
2736-
SILValue packIndex)> emitBody);
2727+
void emitDynamicPackLoop(
2728+
SILLocation loc, CanPackType formalPackType, unsigned componentIndex,
2729+
SILValue startingAfterIndexWithinComponent, SILValue limitWithinComponent,
2730+
GenericEnvironment *openedElementEnv, bool reverse,
2731+
llvm::function_ref<void(SILValue indexWithinComponent,
2732+
SILValue packExpansionIndex, SILValue packIndex)>
2733+
emitBody,
2734+
SILBasicBlock *loopLatch = nullptr);
27372735

27382736
/// A convenience version of dynamic pack loop that visits an entire
27392737
/// pack expansion component in forward order.
2740-
void emitDynamicPackLoop(SILLocation loc,
2741-
CanPackType formalPackType,
2742-
unsigned componentIndex,
2743-
GenericEnvironment *openedElementEnv,
2744-
llvm::function_ref<void(SILValue indexWithinComponent,
2745-
SILValue packExpansionIndex,
2746-
SILValue packIndex)> emitBody);
2738+
void emitDynamicPackLoop(
2739+
SILLocation loc, CanPackType formalPackType, unsigned componentIndex,
2740+
GenericEnvironment *openedElementEnv,
2741+
llvm::function_ref<void(SILValue indexWithinComponent,
2742+
SILValue packExpansionIndex, SILValue packIndex)>
2743+
emitBody,
2744+
SILBasicBlock *loopLatch = nullptr);
27472745

27482746
/// Emit a transform on each element of a pack-expansion component
27492747
/// of a pack, write the result into a pack-expansion component of

lib/SILGen/SILGenPack.cpp

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -662,28 +662,27 @@ void SILGenFunction::projectTupleElementsToPack(SILLocation loc,
662662
});
663663
}
664664

665-
void SILGenFunction::emitDynamicPackLoop(SILLocation loc,
666-
CanPackType formalPackType,
667-
unsigned componentIndex,
668-
GenericEnvironment *openedElementEnv,
669-
llvm::function_ref<void(SILValue indexWithinComponent,
670-
SILValue packExpansionIndex,
671-
SILValue packIndex)> emitBody) {
665+
void SILGenFunction::emitDynamicPackLoop(
666+
SILLocation loc, CanPackType formalPackType, unsigned componentIndex,
667+
GenericEnvironment *openedElementEnv,
668+
llvm::function_ref<void(SILValue indexWithinComponent,
669+
SILValue packExpansionIndex, SILValue packIndex)>
670+
emitBody,
671+
SILBasicBlock *loopLatch) {
672672
return emitDynamicPackLoop(loc, formalPackType, componentIndex,
673673
/*startAfter*/ SILValue(), /*limit*/ SILValue(),
674-
openedElementEnv, /*reverse*/false, emitBody);
674+
openedElementEnv, /*reverse*/ false, emitBody,
675+
loopLatch);
675676
}
676677

677-
void SILGenFunction::emitDynamicPackLoop(SILLocation loc,
678-
CanPackType formalPackType,
679-
unsigned componentIndex,
680-
SILValue startingAfterIndexInComponent,
681-
SILValue limitWithinComponent,
682-
GenericEnvironment *openedElementEnv,
683-
bool reverse,
684-
llvm::function_ref<void(SILValue indexWithinComponent,
685-
SILValue packExpansionIndex,
686-
SILValue packIndex)> emitBody) {
678+
void SILGenFunction::emitDynamicPackLoop(
679+
SILLocation loc, CanPackType formalPackType, unsigned componentIndex,
680+
SILValue startingAfterIndexInComponent, SILValue limitWithinComponent,
681+
GenericEnvironment *openedElementEnv, bool reverse,
682+
llvm::function_ref<void(SILValue indexWithinComponent,
683+
SILValue packExpansionIndex, SILValue packIndex)>
684+
emitBody,
685+
SILBasicBlock *loopLatch) {
687686
assert(isa<PackExpansionType>(formalPackType.getElementType(componentIndex)));
688687
assert((!startingAfterIndexInComponent || !reverse) &&
689688
"cannot reverse with a starting index");
@@ -764,6 +763,7 @@ void SILGenFunction::emitDynamicPackLoop(SILLocation loc,
764763
// the incoming index - 1 if reverse)
765764
SILValue curIndex = incomingIndex;
766765
if (reverse) {
766+
assert(!loopLatch && "Only forward iteration supported with loop latch");
767767
curIndex = B.createBuiltinBinaryFunction(loc, "sub", wordTy, wordTy,
768768
{ incomingIndex, one });
769769
}
@@ -791,6 +791,13 @@ void SILGenFunction::emitDynamicPackLoop(SILLocation loc,
791791
{
792792
FullExpr scope(Cleanups, CleanupLocation(loc));
793793
emitBody(curIndex, packExpansionIndex, packIndex);
794+
if (loopLatch) {
795+
B.createBranch(loc, loopLatch);
796+
}
797+
}
798+
799+
if (loopLatch) {
800+
B.emitBlock(loopLatch);
794801
}
795802

796803
// The index to pass to the loop condition block (the current index + 1

lib/SILGen/SILGenStmt.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1255,9 +1255,7 @@ void StmtEmitter::visitForEachStmt(ForEachStmt *S) {
12551255
PackType::get(SGF.getASTContext(), expansion->getType())
12561256
->getCanonicalType());
12571257

1258-
// Create a new basic block and jump into it.
12591258
JumpDest loopDest = createJumpDest(S->getBody());
1260-
SGF.B.emitBlock(loopDest.getBlock(), S);
12611259

12621260
SGF.emitDynamicPackLoop(
12631261
SILLocation(expansion), formalPackType, 0,
@@ -1271,7 +1269,8 @@ void StmtEmitter::visitForEachStmt(ForEachStmt *S) {
12711269
SGF.emitExprInto(expansion->getPatternExpr(), letValueInit.get());
12721270
visit(S->getBody());
12731271
return;
1274-
});
1272+
},
1273+
loopDest.getBlock());
12751274

12761275
return;
12771276
}

test/SILGen/pack_iteration.swift

Lines changed: 77 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ enum E<T> {
3030
// CHECK: [[COND:%.*]] = builtin "cmp_eq_Word"([[IDX3]] : $Builtin.Word, [[PACK_LENGTH]] : $Builtin.Word) : $Builtin.Int1
3131
// CHECK: cond_br [[COND]], [[NONE_BB:bb[0-9]+]], [[SOME_BB:bb[0-9]+]]
3232
//
33+
// CHECK: [[NONE_BB]]:
34+
// CHECK: [[FUNC_END_FUNC:%.*]] = function_ref @funcEnd : $@convention(thin) () -> ()
35+
// CHECK: apply [[FUNC_END_FUNC]]() : $@convention(thin) () -> ()
36+
//
3337
// CHECK: [[SOME_BB]]:
3438
// CHECK: [[DYN_PACK_IDX:%.*]] = dynamic_pack_index [[IDX3]] of $Pack{repeat each Element}
3539
// CHECK: open_pack_element [[DYN_PACK_IDX]] of <each Element> at <Pack{repeat each Element}>, shape $each Element, uuid "[[UUID:.*]]"
@@ -43,9 +47,6 @@ enum E<T> {
4347
// CHECK: [[IDX4:%.*]] = builtin "add_Word"([[IDX3]] : $Builtin.Word, [[IDX2]] : $Builtin.Word) : $Builtin.Word
4448
// CHECK: br [[LOOP_DEST]]([[IDX4]] : $Builtin.Word)
4549
//
46-
// CHECK: [[NONE_BB]]:
47-
// CHECK: [[FUNC_END_FUNC:%.*]] = function_ref @funcEnd : $@convention(thin) () -> ()
48-
// CHECK: apply [[FUNC_END_FUNC]]() : $@convention(thin) () -> ()
4950
// CHECK: } // end sil function '$s14pack_iteration14iterateTrivial4overyxxQp_tRvzlF'
5051
func iterateTrivial<each Element>(over elements: repeat each Element) {
5152
for element in repeat each elements {
@@ -54,32 +55,89 @@ func iterateTrivial<each Element>(over elements: repeat each Element) {
5455
funcEnd()
5556
}
5657

57-
// TODO: Write this test
58+
// CHECK-LABEL: sil hidden [ossa] @$s14pack_iteration11equalTuples3lhs3rhsSbxxQp_t_xxQp_ttRvzSQRzlF : $@convention(thin) <each Element where repeat each Element : Equatable> (@pack_guaranteed Pack{repeat each Element}, @pack_guaranteed Pack{repeat each Element}) -> Bool {
59+
// CHECK: bb6:
60+
// CHECK: [[STACK1:%.*]] = alloc_stack $(repeat each Element)
61+
// CHECK: [[STACK2:%.*]] = alloc_stack $(repeat each Element)
62+
// CHECK: [[IDX1:%.*]] = integer_literal $Builtin.Word, 0
63+
// CHECK: [[IDX2:%.*]] = integer_literal $Builtin.Word, 1
64+
// CHECK: [[PACK_LENGTH:%.*]] = pack_length $Pack{repeat each Element}
65+
// CHECK: br [[LOOP_DEST:bb[0-9]+]]([[IDX1]] : $Builtin.Word)
66+
//
67+
// CHECK: [[LOOP_DEST]]([[IDX3:%.*]] : $Builtin.Word):
68+
// CHECK: [[COND:%.*]] = builtin "cmp_eq_Word"([[IDX3]] : $Builtin.Word, [[PACK_LENGTH]] : $Builtin.Word) : $Builtin.Int1
69+
// CHECK: cond_br [[COND]], [[NONE_BB:bb[0-9]+]], [[SOME_BB:bb[0-9]+]]
70+
//
71+
// CHECK: [[SOME_BB]]:
72+
// CHECK: [[DYN_PACK_IDX:%.*]] = dynamic_pack_index [[IDX3]] of $Pack{repeat (each Element, each Element)}
73+
// CHECK: [[OPEN_PACK_ELT:%.*]] = open_pack_element [[DYN_PACK_IDX]] of <each Element where repeat each Element : Equatable> at <Pack{repeat each Element}>, shape $each Element, uuid "[[UUID:.*]]"
74+
// CHECK: [[STACK_LEFT:%.*]] = alloc_stack [lexical] $@pack_element("[[UUID]]") each Element, let, name "left"
75+
// CHECK: [[STACK_RIGHT:%.*]] = alloc_stack [lexical] $@pack_element("[[UUID]]") each Element, let, name "right"
76+
// CHECK: tuple_pack_element_addr [[DYN_PACK_IDX]] of [[STACK1]] : $*(repeat each Element) as $*@pack_element("[[UUID]]") each Element
77+
// CHECK: tuple_pack_element_addr [[DYN_PACK_IDX]] of [[STACK2]] : $*(repeat each Element) as $*@pack_element("[[UUID]]") each Element
78+
// CHECK: [[METATYPE:%.*]] = metatype $@thick (@pack_element("[[UUID]]") each Element).Type
79+
// CHECK: [[WITNESS_METHOD:%.*]] = witness_method $@pack_element("[[UUID]]") each Element, #Equatable."==" : <Self where Self : Equatable> (Self.Type) -> (Self, Self) -> Bool, [[OPEN_PACK_ELT]] : $Builtin.SILToken : $@convention(witness_method: Equatable) <τ_0_0 where τ_0_0 : Equatable> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_0, @thick τ_0_0.Type) -> Bool
80+
// CHECK: apply [[WITNESS_METHOD]]<@pack_element("[[UUID]]") each Element>([[STACK_LEFT]], [[STACK_RIGHT]], [[METATYPE]]) : $@convention(witness_method: Equatable) <τ_0_0 where τ_0_0 : Equatable> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_0, @thick τ_0_0.Type) -> Bool
81+
//
82+
// CHECK: } // end sil function '$s14pack_iteration11equalTuples3lhs3rhsSbxxQp_t_xxQp_ttRvzSQRzlF'
5883
func equalTuples<each Element: Equatable>(lhs: (repeat each Element), rhs: (repeat each Element)) -> Bool {
59-
60-
// %12 = dynamic_pack_index %9 of $Pack{repeat (each Element, each Element)} // users: %19, %17, %14, %13
61-
// %13 = open_pack_element %12 of <each Element where repeat each Element : Equatable> at <Pack{repeat each Element}>, shape $each Element, uuid "E53D635E-3D89-11EE-82A2-7AABAFDC7DCA" // users: %19, %17, %14
62-
// %14 = tuple_pack_element_addr %12 of %4 : $*(repeat (each Element, each Element)) as $*(@pack_element("E53D635E-3D89-11EE-82A2-7AABAFDC7DCA") each Element, @pack_element("E53D635E-3D89-11EE-82A2-7AABAFDC7DCA") each Element) // users: %16, %15
63-
// %15 = tuple_element_addr %14 : $*(@pack_element("E53D635E-3D89-11EE-82A2-7AABAFDC7DCA") each Element, @pack_element("E53D635E-3D89-11EE-82A2-7AABAFDC7DCA") each Element), 0 // user: %18
64-
// %16 = tuple_element_addr %14 : $*(@pack_element("E53D635E-3D89-11EE-82A2-7AABAFDC7DCA") each Element, @pack_element("E53D635E-3D89-11EE-82A2-7AABAFDC7DCA") each Element), 1 // user: %20
65-
// %17 = pack_element_get %12 of %0 : $*Pack{repeat each Element} as $*@pack_element("E53D635E-3D89-11EE-82A2-7AABAFDC7DCA") each Element // user: %18
66-
// copy_addr %17 to [init] %15 : $*@pack_element("E53D635E-3D89-11EE-82A2-7AABAFDC7DCA") each Element // id: %18
67-
// %19 = pack_element_get %12 of %1 : $*Pack{repeat each Element} as $*@pack_element("E53D635E-3D89-11EE-82A2-7AABAFDC7DCA") each Element // user: %20
68-
// copy_addr %19 to [init] %16 : $*@pack_element("E53D635E-3D89-11EE-82A2-7AABAFDC7DCA") each Element // id: %20
69-
// %21 = builtin "add_Word"(%9 : $Builtin.Word, %6 : $Builtin.Word) : $Builtin.Word // user: %22
70-
// br bb1(%21 : $Builtin.Word)
71-
84+
7285
for (left, right) in repeat (each lhs, each rhs) {
7386
guard left == right else { return false }
7487
}
88+
7589
return true
7690
}
7791

78-
// TODO: Write this test
92+
// CHECK-LABEL: sil hidden [ossa] @$s14pack_iteration19iteratePatternMatch4overyAA1EOyxGxQp_tRvzlF : $@convention(thin) <each Element> (@pack_guaranteed Pack{repeat E<each Element>}) -> () {
93+
// CHECK: bb0([[PACK:%.*]] : $*Pack{repeat E<each Element>}):
94+
// CHECK: [[IDX1:%.*]] = integer_literal $Builtin.Word, 0
95+
// CHECK: [[IDX2:%.*]] = integer_literal $Builtin.Word, 1
96+
// CHECK: [[PACK_LENGTH:%.*]] = pack_length $Pack{repeat each Element}
97+
// CHECK: br [[LOOP_DEST:bb[0-9]+]]([[IDX1]] : $Builtin.Word)
98+
//
99+
// CHECK: [[LOOP_DEST]]([[IDX3:%.*]] : $Builtin.Word):
100+
// CHECK: [[COND:%.*]] = builtin "cmp_eq_Word"([[IDX3]] : $Builtin.Word, [[PACK_LENGTH]] : $Builtin.Word) : $Builtin.Int1
101+
// CHECK: cond_br [[COND]], [[NONE_BB:bb[0-9]+]], [[SOME_BB:bb[0-9]+]]
102+
//
103+
// CHECK: [[SOME_BB]]:
104+
// CHECK: [[DYN_PACK_IDX:%.*]] = dynamic_pack_index [[IDX3]] of $Pack{repeat E<each Element>}
105+
// CHECK: open_pack_element [[DYN_PACK_IDX]] of <each Element> at <Pack{repeat each Element}>, shape $each Element, uuid "[[UUID:.*]]"
106+
// CHECK: [[STACK:%.*]] = alloc_stack [lexical] $@pack_element("[[UUID]]") each Element, let, name "value"
107+
// CHECK: [[PACK_ELT_GET:%.*]] = pack_element_get [[DYN_PACK_IDX]] of [[PACK]] : $*Pack{repeat E<each Element>} as $*E<@pack_element("[[UUID]]") each Element>
108+
// CHECK: [[ENUM_STACK:%.*]] = alloc_stack $E<@pack_element("[[UUID]]") each Element>
109+
// CHECK: copy_addr [[PACK_ELT_GET]] to [init] [[ENUM_STACK]] : $*E<@pack_element("[[UUID]]") each Element>
110+
// CHECK: switch_enum_addr [[ENUM_STACK]] : $*E<@pack_element("[[UUID]]") each Element>, case #E.one!enumelt: [[ENUM_MATCH_BB:bb[0-9]+]], case #E.two!enumelt: [[CONTINUE_BB:bb[0-9]+]]
111+
//
112+
// CHECK: [[CONTINUE_BB]]:
113+
// CHECK: destroy_addr [[ENUM_STACK]]
114+
// CHECK: dealloc_stack [[ENUM_STACK]]
115+
// CHECK: dealloc_stack [[STACK]]
116+
// CHECK: br [[LATCH_BB:bb[0-9]+]]
117+
//
118+
// CHECK: [[ENUM_MATCH_BB]]:
119+
// CHECK: [[ENUM_DATA_ADDR:%.*]] = unchecked_take_enum_data_addr %13 : $*E<@pack_element("[[UUID]]") each Element>, #E.one!enumelt
120+
// CHECK: copy_addr [take] [[ENUM_DATA_ADDR]] to [init] [[STACK]]
121+
// CHECK: [[LOOP_END_FUNC:%.*]] = function_ref @loopBodyEnd : $@convention(thin) () -> ()
122+
// CHECK: apply [[LOOP_END_FUNC]]() : $@convention(thin) () -> ()
123+
// CHECK: dealloc_stack [[ENUM_STACK]]
124+
// CHECK: destroy_addr [[STACK]]
125+
// CHECK: dealloc_stack [[STACK]]
126+
// CHECK: br [[LATCH:bb[0-9]+]]
127+
//
128+
// CHECK: [[NONE_BB]]:
129+
// CHECK: [[FUNC_END_FUNC:%.*]] = function_ref @funcEnd : $@convention(thin) () -> ()
130+
// CHECK: apply [[FUNC_END_FUNC]]() : $@convention(thin) () -> ()
131+
//
132+
// CHECK: [[LATCH_BB]]:
133+
// CHECK: [[ADD_WORD:%.*]] = builtin "add_Word"([[IDX3]] : $Builtin.Word, [[IDX2]] : $Builtin.Word) : $Builtin.Word
134+
// CHECK: br [[LOOP_DEST]]([[ADD_WORD]] : $Builtin.Word)
135+
// CHECK: } // end sil function '$s14pack_iteration19iteratePatternMatch4overyAA1EOyxGxQp_tRvzlF'
79136
func iteratePatternMatch<each Element>(over element: repeat E<each Element>) {
80137
for case .one(let value) in repeat each element {
81-
print(value)
138+
loopBodyEnd()
82139
}
140+
funcEnd()
83141
}
84142

85143

0 commit comments

Comments
 (0)