|
| 1 | +// RUN: mlir-opt --split-input-file --tosa-layerwise-constant-fold %s | FileCheck %s |
| 2 | + |
| 3 | +// CHECK-LABEL: @reciprocal_fold_single_valued |
| 4 | +func.func @reciprocal_fold_single_valued() -> tensor<f32> { |
| 5 | + // CHECK: [[RES:]] ={{.*}}tosa.const{{.*}}2.5{{0*}}e-01{{.*}}tensor<f32> |
| 6 | + // CHECK-NOT: tosa.reciprocal |
| 7 | + // CHECK: return [[RES]] |
| 8 | + %0 = "tosa.const"() {value = dense<4.0> : tensor<f32>} : () -> tensor<f32> |
| 9 | + %1 = "tosa.reciprocal"(%0) : (tensor<f32>) -> tensor<f32> |
| 10 | + return %1 : tensor<f32> |
| 11 | +} |
| 12 | + |
| 13 | +// CHECK-LABEL: @reciprocal_fold_splat |
| 14 | +func.func @reciprocal_fold_splat() -> tensor<12x7xf32> { |
| 15 | + // CHECK: [[RES:]] ={{.*}}tosa.const{{.*}}2.5{{0*}}e-01{{.*}}tensor<12x7xf32> |
| 16 | + // CHECK-NOT: tosa.reciprocal |
| 17 | + // CHECK: return [[RES]] |
| 18 | + %0 = "tosa.const"() {value = dense<4.0> : tensor<12x7xf32>} : () -> tensor<12x7xf32> |
| 19 | + %1 = "tosa.reciprocal"(%0) : (tensor<12x7xf32>) -> tensor<12x7xf32> |
| 20 | + return %1 : tensor<12x7xf32> |
| 21 | +} |
| 22 | + |
| 23 | +// CHECK-LABEL: @reciprocal_div_zero |
| 24 | +func.func @reciprocal_div_zero() -> tensor<f32> { |
| 25 | + // 0x7F800000 is the value for +infinity |
| 26 | + // CHECK: [[RES:]] ={{.*}}tosa.const{{.*}}0x7F800000 |
| 27 | + // CHECK-NOT: tosa.reciprocal |
| 28 | + // CHECK: return [[RES]] |
| 29 | + %0 = "tosa.const"() {value = dense<0.0> : tensor<f32>} : () -> tensor<f32> |
| 30 | + %1 = "tosa.reciprocal"(%0) : (tensor<f32>) -> tensor<f32> |
| 31 | + return %1 : tensor<f32> |
| 32 | +} |
| 33 | + |
| 34 | +// CHECK-LABEL: @reciprocal_div_neg_zero |
| 35 | +func.func @reciprocal_div_neg_zero() -> tensor<f32> { |
| 36 | + // 0xFF800000 is the value for -infinity |
| 37 | + // CHECK: [[RES:]] ={{.*}}tosa.const{{.*}}0xFF800000 |
| 38 | + // CHECK-NOT: tosa.reciprocal |
| 39 | + // CHECK: return [[RES]] |
| 40 | + %0 = "tosa.const"() {value = dense<-0.0> : tensor<f32>} : () -> tensor<f32> |
| 41 | + %1 = "tosa.reciprocal"(%0) : (tensor<f32>) -> tensor<f32> |
| 42 | + return %1 : tensor<f32> |
| 43 | +} |
| 44 | + |
| 45 | +// CHECK-LABEL: @reciprocal_div_nan |
| 46 | +func.func @reciprocal_div_nan() -> tensor<f32> { |
| 47 | + // 0x7FC00000 is the value for NAN |
| 48 | + // CHECK: [[RES:]] ={{.*}}tosa.const{{.*}}0x7FC00000 |
| 49 | + // CHECK-NOT: tosa.reciprocal |
| 50 | + // CHECK: return [[RES]] |
| 51 | + %0 = "tosa.const"() {value = dense<0x7FC00000> : tensor<f32>} : () -> tensor<f32> |
| 52 | + %1 = "tosa.reciprocal"(%0) : (tensor<f32>) -> tensor<f32> |
| 53 | + return %1 : tensor<f32> |
| 54 | +} |
| 55 | + |
| 56 | +// CHECK-LABEL: @reciprocal_div_infinity |
| 57 | +func.func @reciprocal_div_infinity() -> tensor<f32> { |
| 58 | + // CHECK: [[RES:]] ={{.*}}tosa.const{{.*}}<0.{{0*}}e+00> |
| 59 | + // CHECK-NOT: tosa.reciprocal |
| 60 | + // CHECK: return [[RES]] |
| 61 | + %0 = "tosa.const"() {value = dense<0x7F800000> : tensor<f32>} : () -> tensor<f32> |
| 62 | + %1 = "tosa.reciprocal"(%0) : (tensor<f32>) -> tensor<f32> |
| 63 | + return %1 : tensor<f32> |
| 64 | +} |
| 65 | + |
| 66 | +// CHECK-LABEL: @reciprocal_div_neg_infinity |
| 67 | +func.func @reciprocal_div_neg_infinity() -> tensor<f32> { |
| 68 | + // CHECK: [[RES:]] ={{.*}}tosa.const{{.*}}<-0.{{0*}}e+00> |
| 69 | + // CHECK-NOT: tosa.reciprocal |
| 70 | + // CHECK: return [[RES]] |
| 71 | + %0 = "tosa.const"() {value = dense<0xFF800000> : tensor<f32>} : () -> tensor<f32> |
| 72 | + %1 = "tosa.reciprocal"(%0) : (tensor<f32>) -> tensor<f32> |
| 73 | + return %1 : tensor<f32> |
| 74 | +} |
| 75 | + |
| 76 | +// CHECK-LABEL: @reciprocal_no_fold |
| 77 | +// The folding optimization works only intra-procedurally, so we won't be able |
| 78 | +// to fold anything here |
| 79 | +func.func @reciprocal_no_fold(%arg0: tensor<?x?xf32>) -> tensor<?x?xf32> { |
| 80 | + // CHECK: tosa.reciprocal |
| 81 | + // CHECK-NEXT: return |
| 82 | + %0 = "tosa.reciprocal"(%arg0) : (tensor<?x?xf32>) -> tensor<?x?xf32> |
| 83 | + return %0 : tensor<?x?xf32> |
| 84 | +} |
| 85 | + |
| 86 | +// CHECK-LABEL: @reciprocal_fold |
| 87 | +func.func @reciprocal_fold() -> tensor<4x6xf32> { |
| 88 | + // CHECK: [[RES:]] ={{.*}}tosa.const |
| 89 | + // CHECK-SAME{LITERAL}: [[5.68828249, 11.4416485, 1.6880486, 0.680272102, -0.875350117, 0.342313349], |
| 90 | + // CHECK-SAME{LITERAL}: [-4.81231928, 0.698080301, 0.65432179, -82.6446304, -4.33651352, -0.747551739], |
| 91 | + // CHECK-SAME{LITERAL}: [-12.4378109, 13.140605, 1.89501607, 0.885582745, 4.08830738, 1.4396776], |
| 92 | + // CHECK-SAME{LITERAL}: [2.02880907, -1.53280187, 0.552730501, 7.15819644, 0.64495325, -0.973709881]] |
| 93 | + // CHECK-NOT: tosa.reciprocal |
| 94 | + // CHECK: return [[RES]] |
| 95 | + %0 = "tosa.const"() { value = dense<[ |
| 96 | + [ 0.1758, 0.0874, 0.5924, 1.4700, -1.1424, 2.9213], |
| 97 | + [-0.2078, 1.4325, 1.5283, -0.0121, -0.2306, -1.3377], |
| 98 | + [-0.0804, 0.0761, 0.5277, 1.1292, 0.2446, 0.6946], |
| 99 | + [ 0.4929, -0.6524, 1.8092, 0.1397, 1.5505, -1.0270]]> |
| 100 | + : tensor<4x6xf32> |
| 101 | + } : () -> tensor<4x6xf32> |
| 102 | + %1 = "tosa.reciprocal"(%0) : (tensor<4x6xf32>) -> tensor<4x6xf32> |
| 103 | + return %1 : tensor<4x6xf32> |
| 104 | +} |
| 105 | + |
| 106 | +// CHECK-LABEL: @reciprocal_of_const_sparse |
| 107 | +// Sparse tensors are currently not supported |
| 108 | +func.func @reciprocal_of_const_sparse() -> tensor<32xbf16> { |
| 109 | + // CHECK: tosa.const |
| 110 | + // CHECK: tosa.reciprocal |
| 111 | + %0 = "tosa.const"() { value = sparse< |
| 112 | + [[0], [3], [11], [17], [20], [23], [25], [30], [31]], |
| 113 | + [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]> |
| 114 | + : tensor<32xbf16> } : () -> tensor<32xbf16> |
| 115 | + %1 = "tosa.reciprocal"(%0) : (tensor<32xbf16>) -> tensor<32xbf16> |
| 116 | + return %1 : tensor<32xbf16> |
| 117 | +} |
0 commit comments