Skip to content

Commit 8666297

Browse files
committed
BoundsCheckOpts: handle more integer comparison builtins
So far, only negated comparisons (via xor) were handled. Now, also handle simplified comparisons
1 parent 4b9ef8c commit 8666297

File tree

2 files changed

+169
-2
lines changed

2 files changed

+169
-2
lines changed

lib/SILOptimizer/LoopTransforms/BoundsCheckOpts.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,11 @@ static bool isSignedLessEqual(SILValue Start, SILValue End, SILBasicBlock &BB) {
353353
m_Specific(Start), m_Specific(End)),
354354
m_One())))
355355
return true;
356+
// Try to match a cond_fail on "SGT Start, End".
357+
if (match(CF->getOperand(),
358+
m_ApplyInst(BuiltinValueKind::ICMP_SGT,
359+
m_Specific(Start), m_Specific(End))))
360+
return true;
356361
// Try to match a cond_fail on "SLT End, Start".
357362
if (match(CF->getOperand(),
358363
m_ApplyInst(BuiltinValueKind::ICMP_SLT, m_Specific(End),
@@ -368,6 +373,11 @@ static bool isSignedLessEqual(SILValue Start, SILValue End, SILBasicBlock &BB) {
368373
m_Specific(PreInclusiveEnd)),
369374
m_One())))
370375
IsPreInclusiveEndLEQ = true;
376+
if (match(CF->getOperand(),
377+
m_ApplyInst(BuiltinValueKind::ICMP_SGT,
378+
m_Specific(Start),
379+
m_Specific(PreInclusiveEnd))))
380+
IsPreInclusiveEndLEQ = true;
371381
if (match(CF->getOperand(),
372382
m_ApplyInst(BuiltinValueKind::ICMP_SLT,
373383
m_Specific(PreInclusiveEnd), m_Specific(Start))))
@@ -379,6 +389,11 @@ static bool isSignedLessEqual(SILValue Start, SILValue End, SILBasicBlock &BB) {
379389
m_Specific(PreInclusiveEnd)),
380390
m_One())))
381391
IsPreInclusiveEndGTEnd = true;
392+
if (match(CF->getOperand(),
393+
m_ApplyInst(BuiltinValueKind::ICMP_SLE,
394+
m_Specific(End),
395+
m_Specific(PreInclusiveEnd))))
396+
IsPreInclusiveEndGTEnd = true;
382397
if (IsPreInclusiveEndLEQ && IsPreInclusiveEndGTEnd)
383398
return true;
384399
}
@@ -910,6 +925,12 @@ static bool isComparisonKnownFalse(BuiltinInst *Builtin,
910925
IndVar.Cmp != BuiltinValueKind::ICMP_EQ)
911926
return false;
912927

928+
if (match(Builtin, m_ApplyInst(BuiltinValueKind::ICMP_SGE,
929+
m_Specific(IndVar.HeaderVal),
930+
m_Specific(IndVar.End)))) {
931+
return true;
932+
}
933+
913934
// Pattern match a false condition patterns that we can detect and optimize:
914935
// Iteration count < 0 (start)
915936
// Iteration count + 1 <= 0 (start)

test/SILOptimizer/abcopts.sil

Lines changed: 148 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -607,7 +607,7 @@ bb2:
607607
return %23 : $Int32
608608
}
609609

610-
// HOIST-LABEL: sil @hoist_rangechecked
610+
// HOIST-LABEL: sil @hoist_rangechecked :
611611
// HOIST: bb0
612612
// HOIST: cond_br {{.*}}, bb2, bb1
613613
// HOIST: bb1:
@@ -667,6 +667,64 @@ bb3:
667667
return %23 : $Int32
668668
}
669669

670+
// HOIST-LABEL: sil @hoist_rangechecked_sgt :
671+
// HOIST: bb0
672+
// HOIST: cond_br {{.*}}, bb2, bb1
673+
// HOIST: bb1:
674+
// HOIST: [[CB:%[0-9]+]] = function_ref @checkbounds
675+
// HOIST: apply [[CB]]
676+
// HOIST: br bb3{{.*}}
677+
// HOIST: bb3{{.*}}:
678+
// HOIST-NOT: function_ref @checkbounds
679+
// HOIST-NOT: apply [[CB]]
680+
// HOIST: cond_br {{.*}}, bb5, bb4
681+
// HOIST: bb4
682+
// HOIST: br bb3
683+
// HOIST: bb5
684+
// HOIST: br bb6
685+
// HOIST: bb6{{.*}}:
686+
// HOIST: } // end sil function 'hoist_rangechecked_sgt'
687+
688+
sil @hoist_rangechecked_sgt : $@convention(thin) (Int32, @inout ArrayInt) -> Int32 {
689+
bb0(%0 : $Int32, %24 : $*ArrayInt):
690+
%100 = integer_literal $Builtin.Int1, -1
691+
%101 = struct $Bool(%100 : $Builtin.Int1)
692+
%1 = struct_extract %0 : $Int32, #Int32._value
693+
%2 = integer_literal $Builtin.Int32, 0
694+
%14 = builtin "cmp_sgt_Int32"(%2 : $Builtin.Int32, %1 : $Builtin.Int32) : $Builtin.Int1
695+
cond_fail %14 : $Builtin.Int1
696+
br bb1(%2 : $Builtin.Int32)
697+
698+
bb1(%4 : $Builtin.Int32):
699+
%8 = builtin "cmp_eq_Int32"(%4 : $Builtin.Int32, %1 : $Builtin.Int32) : $Builtin.Int1
700+
cond_br %8, bb3, bb4
701+
702+
bb4:
703+
%37 = struct $Int32(%4 : $Builtin.Int32)
704+
%52 = function_ref @checkbounds : $@convention(method) (Int32, Bool, @owned ArrayInt) -> _DependenceToken
705+
%53 = load %24 : $*ArrayInt
706+
%54 = struct_extract %53 : $ArrayInt, #ArrayInt.buffer
707+
%55 = struct_extract %54 : $ArrayIntBuffer, #ArrayIntBuffer.storage
708+
retain_value %55 : $Builtin.NativeObject
709+
%58 = apply %52(%37, %101, %53) : $@convention(method) (Int32, Bool, @owned ArrayInt) -> _DependenceToken
710+
%10 = integer_literal $Builtin.Int32, 1
711+
%19 = integer_literal $Builtin.Int1, -1
712+
%20 = builtin "sadd_with_overflow_Int32"(%4 : $Builtin.Int32, %10 : $Builtin.Int32, %19 : $Builtin.Int1) : $(Builtin.Int32, Builtin.Int1)
713+
%21 = tuple_extract %20 : $(Builtin.Int32, Builtin.Int1), 0
714+
715+
%40 = function_ref @getElementAddr : $@convention(method) (Int32, @owned ArrayInt) -> UnsafeMutablePointerInt
716+
retain_value %55 : $Builtin.NativeObject
717+
%42 = apply %40(%37, %53) : $@convention(method) (Int32, @owned ArrayInt) -> UnsafeMutablePointerInt
718+
%43 = struct_extract %42 : $UnsafeMutablePointerInt, #UnsafeMutablePointerInt._rawValue
719+
%44 = pointer_to_address %43 : $Builtin.RawPointer to [strict] $*Int32
720+
store %0 to %44 : $*Int32
721+
br bb1(%21 : $Builtin.Int32)
722+
723+
bb3:
724+
%23 = struct $Int32 (%4 : $Builtin.Int32)
725+
return %23 : $Int32
726+
}
727+
670728
// HOIST-LABEL: sil @hoist_rangechecked_ref_tail_addr
671729
// HOIST: bb0
672730
// HOIST: cond_br {{.*}}, bb2, bb1
@@ -886,7 +944,7 @@ bb3:
886944
return %23 : $Int32
887945
}
888946

889-
// HOIST-LABEL: hoist_inclusive_rangechecked
947+
// HOIST-LABEL: hoist_inclusive_rangechecked :
890948
// HOIST: bb0
891949
// HOIST: cond_br {{.*}}, bb2, bb1
892950
// HOIST: bb1:
@@ -945,6 +1003,62 @@ bb3:
9451003
return %23 : $Int32
9461004
}
9471005

1006+
// HOIST-LABEL: hoist_inclusive_rangechecked_sgt :
1007+
// HOIST: bb0
1008+
// HOIST: cond_br {{.*}}, bb2, bb1
1009+
// HOIST: bb1:
1010+
// HOIST: [[CB:%[0-9]+]] = function_ref @checkbounds
1011+
// HOIST: apply [[CB]]
1012+
// HOIST: br bb3{{.*}}
1013+
// HOIST: bb3{{.*}}:
1014+
// HOIST-NOT: function_ref @checkbounds
1015+
// HOIST-NOT: apply [[CB]]
1016+
// HOIST: cond_br {{.*}}, bb5, bb4
1017+
// HOIST: bb4:
1018+
// HOIST: br bb3
1019+
// HOIST: bb5:
1020+
// HOIST: br bb6
1021+
// HOIST: bb6{{.*}}:
1022+
// HOIST: } // end sil function 'hoist_inclusive_rangechecked_sgt'
1023+
sil @hoist_inclusive_rangechecked_sgt : $@convention(thin) (Int32, @inout ArrayInt) -> Int32 {
1024+
bb0(%0 : $Int32, %24 : $*ArrayInt):
1025+
%100 = integer_literal $Builtin.Int1, -1
1026+
%101 = struct $Bool(%100 : $Builtin.Int1)
1027+
%1 = struct_extract %0 : $Int32, #Int32._value
1028+
%2 = integer_literal $Builtin.Int32, 0
1029+
%14 = builtin "cmp_sgt_Int32"(%2 : $Builtin.Int32, %1 : $Builtin.Int32) : $Builtin.Int1
1030+
cond_fail %14 : $Builtin.Int1
1031+
%63 = integer_literal $Builtin.Int32, 1
1032+
%65 = integer_literal $Builtin.Int1, 0
1033+
%66 = builtin "sadd_with_overflow_Int32"(%1 : $Builtin.Int32, %63 : $Builtin.Int32, %65 : $Builtin.Int1) : $(Builtin.Int32, Builtin.Int1)
1034+
%67 = tuple_extract %66 : $(Builtin.Int32, Builtin.Int1), 0
1035+
%70 = builtin "cmp_sle_Int32"(%67 : $Builtin.Int32, %1 : $Builtin.Int32) : $Builtin.Int1
1036+
cond_fail %70 : $Builtin.Int1
1037+
br bb1(%2 : $Builtin.Int32)
1038+
1039+
bb1(%4 : $Builtin.Int32):
1040+
%8 = builtin "cmp_eq_Int32"(%4 : $Builtin.Int32, %67 : $Builtin.Int32) : $Builtin.Int1
1041+
cond_br %8, bb3, bb4
1042+
1043+
bb4:
1044+
%37 = struct $Int32(%4 : $Builtin.Int32)
1045+
%52 = function_ref @checkbounds : $@convention(method) (Int32, Bool, @owned ArrayInt) -> _DependenceToken
1046+
%53 = load %24 : $*ArrayInt
1047+
%54 = struct_extract %53 : $ArrayInt, #ArrayInt.buffer
1048+
%55 = struct_extract %54 : $ArrayIntBuffer, #ArrayIntBuffer.storage
1049+
retain_value %55 : $Builtin.NativeObject
1050+
%58 = apply %52(%37, %101, %53) : $@convention(method) (Int32, Bool, @owned ArrayInt) -> _DependenceToken
1051+
%10 = integer_literal $Builtin.Int32, 1
1052+
%19 = integer_literal $Builtin.Int1, -1
1053+
%20 = builtin "sadd_with_overflow_Int32"(%4 : $Builtin.Int32, %10 : $Builtin.Int32, %19 : $Builtin.Int1) : $(Builtin.Int32, Builtin.Int1)
1054+
%21 = tuple_extract %20 : $(Builtin.Int32, Builtin.Int1), 0
1055+
br bb1(%21 : $Builtin.Int32)
1056+
1057+
bb3:
1058+
%23 = struct $Int32 (%4 : $Builtin.Int32)
1059+
return %23 : $Int32
1060+
}
1061+
9481062
/// Don't hoist arrays that are variant.
9491063
// HOIST-LABEL: dont_hoist_variant_array
9501064
// HOIST: bb0
@@ -1618,3 +1732,35 @@ bb3:
16181732
return %25 : $Int32
16191733
}
16201734

1735+
1736+
// CHECK-LABEL: sil [ossa] @constant_indvar_sge_condition :
1737+
// CHECK: [[FALSE:%.*]] = integer_literal $Builtin.Int1, 0
1738+
// CHECK: cond_fail [[FALSE]] : $Builtin.Int1, "Index out of bounds"
1739+
// CHECK: } // end sil function 'constant_indvar_sge_condition'
1740+
sil [ossa] @constant_indvar_sge_condition : $@convention(thin) (Builtin.Int64) -> () {
1741+
bb0(%0 : $Builtin.Int64):
1742+
%1 = integer_literal $Builtin.Int64, 0
1743+
%2 = integer_literal $Builtin.Int64, 1
1744+
%3 = integer_literal $Builtin.Int1, -1
1745+
br bb1(%1)
1746+
1747+
1748+
bb1(%5 : $Builtin.Int64):
1749+
%6 = builtin "cmp_sge_Int64"(%5, %0) : $Builtin.Int1
1750+
cond_fail %6, "Index out of bounds"
1751+
%8 = builtin "sadd_with_overflow_Int64"(%5, %2, %3) : $(Builtin.Int64, Builtin.Int1)
1752+
%9 = tuple_extract %8, 0
1753+
%10 = tuple_extract %8, 1
1754+
cond_fail %10, "arithmetic overflow"
1755+
%12 = builtin "cmp_eq_Int64"(%9, %0) : $Builtin.Int1
1756+
cond_br %12, bb3, bb2
1757+
1758+
bb2:
1759+
br bb1(%9)
1760+
1761+
bb3:
1762+
%15 = tuple ()
1763+
return %15
1764+
}
1765+
1766+

0 commit comments

Comments
 (0)