Skip to content

Commit 6324b3c

Browse files
committed
Handle a gap while matching SIL patterns for hoisting array bound checks
1 parent 8f99736 commit 6324b3c

File tree

2 files changed

+72
-6
lines changed

2 files changed

+72
-6
lines changed

lib/SILOptimizer/LoopTransforms/ArrayBoundsCheckOpts.cpp

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -727,16 +727,41 @@ class AccessFunction {
727727
static AccessFunction getLinearFunction(SILValue Idx,
728728
InductionAnalysis &IndVars) {
729729
// Match the actual induction variable buried in the integer struct.
730-
// %2 = struct $Int(%1 : $Builtin.Word)
731-
// = apply %check_bounds(%array, %2) : $@convention(thin) (Int, ArrayInt) -> ()
730+
// bb(%ivar)
731+
// %2 = struct $Int(%ivar : $Builtin.Word)
732+
// = apply %check_bounds(%array, %2) :
733+
// or
734+
// bb(%ivar1)
735+
// %ivar2 = builtin "sadd_with_overflow_Int64"(%ivar1,...)
736+
// %t = tuple_extract %ivar2
737+
// %s = struct $Int(%t : $Builtin.Word)
738+
// = apply %check_bounds(%array, %s) :
739+
732740
auto ArrayIndexStruct = dyn_cast<StructInst>(Idx);
733741
if (!ArrayIndexStruct)
734742
return nullptr;
735743

736744
auto AsArg =
737745
dyn_cast<SILArgument>(ArrayIndexStruct->getElements()[0]);
738-
if (!AsArg)
739-
return nullptr;
746+
747+
if (!AsArg) {
748+
auto *TupleExtract =
749+
dyn_cast<TupleExtractInst>(ArrayIndexStruct->getElements()[0]);
750+
751+
if (!TupleExtract) {
752+
return nullptr;
753+
}
754+
755+
auto *Builtin = dyn_cast<BuiltinInst>(TupleExtract->getOperand());
756+
if (!Builtin || Builtin->getBuiltinKind() != BuiltinValueKind::SAddOver) {
757+
return nullptr;
758+
}
759+
760+
AsArg = dyn_cast<SILArgument>(Builtin->getArguments()[0]);
761+
if (!AsArg) {
762+
return nullptr;
763+
}
764+
}
740765

741766
if (auto *Ind = IndVars[AsArg])
742767
return AccessFunction(Ind);

test/SILOptimizer/abcopts.sil

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
// RUN: %target-sil-opt -parse-serialized-sil -enable-sil-verify-all -loop-rotate -dce -jumpthread-simplify-cfg -abcopts -enable-abcopts=1 %s | %FileCheck %s
2-
// RUN: %target-sil-opt -parse-serialized-sil -enable-sil-verify-all -loop-rotate -dce -jumpthread-simplify-cfg -abcopts -dce -enable-abcopts -enable-abc-hoisting %s | %FileCheck %s --check-prefix=HOIST
31
// RUN: %target-sil-opt -parse-serialized-sil -enable-sil-verify-all -abcopts %s | %FileCheck %s --check-prefix=RANGECHECK
42

53
sil_stage canonical
@@ -1096,6 +1094,49 @@ bb4(%31 : $Builtin.Int32):
10961094
return %32 : $Int32
10971095
}
10981096

1097+
// SIL pattern for :
1098+
// func hoist_new_ind_pattern(_ a : [Int]) {
1099+
// for i in 0...4 {
1100+
// ...a[i]...
1101+
// }
1102+
// }
1103+
// Bounds check for the array should be hoisted out of the loop
1104+
//
1105+
// RANGECHECK-LABEL: sil @hoist_new_ind_pattern :
1106+
// RANGECHECK: [[CB:%.*]] = function_ref @checkbounds : $@convention(method) (Int32, Bool, @owned ArrayInt) -> _DependenceToken
1107+
// RANGECHECK: bb1
1108+
// RANGECHECK-NOT: apply [[CB]]
1109+
// RANGECHECK-LABEL: } // end sil function 'hoist_new_ind_pattern'
1110+
sil @hoist_new_ind_pattern : $@convention(thin) (@owned ArrayInt) -> () {
1111+
bb0(%0 : $ArrayInt):
1112+
%minus1 = integer_literal $Builtin.Int1, -1
1113+
%true = struct $Bool(%minus1 : $Builtin.Int1)
1114+
%zero = integer_literal $Builtin.Int32, 0
1115+
%int0 = struct $Int32 (%zero : $Builtin.Int32)
1116+
%one = integer_literal $Builtin.Int32, 1
1117+
%four = integer_literal $Builtin.Int32, 4
1118+
%intfour = struct $Int32 (%four : $Builtin.Int32)
1119+
%cb = function_ref @checkbounds : $@convention(method) (Int32, Bool, @owned ArrayInt) -> _DependenceToken
1120+
apply %cb(%int0, %true, %0) : $@convention(method) (Int32, Bool, @owned ArrayInt) -> _DependenceToken
1121+
br bb1(%zero : $Builtin.Int32)
1122+
1123+
bb1(%4 : $Builtin.Int32):
1124+
%5 = builtin "sadd_with_overflow_Int32"(%4 : $Builtin.Int32, %one : $Builtin.Int32, %minus1 : $Builtin.Int1) : $(Builtin.Int32, Builtin.Int1)
1125+
%6 = tuple_extract %5 : $(Builtin.Int32, Builtin.Int1), 0
1126+
%7 = tuple_extract %5 : $(Builtin.Int32, Builtin.Int1), 1
1127+
%8 = struct $Int32 (%6 : $Builtin.Int32)
1128+
%9 = builtin "cmp_eq_Int32"(%6 : $Builtin.Int32, %four : $Builtin.Int32) : $Builtin.Int1
1129+
apply %cb(%8, %true, %0) : $@convention(method) (Int32, Bool, @owned ArrayInt) -> _DependenceToken
1130+
cond_br %9, bb3, bb2
1131+
1132+
bb2:
1133+
br bb1(%6 : $Builtin.Int32)
1134+
1135+
bb3:
1136+
%t = tuple ()
1137+
return %t : $()
1138+
}
1139+
10991140
sil public_external [_semantics "array.check_subscript"] @checkbounds_no_meth : $@convention(thin) (Int32, Bool, @owned ArrayInt) -> _DependenceToken {
11001141
bb0(%0: $Int32, %1: $Bool, %2: $ArrayInt):
11011142
unreachable

0 commit comments

Comments
 (0)