1*0aa831e0SKrzysztof Drewniak// RUN: mlir-opt %s -pass-pipeline='builtin.module(func.func(test-affine-reify-value-bounds))' -verify-diagnostics \ 24f8f01b7SMatthias Springer// RUN: -split-input-file | FileCheck %s 34f8f01b7SMatthias Springer 44f8f01b7SMatthias Springer// CHECK: #[[$map:.*]] = affine_map<()[s0, s1] -> (s0 + s1)> 54f8f01b7SMatthias Springer// CHECK-LABEL: func @affine_apply( 64f8f01b7SMatthias Springer// CHECK-SAME: %[[a:.*]]: index, %[[b:.*]]: index 74f8f01b7SMatthias Springer// CHECK: %[[apply:.*]] = affine.apply #[[$map]]()[%[[a]], %[[b]]] 84f8f01b7SMatthias Springer// CHECK: %[[apply:.*]] = affine.apply #[[$map]]()[%[[a]], %[[b]]] 9ae6eedd2SRik Huijzer// CHECK: return %[[apply]] 104f8f01b7SMatthias Springerfunc.func @affine_apply(%a: index, %b: index) -> index { 114f8f01b7SMatthias Springer %0 = affine.apply affine_map<()[s0, s1] -> (s0 + s1)>()[%a, %b] 124f8f01b7SMatthias Springer %1 = "test.reify_bound"(%0) : (index) -> (index) 134f8f01b7SMatthias Springer return %1 : index 144f8f01b7SMatthias Springer} 15041bc485SMatthias Springer 16041bc485SMatthias Springer// ----- 17041bc485SMatthias Springer 18041bc485SMatthias Springer// CHECK-LABEL: func @affine_max_lb( 19041bc485SMatthias Springer// CHECK-SAME: %[[a:.*]]: index 20041bc485SMatthias Springer// CHECK: %[[c2:.*]] = arith.constant 2 : index 21041bc485SMatthias Springer// CHECK: return %[[c2]] 22041bc485SMatthias Springerfunc.func @affine_max_lb(%a: index) -> (index) { 23041bc485SMatthias Springer // Note: There are two LBs: s0 and 2. FlatAffineValueConstraints always 24041bc485SMatthias Springer // returns the constant one at the moment. 25041bc485SMatthias Springer %1 = affine.max affine_map<()[s0] -> (s0, 2)>()[%a] 26041bc485SMatthias Springer %2 = "test.reify_bound"(%1) {type = "LB"}: (index) -> (index) 27041bc485SMatthias Springer return %2 : index 28041bc485SMatthias Springer} 29041bc485SMatthias Springer 30041bc485SMatthias Springer// ----- 31041bc485SMatthias Springer 32041bc485SMatthias Springerfunc.func @affine_max_ub(%a: index) -> (index) { 33041bc485SMatthias Springer %1 = affine.max affine_map<()[s0] -> (s0, 2)>()[%a] 34041bc485SMatthias Springer // expected-error @below{{could not reify bound}} 35041bc485SMatthias Springer %2 = "test.reify_bound"(%1) {type = "UB"}: (index) -> (index) 36041bc485SMatthias Springer return %2 : index 37041bc485SMatthias Springer} 38041bc485SMatthias Springer 39041bc485SMatthias Springer// ----- 40041bc485SMatthias Springer 41041bc485SMatthias Springer// CHECK-LABEL: func @affine_min_ub( 42041bc485SMatthias Springer// CHECK-SAME: %[[a:.*]]: index 43041bc485SMatthias Springer// CHECK: %[[c3:.*]] = arith.constant 3 : index 44041bc485SMatthias Springer// CHECK: return %[[c3]] 45041bc485SMatthias Springerfunc.func @affine_min_ub(%a: index) -> (index) { 46041bc485SMatthias Springer // Note: There are two UBs: s0 + 1 and 3. FlatAffineValueConstraints always 47041bc485SMatthias Springer // returns the constant one at the moment. 48041bc485SMatthias Springer %1 = affine.min affine_map<()[s0] -> (s0, 2)>()[%a] 49041bc485SMatthias Springer %2 = "test.reify_bound"(%1) {type = "UB"}: (index) -> (index) 50041bc485SMatthias Springer return %2 : index 51041bc485SMatthias Springer} 52041bc485SMatthias Springer 53041bc485SMatthias Springer// ----- 54041bc485SMatthias Springer 55041bc485SMatthias Springerfunc.func @affine_min_lb(%a: index) -> (index) { 56041bc485SMatthias Springer %1 = affine.min affine_map<()[s0] -> (s0, 2)>()[%a] 57041bc485SMatthias Springer // expected-error @below{{could not reify bound}} 58041bc485SMatthias Springer %2 = "test.reify_bound"(%1) {type = "LB"}: (index) -> (index) 59041bc485SMatthias Springer return %2 : index 60041bc485SMatthias Springer} 61ebaf8d49SMatthias Springer 62ebaf8d49SMatthias Springer// ----- 63ebaf8d49SMatthias Springer 64ebaf8d49SMatthias Springer// CHECK-LABEL: func @composed_affine_apply( 65ebaf8d49SMatthias Springer// CHECK: %[[cst:.*]] = arith.constant -8 : index 66ebaf8d49SMatthias Springer// CHECK: return %[[cst]] 67ebaf8d49SMatthias Springerfunc.func @composed_affine_apply(%i1 : index) -> (index) { 68ebaf8d49SMatthias Springer // The ValueBoundsOpInterface implementation of affine.apply fully composes 69ebaf8d49SMatthias Springer // the affine map (and its operands) with other affine.apply ops drawn from 70ebaf8d49SMatthias Springer // its operands before adding it to the constraint set. This is to work 71ebaf8d49SMatthias Springer // around a limitation in `FlatLinearConstraints`, which can currently not 72ebaf8d49SMatthias Springer // compute a constant bound for %s. (The affine map simplification logic can 73ebaf8d49SMatthias Springer // simplify %s to -8.) 74ebaf8d49SMatthias Springer %i2 = affine.apply affine_map<(d0) -> ((d0 floordiv 32) * 16)>(%i1) 75ebaf8d49SMatthias Springer %i3 = affine.apply affine_map<(d0) -> ((d0 floordiv 32) * 16 + 8)>(%i1) 76ebaf8d49SMatthias Springer %s = affine.apply affine_map<()[s0, s1] -> (s0 - s1)>()[%i2, %i3] 77f8d314f0SMatthias Springer %reified = "test.reify_bound"(%s) {type = "EQ", constant} : (index) -> (index) 78ebaf8d49SMatthias Springer return %reified : index 79ebaf8d49SMatthias Springer} 80ebaf8d49SMatthias Springer 81ebaf8d49SMatthias Springer 82ebaf8d49SMatthias Springer// ----- 83ebaf8d49SMatthias Springer 84297eca98SMatthias Springerfunc.func @are_equal(%i1 : index) { 85297eca98SMatthias Springer %i2 = affine.apply affine_map<(d0) -> ((d0 floordiv 32) * 16)>(%i1) 86297eca98SMatthias Springer %i3 = affine.apply affine_map<(d0) -> ((d0 floordiv 32) * 16 + 8)>(%i1) 87297eca98SMatthias Springer %s = affine.apply affine_map<()[s0, s1] -> (s0 - s1)>()[%i2, %i3] 88297eca98SMatthias Springer // expected-remark @below{{false}} 89297eca98SMatthias Springer "test.compare"(%i2, %i3) : (index, index) -> () 90297eca98SMatthias Springer return 91297eca98SMatthias Springer} 92297eca98SMatthias Springer 93297eca98SMatthias Springer// ----- 94297eca98SMatthias Springer 95ebaf8d49SMatthias Springer// Test for affine::fullyComposeAndCheckIfEqual 96ebaf8d49SMatthias Springerfunc.func @composed_are_equal(%i1 : index) { 97ebaf8d49SMatthias Springer %i2 = affine.apply affine_map<(d0) -> ((d0 floordiv 32) * 16)>(%i1) 98ebaf8d49SMatthias Springer %i3 = affine.apply affine_map<(d0) -> ((d0 floordiv 32) * 16 + 8)>(%i1) 99ebaf8d49SMatthias Springer %s = affine.apply affine_map<()[s0, s1] -> (s0 - s1)>()[%i2, %i3] 100ebaf8d49SMatthias Springer // expected-remark @below{{different}} 101297eca98SMatthias Springer "test.compare"(%i2, %i3) {compose} : (index, index) -> () 102297eca98SMatthias Springer return 103297eca98SMatthias Springer} 104297eca98SMatthias Springer 105297eca98SMatthias Springer// ----- 106297eca98SMatthias Springer 107297eca98SMatthias Springerfunc.func @compare_affine_max(%a: index, %b: index) { 108297eca98SMatthias Springer %0 = affine.max affine_map<()[s0, s1] -> (s0, s1)>()[%a, %b] 109297eca98SMatthias Springer // expected-remark @below{{true}} 110297eca98SMatthias Springer "test.compare"(%0, %a) {cmp = "GE"} : (index, index) -> () 111297eca98SMatthias Springer // expected-error @below{{unknown}} 112297eca98SMatthias Springer "test.compare"(%0, %a) {cmp = "GT"} : (index, index) -> () 113297eca98SMatthias Springer // expected-remark @below{{false}} 114297eca98SMatthias Springer "test.compare"(%0, %a) {cmp = "LT"} : (index, index) -> () 115297eca98SMatthias Springer // expected-error @below{{unknown}} 116297eca98SMatthias Springer "test.compare"(%0, %a) {cmp = "LE"} : (index, index) -> () 117297eca98SMatthias Springer return 118297eca98SMatthias Springer} 119297eca98SMatthias Springer 120297eca98SMatthias Springer// ----- 121297eca98SMatthias Springer 122297eca98SMatthias Springerfunc.func @compare_affine_min(%a: index, %b: index) { 123297eca98SMatthias Springer %0 = affine.min affine_map<()[s0, s1] -> (s0, s1)>()[%a, %b] 124297eca98SMatthias Springer // expected-error @below{{unknown}} 125297eca98SMatthias Springer "test.compare"(%0, %a) {cmp = "GE"} : (index, index) -> () 126297eca98SMatthias Springer // expected-remark @below{{false}} 127297eca98SMatthias Springer "test.compare"(%0, %a) {cmp = "GT"} : (index, index) -> () 128297eca98SMatthias Springer // expected-error @below{{unknown}} 129297eca98SMatthias Springer "test.compare"(%0, %a) {cmp = "LT"} : (index, index) -> () 130297eca98SMatthias Springer // expected-remark @below{{true}} 131297eca98SMatthias Springer "test.compare"(%0, %a) {cmp = "LE"} : (index, index) -> () 132ebaf8d49SMatthias Springer return 133ebaf8d49SMatthias Springer} 13440dd3aa9SMatthias Springer 13540dd3aa9SMatthias Springer// ----- 13640dd3aa9SMatthias Springer 13740dd3aa9SMatthias Springerfunc.func @compare_const_map() { 13840dd3aa9SMatthias Springer %c5 = arith.constant 5 : index 13940dd3aa9SMatthias Springer // expected-remark @below{{true}} 14040dd3aa9SMatthias Springer "test.compare"(%c5) {cmp = "GT", rhs_map = affine_map<() -> (4)>} 14140dd3aa9SMatthias Springer : (index) -> () 14240dd3aa9SMatthias Springer // expected-remark @below{{true}} 14340dd3aa9SMatthias Springer "test.compare"(%c5) {cmp = "LT", lhs_map = affine_map<() -> (4)>} 14440dd3aa9SMatthias Springer : (index) -> () 14540dd3aa9SMatthias Springer return 14640dd3aa9SMatthias Springer} 14740dd3aa9SMatthias Springer 14840dd3aa9SMatthias Springer// ----- 14940dd3aa9SMatthias Springer 15040dd3aa9SMatthias Springerfunc.func @compare_maps(%a: index, %b: index) { 15140dd3aa9SMatthias Springer // expected-remark @below{{true}} 15240dd3aa9SMatthias Springer "test.compare"(%a, %b, %b, %a) 15340dd3aa9SMatthias Springer {cmp = "GT", lhs_map = affine_map<(d0, d1) -> (1 + d0 + d1)>, 15440dd3aa9SMatthias Springer rhs_map = affine_map<(d0, d1) -> (d0 + d1)>} 15540dd3aa9SMatthias Springer : (index, index, index, index) -> () 15640dd3aa9SMatthias Springer return 15740dd3aa9SMatthias Springer} 158c6f67b8eSKrzysztof Drewniak 159c6f67b8eSKrzysztof Drewniak// ----- 160c6f67b8eSKrzysztof Drewniak 161c6f67b8eSKrzysztof Drewniak// CHECK-DAG: #[[$map1:.+]] = affine_map<()[s0] -> (s0 floordiv 15)> 162c6f67b8eSKrzysztof Drewniak// CHECK-DAG: #[[$map2:.+]] = affine_map<()[s0] -> ((s0 mod 15) floordiv 5)> 163c6f67b8eSKrzysztof Drewniak// CHECK-DAG: #[[$map3:.+]] = affine_map<()[s0] -> (s0 mod 5)> 164c6f67b8eSKrzysztof Drewniak// CHECK-LABEL: func.func @delinearize_static 165c6f67b8eSKrzysztof Drewniak// CHECK-SAME: (%[[arg0:.+]]: index) 166c6f67b8eSKrzysztof Drewniak// CHECK-DAG: %[[v1:.+]] = affine.apply #[[$map1]]()[%[[arg0]]] 167c6f67b8eSKrzysztof Drewniak// CHECK-DAG: %[[v2:.+]] = affine.apply #[[$map2]]()[%[[arg0]]] 168c6f67b8eSKrzysztof Drewniak// CHECK-DAG: %[[v3:.+]] = affine.apply #[[$map3]]()[%[[arg0]]] 169c6f67b8eSKrzysztof Drewniak// CHECK: return %[[v1]], %[[v2]], %[[v3]] 170c6f67b8eSKrzysztof Drewniakfunc.func @delinearize_static(%arg0: index) -> (index, index, index) { 171c6f67b8eSKrzysztof Drewniak %c2 = arith.constant 2 : index 172c6f67b8eSKrzysztof Drewniak %c3 = arith.constant 3 : index 173c6f67b8eSKrzysztof Drewniak %0:3 = affine.delinearize_index %arg0 into (2, 3, 5) : index, index, index 174c6f67b8eSKrzysztof Drewniak %1 = "test.reify_bound"(%0#0) {type = "EQ"} : (index) -> (index) 175c6f67b8eSKrzysztof Drewniak %2 = "test.reify_bound"(%0#1) {type = "EQ"} : (index) -> (index) 176c6f67b8eSKrzysztof Drewniak %3 = "test.reify_bound"(%0#2) {type = "EQ"} : (index) -> (index) 177c6f67b8eSKrzysztof Drewniak // expected-remark @below{{true}} 178c6f67b8eSKrzysztof Drewniak "test.compare"(%0#0, %c2) {cmp = "LT"} : (index, index) -> () 179c6f67b8eSKrzysztof Drewniak // expected-remark @below{{true}} 180c6f67b8eSKrzysztof Drewniak "test.compare"(%0#1, %c3) {cmp = "LT"} : (index, index) -> () 181c6f67b8eSKrzysztof Drewniak return %1, %2, %3 : index, index, index 182c6f67b8eSKrzysztof Drewniak} 183c6f67b8eSKrzysztof Drewniak 184c6f67b8eSKrzysztof Drewniak// ----- 185c6f67b8eSKrzysztof Drewniak 186c6f67b8eSKrzysztof Drewniak// CHECK-DAG: #[[$map1:.+]] = affine_map<()[s0] -> (s0 floordiv 15)> 187c6f67b8eSKrzysztof Drewniak// CHECK-DAG: #[[$map2:.+]] = affine_map<()[s0] -> ((s0 mod 15) floordiv 5)> 188c6f67b8eSKrzysztof Drewniak// CHECK-DAG: #[[$map3:.+]] = affine_map<()[s0] -> (s0 mod 5)> 189c6f67b8eSKrzysztof Drewniak// CHECK-LABEL: func.func @delinearize_static_no_outer_bound 190c6f67b8eSKrzysztof Drewniak// CHECK-SAME: (%[[arg0:.+]]: index) 191c6f67b8eSKrzysztof Drewniak// CHECK-DAG: %[[v1:.+]] = affine.apply #[[$map1]]()[%[[arg0]]] 192c6f67b8eSKrzysztof Drewniak// CHECK-DAG: %[[v2:.+]] = affine.apply #[[$map2]]()[%[[arg0]]] 193c6f67b8eSKrzysztof Drewniak// CHECK-DAG: %[[v3:.+]] = affine.apply #[[$map3]]()[%[[arg0]]] 194c6f67b8eSKrzysztof Drewniak// CHECK: return %[[v1]], %[[v2]], %[[v3]] 195c6f67b8eSKrzysztof Drewniakfunc.func @delinearize_static_no_outer_bound(%arg0: index) -> (index, index, index) { 196c6f67b8eSKrzysztof Drewniak %c2 = arith.constant 2 : index 197c6f67b8eSKrzysztof Drewniak %c3 = arith.constant 3 : index 198c6f67b8eSKrzysztof Drewniak %0:3 = affine.delinearize_index %arg0 into (3, 5) : index, index, index 199c6f67b8eSKrzysztof Drewniak %1 = "test.reify_bound"(%0#0) {type = "EQ"} : (index) -> (index) 200c6f67b8eSKrzysztof Drewniak %2 = "test.reify_bound"(%0#1) {type = "EQ"} : (index) -> (index) 201c6f67b8eSKrzysztof Drewniak %3 = "test.reify_bound"(%0#2) {type = "EQ"} : (index) -> (index) 202c6f67b8eSKrzysztof Drewniak "test.compaare"(%0#0, %c2) {cmp = "LT"} : (index, index) -> () 203c6f67b8eSKrzysztof Drewniak // expected-remark @below{{true}} 204c6f67b8eSKrzysztof Drewniak "test.compare"(%0#1, %c3) {cmp = "LT"} : (index, index) -> () 205c6f67b8eSKrzysztof Drewniak return %1, %2, %3 : index, index, index 206c6f67b8eSKrzysztof Drewniak} 207c6f67b8eSKrzysztof Drewniak 208c6f67b8eSKrzysztof Drewniak// ----- 209c6f67b8eSKrzysztof Drewniak 210c6f67b8eSKrzysztof Drewniak// CHECK: #[[$map:.+]] = affine_map<()[s0, s1] -> (s0 + s1 * 3)> 211c6f67b8eSKrzysztof Drewniak// CHECK-LABEL: func.func @linearize_static 212c6f67b8eSKrzysztof Drewniak// CHECK-SAME: (%[[arg0:.+]]: index, %[[arg1:.+]]: index) 213c6f67b8eSKrzysztof Drewniak// CHECK: %[[v1:.+]] = affine.apply #[[$map]]()[%[[arg1]], %[[arg0]]] 214c6f67b8eSKrzysztof Drewniak// CHECK: return %[[v1]] 215c6f67b8eSKrzysztof Drewniakfunc.func @linearize_static(%arg0: index, %arg1: index) -> index { 216c6f67b8eSKrzysztof Drewniak %c6 = arith.constant 6 : index 217c6f67b8eSKrzysztof Drewniak %0 = affine.linearize_index disjoint [%arg0, %arg1] by (2, 3) : index 218c6f67b8eSKrzysztof Drewniak %1 = "test.reify_bound"(%0) {type = "EQ"} : (index) -> (index) 219c6f67b8eSKrzysztof Drewniak // expected-remark @below{{true}} 220c6f67b8eSKrzysztof Drewniak "test.compare"(%0, %c6) {cmp = "LT"} : (index, index) -> () 221c6f67b8eSKrzysztof Drewniak return %1 : index 222c6f67b8eSKrzysztof Drewniak} 223c6f67b8eSKrzysztof Drewniak 224c6f67b8eSKrzysztof Drewniak// ----- 225c6f67b8eSKrzysztof Drewniak 226c6f67b8eSKrzysztof Drewniak// CHECK: #[[$map:.+]] = affine_map<()[s0, s1] -> (s0 + s1 * 3)> 227c6f67b8eSKrzysztof Drewniak// CHECK-LABEL: func.func @linearize_static_no_outer_bound 228c6f67b8eSKrzysztof Drewniak// CHECK-SAME: (%[[arg0:.+]]: index, %[[arg1:.+]]: index) 229c6f67b8eSKrzysztof Drewniak// CHECK: %[[v1:.+]] = affine.apply #[[$map]]()[%[[arg1]], %[[arg0]]] 230c6f67b8eSKrzysztof Drewniak// CHECK: return %[[v1]] 231c6f67b8eSKrzysztof Drewniakfunc.func @linearize_static_no_outer_bound(%arg0: index, %arg1: index) -> index { 232c6f67b8eSKrzysztof Drewniak %c6 = arith.constant 6 : index 233c6f67b8eSKrzysztof Drewniak %0 = affine.linearize_index disjoint [%arg0, %arg1] by (3) : index 234c6f67b8eSKrzysztof Drewniak %1 = "test.reify_bound"(%0) {type = "EQ"} : (index) -> (index) 235c6f67b8eSKrzysztof Drewniak // expected-error @below{{unknown}} 236c6f67b8eSKrzysztof Drewniak "test.compare"(%0, %c6) {cmp = "LT"} : (index, index) -> () 237c6f67b8eSKrzysztof Drewniak return %1 : index 238c6f67b8eSKrzysztof Drewniak} 239