@@ -854,3 +854,82 @@ bb9(%39 : $Builtin.Int64): // Preds: bb7
854854 dealloc_stack %3 : $*Index // id: %41
855855 return %40 : $Int64 // id: %42
856856}
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