1// RUN: mlir-opt %s -allow-unregistered-dialect -test-linalg-transform-patterns=test-vector-transfer-forwarding-patterns | FileCheck %s 2 3// CHECK-LABEL: testAllocRead 4// CHECK-SAME: %[[ARG0:[0-9a-zA-Z]*]]: memref 5// CHECK-NOT: linalg.fill 6// CHECK-NOT: memref.copy 7// CHECK: %[[ALLOC:.*]] = memref.alloc 8// CHECK: vector.transfer_read %[[ARG0]] 9// CHECK-NOT: in_bounds 10func.func @testAllocRead(%in: memref<? x f32>) -> vector<32 x f32> { 11 %c0 = arith.constant 0: index 12 %f0 = arith.constant 0.0: f32 13 %alloc = memref.alloc() : memref<32 x f32> 14 %subview = memref.subview %alloc[0][16][1] : memref<32 x f32> to memref<16 x f32> 15 memref.copy %in, %subview : memref<? x f32> to memref<16 x f32> 16 %0 = vector.transfer_read %alloc[%c0], %f0 {in_bounds = [true]} : memref<32 x f32>, vector<32 x f32> 17 memref.dealloc %alloc : memref<32 x f32> 18 return %0: vector<32 x f32> 19} 20 21// CHECK-LABEL: testAllocFillRead 22// CHECK-SAME: %[[ARG0:[0-9a-zA-Z]*]]: memref 23// CHECK-NOT: linalg.fill 24// CHECK-NOT: memref.copy 25// CHECK: %[[ALLOC:.*]] = memref.alloc 26// CHECK: vector.transfer_read %[[ARG0]] 27// CHECK-NOT: in_bounds 28func.func @testAllocFillRead(%in: memref<? x f32>) -> vector<32 x f32> { 29 %c0 = arith.constant 0: index 30 %f0 = arith.constant 0.0: f32 31 %alloc = memref.alloc() : memref<32 x f32> 32 linalg.fill ins(%f0 : f32) outs(%alloc : memref<32 x f32>) 33 %subview = memref.subview %alloc[0][16][1] : memref<32 x f32> to memref<16 x f32> 34 memref.copy %in, %subview : memref<? x f32> to memref<16 x f32> 35 %0 = vector.transfer_read %alloc[%c0], %f0 {in_bounds = [true]} : memref<32 x f32>, vector<32 x f32> 36 memref.dealloc %alloc : memref<32 x f32> 37 return %0: vector<32 x f32> 38} 39 40// CHECK-LABEL: testViewRead 41// CHECK-SAME: %[[ARG0:[0-9a-zA-Z]*]]: memref 42// CHECK-NOT: linalg.fill 43// CHECK-NOT: memref.copy 44// CHECK: %[[ALLOC:.*]] = memref.alloc 45// CHECK: vector.transfer_read %[[ARG0]] 46// CHECK-NOT: in_bounds 47func.func @testViewRead(%in: memref<? x f32>) -> vector<32 x f32> { 48 %c0 = arith.constant 0: index 49 %f0 = arith.constant 0.0: f32 50 %alloc = memref.alloc() : memref<128 x i8> 51 %view = memref.view %alloc[%c0][] : memref<128 x i8> to memref<32 x f32> 52 %subview = memref.subview %view[0][16][1] : memref<32 x f32> to memref<16 x f32> 53 memref.copy %in, %subview : memref<? x f32> to memref<16 x f32> 54 %0 = vector.transfer_read %view[%c0], %f0 {in_bounds = [true]} : memref<32 x f32>, vector<32 x f32> 55 memref.dealloc %alloc : memref<128 x i8> 56 return %0: vector<32 x f32> 57} 58 59// CHECK-LABEL: testViewFillRead 60// CHECK-SAME: %[[ARG0:[0-9a-zA-Z]*]]: memref 61// CHECK-NOT: linalg.fill 62// CHECK-NOT: memref.copy 63// CHECK: %[[ALLOC:.*]] = memref.alloc 64// CHECK: vector.transfer_read %[[ARG0]] 65// CHECK-NOT: in_bounds 66func.func @testViewFillRead(%in: memref<? x f32>) -> vector<32 x f32> { 67 %c0 = arith.constant 0: index 68 %f0 = arith.constant 0.0: f32 69 %alloc = memref.alloc() : memref<128 x i8> 70 %view = memref.view %alloc[%c0][] : memref<128 x i8> to memref<32 x f32> 71 %subview = memref.subview %view[0][16][1] : memref<32 x f32> to memref<16 x f32> 72 linalg.fill ins(%f0 : f32) outs(%view : memref<32 x f32>) 73 memref.copy %in, %subview : memref<? x f32> to memref<16 x f32> 74 %0 = vector.transfer_read %view[%c0], %f0 {in_bounds = [true]} : memref<32 x f32>, vector<32 x f32> 75 memref.dealloc %alloc : memref<128 x i8> 76 return %0: vector<32 x f32> 77} 78 79// CHECK-LABEL: testAllocWrite 80// CHECK-SAME: %[[ARG0:[0-9a-zA-Z]*]]: vector 81// CHECK-SAME: %[[ARG1:[0-9a-zA-Z]*]]: memref 82// CHECK-NOT: memref.copy 83// CHECK: %[[ALLOC:.*]] = memref.alloc 84// CHECK: vector.transfer_write %[[ARG0]], %[[ARG1]] 85// CHECK-NOT: in_bounds 86func.func @testAllocWrite(%vec: vector<32 x f32>, %out: memref<? x f32>) { 87 %c0 = arith.constant 0: index 88 %f0 = arith.constant 0.0: f32 89 %alloc = memref.alloc() : memref<32 x f32> 90 %subview = memref.subview %alloc[0][16][1] : memref<32 x f32> to memref<16 x f32> 91 vector.transfer_write %vec, %alloc[%c0] {in_bounds = [true]} : vector<32 x f32>, memref<32 x f32> 92 memref.copy %subview, %out : memref<16 x f32> to memref<? x f32> 93 memref.dealloc %alloc : memref<32 x f32> 94 return 95} 96 97// CHECK-LABEL: testViewWrite 98// CHECK-SAME: %[[ARG0:[0-9a-zA-Z]*]]: vector 99// CHECK-SAME: %[[ARG1:[0-9a-zA-Z]*]]: memref 100// CHECK-NOT: memref.copy 101// CHECK: %[[ALLOC:.*]] = memref.alloc 102// CHECK: vector.transfer_write %[[ARG0]], %[[ARG1]] 103// CHECK-NOT: in_bounds 104func.func @testViewWrite(%vec: vector<32 x f32>, %out: memref<? x f32>) { 105 %c0 = arith.constant 0: index 106 %f0 = arith.constant 0.0: f32 107 %alloc = memref.alloc() : memref<128 x i8> 108 %view = memref.view %alloc[%c0][] : memref<128 x i8> to memref<32 x f32> 109 %subview = memref.subview %view[0][16][1] : memref<32 x f32> to memref<16 x f32> 110 vector.transfer_write %vec, %view[%c0] {in_bounds = [true]} : vector<32 x f32>, memref<32 x f32> 111 memref.copy %subview, %out : memref<16 x f32> to memref<? x f32> 112 memref.dealloc %alloc : memref<128 x i8> 113 return 114} 115 116///===--------------------------------------------------------------------===/// 117// Negative tests 118///===--------------------------------------------------------------------===/// 119 120// This should fail the rewrite due to mismatching fill and transfer read value. 121// CHECK-LABEL: failAllocFillRead 122// CHECK-SAME: %[[ARG0:[0-9a-zA-Z]*]]: memref 123// CHECK-NOT: vector.transfer_read %[[ARG0]] 124// CHECK: %[[ALLOC:.*]] = memref.alloc 125// CHECK: memref.copy 126// CHECK: vector.transfer_read %[[ALLOC]] 127func.func @failAllocFillRead(%in: memref<? x f32>) -> vector<32 x f32> { 128 %c0 = arith.constant 0: index 129 %f0 = arith.constant 0.0: f32 130 %f1 = arith.constant 1.0: f32 131 %alloc = memref.alloc() : memref<32 x f32> 132 linalg.fill ins(%f0 : f32) outs(%alloc : memref<32 x f32>) 133 %subview = memref.subview %alloc[0][16][1] : memref<32 x f32> to memref<16 x f32> 134 memref.copy %in, %subview : memref<? x f32> to memref<16 x f32> 135 "some_interleaved_use"(%subview) : (memref<16 x f32>) -> () 136 %0 = vector.transfer_read %alloc[%c0], %f1: memref<32 x f32>, vector<32 x f32> 137 memref.dealloc %alloc : memref<32 x f32> 138 return %0: vector<32 x f32> 139} 140 141// This should fail the rewrite due to some interleaved use. 142// CHECK-LABEL: failAllocWrite 143// CHECK-SAME: %[[ARG0:[0-9a-zA-Z]*]]: vector 144// CHECK-SAME: %[[ARG1:[0-9a-zA-Z]*]]: memref 145// CHECK-NOT: vector.transfer_write %[[ARG0]], %[[ARG1]] 146// CHECK: %[[ALLOC:.*]] = memref.alloc 147// CHECK: vector.transfer_write %[[ARG0]], %[[ALLOC]] 148// CHECK: memref.copy 149func.func @failAllocWrite(%vec: vector<32 x f32>, %out: memref<? x f32>) { 150 %c0 = arith.constant 0: index 151 %f0 = arith.constant 0.0: f32 152 %alloc = memref.alloc() : memref<32 x f32> 153 %subview = memref.subview %alloc[0][16][1] : memref<32 x f32> to memref<16 x f32> 154 vector.transfer_write %vec, %alloc[%c0] : vector<32 x f32>, memref<32 x f32> 155 "some_interleaved_use"(%subview) : (memref<16 x f32>) -> () 156 memref.copy %subview, %out : memref<16 x f32> to memref<? x f32> 157 memref.dealloc %alloc : memref<32 x f32> 158 return 159} 160