@@ -854,3 +854,82 @@ bb9(%39 : $Builtin.Int64): // Preds: bb7
854
854
dealloc_stack %3 : $*Index // id: %41
855
855
return %40 : $Int64 // id: %42
856
856
}
857
+
858
+ // testConditionalTrapInInfiniteSyncLoop and
859
+ // testConditionalTrapDominatingSyncLoopExit
860
+ //
861
+ // It's legal for the optimizer to consider code after the loop as
862
+ // always reachable, but when a loop has no exits, or when the loops
863
+ // exits are dominated by a conditional statement we should not
864
+ // consider conditional statements within the loop as dominating all
865
+ // possible execution paths through the loop. At least not when there
866
+ // is at least one path through the loop that contains a
867
+ // "synchronization point", such as a function that may contain a
868
+ // memory barrier, perform I/O, or exit the program.
869
+ sil @mayExit : $@convention(thin) () -> ()
870
+
871
+ // CHECK-LABEL: sil @testConditionalTrapInInfiniteSyncLoop : $@convention(thin) (Builtin.Int1, Builtin.Int1) -> () {
872
+ // CHECK: bb0
873
+ // CHECK-NOT: cond_fail
874
+ // CHECK: br bb1
875
+ // CHECK: bb1:
876
+ // CHECK: cond_br %0, bb2, bb3
877
+ // CHECK: bb2:
878
+ // CHECK: cond_fail %1 : $Builtin.Int1, "arithmetic overflow"
879
+ // CHECK-LABEL: } // end sil function 'testConditionalTrapInInfiniteSyncLoop'
880
+ sil @testConditionalTrapInInfiniteSyncLoop : $@convention(thin) (Builtin.Int1, Builtin.Int1) -> () {
881
+ bb0(%0 : $Builtin.Int1, %1 : $Builtin.Int1):
882
+ br bb1
883
+
884
+ bb1: // loop head
885
+ cond_br %0, bb2, bb3
886
+
887
+ bb2: // maybe never executed
888
+ cond_fail %1 : $Builtin.Int1, "arithmetic overflow"
889
+ br bb4
890
+
891
+ bb3:
892
+ // synchronization point: has "real" side-effects that we can't
893
+ // reorder with traps
894
+ %f = function_ref @mayExit : $@convention(thin) () -> ()
895
+ apply %f() : $@convention(thin) () -> ()
896
+ br bb4
897
+
898
+ bb4: // latch
899
+ br bb1
900
+ }
901
+
902
+ // CHECK-LABEL: sil @testConditionalTrapDominatingSyncLoopExit : $@convention(thin) (Builtin.Int1, Builtin.Int1, Builtin.Int1) -> () {
903
+ // CHECK: bb0
904
+ // CHECK-NOT: cond_fail
905
+ // CHECK: br bb1
906
+ // CHECK: bb1:
907
+ // CHECK: cond_br %0, bb2, bb4
908
+ // CHECK: bb2:
909
+ // CHECK: cond_fail %1 : $Builtin.Int1, "arithmetic overflow"
910
+ // CHECK-LABEL: } // end sil function 'testConditionalTrapDominatingSyncLoopExit'
911
+ sil @testConditionalTrapDominatingSyncLoopExit : $@convention(thin) (Builtin.Int1, Builtin.Int1, Builtin.Int1) -> () {
912
+ bb0(%0 : $Builtin.Int1, %1 : $Builtin.Int1, %2 : $Builtin.Int1):
913
+ br bb1
914
+
915
+ bb1: // loop head
916
+ cond_br %0, bb2, bb4
917
+
918
+ bb2: // maybe never executed
919
+ cond_fail %1 : $Builtin.Int1, "arithmetic overflow"
920
+ cond_br %2, bb3, bb5
921
+
922
+ bb3: // tail
923
+ br bb1
924
+
925
+ bb4:
926
+ // synchronization point: has "real" side-effects that we can't
927
+ // reorder with traps
928
+ %f = function_ref @mayExit : $@convention(thin) () -> ()
929
+ apply %f() : $@convention(thin) () -> ()
930
+ br bb1
931
+
932
+ bb5:
933
+ %99 = tuple ()
934
+ return %99 : $()
935
+ }
0 commit comments