File: simplify_cfg_trivial_jumpthread.sil

package info (click to toggle)
swiftlang 6.0.3-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,519,992 kB
  • sloc: cpp: 9,107,863; ansic: 2,040,022; asm: 1,135,751; python: 296,500; objc: 82,456; f90: 60,502; lisp: 34,951; pascal: 19,946; sh: 18,133; perl: 7,482; ml: 4,937; javascript: 4,117; makefile: 3,840; awk: 3,535; xml: 914; fortran: 619; cs: 573; ruby: 573
file content (143 lines) | stat: -rw-r--r-- 3,941 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
// RUN: %target-sil-opt -enable-sil-verify-all %s -simplify-cfg | %FileCheck %s

// Tests tryJumpThreading with OSSA for trivial branch and terminator
// arguments. This does not require -jumpthread-simplify-cfg, which
// is only for dominator-based jump-threading.

sil_stage canonical

import Builtin
import Swift

internal enum Enum {
  case one
  case two
  case three
}

enum BoolLike { case true_, false_ }

// Test that SimplifyCFG::simplifyBlocks, tryJumpThreading does not
// perform unbounded loop peeling.
//
// rdar://73357726
// https://github.com/apple/swift/issues/56457
// Compiling with optimisation runs indefinitely for grpc-swift
//
// Note: this no longer attempts to run jump-threading infinitely, so
// does not actually unit test the bailout. But it is still an
// interesting test case.
//
// CHECK-LABEL: sil [ossa] @testInfinitePeeling : $@convention(method) (Builtin.Int64, Enum) -> () {
//
// There is only one switch_enum blocks, and it is no longer in a loop.
// CHECK: bb0(%0 : $Builtin.Int64, %1 : $Enum):
// CHECK:   switch_enum %1 : $Enum, case #Enum.one!enumelt: bb4, default bb1
// CHECK: bb1(%{{.*}} : $Enum):
// CHECK:   br bb5
// CHECK: bb2:
// CHECK:   br bb6
//
// CHECK: bb3:
// CHECK:   br bb5
//
// This is the cond_br block after jump-threading.
// CHECK: bb4:
// CHECK:   cond_br %{{.*}}, bb3, bb2
//
// The original loop has been removed here.
// CHECK: bb5:
// CHECK:   br bb6
//
// CHECK: bb6:
// CHECK:   return
// CHECK-LABEL: } // end sil function 'testInfinitePeeling'
sil [ossa] @testInfinitePeeling : $@convention(method) (Builtin.Int64, Enum) -> () {
bb0(%0 : $Builtin.Int64, %1 : $Enum):
  %2 = integer_literal $Builtin.Int64, 99999999
  br bb1(%0 : $Builtin.Int64, %1 : $Enum)

bb1(%4 : $Builtin.Int64, %5 : $Enum):
  switch_enum %5 : $Enum, case #Enum.one!enumelt: bb4, default bb5

bb2(%7 : $Builtin.Int64, %8 : $Enum):
  %9 = builtin "cmp_slt_Int64"(%2 : $Builtin.Int64, %7 : $Builtin.Int64) : $Builtin.Int1
  cond_br %9, bb3, bb6

bb3:
  br bb1(%7 : $Builtin.Int64, %8 : $Enum)

bb4:
  %12 = integer_literal $Builtin.Int64, 1
  %13 = integer_literal $Builtin.Int1, -1
  %14 = builtin "sadd_with_overflow_Int64"(%4 : $Builtin.Int64, %12 : $Builtin.Int64, %13 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1)
  %15 = tuple_extract %14 : $(Builtin.Int64, Builtin.Int1), 0
  %16 = enum $Enum, #Enum.two!enumelt
  br bb2(%15 : $Builtin.Int64, %16 : $Enum)

bb5(%17 : $Enum):
  br bb2(%2 : $Builtin.Int64, %17 : $Enum)

bb6:
  %19 = tuple ()
  return %19 : $()
}

class C {
  @_hasStorage @_hasInitialValue var field: Int { get set }
  init()
}

// func testThread2(a : Int32) -> Int32 {
//   enum b = (a ? _true : _false)
//   if b == _true { return 42 } else { return 17 }
//

/// CHECK-LABEL: sil [ossa] @testThread2
/// CHECK: bb0([[COND:%.*]] : {{.*}}):
/// CHECK: cond_br [[COND]], bb1, bb2
/// CHECK: bb1:
/// CHECK:  integer_literal $Builtin.Int64, 42
/// CHeCK:  br bb3
/// CHECK: bb2:
/// CHECK:  integer_literal $Builtin.Int64, 17
/// CHECK:  br bb3
/// CHECK: bb3
/// CHECK:  return

sil [ossa] @testThread2 : $@convention(thin) (Builtin.Int1) -> Int64 {
bb0(%0 : $Builtin.Int1):
  %t = integer_literal $Builtin.Int1, 1
  %f = integer_literal $Builtin.Int1, 0
  cond_br %0, bb1, bb2

bb1:
  %4 = enum $BoolLike, #BoolLike.true_!enumelt
  br bb3(%4 : $BoolLike)

bb2:
  %8 = enum $BoolLike, #BoolLike.false_!enumelt
  br bb3(%8 : $BoolLike)

bb3(%6 : $BoolLike):
  %100 = select_enum %6 : $BoolLike, case #BoolLike.true_!enumelt: %t, case #BoolLike.false_!enumelt: %f : $Builtin.Int1
  br bb4

bb4:
  cond_br %100, bb5, bb6

bb5:
  %11 = metatype $@thin Int64.Type
  %12 = integer_literal $Builtin.Int64, 42
  %13 = struct $Int64 (%12 : $Builtin.Int64)
  br bb7(%13 : $Int64)

bb6:
  %15 = metatype $@thin Int64.Type
  %16 = integer_literal $Builtin.Int64, 17
  %17 = struct $Int64 (%16 : $Builtin.Int64)
  br bb7(%17 : $Int64)

bb7(%19 : $Int64):
  return %19 : $Int64
}