1043 lines · plain
1// RUN: mlir-opt -allow-unregistered-dialect -int-range-optimizations -canonicalize %s | FileCheck %s2 3// CHECK-LABEL: func @add_min_max4// CHECK: %[[c3:.*]] = arith.constant 3 : index5// CHECK: return %[[c3]]6func.func @add_min_max(%a: index, %b: index) -> index {7 %c1 = arith.constant 1 : index8 %c2 = arith.constant 2 : index9 %0 = arith.minsi %a, %c1 : index10 %1 = arith.maxsi %0, %c1 : index11 %2 = arith.minui %b, %c2 : index12 %3 = arith.maxui %2, %c2 : index13 %4 = arith.addi %1, %3 : index14 func.return %4 : index15}16 17// CHECK-LABEL: func @add_lower_bound18// CHECK: %[[sge:.*]] = arith.cmpi sge19// CHECK: return %[[sge]]20func.func @add_lower_bound(%a : i32, %b : i32) -> i1 {21 %c1 = arith.constant 1 : i3222 %c2 = arith.constant 2 : i3223 %0 = arith.maxsi %a, %c1 : i3224 %1 = arith.maxsi %b, %c1 : i3225 %2 = arith.addi %0, %1 : i3226 %3 = arith.cmpi sge, %2, %c2 : i3227 %4 = arith.cmpi uge, %2, %c2 : i3228 %5 = arith.andi %3, %4 : i129 func.return %5 : i130}31 32// CHECK-LABEL: func @sub_signed_vs_unsigned33// CHECK-NOT: arith.cmpi sle34// CHECK: %[[unsigned:.*]] = arith.cmpi ule35// CHECK: return %[[unsigned]] : i136func.func @sub_signed_vs_unsigned(%v : i64) -> i1 {37 %c0 = arith.constant 0 : i6438 %c2 = arith.constant 2 : i6439 %c-5 = arith.constant -5 : i6440 %0 = arith.minsi %v, %c2 : i6441 %1 = arith.maxsi %0, %c-5 : i6442 %2 = arith.subi %1, %c2 : i6443 %3 = arith.cmpi sle, %2, %c0 : i6444 %4 = arith.cmpi ule, %2, %c0 : i6445 %5 = arith.andi %3, %4 : i146 func.return %5 : i147}48 49// CHECK-LABEL: func @multiply_negatives50// CHECK: %[[false:.*]] = arith.constant false51// CHECK: return %[[false]]52func.func @multiply_negatives(%a : index, %b : index) -> i1 {53 %c2 = arith.constant 2 : index54 %c3 = arith.constant 3 : index55 %c_1 = arith.constant -1 : index56 %c_2 = arith.constant -2 : index57 %c_4 = arith.constant -4 : index58 %c_12 = arith.constant -12 : index59 %0 = arith.maxsi %a, %c2 : index60 %1 = arith.minsi %0, %c3 : index61 %2 = arith.minsi %b, %c_1 : index62 %3 = arith.maxsi %2, %c_4 : index63 %4 = arith.muli %1, %3 : index64 %5 = arith.cmpi slt, %4, %c_12 : index65 %6 = arith.cmpi slt, %c_1, %4 : index66 %7 = arith.ori %5, %6 : i167 func.return %7 : i168}69 70// CHECK-LABEL: func @multiply_unsigned_bounds71// CHECK: %[[true:.*]] = arith.constant true72// CHECK: return %[[true]]73func.func @multiply_unsigned_bounds(%a : i16, %b : i16) -> i1 {74 %c0 = arith.constant 0 : i1675 %c4 = arith.constant 4 : i1676 %c_mask = arith.constant 0x3fff : i1677 %c_bound = arith.constant 0xfffc : i1678 %0 = arith.andi %a, %c_mask : i1679 %1 = arith.minui %b, %c4 : i1680 %2 = arith.muli %0, %1 : i1681 %3 = arith.cmpi uge, %2, %c0 : i1682 %4 = arith.cmpi ule, %2, %c_bound : i1683 %5 = arith.andi %3, %4 : i184 func.return %5 : i185}86 87// CHECK-LABEL: @for_loop_with_increasing_arg88// CHECK: %[[ret:.*]] = arith.cmpi ule89// CHECK: return %[[ret]]90func.func @for_loop_with_increasing_arg() -> i1 {91 %c0 = arith.constant 0 : index92 %c1 = arith.constant 1 : index93 %c4 = arith.constant 4 : index94 %c16 = arith.constant 16 : index95 %0 = scf.for %arg0 = %c0 to %c4 step %c1 iter_args(%arg1 = %c0) -> index {96 %10 = arith.addi %arg0, %arg1 : index97 scf.yield %10 : index98 }99 %1 = arith.cmpi ule, %0, %c16 : index100 func.return %1 : i1101}102 103// CHECK-LABEL: @for_loop_with_constant_result104// CHECK: %[[true:.*]] = arith.constant true105// CHECK: return %[[true]]106func.func @for_loop_with_constant_result() -> i1 {107 %c0 = arith.constant 0 : index108 %c1 = arith.constant 1 : index109 %c4 = arith.constant 4 : index110 %true = arith.constant true111 %0 = scf.for %arg0 = %c0 to %c4 step %c1 iter_args(%arg1 = %true) -> i1 {112 %10 = arith.cmpi ule, %arg0, %c4 : index113 %11 = arith.andi %10, %arg1 : i1114 scf.yield %11 : i1115 }116 func.return %0 : i1117}118 119// Test to catch a bug present in some versions of the data flow analysis120// CHECK-LABEL: func @while_false121// CHECK: %[[false:.*]] = arith.constant false122// CHECK: scf.condition(%[[false]])123func.func @while_false(%arg0 : index) -> index {124 %c0 = arith.constant 0 : index125 %c1 = arith.constant 1 : index126 %c2 = arith.constant 2 : index127 %0 = arith.divui %arg0, %c2 : index128 %1 = scf.while (%arg1 = %0) : (index) -> index {129 %2 = arith.cmpi slt, %arg1, %c0 : index130 scf.condition(%2) %arg1 : index131 } do {132 ^bb0(%arg2 : index):133 scf.yield %c2 : index134 }135 func.return %1 : index136}137 138// CHECK-LABEL: func @div_bounds_positive139// CHECK: %[[true:.*]] = arith.constant true140// CHECK: return %[[true]]141func.func @div_bounds_positive(%arg0 : index) -> i1 {142 %c0 = arith.constant 0 : index143 %c2 = arith.constant 2 : index144 %c4 = arith.constant 4 : index145 %0 = arith.maxsi %arg0, %c2 : index146 %1 = arith.divsi %c4, %0 : index147 %2 = arith.divui %c4, %0 : index148 149 %3 = arith.cmpi sge, %1, %c0 : index150 %4 = arith.cmpi sle, %1, %c2 : index151 %5 = arith.cmpi sge, %2, %c0 : index152 %6 = arith.cmpi sle, %1, %c2 : index153 154 %7 = arith.andi %3, %4 : i1155 %8 = arith.andi %7, %5 : i1156 %9 = arith.andi %8, %6 : i1157 func.return %9 : i1158}159 160// CHECK-LABEL: func @div_bounds_negative161// CHECK: %[[true:.*]] = arith.constant true162// CHECK: return %[[true]]163func.func @div_bounds_negative(%arg0 : index) -> i1 {164 %c0 = arith.constant 0 : index165 %c_2 = arith.constant -2 : index166 %c4 = arith.constant 4 : index167 %0 = arith.minsi %arg0, %c_2 : index168 %1 = arith.divsi %c4, %0 : index169 %2 = arith.divui %c4, %0 : index170 171 %3 = arith.cmpi sle, %1, %c0 : index172 %4 = arith.cmpi sge, %1, %c_2 : index173 %5 = arith.cmpi eq, %2, %c0 : index174 175 %7 = arith.andi %3, %4 : i1176 %8 = arith.andi %7, %5 : i1177 func.return %8 : i1178}179 180// CHECK-LABEL: func @div_zero_undefined181// CHECK: %[[true:.*]] = arith.constant true182// CHECK: return %[[true]]183func.func @div_zero_undefined(%arg0 : index) -> i1 {184 %c0 = arith.constant 0 : index185 %c1 = arith.constant 1 : index186 %c4 = arith.constant 4 : index187 %0 = arith.andi %arg0, %c1 : index188 %1 = arith.divui %c4, %0 : index189 %2 = arith.cmpi ule, %1, %c4 : index190 func.return %2 : i1191}192 193// CHECK-LABEL: func @div_refine_min194// CHECK: %[[true:.*]] = arith.constant true195// CHECK: return %[[true]]196func.func @div_refine_min(%arg0 : index) -> i1 {197 %c0 = arith.constant 1 : index198 %c1 = arith.constant 2 : index199 %c4 = arith.constant 4 : index200 %0 = arith.andi %arg0, %c1 : index201 %1 = arith.divui %c4, %0 : index202 %2 = arith.cmpi uge, %1, %c0 : index203 func.return %2 : i1204}205 206// CHECK-LABEL: func @ceil_divui207// CHECK: %[[ret:.*]] = arith.cmpi eq208// CHECK: return %[[ret]]209func.func @ceil_divui(%arg0 : index) -> i1 {210 %c0 = arith.constant 0 : index211 %c1 = arith.constant 1 : index212 %c3 = arith.constant 3 : index213 %c4 = arith.constant 4 : index214 215 %0 = arith.minui %arg0, %c3 : index216 %1 = arith.maxui %0, %c1 : index217 %2 = arith.ceildivui %1, %c4 : index218 %3 = arith.cmpi eq, %2, %c1 : index219 220 %4 = arith.maxui %0, %c0 : index221 %5 = arith.ceildivui %4, %c4 : index222 %6 = arith.cmpi eq, %5, %c1 : index223 %7 = arith.andi %3, %6 : i1224 func.return %7 : i1225}226 227// CHECK-LABEL: func @ceil_divui_by_zero_issue_131273228// CHECK-NEXT: return229func.func @ceil_divui_by_zero_issue_131273() {230 %0 = test.with_bounds {smax = 0 : i32, smin = -1 : i32, umax = 0 : i32, umin = -1 : i32} : i32231 %c7_i32 = arith.constant 7 : i32232 %1 = arith.ceildivui %c7_i32, %0 : i32233 return234}235 236// CHECK-LABEL: func @ceil_divsi237// CHECK: %[[ret:.*]] = arith.cmpi eq238// CHECK: return %[[ret]]239func.func @ceil_divsi(%arg0 : index) -> i1 {240 %c0 = arith.constant 0 : index241 %c1 = arith.constant 1 : index242 %c3 = arith.constant 3 : index243 %c4 = arith.constant 4 : index244 %c-4 = arith.constant -4 : index245 246 %0 = arith.minsi %arg0, %c3 : index247 %1 = arith.maxsi %0, %c1 : index248 %2 = arith.ceildivsi %1, %c4 : index249 %3 = arith.cmpi eq, %2, %c1 : index250 %4 = arith.ceildivsi %1, %c-4 : index251 %5 = arith.cmpi eq, %4, %c0 : index252 %6 = arith.andi %3, %5 : i1253 254 %7 = arith.maxsi %0, %c0 : index255 %8 = arith.ceildivsi %7, %c4 : index256 %9 = arith.cmpi eq, %8, %c1 : index257 %10 = arith.andi %6, %9 : i1258 func.return %10 : i1259}260 261// There was a bug, which was causing this expr errorneously fold to constant262// CHECK-LABEL: func @ceil_divsi_full_range263// CHECK-SAME: (%[[arg:.*]]: index)264// CHECK: %[[c64:.*]] = arith.constant 64 : index265// CHECK: %[[ret:.*]] = arith.ceildivsi %[[arg]], %[[c64]] : index266// CHECK: return %[[ret]]267func.func @ceil_divsi_full_range(%6: index) -> index {268 %c64 = arith.constant 64 : index269 %55 = arith.ceildivsi %6, %c64 : index270 return %55 : index271}272 273// CHECK-LABEL: func @ceil_divsi_intmin_bug_115293274// CHECK: %[[ret:.*]] = arith.constant true275// CHECK: return %[[ret]]276func.func @ceil_divsi_intmin_bug_115293() -> i1 {277 %intMin_i64 = test.with_bounds { smin = -9223372036854775808 : si64, smax = -9223372036854775808 : si64, umin = 9223372036854775808 : ui64, umax = 9223372036854775808 : ui64 } : i64278 %denom_i64 = test.with_bounds { smin = 1189465982 : si64, smax = 1189465982 : si64, umin = 1189465982 : ui64, umax = 1189465982 : ui64 } : i64279 %res_i64 = test.with_bounds { smin = 7754212542 : si64, smax = 7754212542 : si64, umin = 7754212542 : ui64, umax = 7754212542 : ui64 } : i64280 281 %0 = arith.ceildivsi %intMin_i64, %denom_i64 : i64282 %1 = arith.cmpi eq, %0, %res_i64 : i64283 func.return %1 : i1284}285 286// CHECK-LABEL: func @floor_divsi287// CHECK: %[[true:.*]] = arith.constant true288// CHECK: return %[[true]]289func.func @floor_divsi(%arg0 : index) -> i1 {290 %c4 = arith.constant 4 : index291 %c-1 = arith.constant -1 : index292 %c-3 = arith.constant -3 : index293 %c-4 = arith.constant -4 : index294 295 %0 = arith.minsi %arg0, %c-1 : index296 %1 = arith.maxsi %0, %c-4 : index297 %2 = arith.floordivsi %1, %c4 : index298 %3 = arith.cmpi eq, %2, %c-1 : index299 func.return %3 : i1300}301 302// CHECK-LABEL: func @remui_base303// CHECK: %[[true:.*]] = arith.constant true304// CHECK: return %[[true]]305func.func @remui_base(%arg0 : index, %arg1 : index ) -> i1 {306 %c2 = arith.constant 2 : index307 %c4 = arith.constant 4 : index308 309 %0 = arith.minui %arg1, %c4 : index310 %1 = arith.maxui %0, %c2 : index311 %2 = arith.remui %arg0, %1 : index312 %3 = arith.cmpi ult, %2, %c4 : index313 func.return %3 : i1314}315 316// CHECK-LABEL: func @remui_base_maybe_zero317// CHECK: %[[true:.*]] = arith.constant true318// CHECK: return %[[true]]319func.func @remui_base_maybe_zero(%arg0 : index, %arg1 : index ) -> i1 {320 %c4 = arith.constant 4 : index321 %c5 = arith.constant 5 : index322 323 %0 = arith.minui %arg1, %c4 : index324 %1 = arith.remui %arg0, %0 : index325 %2 = arith.cmpi ult, %1, %c5 : index326 func.return %2 : i1327}328 329// CHECK-LABEL: func @remsi_base330// CHECK: %[[ret:.*]] = arith.cmpi sge331// CHECK: return %[[ret]]332func.func @remsi_base(%arg0 : index, %arg1 : index ) -> i1 {333 %c0 = arith.constant 0 : index334 %c2 = arith.constant 2 : index335 %c4 = arith.constant 4 : index336 %c-4 = arith.constant -4 : index337 %true = arith.constant true338 339 %0 = arith.minsi %arg1, %c4 : index340 %1 = arith.maxsi %0, %c2 : index341 %2 = arith.remsi %arg0, %1 : index342 %3 = arith.cmpi sgt, %2, %c-4 : index343 %4 = arith.cmpi slt, %2, %c4 : index344 %5 = arith.cmpi sge, %2, %c0 : index345 %6 = arith.andi %3, %4 : i1346 %7 = arith.andi %5, %6 : i1347 func.return %7 : i1348}349 350// CHECK-LABEL: func @remsi_positive351// CHECK: %[[true:.*]] = arith.constant true352// CHECK: return %[[true]]353func.func @remsi_positive(%arg0 : index, %arg1 : index ) -> i1 {354 %c0 = arith.constant 0 : index355 %c2 = arith.constant 2 : index356 %c4 = arith.constant 4 : index357 %true = arith.constant true358 359 %0 = arith.minsi %arg1, %c4 : index360 %1 = arith.maxsi %0, %c2 : index361 %2 = arith.maxsi %arg0, %c0 : index362 %3 = arith.remsi %2, %1 : index363 %4 = arith.cmpi sge, %3, %c0 : index364 %5 = arith.cmpi slt, %3, %c4 : index365 %6 = arith.andi %4, %5 : i1366 func.return %6 : i1367}368 369// CHECK-LABEL: func @remui_restricted370// CHECK: %[[true:.*]] = arith.constant true371// CHECK: return %[[true]]372func.func @remui_restricted(%arg0 : index) -> i1 {373 %c2 = arith.constant 2 : index374 %c3 = arith.constant 3 : index375 %c4 = arith.constant 4 : index376 377 %0 = arith.minui %arg0, %c3 : index378 %1 = arith.maxui %0, %c2 : index379 %2 = arith.remui %1, %c4 : index380 %3 = arith.cmpi ule, %2, %c3 : index381 %4 = arith.cmpi uge, %2, %c2 : index382 %5 = arith.andi %3, %4 : i1383 func.return %5 : i1384}385 386// CHECK-LABEL: func @remsi_restricted387// CHECK: %[[true:.*]] = arith.constant true388// CHECK: return %[[true]]389func.func @remsi_restricted(%arg0 : index) -> i1 {390 %c2 = arith.constant 2 : index391 %c3 = arith.constant 3 : index392 %c-4 = arith.constant -4 : index393 394 %0 = arith.minsi %arg0, %c3 : index395 %1 = arith.maxsi %0, %c2 : index396 %2 = arith.remsi %1, %c-4 : index397 %3 = arith.cmpi ule, %2, %c3 : index398 %4 = arith.cmpi uge, %2, %c2 : index399 %5 = arith.andi %3, %4 : i1400 func.return %5 : i1401}402 403// CHECK-LABEL: func @remui_restricted_fails404// CHECK: %[[ret:.*]] = arith.cmpi ne405// CHECK: return %[[ret]]406func.func @remui_restricted_fails(%arg0 : index) -> i1 {407 %c2 = arith.constant 2 : index408 %c3 = arith.constant 3 : index409 %c4 = arith.constant 4 : index410 %c5 = arith.constant 5 : index411 412 %0 = arith.minui %arg0, %c5 : index413 %1 = arith.maxui %0, %c3 : index414 %2 = arith.remui %1, %c4 : index415 %3 = arith.cmpi ne, %2, %c2 : index416 func.return %3 : i1417}418 419// CHECK-LABEL: func @remsi_restricted_fails420// CHECK: %[[ret:.*]] = arith.cmpi ne421// CHECK: return %[[ret]]422func.func @remsi_restricted_fails(%arg0 : index) -> i1 {423 %c2 = arith.constant 2 : index424 %c3 = arith.constant 3 : index425 %c5 = arith.constant 5 : index426 %c-4 = arith.constant -4 : index427 428 %0 = arith.minsi %arg0, %c5 : index429 %1 = arith.maxsi %0, %c3 : index430 %2 = arith.remsi %1, %c-4 : index431 %3 = arith.cmpi ne, %2, %c2 : index432 func.return %3 : i1433}434 435// CHECK-LABEL: func @andi436// CHECK: %[[ret:.*]] = arith.cmpi ugt437// CHECK: return %[[ret]]438func.func @andi(%arg0 : index) -> i1 {439 %c2 = arith.constant 2 : index440 %c5 = arith.constant 5 : index441 %c7 = arith.constant 7 : index442 443 %0 = arith.minsi %arg0, %c5 : index444 %1 = arith.maxsi %0, %c2 : index445 %2 = arith.andi %1, %c7 : index446 %3 = arith.cmpi ugt, %2, %c5 : index447 %4 = arith.cmpi ule, %2, %c7 : index448 %5 = arith.andi %3, %4 : i1449 func.return %5 : i1450}451 452// CHECK-LABEL: func @andi_doesnt_make_nonnegative453// CHECK: %[[ret:.*]] = arith.cmpi sge454// CHECK: return %[[ret]]455func.func @andi_doesnt_make_nonnegative(%arg0 : index) -> i1 {456 %c0 = arith.constant 0 : index457 %c1 = arith.constant 1 : index458 %0 = arith.addi %arg0, %c1 : index459 %1 = arith.andi %arg0, %0 : index460 %2 = arith.cmpi sge, %1, %c0 : index461 func.return %2 : i1462}463 464 465// CHECK-LABEL: func @ori466// CHECK: %[[true:.*]] = arith.constant true467// CHECK: return %[[true]]468func.func @ori(%arg0 : i128, %arg1 : i128) -> i1 {469 %c-1 = arith.constant -1 : i128470 %c0 = arith.constant 0 : i128471 472 %0 = arith.minsi %arg1, %c-1 : i128473 %1 = arith.ori %arg0, %0 : i128474 %2 = arith.cmpi slt, %1, %c0 : i128475 func.return %2 : i1476}477 478// CHECK-LABEL: func @xori_issue_82168479// arith.cmpi was erroneously folded to %false, see Issue #82168.480// CHECK: %[[R:.*]] = arith.cmpi eq, %{{.*}}, %{{.*}} : i64481// CHECK: return %[[R]]482func.func @xori_issue_82168() -> i1 {483 %c0_i64 = arith.constant 0 : i64484 %c2060639849_i64 = arith.constant 2060639849 : i64485 %2 = test.with_bounds { umin = 2060639849 : i64, umax = 2060639850 : i64, smin = 2060639849 : i64, smax = 2060639850 : i64 } : i64486 %3 = arith.xori %2, %c2060639849_i64 : i64487 %4 = arith.cmpi eq, %3, %c0_i64 : i64488 func.return %4 : i1489}490 491// CHECK-LABEL: func @xori_i1492// CHECK-DAG: %[[true:.*]] = arith.constant true493// CHECK-DAG: %[[false:.*]] = arith.constant false494// CHECK: return %[[true]], %[[false]]495func.func @xori_i1() -> (i1, i1) {496 %true = arith.constant true497 %1 = test.with_bounds { umin = 0 : i1, umax = 0 : i1, smin = 0 : i1, smax = 0 : i1 } : i1498 %2 = test.with_bounds { umin = 1 : i1, umax = 1 : i1, smin = 1 : i1, smax = 1 : i1 } : i1499 %3 = arith.xori %1, %true : i1500 %4 = arith.xori %2, %true : i1501 func.return %3, %4 : i1, i1502}503 504// CHECK-LABEL: func @xori505// CHECK: %[[false:.*]] = arith.constant false506// CHECK: return %[[false]]507func.func @xori(%arg0 : i64, %arg1 : i64) -> i1 {508 %c0 = arith.constant 0 : i64509 %c7 = arith.constant 7 : i64510 %c15 = arith.constant 15 : i64511 %true = arith.constant true512 513 %0 = arith.minui %arg0, %c7 : i64514 %1 = arith.minui %arg1, %c15 : i64515 %2 = arith.xori %0, %1 : i64516 %3 = arith.cmpi sle, %2, %c15 : i64517 %4 = arith.xori %3, %true : i1518 func.return %4 : i1519}520 521// CHECK-LABEL: func @extui522// CHECK: %[[true:.*]] = arith.constant true523// CHECK: return %[[true]]524func.func @extui(%arg0 : i16) -> i1 {525 %ci16_max = arith.constant 0xffff : i32526 %0 = arith.extui %arg0 : i16 to i32527 %1 = arith.cmpi ule, %0, %ci16_max : i32528 func.return %1 : i1529}530 531// CHECK-LABEL: func @extsi532// CHECK: %[[true:.*]] = arith.constant true533// CHECK: return %[[true]]534func.func @extsi(%arg0 : i16) -> i1 {535 %ci16_smax = arith.constant 0x7fff : i32536 %ci16_smin = arith.constant 0xffff8000 : i32537 %0 = arith.extsi %arg0 : i16 to i32538 %1 = arith.cmpi sle, %0, %ci16_smax : i32539 %2 = arith.cmpi sge, %0, %ci16_smin : i32540 %3 = arith.andi %1, %2 : i1541 func.return %3 : i1542}543 544// CHECK-LABEL: func @trunci545// CHECK: %[[true:.*]] = arith.constant true546// CHECK: return %[[true]]547func.func @trunci(%arg0 : i32) -> i1 {548 %c-14_i32 = arith.constant -14 : i32549 %c-14_i16 = arith.constant -14 : i16550 %ci16_smin = arith.constant 0xffff8000 : i32551 %0 = arith.minsi %arg0, %c-14_i32 : i32552 %1 = arith.maxsi %0, %ci16_smin : i32553 %2 = arith.trunci %1 : i32 to i16554 %3 = arith.cmpi sle, %2, %c-14_i16 : i16555 %4 = arith.extsi %2 : i16 to i32556 %5 = arith.cmpi sle, %4, %c-14_i32 : i32557 %6 = arith.cmpi sge, %4, %ci16_smin : i32558 %7 = arith.andi %3, %5 : i1559 %8 = arith.andi %7, %6 : i1560 func.return %8 : i1561}562 563// CHECK-LABEL: func @index_cast564// CHECK: %[[true:.*]] = arith.constant true565// CHECK: return %[[true]]566func.func @index_cast(%arg0 : index) -> i1 {567 %ci32_smin = arith.constant 0xffffffff80000000 : i64568 %0 = arith.index_cast %arg0 : index to i32569 %1 = arith.index_cast %0 : i32 to index570 %2 = arith.index_cast %ci32_smin : i64 to index571 %3 = arith.cmpi sge, %1, %2 : index572 func.return %3 : i1573}574 575// CHECK-LABEL: func @shli576// CHECK: %[[ret:.*]] = arith.cmpi sgt577// CHECK: return %[[ret]]578func.func @shli(%arg0 : i32, %arg1 : i1) -> i1 {579 %c2 = arith.constant 2 : i32580 %c4 = arith.constant 4 : i32581 %c8 = arith.constant 8 : i32582 %c32 = arith.constant 32 : i32583 %c-1 = arith.constant -1 : i32584 %c-16 = arith.constant -16 : i32585 %0 = arith.maxsi %arg0, %c-1 : i32586 %1 = arith.minsi %0, %c2 : i32587 %2 = arith.select %arg1, %c2, %c4 : i32588 %3 = arith.shli %1, %2 : i32589 %4 = arith.cmpi sge, %3, %c-16 : i32590 %5 = arith.cmpi sle, %3, %c32 : i32591 %6 = arith.cmpi sgt, %3, %c8 : i32592 %7 = arith.andi %4, %5 : i1593 %8 = arith.andi %7, %6 : i1594 func.return %8 : i1595}596 597// CHECK-LABEL: func @shrui598// CHECK: %[[ret:.*]] = arith.cmpi uge599// CHECK: return %[[ret]]600func.func @shrui(%arg0 : i1) -> i1 {601 %c2 = arith.constant 2 : i32602 %c4 = arith.constant 4 : i32603 %c8 = arith.constant 8 : i32604 %c32 = arith.constant 32 : i32605 %0 = arith.select %arg0, %c2, %c4 : i32606 %1 = arith.shrui %c32, %0 : i32607 %2 = arith.cmpi ule, %1, %c8 : i32608 %3 = arith.cmpi uge, %1, %c2 : i32609 %4 = arith.cmpi uge, %1, %c8 : i32610 %5 = arith.andi %2, %3 : i1611 %6 = arith.andi %5, %4 : i1612 func.return %6 : i1613}614 615// CHECK-LABEL: func @shrsi616// CHECK: %[[ret:.*]] = arith.cmpi slt617// CHECK: return %[[ret]]618func.func @shrsi(%arg0 : i32, %arg1 : i1) -> i1 {619 %c2 = arith.constant 2 : i32620 %c4 = arith.constant 4 : i32621 %c8 = arith.constant 8 : i32622 %c32 = arith.constant 32 : i32623 %c-8 = arith.constant -8 : i32624 %c-32 = arith.constant -32 : i32625 %0 = arith.maxsi %arg0, %c-32 : i32626 %1 = arith.minsi %0, %c32 : i32627 %2 = arith.select %arg1, %c2, %c4 : i32628 %3 = arith.shrsi %1, %2 : i32629 %4 = arith.cmpi sge, %3, %c-8 : i32630 %5 = arith.cmpi sle, %3, %c8 : i32631 %6 = arith.cmpi slt, %3, %c2 : i32632 %7 = arith.andi %4, %5 : i1633 %8 = arith.andi %7, %6 : i1634 func.return %8 : i1635}636 637// CHECK-LABEL: func @no_aggressive_eq638// CHECK: %[[ret:.*]] = arith.cmpi eq639// CHECK: return %[[ret]]640func.func @no_aggressive_eq(%arg0 : index) -> i1 {641 %c1 = arith.constant 1 : index642 %0 = arith.andi %arg0, %c1 : index643 %1 = arith.minui %arg0, %c1 : index644 %2 = arith.cmpi eq, %0, %1 : index645 func.return %2 : i1646}647 648// CHECK-LABEL: func @select_union649// CHECK: %[[ret:.*]] = arith.cmpi ne650// CHECK: return %[[ret]]651 652func.func @select_union(%arg0 : index, %arg1 : i1) -> i1 {653 %c64 = arith.constant 64 : index654 %c100 = arith.constant 100 : index655 %c128 = arith.constant 128 : index656 %c192 = arith.constant 192 : index657 %0 = arith.remui %arg0, %c64 : index658 %1 = arith.addi %0, %c128 : index659 %2 = arith.select %arg1, %0, %1 : index660 %3 = arith.cmpi slt, %2, %c192 : index661 %4 = arith.cmpi ne, %c100, %2 : index662 %5 = arith.andi %3, %4 : i1663 func.return %5 : i1664}665 666// CHECK-LABEL: func @if_union667// CHECK: %[[true:.*]] = arith.constant true668// CHECK: return %[[true]]669func.func @if_union(%arg0 : index, %arg1 : i1) -> i1 {670 %c4 = arith.constant 4 : index671 %c16 = arith.constant 16 : index672 %c-1 = arith.constant -1 : index673 %c-4 = arith.constant -4 : index674 %0 = arith.minui %arg0, %c4 : index675 %1 = scf.if %arg1 -> index {676 %10 = arith.muli %0, %0 : index677 scf.yield %10 : index678 } else {679 %20 = arith.muli %0, %c-1 : index680 scf.yield %20 : index681 }682 %2 = arith.cmpi sle, %1, %c16 : index683 %3 = arith.cmpi sge, %1, %c-4 : index684 %4 = arith.andi %2, %3 : i1685 func.return %4 : i1686}687 688// CHECK-LABEL: func @branch_union689// CHECK: %[[true:.*]] = arith.constant true690// CHECK: return %[[true]]691func.func @branch_union(%arg0 : index, %arg1 : i1) -> i1 {692 %c4 = arith.constant 4 : index693 %c16 = arith.constant 16 : index694 %c-1 = arith.constant -1 : index695 %c-4 = arith.constant -4 : index696 %0 = arith.minui %arg0, %c4 : index697 cf.cond_br %arg1, ^bb1, ^bb2698^bb1 :699 %1 = arith.muli %0, %0 : index700 cf.br ^bb3(%1 : index)701^bb2 :702 %2 = arith.muli %0, %c-1 : index703 cf.br ^bb3(%2 : index)704^bb3(%3 : index) :705 %4 = arith.cmpi sle, %3, %c16 : index706 %5 = arith.cmpi sge, %3, %c-4 : index707 %6 = arith.andi %4, %5 : i1708 func.return %6 : i1709}710 711// CHECK-LABEL: func @loop_bound_not_inferred_with_branch712// CHECK-DAG: %[[min:.*]] = arith.cmpi sge713// CHECK-DAG: %[[max:.*]] = arith.cmpi slt714// CHECK-DAG: %[[ret:.*]] = arith.andi %[[min]], %[[max]]715// CHECK: return %[[ret]]716func.func @loop_bound_not_inferred_with_branch(%arg0 : index, %arg1 : i1) -> i1 {717 %c0 = arith.constant 0 : index718 %c1 = arith.constant 1 : index719 %c4 = arith.constant 4 : index720 %0 = arith.minui %arg0, %c4 : index721 cf.br ^bb2(%c0 : index)722^bb1(%1 : index) :723 %2 = arith.addi %1, %c1 : index724 cf.br ^bb2(%2 : index)725^bb2(%3 : index):726 %4 = arith.cmpi ult, %3, %c4 : index727 cf.cond_br %4, ^bb1(%3 : index), ^bb3(%3 : index)728^bb3(%5 : index) :729 %6 = arith.cmpi sge, %5, %c0 : index730 %7 = arith.cmpi slt, %5, %c4 : index731 %8 = arith.andi %6, %7 : i1732 func.return %8 : i1733}734 735// Test fon a bug where the noive implementation of trunctation led to the cast736// value being set to [0, 0].737// CHECK-LABEL: func.func @truncation_spillover738// CHECK: %[[unreplaced:.*]] = arith.index_cast739// CHECK: memref.store %[[unreplaced]]740func.func @truncation_spillover(%arg0 : memref<?xi32>) -> index {741 %c0 = arith.constant 0 : index742 %c1 = arith.constant 1 : index743 %c2 = arith.constant 2 : index744 %c49 = arith.constant 49 : index745 %0 = scf.for %arg1 = %c0 to %c2 step %c1 iter_args(%arg2 = %c0) -> index {746 %1 = arith.divsi %arg2, %c49 : index747 %2 = arith.index_cast %1 : index to i32748 memref.store %2, %arg0[%c0] : memref<?xi32>749 %3 = arith.addi %arg2, %arg1 : index750 scf.yield %3 : index751 }752 func.return %0 : index753}754 755// CHECK-LABEL: func.func @trunc_catches_overflow756// CHECK: %[[sge:.*]] = arith.cmpi sge757// CHECK: return %[[sge]]758func.func @trunc_catches_overflow(%arg0 : i16) -> i1 {759 %c0_i16 = arith.constant 0 : i16760 %c130_i16 = arith.constant 130 : i16761 %c0_i8 = arith.constant 0 : i8762 %0 = arith.maxui %arg0, %c0_i16 : i16763 %1 = arith.minui %0, %c130_i16 : i16764 %2 = arith.trunci %1 : i16 to i8765 %3 = arith.cmpi sge, %2, %c0_i8 : i8766 %4 = arith.cmpi uge, %2, %c0_i8 : i8767 %5 = arith.andi %3, %4 : i1768 func.return %5 : i1769}770 771// CHECK-LABEL: func.func @trunc_respects_same_high_half772// CHECK: %[[false:.*]] = arith.constant false773// CHECK: return %[[false]]774func.func @trunc_respects_same_high_half(%arg0 : i16) -> i1 {775 %c256_i16 = arith.constant 256 : i16776 %c257_i16 = arith.constant 257 : i16777 %c2_i8 = arith.constant 2 : i8778 %0 = arith.maxui %arg0, %c256_i16 : i16779 %1 = arith.minui %0, %c257_i16 : i16780 %2 = arith.trunci %1 : i16 to i8781 %3 = arith.cmpi sge, %2, %c2_i8 : i8782 func.return %3 : i1783}784 785// CHECK-LABEL: func.func @trunc_handles_small_signed_ranges786// CHECK: %[[true:.*]] = arith.constant true787// CHECK: return %[[true]]788func.func @trunc_handles_small_signed_ranges(%arg0 : i16) -> i1 {789 %c-2_i16 = arith.constant -2 : i16790 %c2_i16 = arith.constant 2 : i16791 %c-2_i8 = arith.constant -2 : i8792 %c2_i8 = arith.constant 2 : i8793 %0 = arith.maxsi %arg0, %c-2_i16 : i16794 %1 = arith.minsi %0, %c2_i16 : i16795 %2 = arith.trunci %1 : i16 to i8796 %3 = arith.cmpi sge, %2, %c-2_i8 : i8797 %4 = arith.cmpi sle, %2, %c2_i8 : i8798 %5 = arith.andi %3, %4 : i1799 func.return %5 : i1800}801 802/// Catch a bug that crept in during an earlier refactoring that made unsigned803/// extension use the signed ranges804 805// CHECK-LABEL: func.func @extui_uses_unsigned806// CHECK: %[[true:.*]] = arith.constant true807// CHECK: return %[[true]]808func.func @extui_uses_unsigned(%arg0 : i32) -> i1 {809 %ci32_smin = arith.constant 0x80000000 : i32810 %ci32_smin_64 = arith.constant 0x80000000 : i64811 %c0_i64 = arith.constant 0 : i64812 %0 = arith.minui %arg0, %ci32_smin : i32813 %1 = arith.extui %0 : i32 to i64814 %2 = arith.cmpi sge, %1, %c0_i64 : i64815 %3 = arith.cmpi ule, %1, %ci32_smin_64 : i64816 %4 = arith.andi %2, %3 : i1817 func.return %4 : i1818}819 820/// Catch a bug that caused a crash in getLoopBoundFromFold when821/// SparseConstantPropagation is loaded in the solver.822 823// CHECK-LABEL: func.func @caller(824// CHECK-SAME: %[[VAL_0:.*]]: memref<?xindex, 4>) {825// CHECK: call @callee(%[[VAL_0]]) : (memref<?xindex, 4>) -> ()826// CHECK: return827// CHECK: }828func.func @caller(%arg0: memref<?xindex, 4>) {829 call @callee(%arg0) : (memref<?xindex, 4>) -> ()830 return831}832 833// CHECK-LABEL: func.func private @callee(834// CHECK-SAME: %[[VAL_0:.*]]: memref<?xindex, 4>) {835// CHECK: return836// CHECK: }837func.func private @callee(%arg0: memref<?xindex, 4>) {838 %c1 = arith.constant 1 : index839 %c0 = arith.constant 0 : index840 %0 = affine.load %arg0[0] : memref<?xindex, 4>841 scf.for %arg1 = %c0 to %0 step %c1 {842 }843 return844}845 846// CHECK-LABEL: func @test_i8_bounds847// CHECK: test.reflect_bounds {smax = 127 : si8, smin = -128 : si8, umax = 255 : ui8, umin = 0 : ui8}848func.func @test_i8_bounds() -> i8 {849 %cst1 = arith.constant 1 : i8850 %0 = test.with_bounds { umin = 0 : i8, umax = 255 : i8, smin = -128 : i8, smax = 127 : i8 } : i8851 %1 = arith.addi %0, %cst1 : i8852 %2 = test.reflect_bounds %1 : i8853 return %2: i8854}855 856// CHECK-LABEL: func @test_add_1857// CHECK: test.reflect_bounds {smax = 127 : si8, smin = -128 : si8, umax = 255 : ui8, umin = 0 : ui8}858func.func @test_add_1() -> i8 {859 %cst1 = arith.constant 1 : i8860 %0 = test.with_bounds { umin = 0 : i8, umax = 255 : i8, smin = -128 : i8, smax = 127 : i8 } : i8861 %1 = arith.addi %0, %cst1 : i8862 %2 = test.reflect_bounds %1 : i8863 return %2: i8864}865 866// Tests below check inference with overflow flags.867 868// CHECK-LABEL: func @test_add_i8_wrap1869// CHECK: test.reflect_bounds {smax = 127 : si8, smin = -128 : si8, umax = 128 : ui8, umin = 1 : ui8}870func.func @test_add_i8_wrap1() -> i8 {871 %cst1 = arith.constant 1 : i8872 %0 = test.with_bounds { umin = 0 : i8, umax = 127 : i8, smin = 0 : i8, smax = 127 : i8 } : i8873 // smax overflow874 %1 = arith.addi %0, %cst1 : i8875 %2 = test.reflect_bounds %1 : i8876 return %2: i8877}878 879// CHECK-LABEL: func @test_add_i8_wrap2880// CHECK: test.reflect_bounds {smax = 127 : si8, smin = -128 : si8, umax = 128 : ui8, umin = 1 : ui8}881func.func @test_add_i8_wrap2() -> i8 {882 %cst1 = arith.constant 1 : i8883 %0 = test.with_bounds { umin = 0 : i8, umax = 127 : i8, smin = 0 : i8, smax = 127 : i8 } : i8884 // smax overflow885 %1 = arith.addi %0, %cst1 overflow<nuw> : i8886 %2 = test.reflect_bounds %1 : i8887 return %2: i8888}889 890// CHECK-LABEL: func @test_add_i8_nowrap891// CHECK: test.reflect_bounds {smax = 127 : si8, smin = 1 : si8, umax = 127 : ui8, umin = 1 : ui8}892func.func @test_add_i8_nowrap() -> i8 {893 %cst1 = arith.constant 1 : i8894 %0 = test.with_bounds { umin = 0 : i8, umax = 127 : i8, smin = 0 : i8, smax = 127 : i8 } : i8895 // nsw flag stops smax from overflowing896 %1 = arith.addi %0, %cst1 overflow<nsw> : i8897 %2 = test.reflect_bounds %1 : i8898 return %2: i8899}900 901// CHECK-LABEL: func @test_sub_i8_wrap1902// CHECK: test.reflect_bounds {smax = 5 : si8, smin = -10 : si8, umax = 255 : ui8, umin = 0 : ui8} %1 : i8903func.func @test_sub_i8_wrap1() -> i8 {904 %cst10 = arith.constant 10 : i8905 %0 = test.with_bounds { umin = 0 : i8, umax = 15 : i8, smin = 0 : i8, smax = 15 : i8 } : i8906 // umin underflows907 %1 = arith.subi %0, %cst10 : i8908 %2 = test.reflect_bounds %1 : i8909 return %2: i8910}911 912// CHECK-LABEL: func @test_sub_i8_wrap2913// CHECK: test.reflect_bounds {smax = 5 : si8, smin = -10 : si8, umax = 255 : ui8, umin = 0 : ui8} %1 : i8914func.func @test_sub_i8_wrap2() -> i8 {915 %cst10 = arith.constant 10 : i8916 %0 = test.with_bounds { umin = 0 : i8, umax = 15 : i8, smin = 0 : i8, smax = 15 : i8 } : i8917 // umin underflows918 %1 = arith.subi %0, %cst10 overflow<nsw> : i8919 %2 = test.reflect_bounds %1 : i8920 return %2: i8921}922 923// CHECK-LABEL: func @test_sub_i8_nowrap924// CHECK: test.reflect_bounds {smax = 5 : si8, smin = 0 : si8, umax = 5 : ui8, umin = 0 : ui8}925func.func @test_sub_i8_nowrap() -> i8 {926 %cst10 = arith.constant 10 : i8927 %0 = test.with_bounds { umin = 0 : i8, umax = 15 : i8, smin = 0 : i8, smax = 15 : i8 } : i8928 // nuw flag stops umin from underflowing929 %1 = arith.subi %0, %cst10 overflow<nuw> : i8930 %2 = test.reflect_bounds %1 : i8931 return %2: i8932}933 934// CHECK-LABEL: func @test_mul_i8_wrap935// CHECK: test.reflect_bounds {smax = 127 : si8, smin = -128 : si8, umax = 200 : ui8, umin = 100 : ui8}936func.func @test_mul_i8_wrap() -> i8 {937 %cst10 = arith.constant 10 : i8938 %0 = test.with_bounds { umin = 10 : i8, umax = 20 : i8, smin = 10 : i8, smax = 20 : i8 } : i8939 // smax overflows940 %1 = arith.muli %0, %cst10 : i8941 %2 = test.reflect_bounds %1 : i8942 return %2: i8943}944 945// CHECK-LABEL: func @test_mul_i8_nowrap946// CHECK: test.reflect_bounds {smax = 127 : si8, smin = 100 : si8, umax = 127 : ui8, umin = 100 : ui8}947func.func @test_mul_i8_nowrap() -> i8 {948 %cst10 = arith.constant 10 : i8949 %0 = test.with_bounds { umin = 10 : i8, umax = 20 : i8, smin = 10 : i8, smax = 20 : i8 } : i8950 // nsw stops overflow951 %1 = arith.muli %0, %cst10 overflow<nsw> : i8952 %2 = test.reflect_bounds %1 : i8953 return %2: i8954}955 956// CHECK-LABEL: func @test_shl_i8_wrap1957// CHECK: test.reflect_bounds {smax = 127 : si8, smin = -128 : si8, umax = 160 : ui8, umin = 80 : ui8}958func.func @test_shl_i8_wrap1() -> i8 {959 %cst3 = arith.constant 3 : i8960 %0 = test.with_bounds { umin = 10 : i8, umax = 20 : i8, smin = 10 : i8, smax = 20 : i8 } : i8961 // smax overflows962 %1 = arith.shli %0, %cst3 : i8963 %2 = test.reflect_bounds %1 : i8964 return %2: i8965}966 967// CHECK-LABEL: func @test_shl_i8_wrap2968// CHECK: test.reflect_bounds {smax = 127 : si8, smin = -128 : si8, umax = 160 : ui8, umin = 80 : ui8}969func.func @test_shl_i8_wrap2() -> i8 {970 %cst3 = arith.constant 3 : i8971 %0 = test.with_bounds { umin = 10 : i8, umax = 20 : i8, smin = 10 : i8, smax = 20 : i8 } : i8972 // smax overflows973 %1 = arith.shli %0, %cst3 overflow<nuw> : i8974 %2 = test.reflect_bounds %1 : i8975 return %2: i8976}977 978// CHECK-LABEL: func @test_shl_i8_nowrap979// CHECK: test.reflect_bounds {smax = 127 : si8, smin = 80 : si8, umax = 127 : ui8, umin = 80 : ui8}980func.func @test_shl_i8_nowrap() -> i8 {981 %cst3 = arith.constant 3 : i8982 %0 = test.with_bounds { umin = 10 : i8, umax = 20 : ui8, smin = 10 : i8, smax = 20 : i8 } : i8983 // nsw stops smax overflow984 %1 = arith.shli %0, %cst3 overflow<nsw> : i8985 %2 = test.reflect_bounds %1 : i8986 return %2: i8987}988 989/// A test case to ensure that the ranges for unsupported ops are initialized990/// properly to maxRange, rather than left uninitialized.991/// In this test case, the previous behavior would leave the ranges for %a and992/// %b uninitialized, resulting in arith.cmpf's range not being updated, even993/// though it has an integer valued result.994 995// CHECK-LABEL: func @test_cmpf_propagates996// CHECK: test.reflect_bounds {smax = 2 : index, smin = 1 : index, umax = 2 : index, umin = 1 : index}997func.func @test_cmpf_propagates(%a: f32, %b: f32) -> index {998 %c1 = arith.constant 1 : index999 %c2 = arith.constant 2 : index1000 1001 %0 = arith.cmpf ueq, %a, %b : f321002 %1 = arith.select %0, %c1, %c2 : index1003 %2 = test.reflect_bounds %1 : index1004 func.return %2 : index1005}1006 1007// CHECK-LABEL: func @zero_trip_loop1008func.func @zero_trip_loop() {1009 %idx1 = arith.constant 1 : index1010 scf.for %arg0 = %idx1 to %idx1 step %idx1 {1011 %138 = index.floordivs %arg0, %arg01012 }1013 return1014}1015 1016// CHECK-LABEL: func @zero_trip_loop21017func.func @zero_trip_loop2() {1018 %idx1 = arith.constant 1 : index1019 %idxm1 = arith.constant -1 : index1020 scf.for %arg0 = %idx1 to %idx1 step %idxm1 {1021 %138 = index.floordivs %arg0, %arg01022 }1023 return1024}1025 1026// CHECK-LABEL: @noninteger_operation_result1027func.func @noninteger_operation_result(%lb: index, %ub: index, %step: index, %cond: i1) {1028 %c1_i32 = arith.constant 1 : i321029 1030 %0 = "some_fp_op"() : () -> f321031 // CHECK: [[OUTS:%.*]]:2 = scf.for1032 %outs:2 = scf.for %i = %lb to %ub step %step iter_args(%a = %c1_i32, %b = %0) -> (i32, f32) {1033 %1:2 = "some_op"() : () -> (i32, f32)1034 scf.yield %1#0, %1#1 : i32, f321035 }1036 1037 // CHECK: [[RESULT:%.*]] = arith.select %{{.*}}, %c1_i32, [[OUTS]]#01038 %result = arith.select %cond, %c1_i32, %outs#0 : i321039 // CHECK: "use"([[RESULT]], [[OUTS]]#1)1040 "use"(%result, %outs#1) : (i32, f32) -> ()1041 return1042}1043