brintos

brintos / llvm-project-archived public Read only

0
0
Text · 36.1 KiB · b3f4260 Raw
584 lines · plain
1// RUN: mlir-opt --verify-diagnostics --split-input-file --verify-each --tosa-reduce-transposes %s | FileCheck %s2 3// CHECK-LABEL: @test_transpose_tracks_to_nullifying_single_step4// CHECK-NEXT: %[[RESULT:.*]] = tosa.ceil %arg05// CHECK-NEXT: return %[[RESULT]]6func.func @test_transpose_tracks_to_nullifying_single_step(%arg0: tensor<1x2x3x4xi32>) -> tensor<1x2x3x4xi32> {7  %0 = tosa.transpose %arg0 {perms = array<i32: 0, 2, 3, 1>}: (tensor<1x2x3x4xi32>) -> tensor<1x3x4x2xi32>8  %ceil = tosa.ceil %0 : (tensor<1x3x4x2xi32>) -> tensor<1x3x4x2xi32>9  %1 = tosa.transpose %ceil {perms = array<i32: 0, 3, 1, 2>}: (tensor<1x3x4x2xi32>) -> tensor<1x2x3x4xi32>10  return %1 : tensor<1x2x3x4xi32>11}12 13// -----14 15// CHECK-LABEL: @test_transpose_tracks_to_nullifying_multi_unary_step16// CHECK-NEXT: %[[CLAMP:.*]] = tosa.clamp %arg017// CHECK-NEXT: %[[ABS:.*]] = tosa.abs %[[CLAMP]]18// CHECK-NEXT: %[[NOT:.*]] = tosa.bitwise_not %[[ABS]]19// CHECK-NEXT: return %[[NOT]]20func.func @test_transpose_tracks_to_nullifying_multi_unary_step(%arg0: tensor<1x2x3x4xi32>) -> tensor<1x2x3x4xi32> {21  %0 = tosa.transpose %arg0 {perms = array<i32: 0, 2, 3, 1>}: (tensor<1x2x3x4xi32>) -> tensor<1x3x4x2xi32>22  %clamp = tosa.clamp %0 {max_val = 1 : i32, min_val = 0 : i32} : (tensor<1x3x4x2xi32>) -> tensor<1x3x4x2xi32>23  %abs = tosa.abs %clamp : (tensor<1x3x4x2xi32>) -> tensor<1x3x4x2xi32>24  %bitwise_not = tosa.bitwise_not %abs : (tensor<1x3x4x2xi32>) -> tensor<1x3x4x2xi32>25  %1 = tosa.transpose %bitwise_not {perms = array<i32: 0, 3, 1, 2>}: (tensor<1x3x4x2xi32>) -> tensor<1x2x3x4xi32>26  return %1 : tensor<1x2x3x4xi32>27}28 29// -----30 31// CHECK-LABEL: @test_transpose_tracks_to_nullifying_diverging_binary32// CHECK-NEXT: %[[CLAMP:.*]] = tosa.clamp %arg033// CHECK-NEXT: %[[ABS:.*]] = tosa.abs %arg134// CHECK-NEXT: %[[ADD:.*]] = tosa.add %[[CLAMP]], %[[ABS]]35// CHECK-NEXT: return %[[ADD]]36func.func @test_transpose_tracks_to_nullifying_diverging_binary(%arg0: tensor<1x2x3x4xi32>, %arg1: tensor<1x2x3x4xi32>) -> tensor<1x2x3x4xi32> {37  %transpose0 = tosa.transpose %arg0 {perms = array<i32: 0, 2, 3, 1>}: (tensor<1x2x3x4xi32>) -> tensor<1x3x4x2xi32>38  %transpose1 = tosa.transpose %arg1 {perms = array<i32: 0, 2, 3, 1>}: (tensor<1x2x3x4xi32>) -> tensor<1x3x4x2xi32>39  %clamp = tosa.clamp %transpose0 {max_val = 1 : i32, min_val = 0 : i32} : (tensor<1x3x4x2xi32>) -> tensor<1x3x4x2xi32>40  %abs = tosa.abs %transpose1 : (tensor<1x3x4x2xi32>) -> tensor<1x3x4x2xi32>41  %add = tosa.add %clamp, %abs : (tensor<1x3x4x2xi32>, tensor<1x3x4x2xi32>) -> tensor<1x3x4x2xi32>42  %result = tosa.transpose %add {perms = array<i32: 0, 3, 1, 2>}: (tensor<1x3x4x2xi32>) -> tensor<1x2x3x4xi32>43  return %result : tensor<1x2x3x4xi32>44}45 46// -----47 48 49// CHECK-LABEL: @test_transpose_tracks_to_nullifying_diverging_binary_with_broadcasting50// CHECK-NEXT: %[[CLAMP:.*]] = tosa.clamp %arg051// CHECK-NEXT: %[[ABS:.*]] = tosa.abs %arg152// CHECK-NEXT: %[[ADD:.*]] = tosa.add %[[CLAMP]], %[[ABS]]53// CHECK-NEXT: return %[[ADD]]54func.func @test_transpose_tracks_to_nullifying_diverging_binary_with_broadcasting(%arg0: tensor<1x2x3x4xi32>, %arg1: tensor<1x2x1x4xi32>) -> tensor<1x2x3x4xi32> {55  %transpose0 = tosa.transpose %arg0 {perms = array<i32: 0, 2, 3, 1>}: (tensor<1x2x3x4xi32>) -> tensor<1x3x4x2xi32>56  %transpose1 = tosa.transpose %arg1 {perms = array<i32: 0, 2, 3, 1>}: (tensor<1x2x1x4xi32>) -> tensor<1x1x4x2xi32>57  %clamp = tosa.clamp %transpose0 {max_val = 1 : i32, min_val = 0 : i32} : (tensor<1x3x4x2xi32>) -> tensor<1x3x4x2xi32>58  %abs = tosa.abs %transpose1 : (tensor<1x1x4x2xi32>) -> tensor<1x1x4x2xi32>59  %add = tosa.add %clamp, %abs : (tensor<1x3x4x2xi32>, tensor<1x1x4x2xi32>) -> tensor<1x3x4x2xi32>60  %result = tosa.transpose %add {perms = array<i32: 0, 3, 1, 2>}: (tensor<1x3x4x2xi32>) -> tensor<1x2x3x4xi32>61  return %result : tensor<1x2x3x4xi32>62}63 64// -----65 66// CHECK-LABEL: @test_transpose_tracks_to_nullifying__converging_binary67// CHECK-NEXT: %[[RESULT:.*]] = tosa.add %arg0, %arg068// CHECK-NEXT: return %[[RESULT]]69func.func @test_transpose_tracks_to_nullifying__converging_binary(%arg0: tensor<1x2x3x4xi32>) -> tensor<1x2x3x4xi32> {70  %0 = tosa.transpose %arg0 {perms = array<i32: 0, 2, 3, 1>}: (tensor<1x2x3x4xi32>) -> tensor<1x3x4x2xi32>71  %clamp = tosa.add %0, %0 : (tensor<1x3x4x2xi32>, tensor<1x3x4x2xi32>) -> tensor<1x3x4x2xi32>72  %1 = tosa.transpose %clamp {perms = array<i32: 0, 3, 1, 2>}: (tensor<1x3x4x2xi32>) -> tensor<1x2x3x4xi32>73  return %1 : tensor<1x2x3x4xi32>74}75 76// -----77 78// CHECK-LABEL: @test_torch_conv2d_with_elementwise_in_between79// CHECK: %[[CONV1:.*]] = tosa.conv2d80// CHECK: %[[CEIL:.*]] = tosa.ceil %[[CONV1]]81// CHECK: %[[CONV2:.*]] = tosa.conv2d %[[CEIL]]82// CHECK: %[[FLOOR:.*]] = tosa.floor %[[CONV2]]83// CHECK: %[[CONV3:.*]] = tosa.conv2d %[[FLOOR]]84// CHECK: %[[RES:.*]] = tosa.transpose %[[CONV3]]85// CHECK: return %[[RES]]86func.func @test_torch_conv2d_with_elementwise_in_between(%arg0: tensor<3x3x10x10xf32>) -> tensor<3x3x7x7xf32> {87    %input_zp = "tosa.const"() <{values = dense<0.0> : tensor<1xf32>}> : () -> tensor<1xf32>88    %weight_zp = "tosa.const"() <{values = dense<0.0> : tensor<1xf32>}> : () -> tensor<1xf32>89    %0 = "tosa.const"() <{values = dense_resource<torch_tensor_3_torch.float32_2> : tensor<3xf32>}> : () -> tensor<3xf32>90    %1 = "tosa.const"() <{values = dense_resource<torch_tensor_3_3_2_2_torch.float32_2> : tensor<3x3x2x2xf32>}> : () -> tensor<3x3x2x2xf32>91    %2 = "tosa.const"() <{values = dense_resource<torch_tensor_3_torch.float32_1> : tensor<3xf32>}> : () -> tensor<3xf32>92    %3 = "tosa.const"() <{values = dense_resource<torch_tensor_3_3_2_2_torch.float32_1> : tensor<3x3x2x2xf32>}> : () -> tensor<3x3x2x2xf32>93    %4 = "tosa.const"() <{values = dense_resource<torch_tensor_3_3_2_2_torch.float32> : tensor<3x3x2x2xf32>}> : () -> tensor<3x3x2x2xf32>94    %5 = "tosa.const"() <{values = dense_resource<torch_tensor_3_torch.float32> : tensor<3xf32>}> : () -> tensor<3xf32>95    %6 = "tosa.const"() <{values = dense<[0, 2, 3, 1]> : tensor<4xi32>}> : () -> tensor<4xi32>96    %7 = "tosa.const"() <{values = dense<[0, 3, 1, 2]> : tensor<4xi32>}> : () -> tensor<4xi32>97    %8 = tosa.transpose %arg0 {perms = array<i32: 0, 2, 3, 1>}: (tensor<3x3x10x10xf32>) -> tensor<3x10x10x3xf32>98    %9 = tosa.transpose %4 {perms = array<i32: 0, 2, 3, 1>}: (tensor<3x3x2x2xf32>) -> tensor<3x2x2x3xf32>99    %10 = tosa.conv2d %8, %9, %5, %input_zp, %weight_zp {acc_type = f32, dilation = array<i64: 1, 1>, pad = array<i64: 0, 0, 0, 0>, stride = array<i64: 1, 1>} : (tensor<3x10x10x3xf32>, tensor<3x2x2x3xf32>, tensor<3xf32>, tensor<1xf32>, tensor<1xf32>) -> tensor<3x9x9x3xf32>100    %11 = tosa.transpose %10 {perms = array<i32: 0, 3, 1, 2>}: (tensor<3x9x9x3xf32>) -> tensor<3x3x9x9xf32>101    %12 = tosa.ceil %11 : (tensor<3x3x9x9xf32>) -> tensor<3x3x9x9xf32>102    %13 = tosa.transpose %12 {perms = array<i32: 0, 2, 3, 1>}: (tensor<3x3x9x9xf32>) -> tensor<3x9x9x3xf32>103    %14 = tosa.transpose %3 {perms = array<i32: 0, 2, 3, 1>}: (tensor<3x3x2x2xf32>) -> tensor<3x2x2x3xf32>104    %15 = tosa.conv2d %13, %14, %2, %input_zp, %weight_zp {acc_type = f32, dilation = array<i64: 1, 1>, pad = array<i64: 0, 0, 0, 0>, stride = array<i64: 1, 1>} : (tensor<3x9x9x3xf32>, tensor<3x2x2x3xf32>, tensor<3xf32>, tensor<1xf32>, tensor<1xf32>) -> tensor<3x8x8x3xf32>105    %16 = tosa.transpose %15 {perms = array<i32: 0, 3, 1, 2>}: (tensor<3x8x8x3xf32>) -> tensor<3x3x8x8xf32>106    %17 = tosa.floor %16 : (tensor<3x3x8x8xf32>) -> tensor<3x3x8x8xf32>107    %18 = tosa.transpose %17 {perms = array<i32: 0, 2, 3, 1>}: (tensor<3x3x8x8xf32>) -> tensor<3x8x8x3xf32>108    %19 = tosa.transpose %1 {perms = array<i32: 0, 2, 3, 1>}: (tensor<3x3x2x2xf32>) -> tensor<3x2x2x3xf32>109    %20 = tosa.conv2d %18, %19, %0, %input_zp, %weight_zp {acc_type = f32, dilation = array<i64: 1, 1>, pad = array<i64: 0, 0, 0, 0>, stride = array<i64: 1, 1>} : (tensor<3x8x8x3xf32>, tensor<3x2x2x3xf32>, tensor<3xf32>, tensor<1xf32>, tensor<1xf32>) -> tensor<3x7x7x3xf32>110    %21 = tosa.transpose %20 {perms = array<i32: 0, 3, 1, 2>}: (tensor<3x7x7x3xf32>) -> tensor<3x3x7x7xf32>111    return %21 : tensor<3x3x7x7xf32>112}113 114// -----115 116// CHECK-LABEL: @test_mulop_conversion117// CHECK-NEXT: %[[SHIFT:.*]] = "tosa.const"() <{values = dense<0> : tensor<1xi8>}> : () -> tensor<1xi8>118// CHECK-NEXT: %[[RES:.*]] = tosa.mul %arg0, %arg1, %[[SHIFT]]119// CHECK-NEXT: return %[[RES]]120func.func @test_mulop_conversion(%arg0: tensor<1x2x3x4xi32>, %arg1: tensor<1x2x3x4xi32>) -> tensor<1x2x3x4xi32> {121  %transpose0 = tosa.transpose %arg0 {perms = array<i32: 0, 2, 3, 1>}: (tensor<1x2x3x4xi32>) -> tensor<1x3x4x2xi32>122  %transpose1 = tosa.transpose %arg1 {perms = array<i32: 0, 2, 3, 1>}: (tensor<1x2x3x4xi32>) -> tensor<1x3x4x2xi32>123  %shift = "tosa.const"() <{values = dense<0> : tensor<1xi8>}> : () -> tensor<1xi8>124  %mul = tosa.mul %transpose0, %transpose1, %shift : (tensor<1x3x4x2xi32>, tensor<1x3x4x2xi32>, tensor<1xi8>) -> tensor<1x3x4x2xi32>125  %result = tosa.transpose %mul {perms = array<i32: 0, 3, 1, 2>}: (tensor<1x3x4x2xi32>) -> tensor<1x2x3x4xi32>126  return %result : tensor<1x2x3x4xi32>127}128 129// -----130 131// COM: this case is a reshape we don't convert, since can't fold the transpose into it.132// COM: a transform actually occurs underneath the hood, but it results in identical IR.133// CHECK-LABEL: @test_basic_non_broadcasting_reshape134// CHECK: %[[SHAPE:.+]] = tosa.const_shape {values = dense<[1, 3, 2]> : tensor<3xindex>}135// CHECK: %[[RESHAPED:.+]] = tosa.reshape %arg0, %[[SHAPE]] : (tensor<2x3xi32>, !tosa.shape<3>) -> tensor<1x3x2xi32>136// CHECK: tosa.transpose %[[RESHAPED]] {perms = array<i32: 0, 2, 1>} : (tensor<1x3x2xi32>) -> tensor<1x2x3xi32>137func.func @test_basic_non_broadcasting_reshape(%arg0: tensor<2x3xi32>) -> tensor<1x2x3xi32> {138  %shape = tosa.const_shape {values = dense<[1, 3, 2]> : tensor<3xindex>} : () -> !tosa.shape<3>139  %1 = tosa.reshape %arg0, %shape : (tensor<2x3xi32>, !tosa.shape<3>) -> tensor<1x3x2xi32>140  %2 = tosa.transpose %1 {perms = array<i32: 0, 2, 1>}: (tensor<1x3x2xi32>) -> tensor<1x2x3xi32>141  return %2 : tensor<1x2x3xi32>142}143 144// -----145 146// CHECK-LABEL: @test_dynamic_broadcasting_reshape147// CHECK-DAG: %[[SHAPE:.*]] = tosa.const_shape  {values = dense<[1, 1, -1]> : tensor<3xindex>}148// CHECK: %[[RES:.*]] = tosa.reshape %arg0, %[[SHAPE]] : (tensor<?xi32>, !tosa.shape<3>) -> tensor<1x1x?xi32>149// CHECK: return %[[RES]]150func.func @test_dynamic_broadcasting_reshape(%arg0: tensor<?xi32>) -> tensor<1x1x?xi32> {151  %shape = tosa.const_shape {values = dense<[1, -1, 1]> : tensor<3xindex>} : () -> !tosa.shape<3>152  %1 = tosa.reshape %arg0, %shape : (tensor<?xi32>, !tosa.shape<3>) -> tensor<1x?x1xi32>153  %2 = tosa.transpose %1 {perms = array<i32: 0, 2, 1>}: (tensor<1x?x1xi32>) -> tensor<1x1x?xi32>154  return %2 : tensor<1x1x?xi32>155}156 157// -----158 159// CHECK-LABEL: @test_reshape_for_broadcast160// CHECK-DAG: %[[RESHAPE_INPUT:.*]] = "tosa.const"() <{values = dense<[1, 2, 3, 4]>161// CHECK-DAG: %[[SHAPE:.*]] = tosa.const_shape  {values = dense<[4, 1, 1]> : tensor<3xindex>}162// CHECK: %[[RESHAPE:.*]] = tosa.reshape %[[RESHAPE_INPUT]], %[[SHAPE]] : (tensor<4xi32>, !tosa.shape<3>) -> tensor<4x1x1xi32>163// CHECK: %[[ADD:.*]] = tosa.add %arg0, %[[RESHAPE]]164// CHECK: return %[[ADD]]165func.func @test_reshape_for_broadcast(%arg0: tensor<4x3x2xi32>) -> tensor<4x3x2xi32> {166  %0 = "tosa.const"() {values = dense<[1,2,3,4]> : tensor<4xi32>} : () -> tensor<4xi32>167  %1 = tosa.const_shape {values = dense<[1, 1, 4]> : tensor<3xindex>} : () -> !tosa.shape<3>168  %reshape = tosa.reshape %0, %1 : (tensor<4xi32>, !tosa.shape<3>) -> tensor<1x1x4xi32>169  %transpose0 = tosa.transpose %arg0 {perms = array<i32: 2, 1, 0>}: (tensor<4x3x2xi32>) -> tensor<2x3x4xi32>170  %add = tosa.add %transpose0, %reshape : (tensor<2x3x4xi32>, tensor<1x1x4xi32>) -> tensor<2x3x4xi32>171  %transpose1 = tosa.transpose %add {perms = array<i32: 2, 1, 0>}: (tensor<2x3x4xi32>) -> tensor<4x3x2xi32>172  return %transpose1 : tensor<4x3x2xi32>173}174 175// -----176 177// COM: taken directly from ResNet18 translation.178// COM: changes: %74 as argument instead of result of conv2d179 180// CHECK-LABEL: @test_resnet18_common_case181// COM: note that %74 is now represented by %arg2182// CHECK-DAG: %[[CONST0:.+]] = "tosa.const"() <{values = dense<0> : tensor<1xi8>}> : () -> tensor<1xi8>183// CHECK-DAG: %[[VAL_3:.*]] = "tosa.const"() <{values = dense_resource<torch_tensor_64_torch.float32_1> : tensor<64xf32>}> : () -> tensor<64xf32>184// CHECK-DAG: %[[VAL_4:.*]] = "tosa.const"() <{values = dense_resource<torch_tensor_64_torch.float32> : tensor<64xf32>}> : () -> tensor<64xf32>185// CHECK-DAG: %[[VAL_5:.*]] = "tosa.const"() <{values = dense<9.99999974E-6> : tensor<1xf32>}> : () -> tensor<1xf32>186// CHECK-DAG: %[[VAL_6:.*]] = "tosa.const"() <{values = dense<5.000000e-01> : tensor<1xf32>}> : () -> tensor<1xf32>187// CHECK-DAG: %[[VAL_7:.*]] = tosa.add %arg1, %[[VAL_5]] : (tensor<64xf32>, tensor<1xf32>) -> tensor<64xf32>188// CHECK-DAG: %[[VAL_8:.*]] = tosa.pow %[[VAL_7]], %[[VAL_6]] : (tensor<64xf32>, tensor<1xf32>) -> tensor<64xf32>189// CHECK-DAG: %[[VAL_9:.*]] = tosa.reciprocal %[[VAL_8]] : (tensor<64xf32>) -> tensor<64xf32>190// CHECK-DAG: %[[VAL_10:.*]] = tosa.const_shape  {values = dense<[1, 1, 1, 64]> : tensor<4xindex>} : () -> !tosa.shape<4>191// CHECK-DAG: %[[VAL_11:.*]] = tosa.reshape %arg0, %[[VAL_10]] : (tensor<64xf32>, !tosa.shape<4>) -> tensor<1x1x1x64xf32>192// CHECK-DAG: %[[VAL_12:.*]] = tosa.sub %arg2, %[[VAL_11]] : (tensor<1x112x112x64xf32>, tensor<1x1x1x64xf32>) -> tensor<1x112x112x64xf32>193// CHECK-DAG: %[[VAL_13:.*]] = tosa.const_shape  {values = dense<[1, 1, 1, 64]> : tensor<4xindex>} : () -> !tosa.shape<4>194// CHECK-DAG: %[[VAL_14:.*]] = tosa.reshape %[[VAL_9]], %[[VAL_13]] : (tensor<64xf32>, !tosa.shape<4>) -> tensor<1x1x1x64xf32>195// CHECK-DAG: %[[VAL_15:.*]] = tosa.mul %[[VAL_12]], %[[VAL_14]], %[[CONST0]] : (tensor<1x112x112x64xf32>, tensor<1x1x1x64xf32>, tensor<1xi8>) -> tensor<1x112x112x64xf32>196// CHECK-DAG: %[[VAL_16:.*]] = tosa.const_shape  {values = dense<[1, 1, 1, 64]> : tensor<4xindex>} : () -> !tosa.shape<4>197// CHECK-DAG: %[[VAL_17:.*]] = tosa.reshape %[[VAL_4]], %[[VAL_16]] : (tensor<64xf32>, !tosa.shape<4>) -> tensor<1x1x1x64xf32>198// CHECK-DAG: %[[VAL_18:.*]] = tosa.mul %[[VAL_15]], %[[VAL_17]], %[[CONST0]] : (tensor<1x112x112x64xf32>, tensor<1x1x1x64xf32>, tensor<1xi8>) -> tensor<1x112x112x64xf32>199// CHECK-DAG: %[[VAL_19:.*]] = tosa.const_shape  {values = dense<[1, 1, 1, 64]> : tensor<4xindex>} : () -> !tosa.shape<4>200// CHECK-DAG: %[[VAL_20:.*]] = tosa.reshape %[[VAL_3]], %[[VAL_19]] : (tensor<64xf32>, !tosa.shape<4>) -> tensor<1x1x1x64xf32>201// CHECK-DAG: %[[VAL_21:.*]] = tosa.add %[[VAL_18]], %[[VAL_20]] : (tensor<1x112x112x64xf32>, tensor<1x1x1x64xf32>) -> tensor<1x112x112x64xf32>202// CHECK-DAG: %[[VAL_22:.*]] = tosa.clamp %[[VAL_21]] {max_val = 3.40282347E+38 : f32, min_val = 0.000000e+00 : f32} : (tensor<1x112x112x64xf32>) -> tensor<1x112x112x64xf32>203func.func @test_resnet18_common_case(%arg0: tensor<64xf32>, %arg1: tensor<64xf32>, %74: tensor<1x112x112x64xf32>) -> tensor<1x112x112x64xf32> {204    %shift = "tosa.const"() {values = dense<0> : tensor<1xi8>} : () -> tensor<1xi8>205    %58 = tosa.const_shape {values = dense<[1, 64, 1, 1]> : tensor<4xindex>} : () -> !tosa.shape<4>206    %59 = "tosa.const"() <{values = dense_resource<torch_tensor_64_torch.float32_1> : tensor<64xf32>}> : () -> tensor<64xf32>207    %60 = "tosa.const"() <{values = dense_resource<torch_tensor_64_torch.float32> : tensor<64xf32>}> : () -> tensor<64xf32>208    %63 = "tosa.const"() <{values = dense<[0, 2, 3, 1]> : tensor<4xi32>}> : () -> tensor<4xi32>209    %64 = "tosa.const"() <{values = dense<[0, 3, 1, 2]> : tensor<4xi32>}> : () -> tensor<4xi32>210    %69 = "tosa.const"() <{values = dense<9.99999974E-6> : tensor<1xf32>}> : () -> tensor<1xf32>211    %70 = "tosa.const"() <{values = dense<5.000000e-01> : tensor<1xf32>}> : () -> tensor<1xf32>212    %75 = tosa.transpose %74 {perms = array<i32: 0, 3, 1, 2>}: (tensor<1x112x112x64xf32>) -> tensor<1x64x112x112xf32>213    %76 = tosa.add %arg1, %69 : (tensor<64xf32>, tensor<1xf32>) -> tensor<64xf32>214    %77 = tosa.pow %76, %70 : (tensor<64xf32>, tensor<1xf32>) -> tensor<64xf32>215    %78 = tosa.reciprocal %77 : (tensor<64xf32>) -> tensor<64xf32>216    %79 = tosa.reshape %arg0, %58 : (tensor<64xf32>, !tosa.shape<4>) -> tensor<1x64x1x1xf32>217    %80 = tosa.sub %75, %79 : (tensor<1x64x112x112xf32>, tensor<1x64x1x1xf32>) -> tensor<1x64x112x112xf32>218    %81 = tosa.reshape %78, %58 : (tensor<64xf32>, !tosa.shape<4>) -> tensor<1x64x1x1xf32>219    %82 = tosa.mul %80, %81, %shift : (tensor<1x64x112x112xf32>, tensor<1x64x1x1xf32>, tensor<1xi8>) -> tensor<1x64x112x112xf32>220    %83 = tosa.reshape %60, %58 : (tensor<64xf32>, !tosa.shape<4>) -> tensor<1x64x1x1xf32>221    %84 = tosa.mul %82, %83, %shift : (tensor<1x64x112x112xf32>, tensor<1x64x1x1xf32>, tensor<1xi8>) -> tensor<1x64x112x112xf32>222    %85 = tosa.reshape %59, %58 : (tensor<64xf32>, !tosa.shape<4>) -> tensor<1x64x1x1xf32>223    %86 = tosa.add %84, %85 : (tensor<1x64x112x112xf32>, tensor<1x64x1x1xf32>) -> tensor<1x64x112x112xf32>224    %87 = tosa.clamp %86 {max_val = 3.40282347E+38 : f32, min_val = 0.000000e+00 : f32} : (tensor<1x64x112x112xf32>) -> tensor<1x64x112x112xf32>225    %88 = tosa.transpose %87 {perms = array<i32: 0, 2, 3, 1>}: (tensor<1x64x112x112xf32>) -> tensor<1x112x112x64xf32>226    return %88 : tensor<1x112x112x64xf32>227}228 229// -----230 231// CHECK-LABEL: @test_back_to_back_nullifiers232// CHECK: %[[RES:.*]] = tosa.transpose %arg0 {perms = array<i32: 1, 0>}233// CHECK: return %[[RES]]234func.func @test_back_to_back_nullifiers(%arg0: tensor<2x3xi32>) -> tensor<3x2xi32> {235  %0 = tosa.transpose %arg0 {perms = array<i32: 1, 0>}: (tensor<2x3xi32>) -> tensor<3x2xi32>236  %1 = tosa.transpose %0 {perms = array<i32: 1, 0>}: (tensor<3x2xi32>) -> tensor<2x3xi32>237  %2 = tosa.transpose %1 {perms = array<i32: 1, 0>}: (tensor<2x3xi32>) -> tensor<3x2xi32>238  return %2 : tensor<3x2xi32>239}240 241// -----242 243// CHECK-LABEL: @test_back_to_back_nullifiers_different_transposes244// CHECK: %[[RES:.*]] = tosa.transpose %arg0 {perms = array<i32: 0, 2, 3, 1>}245// CHECK: return %[[RES]]246func.func @test_back_to_back_nullifiers_different_transposes(%arg0: tensor<2x3x4x5xi32>) -> tensor<2x4x5x3xi32> {247  %0 = tosa.transpose %arg0 {perms = array<i32: 0, 2, 3, 1>}: (tensor<2x3x4x5xi32>) -> tensor<2x4x5x3xi32>248  %1 = tosa.transpose %0 {perms = array<i32: 0, 3, 1, 2>}: (tensor<2x4x5x3xi32>) -> tensor<2x3x4x5xi32>249  %2 = tosa.transpose %1 {perms = array<i32: 0, 2, 3, 1>}: (tensor<2x3x4x5xi32>) -> tensor<2x4x5x3xi32>250  return %2 : tensor<2x4x5x3xi32>251}252 253// -----254 255// CHECK-LABEL: @test_no_transform_if_outside_fan_in_cone256// CHECK: %[[CLAMP_IN:.*]] = tosa.transpose257// CHECK: %[[RES2:.*]] = tosa.clamp %[[CLAMP_IN]]258// CHECK: %[[RES1:.*]] = tosa.transpose259// CHECK: return %[[RES1]], %[[RES2]]260func.func @test_no_transform_if_outside_fan_in_cone(%arg0: tensor<3x3x3x3xi32>) -> (tensor<3x3x3x3xi32>, tensor<3x3x3x3xi32>) {261  %0 = tosa.transpose %arg0 {perms = array<i32: 0, 2, 3, 1>} : (tensor<3x3x3x3xi32>) -> tensor<3x3x3x3xi32>262  %clamp = tosa.clamp %0  {max_val = 2147483647 : i32, min_val = 0 : i32} : (tensor<3x3x3x3xi32>) -> tensor<3x3x3x3xi32>263  %1 = tosa.transpose %clamp {perms = array<i32: 0, 3, 1, 2>} : (tensor<3x3x3x3xi32>) -> tensor<3x3x3x3xi32>264  return %1, %clamp : tensor<3x3x3x3xi32>, tensor<3x3x3x3xi32>265}266 267// -----268 269// CHECK-LABEL: @test_two_different_downstream_converge_to_reshape_same_perms270// CHECK-DAG: %[[RESHAPE:.*]] = tosa.reshape %arg0271// CHECK-DAG: %[[CLAMP:.*]] = tosa.clamp %[[RESHAPE]]272// CHECK: return %[[RESHAPE]], %[[CLAMP]]273func.func @test_two_different_downstream_converge_to_reshape_same_perms(%arg0: tensor<64xf32>) -> (tensor<1x1x64xf32>, tensor<1x1x64xf32>) {274  %0 = "tosa.const"() <{values = dense<[0, 2, 1]> : tensor<3xi32>}> : () -> tensor<3xi32>275  %shape = tosa.const_shape {values = dense<[1, 64, 1]> : tensor<3xindex>} : () -> !tosa.shape<3>276  %1 = tosa.reshape %arg0, %shape : (tensor<64xf32>, !tosa.shape<3>) -> tensor<1x64x1xf32>277  %2 = tosa.clamp %1 {max_val = 3.40282347E+38 : f32, min_val = 0.000000e+00 : f32} : (tensor<1x64x1xf32>) -> tensor<1x64x1xf32>278  %3 = tosa.transpose %1 {perms = array<i32: 0, 2, 1>}: (tensor<1x64x1xf32>) -> tensor<1x1x64xf32>279  %4 = tosa.transpose %2 {perms = array<i32: 0, 2, 1>}: (tensor<1x64x1xf32>) -> tensor<1x1x64xf32>280  return %3, %4 : tensor<1x1x64xf32>, tensor<1x1x64xf32>281}282 283// -----284 285// CHECK-LABEL: @test_two_different_downstream_converge_to_reshape_different_perms286// CHECK-DAG: %[[RESHAPE:.*]] = tosa.reshape287// CHECK-DAG: %[[CLAMP:.*]] = tosa.clamp %[[RESHAPE]]288// CHECK-DAG: %[[RET1:.*]] = tosa.transpose289// CHECK-DAG: %[[RET2:.*]] = tosa.transpose290// CHECK-DAG: return %[[RET1]], %[[RET2]]291func.func @test_two_different_downstream_converge_to_reshape_different_perms(%arg0: tensor<64xf32>) -> (tensor<1x1x64xf32>, tensor<64x1x1xf32>) {292  %shape = tosa.const_shape {values = dense<[1, 64, 1]> : tensor<3xindex>} : () -> !tosa.shape<3>293  %2 = tosa.reshape %arg0, %shape : (tensor<64xf32>, !tosa.shape<3>) -> tensor<1x64x1xf32>294  %3 = tosa.clamp %2 {max_val = 3.40282347E+38 : f32, min_val = 0.000000e+00 : f32} : (tensor<1x64x1xf32>) -> tensor<1x64x1xf32>295  %4 = tosa.transpose %2 {perms = array<i32: 0, 2, 1>}: (tensor<1x64x1xf32>) -> tensor<1x1x64xf32>296  %5 = tosa.transpose %3 {perms = array<i32: 1, 2, 0>}: (tensor<1x64x1xf32>) -> tensor<64x1x1xf32>297  return %4, %5 : tensor<1x1x64xf32>, tensor<64x1x1xf32>298}299 300// -----301 302// COM: no transform303// CHECK-LABEL: @test_outside_perms_usage_of_fan_in304// CHECK: tosa.transpose305// CHECK: tosa.clamp306// CHECK: %[[RES1:.*]] = tosa.transpose307// CHECK: %[[RES2:.*]] = tosa.add308// CHECK: return %[[RES1]], %[[RES2]]309func.func @test_outside_perms_usage_of_fan_in(%arg0: tensor<2x3xf32>, %arg1: tensor<3x2xf32>) -> (tensor<2x3xf32>, tensor<3x2xf32>) {310  %1 = tosa.transpose %arg0 {perms = array<i32: 1, 0>}: (tensor<2x3xf32>) -> tensor<3x2xf32>311  %2 = tosa.clamp %1  {max_val = 3.40282347E+38 : f32, min_val = 0.000000e+00 : f32} : (tensor<3x2xf32>) -> tensor<3x2xf32>312  %3 = tosa.transpose %2 {perms = array<i32: 1, 0>}: (tensor<3x2xf32>) -> tensor<2x3xf32>313  %4 = tosa.add %arg1, %2 : (tensor<3x2xf32>, tensor<3x2xf32>) -> tensor<3x2xf32>314  return %3, %4: tensor<2x3xf32>, tensor<3x2xf32>315}316 317// -----318 319// COM: this use-case is important for ResNet. we want to allow these, but disallow if falls into an illegal area (outside fan-ins that get converted),320// COM: since then we would get duplicate ops.321// CHECK-LABEL: @test_use_present_in_another_valid_perms_fan_in322// CHECK-DAG: %[[NEW_CLAMP:.*]] = tosa.clamp %arg0323// CHECK-DAG: %[[NEW_ADD:.*]] = tosa.add %arg1, %[[NEW_CLAMP]]324// CHECK: return %[[NEW_CLAMP]], %[[NEW_ADD]]325func.func @test_use_present_in_another_valid_perms_fan_in(%arg0: tensor<2x3xf32>, %arg1: tensor<2x3xf32>) -> (tensor<2x3xf32>, tensor<2x3xf32>) {326  %1 = tosa.transpose %arg0 {perms = array<i32: 1, 0>}: (tensor<2x3xf32>) -> tensor<3x2xf32>327  %2 = tosa.clamp %1  {max_val = 3.40282347E+38 : f32, min_val = 0.000000e+00 : f32} : (tensor<3x2xf32>) -> tensor<3x2xf32>328  %3 = tosa.transpose %2 {perms = array<i32: 1, 0>}: (tensor<3x2xf32>) -> tensor<2x3xf32>329  %4 = tosa.transpose %arg1 {perms = array<i32: 1, 0>}: (tensor<2x3xf32>) -> tensor<3x2xf32>330  %5 = tosa.add %4, %2 : (tensor<3x2xf32>, tensor<3x2xf32>) -> tensor<3x2xf32>331  %6 = tosa.transpose %5 {perms = array<i32: 1, 0>}: (tensor<3x2xf32>) -> tensor<2x3xf32>332  return %3, %6: tensor<2x3xf32>, tensor<2x3xf32>333}334 335// -----336 337// COM: no transform, since we would get duplicates338// CHECK-LABEL: @test_two_same_perms_fan_in_but_one_doesnt_convert_dependents339// CHECK: tosa.transpose340// CHECK: %[[CEIL:.*]] = tosa.ceil341// CHECK: %[[ADD:.*]] = tosa.add %[[CEIL]]342// CHECK: %[[RES1:.*]] = tosa.transpose %[[CEIL]]343// CHECK: %[[RES2:.*]] = tosa.transpose %[[ADD]]344// CHECK: return %[[RES1]], %[[RES2]]345func.func @test_two_same_perms_fan_in_but_one_doesnt_convert_dependents(%arg0: tensor<2x3xi32>, %arg1: tensor<3x2xi32>) -> (tensor<2x3xi32>, tensor<2x3xi32>) {346  %1 = tosa.transpose %arg0 {perms = array<i32: 1, 0>}: (tensor<2x3xi32>) -> tensor<3x2xi32>347  %2 = tosa.ceil %1 : (tensor<3x2xi32>) -> tensor<3x2xi32>348  %3 = tosa.add %2, %arg1 : (tensor<3x2xi32>, tensor<3x2xi32>) -> tensor<3x2xi32>349  %4 = tosa.transpose %2 {perms = array<i32: 1, 0>}: (tensor<3x2xi32>) -> tensor<2x3xi32>350  %5 = tosa.transpose %3 {perms = array<i32: 1, 0>}: (tensor<3x2xi32>) -> tensor<2x3xi32>351  return %4, %5 : tensor<2x3xi32>, tensor<2x3xi32>352}353 354// -----355 356// CHECK-LABEL: @test_direct_use_in_other_transpose_with_same_perms357// CHECK-NEXT: %[[RES:.*]] = tosa.clamp %arg0358// CHECK-NEXT: return %[[RES]], %[[RES]]359func.func @test_direct_use_in_other_transpose_with_same_perms(%arg0: tensor<3x3x3x3xi32>) -> (tensor<3x3x3x3xi32>, tensor<3x3x3x3xi32>) {360  %0 = tosa.transpose %arg0 {perms = array<i32: 0, 2, 3, 1>}: (tensor<3x3x3x3xi32>) -> tensor<3x3x3x3xi32>361  %clamp = tosa.clamp %0 {max_val = 2147483647 : i32, min_val = 0 : i32} : (tensor<3x3x3x3xi32>) -> tensor<3x3x3x3xi32>362  %1 = tosa.transpose %clamp {perms = array<i32: 0, 3, 1, 2>}: (tensor<3x3x3x3xi32>) -> tensor<3x3x3x3xi32>363  %2 = tosa.transpose %clamp {perms = array<i32: 0, 3, 1, 2>}: (tensor<3x3x3x3xi32>) -> tensor<3x3x3x3xi32>364  return %1, %2 : tensor<3x3x3x3xi32>, tensor<3x3x3x3xi32>365}366 367// -----368 369// CHECK-LABEL: @test_const_transpose370// CHECK: %[[NEW:.*]] = "tosa.const"() <{values = dense<0> : tensor<2x3xi32>}> : () -> tensor<2x3xi32>371// CHECK-NOT: tosa.transpose372// CHECK: return %[[NEW]]373func.func @test_const_transpose() -> tensor<2x3xi32> {374  %0 = "tosa.const"() {values = dense<0> : tensor<3x2xi32>} : () -> tensor<3x2xi32>375  %1 = tosa.transpose %0 {perms = array<i32: 1, 0>}: (tensor<3x2xi32>) -> tensor<2x3xi32>376  return %1 : tensor<2x3xi32>377}378 379// -----380 381// CHECK-LABEL: @test_transpose_tracks_to_const_single_step382// CHECK: %[[NEW_CONST:.*]] = "tosa.const"() <{values = dense<0> : tensor<1x2x3x4xi32>}> : () -> tensor<1x2x3x4xi32>383// CHECK: %[[NEW_CLAMP:.*]] = tosa.clamp %[[NEW_CONST]] {max_val = 2147483647 : i32, min_val = 0 : i32} : (tensor<1x2x3x4xi32>) -> tensor<1x2x3x4xi32>384// CHECK-NOT: tosa.transpose385// CHECK: return %[[NEW_CLAMP]]386func.func @test_transpose_tracks_to_const_single_step() -> tensor<1x2x3x4xi32> {387  %0 = "tosa.const"() {values = dense<0> : tensor<1x3x4x2xi32>} : () -> tensor<1x3x4x2xi32>388  %clamp = tosa.clamp %0 {max_val = 2147483647 : i32, min_val = 0 : i32} : (tensor<1x3x4x2xi32>) -> tensor<1x3x4x2xi32>389  %1 = tosa.transpose %clamp {perms = array<i32: 0, 3, 1, 2>}: (tensor<1x3x4x2xi32>) -> tensor<1x2x3x4xi32>390  return %1 : tensor<1x2x3x4xi32>391}392 393// -----394 395// CHECK-LABEL: @test_static_unary_path_to_const396// CHECK: %[[NEW_CONST:.*]] = "tosa.const"() <{values = dense<1> : tensor<1x2x3x4xi32>}> : () -> tensor<1x2x3x4xi32>397// CHECK: %[[NEW_CLAMP:.*]] = tosa.clamp %[[NEW_CONST]] {max_val = 2147483647 : i32, min_val = 0 : i32} : (tensor<1x2x3x4xi32>) -> tensor<1x2x3x4xi32>398// CHECK: %[[NEW_ABS:.*]] = tosa.abs %[[NEW_CLAMP]] : (tensor<1x2x3x4xi32>) -> tensor<1x2x3x4xi32>399// CHECK: %[[NEW_NOT:.*]] = tosa.bitwise_not %[[NEW_ABS]] : (tensor<1x2x3x4xi32>) -> tensor<1x2x3x4xi32>400// CHECK: return %[[NEW_NOT]]401func.func @test_static_unary_path_to_const() -> tensor<1x2x3x4xi32> {402  %0 = "tosa.const"() {values = dense<1> : tensor<1x3x4x2xi32>} : () -> tensor<1x3x4x2xi32>403  %clamp = tosa.clamp %0 {max_val = 2147483647 : i32, min_val = 0 : i32} : (tensor<1x3x4x2xi32>) -> tensor<1x3x4x2xi32>404  %abs = tosa.abs %clamp : (tensor<1x3x4x2xi32>) -> tensor<1x3x4x2xi32>405  %bitwise_not = tosa.bitwise_not %abs : (tensor<1x3x4x2xi32>) -> tensor<1x3x4x2xi32>406  %1 = tosa.transpose %bitwise_not {perms = array<i32: 0, 3, 1, 2>}: (tensor<1x3x4x2xi32>) -> tensor<1x2x3x4xi32>407  return %1 : tensor<1x2x3x4xi32>408}409 410// -----411 412// CHECK-LABEL: @test_static_diverges_to_non_splat_const_and_nullifying413// CHECK: %[[NEW_CONST:.*]] = "tosa.const"()414// CHECK-SAME{LITERAL}: dense<[[[[1, 3, 5, 7], [9, 11, 13, 15], [17, 19, 21, 23]], [[2, 4, 6, 8], [10, 12, 14, 16], [18, 20, 22, 24]]]]>415// CHECK: tensor<1x2x3x4xi32>}> : () -> tensor<1x2x3x4xi32>416// CHECK: %[[NEW_CLAMP:.*]] = tosa.clamp %arg0 {max_val = 2147483647 : i32, min_val = 0 : i32} : (tensor<1x2x3x4xi32>) -> tensor<1x2x3x4xi32>417// CHECK: %[[NEW_ABS:.*]] = tosa.abs %[[NEW_CONST]] : (tensor<1x2x3x4xi32>) -> tensor<1x2x3x4xi32>418// CHECK: %[[NEW_ADD:.*]] = tosa.add %[[NEW_ABS]], %[[NEW_CLAMP]] : (tensor<1x2x3x4xi32>, tensor<1x2x3x4xi32>) -> tensor<1x2x3x4xi32>419// CHECK: return %[[NEW_ADD]]420func.func @test_static_diverges_to_non_splat_const_and_nullifying(%arg0: tensor<1x2x3x4xi32>) -> tensor<1x2x3x4xi32> {421  %transpose0 = tosa.transpose %arg0 {perms = array<i32: 0, 2, 3, 1>}: (tensor<1x2x3x4xi32>) -> tensor<1x3x4x2xi32>422  %const = "tosa.const"() {values = dense<[[[[1, 2], [3, 4], [5, 6], [7, 8]],423   [[9, 10], [11, 12], [13, 14], [15, 16]],424   [[17, 18], [19, 20], [21, 22], [23, 24]]]]> : tensor<1x3x4x2xi32>} : () -> tensor<1x3x4x2xi32>425  %clamp = tosa.clamp %transpose0 {max_val = 2147483647 : i32, min_val = 0 : i32} : (tensor<1x3x4x2xi32>) -> tensor<1x3x4x2xi32>426  %abs = tosa.abs %const : (tensor<1x3x4x2xi32>) -> tensor<1x3x4x2xi32>427  %add = tosa.add %abs, %clamp : (tensor<1x3x4x2xi32>, tensor<1x3x4x2xi32>) -> tensor<1x3x4x2xi32>428  %result = tosa.transpose %add {perms = array<i32: 0, 3, 1, 2>}: (tensor<1x3x4x2xi32>) -> tensor<1x2x3x4xi32>429  return %result : tensor<1x2x3x4xi32>430}431 432// -----433 434// CHECK-LABEL: @test_multi_downstream_both_nullify435// CHECK-NEXT: %[[RES:.*]] = tosa.clamp %arg0436// CHECK-NEXT: return %[[RES]], %[[RES]]437func.func @test_multi_downstream_both_nullify(%arg0: tensor<3x3x3x3xi32>) -> (tensor<3x3x3x3xi32>, tensor<3x3x3x3xi32>) {438  %0 = tosa.transpose %arg0 {perms = array<i32: 0, 2, 3, 1>}: (tensor<3x3x3x3xi32>) -> tensor<3x3x3x3xi32>439  %clamp = tosa.clamp %0 {max_val = 2147483647 : i32, min_val = 0 : i32} : (tensor<3x3x3x3xi32>) -> tensor<3x3x3x3xi32>440  %1 = tosa.transpose %clamp {perms = array<i32: 0, 3, 1, 2>}: (tensor<3x3x3x3xi32>) -> tensor<3x3x3x3xi32>441  %2 = tosa.transpose %clamp {perms = array<i32: 0, 3, 1, 2>}: (tensor<3x3x3x3xi32>) -> tensor<3x3x3x3xi32>442  return %1, %2 : tensor<3x3x3x3xi32>, tensor<3x3x3x3xi32>443}444 445// -----446 447// COM: we don't perform this transformation intentionally, since we would then get duplicates448// CHECK-LABEL: @test_multi_downstream_one_nullifies_upstream_other_does_not449// CHECK: tosa.transpose450// CHECK: tosa.clamp451// CHECK: tosa.transpose452// CHECK: tosa.transpose453func.func @test_multi_downstream_one_nullifies_upstream_other_does_not(%arg0: tensor<3x3x3x3xi32>) -> (tensor<3x3x3x3xi32>, tensor<3x3x3x3xi32>) {454  %0 = tosa.transpose %arg0 {perms = array<i32: 0, 2, 3, 1>}: (tensor<3x3x3x3xi32>) -> tensor<3x3x3x3xi32>455  %clamp = tosa.clamp %0 {max_val = 2147483647 : i32, min_val = 0 : i32} : (tensor<3x3x3x3xi32>) -> tensor<3x3x3x3xi32>456  %1 = tosa.transpose %clamp {perms = array<i32: 0, 3, 1, 2>}: (tensor<3x3x3x3xi32>) -> tensor<3x3x3x3xi32>457  %2 = tosa.transpose %clamp {perms = array<i32: 0, 2, 3, 1>}: (tensor<3x3x3x3xi32>) -> tensor<3x3x3x3xi32>458  return %1, %2 : tensor<3x3x3x3xi32>, tensor<3x3x3x3xi32>459}460 461// -----462 463// CHECK-LABEL: @test_unknown_dim_inner_replacement_matches464// CHECK-NEXT: return %arg0465func.func @test_unknown_dim_inner_replacement_matches(%arg0: tensor<3x2xi32>) -> tensor<3x2xi32> {466  %0 = tosa.transpose %arg0 {perms = array<i32: 1, 0>}: (tensor<3x2xi32>) -> tensor<?x3xi32>467  %1 = tosa.transpose %0 {perms = array<i32: 1, 0>}: (tensor<?x3xi32>) -> tensor<3x2xi32>468  return %1 : tensor<3x2xi32>469}470 471// -----472 473 474// CHECK-LABEL: @test_unknown_dim_outer_replacement_matches475// CHECK-NEXT: return %arg0476func.func @test_unknown_dim_outer_replacement_matches(%arg0: tensor<3x?xi32>) -> tensor<3x?xi32> {477  %0 = tosa.transpose %arg0 {perms = array<i32: 1, 0>}: (tensor<3x?xi32>) -> tensor<2x3xi32>478  %1 = tosa.transpose %0 {perms = array<i32: 1, 0>}: (tensor<2x3xi32>) -> tensor<3x?xi32>479  return %1 : tensor<3x?xi32>480}481 482// -----483 484// CHECK-LABEL: @test_transpose_tracks_to_nullifying_diverging_binary_unknown_dim_replacements_match485// CHECK-NEXT: %[[CLAMP:.*]] = tosa.clamp %arg0486// CHECK-NEXT: %[[ABS:.*]] = tosa.abs %arg1487// CHECK-NEXT: %[[ADD:.*]] = tosa.add %[[CLAMP]], %[[ABS]]488// CHECK-NEXT: return %[[ADD]]489func.func @test_transpose_tracks_to_nullifying_diverging_binary_unknown_dim_replacements_match(%arg0: tensor<1x?x3x4xi32>, %arg1: tensor<1x2x?x4xi32>) -> tensor<1x2x3x4xi32> {490  %transpose0 = tosa.transpose %arg0 {perms = array<i32: 0, 2, 3, 1>}: (tensor<1x?x3x4xi32>) -> tensor<?x3x4x?xi32>491  %transpose1 = tosa.transpose %arg1 {perms = array<i32: 0, 2, 3, 1>}: (tensor<1x2x?x4xi32>) -> tensor<1x?x?x2xi32>492  %clamp = tosa.clamp %transpose0 {min_val = 0 : i32, max_val = 1 : i32} : (tensor<?x3x4x?xi32>) -> tensor<?x3x4x?xi32>493  %abs = tosa.abs %transpose1 : (tensor<1x?x?x2xi32>) -> tensor<1x?x?x2xi32>494  %add = tosa.add %clamp, %abs : (tensor<?x3x4x?xi32>, tensor<1x?x?x2xi32>) -> tensor<1x3x4x2xi32>495  %result = tosa.transpose %add {perms = array<i32: 0, 3, 1, 2>}: (tensor<1x3x4x2xi32>) -> tensor<1x2x3x4xi32>496  return %result : tensor<1x2x3x4xi32>497}498 499// -----500 501// COM: due to tracking back to a non-nullifying transpose, we can't get rid of the transposes entirely.502// COM: later editions of the pass may wish to fold these into a single transpose.503// CHECK-LABEL: @test_unimplemented_transpose_tracks_to_non_nullifying_transpose_single_step504// CHECK-NEXT: tosa.transpose505// CHECK-NEXT: tosa.clamp506// CHECK-NEXT: tosa.transpose507// CHECK-NEXT: return508func.func @test_unimplemented_transpose_tracks_to_non_nullifying_transpose_single_step(%arg0: tensor<1x2x3x4xi32>) -> tensor<1x2x4x3xi32> {509  %0 = tosa.transpose %arg0 {perms = array<i32: 0, 3, 2, 1>}: (tensor<1x2x3x4xi32>) -> tensor<1x4x3x2xi32>510  %clamp = tosa.clamp %0 {min_val = 0 : i32, max_val = 1 : i32} : (tensor<1x4x3x2xi32>) -> tensor<1x4x3x2xi32>511  %1 = tosa.transpose %clamp {perms = array<i32: 0, 3, 1, 2>} : (tensor<1x4x3x2xi32>) -> tensor<1x2x4x3xi32>512  return %1 : tensor<1x2x4x3xi32>513}514 515// -----516 517// COM: we don't deal with this case. resolution of shapes required.518// CHECK-LABEL: @test_unimplemented_unknown_dim_input_nullifying_pair519// CHECK-NEXT: tosa.transpose520// CHECK-NEXT: tosa.transpose521// CHECK-NEXT: return522func.func @test_unimplemented_unknown_dim_input_nullifying_pair(%arg0: tensor<3x?xi32>) -> tensor<3x2xi32> {523  %0 = tosa.transpose %arg0 {perms = array<i32: 1, 0>}: (tensor<3x?xi32>) -> tensor<2x3xi32>524  %1 = tosa.transpose %0 {perms = array<i32: 1, 0>}: (tensor<2x3xi32>) -> tensor<3x2xi32>525  return %1 : tensor<3x2xi32>526}527 528// -----529 530// CHECK-LABEL: @test_unimplemented_unknown_dim_replacement_does_not_match531// CHECK-NEXT: tosa.transpose532// CHECK-NEXT: tosa.transpose533// CHECK-NEXT: return534func.func @test_unimplemented_unknown_dim_replacement_does_not_match(%arg0: tensor<3x?xi32>) -> tensor<?x?xi32> {535  %0 = tosa.transpose %arg0 {perms = array<i32: 1, 0>}: (tensor<3x?xi32>) -> tensor<?x3xi32>536  %1 = tosa.transpose %0 {perms = array<i32: 1, 0>}: (tensor<?x3xi32>) -> tensor<?x?xi32>537  return %1 : tensor<?x?xi32>538}539 540// -----541 542// COM: this would be able to be converted if --tosa-infer-shapes was run beforehand543// CHECK-LABEL: @test_unimplemented_unranked_tensors_present544// CHECK-NEXT: tosa.transpose545// CHECK-NEXT: tosa.transpose546// CHECK-NEXT: return547func.func @test_unimplemented_unranked_tensors_present(%arg0: tensor<3x2xi32>) -> tensor<*xi32> {548  %0 = tosa.transpose %arg0 {perms = array<i32: 0, 1>}: (tensor<3x2xi32>) -> tensor<*xi32>549  %1 = tosa.transpose %0 {perms = array<i32: 0, 1>}: (tensor<*xi32>) -> tensor<*xi32>550  return %1 : tensor<*xi32>551}552 553// -----554 555// CHECK-LABEL: @test_unimplemented_unranked_everything556// CHECK-NEXT: tosa.transpose557// CHECK-NEXT: tosa.transpose558// CHECK-NEXT: return559func.func @test_unimplemented_unranked_everything(%arg0: tensor<*xi32>) -> tensor<*xi32> {560  %0 = tosa.transpose %arg0 {perms = array<i32: 1, 0>}: (tensor<*xi32>) -> tensor<*xi32>561  %1 = tosa.transpose %0 {perms = array<i32: 1, 0>}: (tensor<*xi32>) -> tensor<*xi32>562  return %1 : tensor<*xi32>563}564 565// -----566 567// CHECK-LABEL: @test_unimplemented_static_diverges_to_one_nullifying_one_non_nullifying568// CHECK-NEXT: tosa.transpose569// CHECK-NEXT: tosa.transpose570// CHECK-NEXT: tosa.clamp571// CHECK-NEXT: tosa.abs572// CHECK-NEXT: tosa.add573// CHECK-NEXT: tosa.transpose574// CHECK-NEXT: return575func.func @test_unimplemented_static_diverges_to_one_nullifying_one_non_nullifying(%arg0: tensor<1x2x3x4xi32>, %arg1: tensor<1x2x4x3xi32>) -> tensor<1x2x3x4xi32> {576  %transpose0 = tosa.transpose %arg0 {perms = array<i32: 0, 2, 3, 1>}: (tensor<1x2x3x4xi32>) -> tensor<1x3x4x2xi32>577  %transpose1 = tosa.transpose %arg1 {perms = array<i32: 0, 3, 2, 1>}: (tensor<1x2x4x3xi32>) -> tensor<1x3x4x2xi32>578  %clamp = tosa.clamp %transpose0 {min_val = 0 : i32, max_val = 1 : i32} : (tensor<1x3x4x2xi32>) -> tensor<1x3x4x2xi32>579  %abs = tosa.abs %transpose1 : (tensor<1x3x4x2xi32>) -> tensor<1x3x4x2xi32>580  %add = tosa.add %clamp, %abs : (tensor<1x3x4x2xi32>, tensor<1x3x4x2xi32>) -> tensor<1x3x4x2xi32>581  %result = tosa.transpose %add {perms = array<i32: 0, 3, 1, 2>}: (tensor<1x3x4x2xi32>) -> tensor<1x2x3x4xi32>582  return %result : tensor<1x2x3x4xi32>583}584