brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.5 KiB · c78c859 Raw
258 lines · plain
1// RUN: mlir-opt -allow-unregistered-dialect %s -pass-pipeline="builtin.module(func.func(sccp))" -split-input-file | FileCheck %s2 3/// Check simple forward constant propagation without any control flow.4 5// CHECK-LABEL: func @no_control_flow6func.func @no_control_flow(%arg0: i32) -> i32 {7  // CHECK: %[[CST:.*]] = arith.constant 1 : i328  // CHECK: return %[[CST]] : i329 10  %cond = arith.constant true11  %cst_1 = arith.constant 1 : i3212  %select = arith.select %cond, %cst_1, %arg0 : i3213  return %select : i3214}15 16/// Check that a constant is properly propagated when only one edge of a branch17/// is taken.18 19// CHECK-LABEL: func @simple_control_flow20func.func @simple_control_flow(%arg0 : i32) -> i32 {21  // CHECK: %[[CST:.*]] = arith.constant 1 : i3222 23  %cond = arith.constant true24  %1 = arith.constant 1 : i3225  cf.cond_br %cond, ^bb1, ^bb2(%arg0 : i32)26 27^bb1:28  cf.br ^bb2(%1 : i32)29 30^bb2(%arg : i32):31  // CHECK: ^bb2(%{{.*}}: i32):32  // CHECK: return %[[CST]] : i3233 34  return %arg : i3235}36 37/// Check that the arguments go to overdefined if the branch cannot detect when38/// a specific successor is taken.39 40// CHECK-LABEL: func @simple_control_flow_overdefined41func.func @simple_control_flow_overdefined(%arg0 : i32, %arg1 : i1) -> i32 {42  %1 = arith.constant 1 : i3243  cf.cond_br %arg1, ^bb1, ^bb2(%arg0 : i32)44 45^bb1:46  cf.br ^bb2(%1 : i32)47 48^bb2(%arg : i32):49  // CHECK: ^bb2(%[[ARG:.*]]: i32):50  // CHECK: return %[[ARG]] : i3251 52  return %arg : i3253}54 55/// Check that the arguments go to overdefined if there are conflicting56/// constants.57 58// CHECK-LABEL: func @simple_control_flow_constant_overdefined59func.func @simple_control_flow_constant_overdefined(%arg0 : i32, %arg1 : i1) -> i32 {60  %1 = arith.constant 1 : i3261  %2 = arith.constant 2 : i3262  cf.cond_br %arg1, ^bb1, ^bb2(%arg0 : i32)63 64^bb1:65  cf.br ^bb2(%2 : i32)66 67^bb2(%arg : i32):68  // CHECK: ^bb2(%[[ARG:.*]]: i32):69  // CHECK: return %[[ARG]] : i3270 71  return %arg : i3272}73 74/// Check that the arguments go to overdefined if the branch is unknown.75 76// CHECK-LABEL: func @unknown_terminator77func.func @unknown_terminator(%arg0 : i32, %arg1 : i1) -> i32 {78  %1 = arith.constant 1 : i3279  "foo.cond_br"() [^bb1, ^bb2] : () -> ()80 81^bb1:82  cf.br ^bb2(%1 : i32)83 84^bb2(%arg : i32):85  // CHECK: ^bb2(%[[ARG:.*]]: i32):86  // CHECK: return %[[ARG]] : i3287 88  return %arg : i3289}90 91/// Check that arguments are properly merged across loop-like control flow.92 93func.func private @ext_cond_fn() -> i194 95// CHECK-LABEL: func @simple_loop96func.func @simple_loop(%arg0 : i32, %cond1 : i1) -> i32 {97  // CHECK: %[[CST:.*]] = arith.constant 1 : i3298 99  %cst_1 = arith.constant 1 : i32100  cf.cond_br %cond1, ^bb1(%cst_1 : i32), ^bb2(%cst_1 : i32)101 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)106 107  %cst_0 = arith.constant 0 : i32108  %res = arith.addi %iv, %cst_0 : i32109  %cond2 = call @ext_cond_fn() : () -> i1110  cf.cond_br %cond2, ^bb1(%res : i32), ^bb2(%res : i32)111 112^bb2(%arg : i32):113  // CHECK: ^bb2(%{{.*}}: i32):114  // CHECK: return %[[CST]] : i32115 116  return %arg : i32117}118 119/// Test that we can properly propagate within inner control, and in situations120/// where the executable edges within the CFG are sensitive to the current state121/// of the analysis.122 123// CHECK-LABEL: func @simple_loop_inner_control_flow124func.func @simple_loop_inner_control_flow(%arg0 : i32) -> i32 {125  // CHECK-DAG: %[[CST:.*]] = arith.constant 1 : i32126  // CHECK-DAG: %[[TRUE:.*]] = arith.constant true127 128  %cst_1 = arith.constant 1 : i32129  cf.br ^bb1(%cst_1 : i32)130 131^bb1(%iv: i32):132  %cond2 = call @ext_cond_fn() : () -> i1133  cf.cond_br %cond2, ^bb5(%iv : i32), ^bb2134 135^bb2:136  // CHECK: ^bb2:137  // CHECK: cf.cond_br %[[TRUE]], ^bb3, ^bb4138 139  %cst_20 = arith.constant 20 : i32140  %cond = arith.cmpi ult, %iv, %cst_20 : i32141  cf.cond_br %cond, ^bb3, ^bb4142 143^bb3:144  // CHECK: ^bb3:145  // CHECK: cf.br ^bb1(%[[CST]] : i32)146 147  %cst_1_2 = arith.constant 1 : i32148  cf.br ^bb1(%cst_1_2 : i32)149 150^bb4:151  %iv_inc = arith.addi %iv, %cst_1 : i32152  cf.br ^bb1(%iv_inc : i32)153 154^bb5(%result: i32):155  // CHECK: ^bb5(%{{.*}}: i32):156  // CHECK: return %[[CST]] : i32157 158  return %result : i32159}160 161/// Check that arguments go to overdefined when loop backedges produce a162/// conflicting value.163 164func.func private @ext_cond_and_value_fn() -> (i1, i32)165 166// CHECK-LABEL: func @simple_loop_overdefined167func.func @simple_loop_overdefined(%arg0 : i32, %cond1 : i1) -> i32 {168  %cst_1 = arith.constant 1 : i32169  cf.cond_br %cond1, ^bb1(%cst_1 : i32), ^bb2(%cst_1 : i32)170 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)174 175^bb2(%arg : i32):176  // CHECK: ^bb2(%[[ARG:.*]]: i32):177  // CHECK: return %[[ARG]] : i32178 179  return %arg : i32180}181 182// Check that we reprocess executable edges when information changes.183 184// CHECK-LABEL: func @recheck_executable_edge185func.func @recheck_executable_edge(%cond0: i1) -> (i1, i1) {186  %true = arith.constant true187  %false = arith.constant false188  cf.cond_br %cond0, ^bb_1a, ^bb2(%false : i1)189^bb_1a:190  cf.br ^bb2(%true : i1)191 192^bb2(%x: i1):193  // CHECK: ^bb2(%[[X:.*]]: i1):194  cf.br ^bb3(%x : i1)195 196^bb3(%y: i1):197  // CHECK: ^bb3(%[[Y:.*]]: i1):198  // CHECK: return %[[X]], %[[Y]]199  return %x, %y : i1, i1200}201 202// CHECK-LABEL: func @simple_produced_operand203func.func @simple_produced_operand() -> (i32, i32) {204  // CHECK: %[[ONE:.*]] = arith.constant 1205  %1 = arith.constant 1 : i32206  "test.internal_br"(%1) [^bb1, ^bb2] {207    operandSegmentSizes = array<i32: 0, 1>208  } : (i32) -> ()209 210^bb1:211  cf.br ^bb2(%1, %1 : i32, i32)212 213^bb2(%arg1 : i32, %arg2 : i32):214  // CHECK: ^bb2(%[[ARG:.*]]: i32, %{{.*}}: i32):215  // CHECK: return %[[ARG]], %[[ONE]] : i32, i32216 217  return %arg1, %arg2 : i32, i32218}219 220// CHECK-LABEL: inplace_fold221func.func @inplace_fold() -> (i32) {222  %0 = "test.op_in_place_fold_success"() : () -> i1223  %1 = arith.constant 5 : i32224  cf.cond_br %0, ^a, ^b225 226^a:227  // CHECK-NOT: addi228  %3 = arith.addi %1, %1 : i32229  return %3 : i32230 231^b:232  return %1 : i32233}234 235// CHECK-LABEL: op_with_region236func.func @op_with_region() -> (i32) {237  %0 = "test.op_with_region"() ({}) : () -> i1238  %1 = arith.constant 5 : i32239  cf.cond_br %0, ^a, ^b240 241^a:242  // CHECK-NOT: addi243  %3 = arith.addi %1, %1 : i32244  return %3 : i32245 246^b:247  return %1 : i32248}249 250// CHECK-LABEL: no_crash_with_different_source_type251func.func @no_crash_with_different_source_type() {252  // CHECK: llvm.mlir.constant(0 : index) : i64253  %0 = llvm.mlir.constant(0 : index) : i64254  // CHECK: vector.broadcast %[[CST:.*]] : i64 to vector<128xi64>255  %1 = vector.broadcast %0 : i64 to vector<128xi64>256  llvm.return257}258