Fix GCC build problem with 288f05f related to SmallVector. (#116958)
[llvm-project.git] / mlir / test / Transforms / sccp.mlir
blobdcae052c29c24872c90eb57bfb556febaaf0d841
1 // RUN: mlir-opt -allow-unregistered-dialect %s -pass-pipeline="builtin.module(func.func(sccp))" -split-input-file | FileCheck %s
3 /// Check simple forward constant propagation without any control flow.
5 // CHECK-LABEL: func @no_control_flow
6 func.func @no_control_flow(%arg0: i32) -> i32 {
7   // CHECK: %[[CST:.*]] = arith.constant 1 : i32
8   // CHECK: return %[[CST]] : i32
10   %cond = arith.constant true
11   %cst_1 = arith.constant 1 : i32
12   %select = arith.select %cond, %cst_1, %arg0 : i32
13   return %select : i32
16 /// Check that a constant is properly propagated when only one edge of a branch
17 /// is taken.
19 // CHECK-LABEL: func @simple_control_flow
20 func.func @simple_control_flow(%arg0 : i32) -> i32 {
21   // CHECK: %[[CST:.*]] = arith.constant 1 : i32
23   %cond = arith.constant true
24   %1 = arith.constant 1 : i32
25   cf.cond_br %cond, ^bb1, ^bb2(%arg0 : i32)
27 ^bb1:
28   cf.br ^bb2(%1 : i32)
30 ^bb2(%arg : i32):
31   // CHECK: ^bb2(%{{.*}}: i32):
32   // CHECK: return %[[CST]] : i32
34   return %arg : i32
37 /// Check that the arguments go to overdefined if the branch cannot detect when
38 /// a specific successor is taken.
40 // CHECK-LABEL: func @simple_control_flow_overdefined
41 func.func @simple_control_flow_overdefined(%arg0 : i32, %arg1 : i1) -> i32 {
42   %1 = arith.constant 1 : i32
43   cf.cond_br %arg1, ^bb1, ^bb2(%arg0 : i32)
45 ^bb1:
46   cf.br ^bb2(%1 : i32)
48 ^bb2(%arg : i32):
49   // CHECK: ^bb2(%[[ARG:.*]]: i32):
50   // CHECK: return %[[ARG]] : i32
52   return %arg : i32
55 /// Check that the arguments go to overdefined if there are conflicting
56 /// constants.
58 // CHECK-LABEL: func @simple_control_flow_constant_overdefined
59 func.func @simple_control_flow_constant_overdefined(%arg0 : i32, %arg1 : i1) -> i32 {
60   %1 = arith.constant 1 : i32
61   %2 = arith.constant 2 : i32
62   cf.cond_br %arg1, ^bb1, ^bb2(%arg0 : i32)
64 ^bb1:
65   cf.br ^bb2(%2 : i32)
67 ^bb2(%arg : i32):
68   // CHECK: ^bb2(%[[ARG:.*]]: i32):
69   // CHECK: return %[[ARG]] : i32
71   return %arg : i32
74 /// Check that the arguments go to overdefined if the branch is unknown.
76 // CHECK-LABEL: func @unknown_terminator
77 func.func @unknown_terminator(%arg0 : i32, %arg1 : i1) -> i32 {
78   %1 = arith.constant 1 : i32
79   "foo.cond_br"() [^bb1, ^bb2] : () -> ()
81 ^bb1:
82   cf.br ^bb2(%1 : i32)
84 ^bb2(%arg : i32):
85   // CHECK: ^bb2(%[[ARG:.*]]: i32):
86   // CHECK: return %[[ARG]] : i32
88   return %arg : i32
91 /// Check that arguments are properly merged across loop-like control flow.
93 func.func private @ext_cond_fn() -> i1
95 // CHECK-LABEL: func @simple_loop
96 func.func @simple_loop(%arg0 : i32, %cond1 : i1) -> i32 {
97   // CHECK: %[[CST:.*]] = arith.constant 1 : i32
99   %cst_1 = arith.constant 1 : i32
100   cf.cond_br %cond1, ^bb1(%cst_1 : i32), ^bb2(%cst_1 : i32)
102 ^bb1(%iv: i32):
103   // CHECK: ^bb1(%{{.*}}: i32):
104   // CHECK-NEXT: %[[COND:.*]] = call @ext_cond_fn()
105   // CHECK-NEXT: cf.cond_br %[[COND]], ^bb1(%[[CST]] : i32), ^bb2(%[[CST]] : i32)
107   %cst_0 = arith.constant 0 : i32
108   %res = arith.addi %iv, %cst_0 : i32
109   %cond2 = call @ext_cond_fn() : () -> i1
110   cf.cond_br %cond2, ^bb1(%res : i32), ^bb2(%res : i32)
112 ^bb2(%arg : i32):
113   // CHECK: ^bb2(%{{.*}}: i32):
114   // CHECK: return %[[CST]] : i32
116   return %arg : i32
119 /// Test that we can properly propagate within inner control, and in situations
120 /// where the executable edges within the CFG are sensitive to the current state
121 /// of the analysis.
123 // CHECK-LABEL: func @simple_loop_inner_control_flow
124 func.func @simple_loop_inner_control_flow(%arg0 : i32) -> i32 {
125   // CHECK-DAG: %[[CST:.*]] = arith.constant 1 : i32
126   // CHECK-DAG: %[[TRUE:.*]] = arith.constant true
128   %cst_1 = arith.constant 1 : i32
129   cf.br ^bb1(%cst_1 : i32)
131 ^bb1(%iv: i32):
132   %cond2 = call @ext_cond_fn() : () -> i1
133   cf.cond_br %cond2, ^bb5(%iv : i32), ^bb2
135 ^bb2:
136   // CHECK: ^bb2:
137   // CHECK: cf.cond_br %[[TRUE]], ^bb3, ^bb4
139   %cst_20 = arith.constant 20 : i32
140   %cond = arith.cmpi ult, %iv, %cst_20 : i32
141   cf.cond_br %cond, ^bb3, ^bb4
143 ^bb3:
144   // CHECK: ^bb3:
145   // CHECK: cf.br ^bb1(%[[CST]] : i32)
147   %cst_1_2 = arith.constant 1 : i32
148   cf.br ^bb1(%cst_1_2 : i32)
150 ^bb4:
151   %iv_inc = arith.addi %iv, %cst_1 : i32
152   cf.br ^bb1(%iv_inc : i32)
154 ^bb5(%result: i32):
155   // CHECK: ^bb5(%{{.*}}: i32):
156   // CHECK: return %[[CST]] : i32
158   return %result : i32
161 /// Check that arguments go to overdefined when loop backedges produce a
162 /// conflicting value.
164 func.func private @ext_cond_and_value_fn() -> (i1, i32)
166 // CHECK-LABEL: func @simple_loop_overdefined
167 func.func @simple_loop_overdefined(%arg0 : i32, %cond1 : i1) -> i32 {
168   %cst_1 = arith.constant 1 : i32
169   cf.cond_br %cond1, ^bb1(%cst_1 : i32), ^bb2(%cst_1 : i32)
171 ^bb1(%iv: i32):
172   %cond2, %res = call @ext_cond_and_value_fn() : () -> (i1, i32)
173   cf.cond_br %cond2, ^bb1(%res : i32), ^bb2(%res : i32)
175 ^bb2(%arg : i32):
176   // CHECK: ^bb2(%[[ARG:.*]]: i32):
177   // CHECK: return %[[ARG]] : i32
179   return %arg : i32
182 // Check that we reprocess executable edges when information changes.
184 // CHECK-LABEL: func @recheck_executable_edge
185 func.func @recheck_executable_edge(%cond0: i1) -> (i1, i1) {
186   %true = arith.constant true
187   %false = arith.constant false
188   cf.cond_br %cond0, ^bb_1a, ^bb2(%false : i1)
189 ^bb_1a:
190   cf.br ^bb2(%true : i1)
192 ^bb2(%x: i1):
193   // CHECK: ^bb2(%[[X:.*]]: i1):
194   cf.br ^bb3(%x : i1)
196 ^bb3(%y: i1):
197   // CHECK: ^bb3(%[[Y:.*]]: i1):
198   // CHECK: return %[[X]], %[[Y]]
199   return %x, %y : i1, i1
202 // CHECK-LABEL: func @simple_produced_operand
203 func.func @simple_produced_operand() -> (i32, i32) {
204   // CHECK: %[[ONE:.*]] = arith.constant 1
205   %1 = arith.constant 1 : i32
206   "test.internal_br"(%1) [^bb1, ^bb2] {
207     operandSegmentSizes = array<i32: 0, 1>
208   } : (i32) -> ()
210 ^bb1:
211   cf.br ^bb2(%1, %1 : i32, i32)
213 ^bb2(%arg1 : i32, %arg2 : i32):
214   // CHECK: ^bb2(%[[ARG:.*]]: i32, %{{.*}}: i32):
215   // CHECK: return %[[ARG]], %[[ONE]] : i32, i32
217   return %arg1, %arg2 : i32, i32
220 // CHECK-LABEL: inplace_fold
221 func.func @inplace_fold() -> (i32) {
222   %0 = "test.op_in_place_fold_success"() : () -> i1
223   %1 = arith.constant 5 : i32
224   cf.cond_br %0, ^a, ^b
227   // CHECK-NOT: addi
228   %3 = arith.addi %1, %1 : i32
229   return %3 : i32
232   return %1 : i32
235 // CHECK-LABEL: op_with_region
236 func.func @op_with_region() -> (i32) {
237   %0 = "test.op_with_region"() ({}) : () -> i1
238   %1 = arith.constant 5 : i32
239   cf.cond_br %0, ^a, ^b
242   // CHECK-NOT: addi
243   %3 = arith.addi %1, %1 : i32
244   return %3 : i32
247   return %1 : i32