11// RUN: mlir-opt %s --transform-interpreter --split-input-file | FileCheck %s
22
3+ // TODO: Align naming with e.g. vector-transfer-flatten.mlir
4+ // TODO: Replace %arg0 with %vec
5+ // TODO: Replace index args as %idx
6+ // TODO: Align argument definition in CHECKS with function body.
7+
38///----------------------------------------------------------------------------------------
49/// vector.transfer_write -> vector.transpose + vector.transfer_write
510/// [Pattern: TransferWritePermutationLowering]
1217/// _is_ a minor identity
1318
1419// CHECK-LABEL: func.func @xfer_write_transposing_permutation_map
15- // CHECK-SAME: %[[ARG_0:.*]]: vector<4x8xi16>,
16- // CHECK-SAME: %[[MEM:.*]]: memref<2x2x8x4xi16>) {
20+ // CHECK-SAME: %[[ARG_0:.*]]: vector<4x8xi16>,
21+ // CHECK-SAME: %[[MEM:.*]]: memref<2x2x8x4xi16>) {
1722// CHECK: %[[TR:.*]] = vector.transpose %[[ARG_0]], [1, 0] : vector<4x8xi16> to vector<8x4xi16>
1823// CHECK: vector.transfer_write
1924// CHECK-NOT: permutation_map
@@ -31,6 +36,31 @@ func.func @xfer_write_transposing_permutation_map(
3136 return
3237}
3338
39+ // Even with out-of-bounds, it is safe to apply this pattern
40+ // CHECK-LABEL: func.func @xfer_write_transposing_permutation_map_out_of_bounds
41+ // CHECK-SAME: %[[ARG_0:.*]]: vector<4x8xi16>,
42+ // CHECK-SAME: %[[MEM:.*]]: memref<2x2x?x?xi16>) {
43+ // CHECK: %[[C0:.*]] = arith.constant 0 : index
44+ // CHECK: %[[TR:.*]] = vector.transpose %[[ARG_0]], [1, 0] : vector<4x8xi16> to vector<8x4xi16>
45+ // Expect the in_bounds attribute to be preserved. Since we don't print it when
46+ // all flags are "false", it should not appear in the output.
47+ // CHECK-NOT: in_bounds
48+ // CHECK: vector.transfer_write
49+ // CHECK-NOT: permutation_map
50+ // CHECK-SAME: %[[TR]], %[[MEM]][%[[C0]], %[[C0]], %[[C0]], %[[C0]]] : vector<8x4xi16>, memref<2x2x?x?xi16>
51+ func.func @xfer_write_transposing_permutation_map_out_of_bounds (
52+ %arg0: vector <4 x8 xi16 >,
53+ %mem: memref <2 x2 x?x?xi16 >) {
54+
55+ %c0 = arith.constant 0 : index
56+ vector.transfer_write %arg0 , %mem [%c0 , %c0 , %c0 , %c0 ] {
57+ in_bounds = [false , false ],
58+ permutation_map = affine_map <(d0 , d1 , d2 , d3 ) -> (d3 , d2 )>
59+ } : vector <4 x8 xi16 >, memref <2 x2 x?x?xi16 >
60+
61+ return
62+ }
63+
3464// CHECK-LABEL: func.func @xfer_write_transposing_permutation_map_with_mask_scalable
3565// CHECK-SAME: %[[ARG_0:.*]]: vector<4x[8]xi16>,
3666// CHECK-SAME: %[[MEM:.*]]: memref<2x2x?x4xi16>,
@@ -83,19 +113,44 @@ func.func @xfer_write_transposing_permutation_map_masked(
83113/// * vector.broadcast + vector.transpose + vector.transfer_write with a map
84114/// which _is_ a permutation of a minor identity
85115
86- // CHECK-LABEL: func @permutation_with_mask_xfer_write_fixed_width(
87- // CHECK: %[[vec:.*]] = arith.constant dense<-2.000000e+00> : vector<7x1xf32>
88- // CHECK: %[[mask:.*]] = arith.constant dense<[true, false, true, false, true, true, true]> : vector<7xi1>
89- // CHECK: %[[b:.*]] = vector.broadcast %[[mask]] : vector<7xi1> to vector<1x7xi1>
90- // CHECK: %[[tp:.*]] = vector.transpose %[[b]], [1, 0] : vector<1x7xi1> to vector<7x1xi1>
91- // CHECK: vector.transfer_write %[[vec]], %{{.*}}[%{{.*}}, %{{.*}}], %[[tp]] {in_bounds = [false, true]} : vector<7x1xf32>, memref<?x?xf32>
92- func.func @permutation_with_mask_xfer_write_fixed_width (%mem : memref <?x?xf32 >, %base1 : index ,
93- %base2 : index ) {
94-
95- %fn1 = arith.constant -2.0 : f32
96- %vf0 = vector.splat %fn1 : vector <7 xf32 >
97- %mask = arith.constant dense <[1 , 0 , 1 , 0 , 1 , 1 , 1 ]> : vector <7 xi1 >
98- vector.transfer_write %vf0 , %mem [%base1 , %base2 ], %mask
116+ // CHECK-LABEL: func.func @xfer_write_non_transposing_permutation_map(
117+ // CHECK-SAME: %[[MEM:.*]]: memref<?x?xf32>,
118+ // CHECK-SAME: %[[VEC:.*]]: vector<7xf32>,
119+ // CHECK-SAME: %[[IDX_1:.*]]: index, %[[IDX_2:.*]]: index) {
120+ // CHECK: %[[BC:.*]] = vector.broadcast %[[VEC]] : vector<7xf32> to vector<1x7xf32>
121+ // CHECK: %[[TR:.*]] = vector.transpose %[[BC]], [1, 0] : vector<1x7xf32> to vector<7x1xf32>
122+ // CHECK: vector.transfer_write %[[TR]], %[[MEM]]{{\[}}%[[IDX_1]], %[[IDX_2]]] {in_bounds = [false, true]} : vector<7x1xf32>, memref<?x?xf32>
123+ func.func @xfer_write_non_transposing_permutation_map (
124+ %mem : memref <?x?xf32 >,
125+ %arg0 : vector <7 xf32 >,
126+ %idx_1 : index ,
127+ %idx_2 : index ) {
128+
129+ vector.transfer_write %arg0 , %mem [%idx_1 , %idx_2 ]
130+ {permutation_map = affine_map <(d0 , d1 ) -> (d0 )>}
131+ : vector <7 xf32 >, memref <?x?xf32 >
132+ return
133+ }
134+
135+ // Even with out-of-bounds, it is safe to apply this pattern
136+ // CHECK-LABEL: func.func @xfer_write_non_transposing_permutation_map_with_mask_out_of_bounds(
137+ // CHECK-SAME: %[[MEM:.*]]: memref<?x?xf32>,
138+ // CHECK-SAME: %[[VEC:.*]]: vector<7xf32>,
139+ // CHECK-SAME: %[[IDX_1:.*]]: index, %[[IDX_2:.*]]: index,
140+ // CHECK-SAME: %[[MASK:.*]]: vector<7xi1>) {
141+ // CHECK: %[[BC_VEC:.*]] = vector.broadcast %[[VEC]] : vector<7xf32> to vector<1x7xf32>
142+ // CHECK: %[[BC_MASK:.*]] = vector.broadcast %[[MASK]] : vector<7xi1> to vector<1x7xi1>
143+ // CHECK: %[[TR_MASK:.*]] = vector.transpose %[[BC_MASK]], [1, 0] : vector<1x7xi1> to vector<7x1xi1>
144+ // CHECK: %[[TR_VEC:.*]] = vector.transpose %[[BC_VEC]], [1, 0] : vector<1x7xf32> to vector<7x1xf32>
145+ // CHECK: vector.transfer_write %[[TR_VEC]], %[[MEM]]{{\[}}%[[IDX_1]], %[[IDX_2]]], %[[TR_MASK]] {in_bounds = [false, true]} : vector<7x1xf32>, memref<?x?xf32>
146+ func.func @xfer_write_non_transposing_permutation_map_with_mask_out_of_bounds (
147+ %mem : memref <?x?xf32 >,
148+ %arg0 : vector <7 xf32 >,
149+ %idx_1 : index ,
150+ %idx_2 : index ,
151+ %mask : vector <7 xi1 >) {
152+
153+ vector.transfer_write %arg0 , %mem [%idx_1 , %idx_2 ], %mask
99154 {permutation_map = affine_map <(d0 , d1 ) -> (d0 )>, in_bounds = [false ]}
100155 : vector <7 xf32 >, memref <?x?xf32 >
101156 return
0 commit comments