1// RUN: mlir-opt --split-input-file --tosa-layerwise-constant-fold %s | FileCheck %s 2 3// CHECK-LABEL: @reciprocal_fold_single_valued 4func.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 14func.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 24func.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 35func.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 46func.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 57func.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 67func.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_div_underflow 77func.func @reciprocal_div_underflow() -> tensor<2xf16> { 78 // CHECK: [[RES:]] ={{.*}}tosa.const{{.*}}-0.{{0*}}e+00, 0.{{0*}}e+00 79 // CHECK-NOT: tosa.reciprocal 80 // CHECK: return [[RES]] 81 %0 = "tosa.const"() {value = dense<[-6.0e+15, 6.0e+15]> : tensor<2xf16>} : () -> tensor<2xf16> 82 %1 = "tosa.reciprocal"(%0) : (tensor<2xf16>) -> tensor<2xf16> 83 return %1 : tensor<2xf16> 84} 85 86// CHECK-LABEL: @reciprocal_div_overflow 87func.func @reciprocal_div_overflow() -> tensor<2xf16> { 88 // CHECK: [[RES:]] ={{.*}}tosa.const{{.*}}0x7C00, 0xFC00 89 // CHECK-NOT: tosa.reciprocal 90 // CHECK: return [[RES]] 91 %0 = "tosa.const"() {value = dense<[0.0000001, -0.0000001]> : tensor<2xf16>} : () -> tensor<2xf16> 92 %1 = "tosa.reciprocal"(%0) : (tensor<2xf16>) -> tensor<2xf16> 93 return %1 : tensor<2xf16> 94} 95 96// CHECK-LABEL: @reciprocal_no_fold 97// The folding optimization works only intra-procedurally, so we won't be able 98// to fold anything here 99func.func @reciprocal_no_fold(%arg0: tensor<?x?xf32>) -> tensor<?x?xf32> { 100 // CHECK: tosa.reciprocal 101 // CHECK-NEXT: return 102 %0 = "tosa.reciprocal"(%arg0) : (tensor<?x?xf32>) -> tensor<?x?xf32> 103 return %0 : tensor<?x?xf32> 104} 105 106// CHECK-LABEL: @reciprocal_fold 107func.func @reciprocal_fold() -> tensor<4x6xf32> { 108 // CHECK: [[RES:]] ={{.*}}tosa.const 109 // CHECK-SAME{LITERAL}: [[5.68828249, 11.4416485, 1.6880486, 0.680272102, -0.875350117, 0.342313349], 110 // CHECK-SAME{LITERAL}: [-4.81231928, 0.698080301, 0.65432179, -82.6446304, -4.33651352, -0.747551739], 111 // CHECK-SAME{LITERAL}: [-12.4378109, 13.140605, 1.89501607, 0.885582745, 4.08830738, 1.4396776], 112 // CHECK-SAME{LITERAL}: [2.02880907, -1.53280187, 0.552730501, 7.15819644, 0.64495325, -0.973709881]] 113 // CHECK-NOT: tosa.reciprocal 114 // CHECK: return [[RES]] 115 %0 = "tosa.const"() { value = dense<[ 116 [ 0.1758, 0.0874, 0.5924, 1.4700, -1.1424, 2.9213], 117 [-0.2078, 1.4325, 1.5283, -0.0121, -0.2306, -1.3377], 118 [-0.0804, 0.0761, 0.5277, 1.1292, 0.2446, 0.6946], 119 [ 0.4929, -0.6524, 1.8092, 0.1397, 1.5505, -1.0270]]> 120 : tensor<4x6xf32> 121 } : () -> tensor<4x6xf32> 122 %1 = "tosa.reciprocal"(%0) : (tensor<4x6xf32>) -> tensor<4x6xf32> 123 return %1 : tensor<4x6xf32> 124} 125 126// CHECK-LABEL: @reciprocal_of_const_sparse 127// Sparse tensors are currently not supported 128func.func @reciprocal_of_const_sparse() -> tensor<32xbf16> { 129 // CHECK: tosa.const 130 // CHECK: tosa.reciprocal 131 %0 = "tosa.const"() { value = sparse< 132 [[0], [3], [11], [17], [20], [23], [25], [30], [31]], 133 [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]> 134 : tensor<32xbf16> } : () -> tensor<32xbf16> 135 %1 = "tosa.reciprocal"(%0) : (tensor<32xbf16>) -> tensor<32xbf16> 136 return %1 : tensor<32xbf16> 137} 138