Skip to content

Commit 18c3d1c

Browse files
committed
Enable loop rotate when the header is exiting
1 parent 46d44a8 commit 18c3d1c

File tree

5 files changed

+51
-24
lines changed

5 files changed

+51
-24
lines changed

lib/SILOptimizer/LoopTransforms/LoopRotate.cpp

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ static llvm::cl::opt<int> LoopRotateSizeLimit("looprotate-size-limit",
4444
llvm::cl::init(20));
4545
static llvm::cl::opt<bool> RotateSingleBlockLoop("looprotate-single-block-loop",
4646
llvm::cl::init(false));
47+
static llvm::cl::opt<bool>
48+
LoopRotateInfiniteBudget("looprotate-infinite-budget",
49+
llvm::cl::init(false));
4750

4851
static bool rotateLoop(SILLoop *loop, DominanceInfo *domInfo,
4952
SILLoopInfo *loopInfo, bool rotateSingleBlockLoops,
@@ -118,9 +121,7 @@ canDuplicateOrMoveToPreheader(SILLoop *loop, SILBasicBlock *preheader,
118121
if (!inst->mayHaveSideEffects() && !inst->mayReadFromMemory() &&
119122
!isa<TermInst>(inst) &&
120123
!isa<AllocationInst>(inst) && /* not marked mayhavesideeffects */
121-
!isa<CopyValueInst>(inst) &&
122-
!isa<MoveValueInst>(inst) &&
123-
!isa<BeginBorrowInst>(inst) &&
124+
!hasOwnershipOperandsOrResults(inst) &&
124125
hasLoopInvariantOperands(inst, loop, invariants)) {
125126
moves.push_back(inst);
126127
invariants.insert(inst);
@@ -133,7 +134,7 @@ canDuplicateOrMoveToPreheader(SILLoop *loop, SILBasicBlock *preheader,
133134
cost += (int)instructionInlineCost(instRef);
134135
}
135136

136-
return cost < LoopRotateSizeLimit;
137+
return cost < LoopRotateSizeLimit || LoopRotateInfiniteBudget;
137138
}
138139

139140
static void mapOperands(SILInstruction *inst,
@@ -369,12 +370,6 @@ static bool rotateLoop(SILLoop *loop, DominanceInfo *domInfo,
369370
assert(loop->contains(newHeader) && !loop->contains(exit)
370371
&& "Could not find loop header and exit block");
371372

372-
// It does not make sense to rotate the loop if the new header is loop
373-
// exiting as well.
374-
if (loop->isLoopExiting(newHeader)) {
375-
return false;
376-
}
377-
378373
// Incomplete liveranges in the dead-end exit block can cause a missing adjacent
379374
// phi-argument for a re-borrow if there is a borrow-scope is in the loop.
380375
// But even when we have complete lifetimes, it's probably not worth rotating

test/SILOptimizer/looprotate_nontrivial_ossa.sil

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import Builtin
55
import Swift
66

77
class Klass {
8-
98
}
109

1110
struct BoxStruct {
@@ -244,3 +243,39 @@ bb8:
244243
bb9:
245244
unreachable
246245
}
246+
247+
sil @foo : $@convention(thin) (@in_guaranteed UInt64, @in_guaranteed UInt64) -> (Bool, @error any Error)
248+
249+
sil [ossa] @looprotate_ownership_results : $@convention(thin) (Int32, @guaranteed Klass) -> Int32 {
250+
bb0(%0 : $Int32, %1 : @guaranteed $Klass):
251+
%2 = struct_extract %0, #Int32._value
252+
%3 = integer_literal $Builtin.Int32, 0
253+
br bb1(%2, %3)
254+
255+
bb1(%5 : $Builtin.Int32, %6 : $Builtin.Int32):
256+
%7 = function_ref @foo : $@convention(thin) (@in_guaranteed UInt64, @in_guaranteed UInt64) -> (Bool, @error any Error)
257+
%8 = thin_to_thick_function %7 to $@noescape @callee_guaranteed (@in_guaranteed UInt64, @in_guaranteed UInt64) -> (Bool, @error any Error)
258+
%9 = convert_function %8 to $@noescape @callee_guaranteed @substituted <τ_0_0, τ_0_1> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_1) -> (Bool, @error any Error) for <UInt64, UInt64>, forwarding: @owned
259+
destroy_value %9
260+
%11 = struct $Int32 (%6)
261+
%12 = builtin "cmp_eq_Word"(%6, %2) : $Builtin.Int1
262+
cond_br %12, bb3, bb2
263+
264+
bb2:
265+
%14 = integer_literal $Builtin.Int32, 1
266+
%15 = integer_literal $Builtin.Int1, -1
267+
%16 = builtin "sadd_with_overflow_Word"(%6, %14, %15) : $(Builtin.Int32, Builtin.Int1)
268+
%17 = tuple_extract %16, 0
269+
%18 = enum $Optional<Int32>, #Optional.some!enumelt, %11
270+
%19 = unchecked_enum_data %18, #Optional.some!enumelt
271+
%20 = struct_extract %19, #Int32._value
272+
%21 = integer_literal $Builtin.Int1, -1
273+
%22 = builtin "sadd_with_overflow_Word"(%5, %20, %21) : $(Builtin.Int32, Builtin.Int1)
274+
%23 = tuple_extract %22, 0
275+
br bb1(%23, %17)
276+
277+
bb3:
278+
%25 = struct $Int32 (%5)
279+
return %25
280+
}
281+

test/SILOptimizer/looprotate_ossa.sil

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -85,16 +85,13 @@ bb3:
8585
return %23 : $Int32
8686
}
8787

88-
// CHECK-LABEL: sil [ossa] @dont_rotate_multi_exit_loop :
89-
// CHECK: bb1({{.*}}):
90-
// CHECK: cond_br %{{.*}}, bb4, bb2
91-
// CHECK: bb2:
92-
// CHECK: cond_br undef, bb3, bb5
93-
// CHECK: bb6:
94-
// CHECK: return
95-
// CHECK-NOT: bb7
96-
// CHECK: } // end sil function 'dont_rotate_multi_exit_loop'
97-
sil [ossa] @dont_rotate_multi_exit_loop : $@convention(thin) (Int32, @owned Bar) -> Int32 {
88+
// CHECK-LABEL: sil [ossa] @rotate_multi_exit_loop :
89+
// CHECK: [[METH1:%.*]] = class_method {{.*}} : $Bar, #Bar.foo : (Bar) -> () -> (), $@convention(method) (@guaranteed Bar) -> ()
90+
// CHECK: apply [[METH1]]({{.*}}) : $@convention(method) (@guaranteed Bar) -> ()
91+
// CHECK: [[METH2:%.*]] = class_method {{.*}} : $Bar, #Bar.foo : (Bar) -> () -> (), $@convention(method) (@guaranteed Bar) -> ()
92+
// CHECK: apply [[METH2]]({{.*}}) : $@convention(method) (@guaranteed Bar) -> ()
93+
// CHECK: } // end sil function 'rotate_multi_exit_loop'
94+
sil [ossa] @rotate_multi_exit_loop : $@convention(thin) (Int32, @owned Bar) -> Int32 {
9895
bb0(%0 : $Int32, %25: @owned $Bar):
9996
%1 = struct_extract %0 : $Int32, #Int32._value
10097
%2 = integer_literal $Builtin.Int32, 0

test/SILOptimizer/mutable_span_bounds_check_tests.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ public func span_bubble_sort(_ span: inout MutableSpan<Int>) {
130130
}
131131

132132
// CHECK-SIL-LABEL: sil @$s31mutable_span_bounds_check_tests6sortedySb10SpanExtras07MutableG0VySiGF :
133-
// CHECK-SIL: bb4:
133+
// CHECK-SIL: bb4({{.*}}):
134134
// CHECK-SIL: cond_fail {{.*}}, "precondition failure"
135135
// CHECK-SIL: cond_fail {{.*}}, "precondition failure"
136136
// CHECK-SIL: cond_br

test/SILOptimizer/span_bounds_check_tests.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@ public func span_element_sum(_ v: Span<Int>, _ i: Int) -> Int {
244244
// CHECK-SIL-LABEL: sil @$s23span_bounds_check_tests0A7_searchySiSgs4SpanVyxG_xtSQRzlF :
245245
// CHECK-SIL: bb3:
246246
// CHECK-SIL: cond_fail {{.*}}, "Index out of bounds"
247-
// CHECK-SIL: cond_fail {{.*}}, "Index out of bounds"
247+
// CHECK-SIL-NOT: cond_fail {{.*}}, "Index out of bounds"
248248
// CHECK-SIL: cond_br
249249
// CHECK-SIL-LABEL: } // end sil function '$s23span_bounds_check_tests0A7_searchySiSgs4SpanVyxG_xtSQRzlF'
250250
public func span_search<T : Equatable>(_ v: Span<T>, _ elem: T) -> Int? {
@@ -261,7 +261,7 @@ public func span_search<T : Equatable>(_ v: Span<T>, _ elem: T) -> Int? {
261261
// CHECK-SIL-LABEL: sil @$s23span_bounds_check_tests0A11_search_splySiSgs4SpanVySiG_SitF :
262262
// CHECK-SIL: bb3:
263263
// CHECK-SIL: cond_fail {{.*}}, "Index out of bounds"
264-
// CHECK-SIL: cond_fail {{.*}}, "Index out of bounds"
264+
// CHECK-SIL-NOT: cond_fail {{.*}}, "Index out of bounds"
265265
// CHECK-SIL: cond_br
266266
// CHECK-SIL-LABEL: } // end sil function '$s23span_bounds_check_tests0A11_search_splySiSgs4SpanVySiG_SitF'
267267
public func span_search_spl(_ v: Span<Int>, _ elem: Int) -> Int? {

0 commit comments

Comments
 (0)