1// RUN: mlir-opt %s -pass-pipeline='builtin.module(func.func(test-affine-reify-value-bounds))' -verify-diagnostics \ 2// RUN: -split-input-file | FileCheck %s 3 4// CHECK: #[[$map:.*]] = affine_map<()[s0, s1] -> (s0 + s1)> 5// CHECK-LABEL: func @affine_apply( 6// CHECK-SAME: %[[a:.*]]: index, %[[b:.*]]: index 7// CHECK: %[[apply:.*]] = affine.apply #[[$map]]()[%[[a]], %[[b]]] 8// CHECK: %[[apply:.*]] = affine.apply #[[$map]]()[%[[a]], %[[b]]] 9// CHECK: return %[[apply]] 10func.func @affine_apply(%a: index, %b: index) -> index { 11 %0 = affine.apply affine_map<()[s0, s1] -> (s0 + s1)>()[%a, %b] 12 %1 = "test.reify_bound"(%0) : (index) -> (index) 13 return %1 : index 14} 15 16// ----- 17 18// CHECK-LABEL: func @affine_max_lb( 19// CHECK-SAME: %[[a:.*]]: index 20// CHECK: %[[c2:.*]] = arith.constant 2 : index 21// CHECK: return %[[c2]] 22func.func @affine_max_lb(%a: index) -> (index) { 23 // Note: There are two LBs: s0 and 2. FlatAffineValueConstraints always 24 // returns the constant one at the moment. 25 %1 = affine.max affine_map<()[s0] -> (s0, 2)>()[%a] 26 %2 = "test.reify_bound"(%1) {type = "LB"}: (index) -> (index) 27 return %2 : index 28} 29 30// ----- 31 32func.func @affine_max_ub(%a: index) -> (index) { 33 %1 = affine.max affine_map<()[s0] -> (s0, 2)>()[%a] 34 // expected-error @below{{could not reify bound}} 35 %2 = "test.reify_bound"(%1) {type = "UB"}: (index) -> (index) 36 return %2 : index 37} 38 39// ----- 40 41// CHECK-LABEL: func @affine_min_ub( 42// CHECK-SAME: %[[a:.*]]: index 43// CHECK: %[[c3:.*]] = arith.constant 3 : index 44// CHECK: return %[[c3]] 45func.func @affine_min_ub(%a: index) -> (index) { 46 // Note: There are two UBs: s0 + 1 and 3. FlatAffineValueConstraints always 47 // returns the constant one at the moment. 48 %1 = affine.min affine_map<()[s0] -> (s0, 2)>()[%a] 49 %2 = "test.reify_bound"(%1) {type = "UB"}: (index) -> (index) 50 return %2 : index 51} 52 53// ----- 54 55func.func @affine_min_lb(%a: index) -> (index) { 56 %1 = affine.min affine_map<()[s0] -> (s0, 2)>()[%a] 57 // expected-error @below{{could not reify bound}} 58 %2 = "test.reify_bound"(%1) {type = "LB"}: (index) -> (index) 59 return %2 : index 60} 61 62// ----- 63 64// CHECK-LABEL: func @composed_affine_apply( 65// CHECK: %[[cst:.*]] = arith.constant -8 : index 66// CHECK: return %[[cst]] 67func.func @composed_affine_apply(%i1 : index) -> (index) { 68 // The ValueBoundsOpInterface implementation of affine.apply fully composes 69 // the affine map (and its operands) with other affine.apply ops drawn from 70 // its operands before adding it to the constraint set. This is to work 71 // around a limitation in `FlatLinearConstraints`, which can currently not 72 // compute a constant bound for %s. (The affine map simplification logic can 73 // simplify %s to -8.) 74 %i2 = affine.apply affine_map<(d0) -> ((d0 floordiv 32) * 16)>(%i1) 75 %i3 = affine.apply affine_map<(d0) -> ((d0 floordiv 32) * 16 + 8)>(%i1) 76 %s = affine.apply affine_map<()[s0, s1] -> (s0 - s1)>()[%i2, %i3] 77 %reified = "test.reify_bound"(%s) {type = "EQ", constant} : (index) -> (index) 78 return %reified : index 79} 80 81 82// ----- 83 84func.func @are_equal(%i1 : index) { 85 %i2 = affine.apply affine_map<(d0) -> ((d0 floordiv 32) * 16)>(%i1) 86 %i3 = affine.apply affine_map<(d0) -> ((d0 floordiv 32) * 16 + 8)>(%i1) 87 %s = affine.apply affine_map<()[s0, s1] -> (s0 - s1)>()[%i2, %i3] 88 // expected-remark @below{{false}} 89 "test.compare"(%i2, %i3) : (index, index) -> () 90 return 91} 92 93// ----- 94 95// Test for affine::fullyComposeAndCheckIfEqual 96func.func @composed_are_equal(%i1 : index) { 97 %i2 = affine.apply affine_map<(d0) -> ((d0 floordiv 32) * 16)>(%i1) 98 %i3 = affine.apply affine_map<(d0) -> ((d0 floordiv 32) * 16 + 8)>(%i1) 99 %s = affine.apply affine_map<()[s0, s1] -> (s0 - s1)>()[%i2, %i3] 100 // expected-remark @below{{different}} 101 "test.compare"(%i2, %i3) {compose} : (index, index) -> () 102 return 103} 104 105// ----- 106 107func.func @compare_affine_max(%a: index, %b: index) { 108 %0 = affine.max affine_map<()[s0, s1] -> (s0, s1)>()[%a, %b] 109 // expected-remark @below{{true}} 110 "test.compare"(%0, %a) {cmp = "GE"} : (index, index) -> () 111 // expected-error @below{{unknown}} 112 "test.compare"(%0, %a) {cmp = "GT"} : (index, index) -> () 113 // expected-remark @below{{false}} 114 "test.compare"(%0, %a) {cmp = "LT"} : (index, index) -> () 115 // expected-error @below{{unknown}} 116 "test.compare"(%0, %a) {cmp = "LE"} : (index, index) -> () 117 return 118} 119 120// ----- 121 122func.func @compare_affine_min(%a: index, %b: index) { 123 %0 = affine.min affine_map<()[s0, s1] -> (s0, s1)>()[%a, %b] 124 // expected-error @below{{unknown}} 125 "test.compare"(%0, %a) {cmp = "GE"} : (index, index) -> () 126 // expected-remark @below{{false}} 127 "test.compare"(%0, %a) {cmp = "GT"} : (index, index) -> () 128 // expected-error @below{{unknown}} 129 "test.compare"(%0, %a) {cmp = "LT"} : (index, index) -> () 130 // expected-remark @below{{true}} 131 "test.compare"(%0, %a) {cmp = "LE"} : (index, index) -> () 132 return 133} 134 135// ----- 136 137func.func @compare_const_map() { 138 %c5 = arith.constant 5 : index 139 // expected-remark @below{{true}} 140 "test.compare"(%c5) {cmp = "GT", rhs_map = affine_map<() -> (4)>} 141 : (index) -> () 142 // expected-remark @below{{true}} 143 "test.compare"(%c5) {cmp = "LT", lhs_map = affine_map<() -> (4)>} 144 : (index) -> () 145 return 146} 147 148// ----- 149 150func.func @compare_maps(%a: index, %b: index) { 151 // expected-remark @below{{true}} 152 "test.compare"(%a, %b, %b, %a) 153 {cmp = "GT", lhs_map = affine_map<(d0, d1) -> (1 + d0 + d1)>, 154 rhs_map = affine_map<(d0, d1) -> (d0 + d1)>} 155 : (index, index, index, index) -> () 156 return 157} 158 159// ----- 160 161// CHECK-DAG: #[[$map1:.+]] = affine_map<()[s0] -> (s0 floordiv 15)> 162// CHECK-DAG: #[[$map2:.+]] = affine_map<()[s0] -> ((s0 mod 15) floordiv 5)> 163// CHECK-DAG: #[[$map3:.+]] = affine_map<()[s0] -> (s0 mod 5)> 164// CHECK-LABEL: func.func @delinearize_static 165// CHECK-SAME: (%[[arg0:.+]]: index) 166// CHECK-DAG: %[[v1:.+]] = affine.apply #[[$map1]]()[%[[arg0]]] 167// CHECK-DAG: %[[v2:.+]] = affine.apply #[[$map2]]()[%[[arg0]]] 168// CHECK-DAG: %[[v3:.+]] = affine.apply #[[$map3]]()[%[[arg0]]] 169// CHECK: return %[[v1]], %[[v2]], %[[v3]] 170func.func @delinearize_static(%arg0: index) -> (index, index, index) { 171 %c2 = arith.constant 2 : index 172 %c3 = arith.constant 3 : index 173 %0:3 = affine.delinearize_index %arg0 into (2, 3, 5) : index, index, index 174 %1 = "test.reify_bound"(%0#0) {type = "EQ"} : (index) -> (index) 175 %2 = "test.reify_bound"(%0#1) {type = "EQ"} : (index) -> (index) 176 %3 = "test.reify_bound"(%0#2) {type = "EQ"} : (index) -> (index) 177 // expected-remark @below{{true}} 178 "test.compare"(%0#0, %c2) {cmp = "LT"} : (index, index) -> () 179 // expected-remark @below{{true}} 180 "test.compare"(%0#1, %c3) {cmp = "LT"} : (index, index) -> () 181 return %1, %2, %3 : index, index, index 182} 183 184// ----- 185 186// CHECK-DAG: #[[$map1:.+]] = affine_map<()[s0] -> (s0 floordiv 15)> 187// CHECK-DAG: #[[$map2:.+]] = affine_map<()[s0] -> ((s0 mod 15) floordiv 5)> 188// CHECK-DAG: #[[$map3:.+]] = affine_map<()[s0] -> (s0 mod 5)> 189// CHECK-LABEL: func.func @delinearize_static_no_outer_bound 190// CHECK-SAME: (%[[arg0:.+]]: index) 191// CHECK-DAG: %[[v1:.+]] = affine.apply #[[$map1]]()[%[[arg0]]] 192// CHECK-DAG: %[[v2:.+]] = affine.apply #[[$map2]]()[%[[arg0]]] 193// CHECK-DAG: %[[v3:.+]] = affine.apply #[[$map3]]()[%[[arg0]]] 194// CHECK: return %[[v1]], %[[v2]], %[[v3]] 195func.func @delinearize_static_no_outer_bound(%arg0: index) -> (index, index, index) { 196 %c2 = arith.constant 2 : index 197 %c3 = arith.constant 3 : index 198 %0:3 = affine.delinearize_index %arg0 into (3, 5) : index, index, index 199 %1 = "test.reify_bound"(%0#0) {type = "EQ"} : (index) -> (index) 200 %2 = "test.reify_bound"(%0#1) {type = "EQ"} : (index) -> (index) 201 %3 = "test.reify_bound"(%0#2) {type = "EQ"} : (index) -> (index) 202 "test.compaare"(%0#0, %c2) {cmp = "LT"} : (index, index) -> () 203 // expected-remark @below{{true}} 204 "test.compare"(%0#1, %c3) {cmp = "LT"} : (index, index) -> () 205 return %1, %2, %3 : index, index, index 206} 207 208// ----- 209 210// CHECK: #[[$map:.+]] = affine_map<()[s0, s1] -> (s0 + s1 * 3)> 211// CHECK-LABEL: func.func @linearize_static 212// CHECK-SAME: (%[[arg0:.+]]: index, %[[arg1:.+]]: index) 213// CHECK: %[[v1:.+]] = affine.apply #[[$map]]()[%[[arg1]], %[[arg0]]] 214// CHECK: return %[[v1]] 215func.func @linearize_static(%arg0: index, %arg1: index) -> index { 216 %c6 = arith.constant 6 : index 217 %0 = affine.linearize_index disjoint [%arg0, %arg1] by (2, 3) : index 218 %1 = "test.reify_bound"(%0) {type = "EQ"} : (index) -> (index) 219 // expected-remark @below{{true}} 220 "test.compare"(%0, %c6) {cmp = "LT"} : (index, index) -> () 221 return %1 : index 222} 223 224// ----- 225 226// CHECK: #[[$map:.+]] = affine_map<()[s0, s1] -> (s0 + s1 * 3)> 227// CHECK-LABEL: func.func @linearize_static_no_outer_bound 228// CHECK-SAME: (%[[arg0:.+]]: index, %[[arg1:.+]]: index) 229// CHECK: %[[v1:.+]] = affine.apply #[[$map]]()[%[[arg1]], %[[arg0]]] 230// CHECK: return %[[v1]] 231func.func @linearize_static_no_outer_bound(%arg0: index, %arg1: index) -> index { 232 %c6 = arith.constant 6 : index 233 %0 = affine.linearize_index disjoint [%arg0, %arg1] by (3) : index 234 %1 = "test.reify_bound"(%0) {type = "EQ"} : (index) -> (index) 235 // expected-error @below{{unknown}} 236 "test.compare"(%0, %c6) {cmp = "LT"} : (index, index) -> () 237 return %1 : index 238} 239