diff --git a/js/web/docs/webnn-operators.md b/js/web/docs/webnn-operators.md
index 5ad2311ef8..a6a2ecdf6f 100644
--- a/js/web/docs/webnn-operators.md
+++ b/js/web/docs/webnn-operators.md
@@ -6,108 +6,110 @@ operators and the supported opset domain/versions in **WebNN EP** by ONNX Runtim
(**Note**: ONNX Runtime only *guarantees* support for models stamped with opset version 7 or above for opset domain 'ai.onnx'.)
-[WebNN API](https://webmachinelearning.github.io/webnn) provides two device types `cpu` and `gpu` to leverage different on-device accelerators. WebNN API implementation in Chromium uses TFLite XNNPack delegate backend for `cpu` device type and DirectML backend for `gpu` device type. [The op support status](https://webmachinelearning.github.io/webnn-status/) behind these two backends is inconsistent.
+The [WebNN API](https://webmachinelearning.github.io/webnn) is available in the latest versions of Chrome and Edge on Windows,
+Linux, macOS, Android, and ChromeOS behind an "Enables WebNN API" flag. The operator support status may vary across these
+platforms. Check the [WebNN status](https://webmachinelearning.github.io/webnn-status/) for the latest implementation details.
-| Operator | Opset | WebNN API | WebNN CPU | WebNN GPU | Comments |
-|:------:|:------:|:------:|:-:|:-:|:------|
-| Abs | ai.onnx(7-12, 13+) | abs | ✓ | ✓ | |
-| Add | ai.onnx(7-12, 13, 14+) | add | ✓ | ✓ | |
-| And | ai.onnx(7+) | logicalAnd | ✗ | ✓ | |
-| ArgMax | ai.onnx(7-10, 11, 12, 13+) | argMax | ✓ | ✓ | |
-| ArgMin | ai.onnx(7-10, 11, 12, 13+) | argMin | ✓ | ✓ | |
-| AveragePool | ai.onnx(7-9, 10, 11, 12-18, 19+) | averagePool2d | ✓ | ✓ | Only supports 4-D input, 2-D 'kernel_shape', 'count_include_pad' value is 0 |
-| BatchNormalization | ai.onnx(7-8, 9-13, 14, 15+) | batchNormalization | ✓ | ✓ | Only supports 'training_mode' value is 0, one output |
-| Cast | ai.onnx(7-8, 9-12, 13-18, 19-20, 21+) | cast | ✓ | ✓ | WebNN CPU backend doesn't support casting to uint64 data type |
-| Ceil | ai.onnx(7-12, 13+) | ceil | ✓ | ✓ | |
-| Clip | ai.onnx(7-10, 11, 12, 13+) | clamp | ✓ | ✓ | WebNN CPU backend only supports 3 specific ranges: [0.0, infinity], [-1.0, 1.0], [0.0, 6.0] (Chromium issue: https://issues.chromium.org/issues/326156496) |
-| Concat | ai.onnx(7-10, 11-12, 13+) | concat | ✓ | ✓ | |
-| Conv | ai.onnx(7-10, 11+) | conv2d | ✓ | ✓ | Only supports 3-D or 4-D input and 'W' (weight) |
-| ConvTranspose | ai.onnx(7-10, 11+) | convTranspose2d | ✓ | ✓ | Only supports 3-D or 4-D input and 'W' (weight). WebNN CPU backend only supports default dilations and group |
-| Cos | ai.onnx(7+) | cos | ✓ | ✓ | |
-| CumSum | ai.onnx(11-13, 14+) | cumulativeSum | ✓ | ✓ | 'axis' input should be a constant |
-| Div | ai.onnx(7-12, 13, 14+) | div | ✓ | ✓ | |
-| DequantizeLinear | ai.onnx(10-12, 13-18, 19-20, 21-22, 23+) | dequantizeLinear | ✓ | ✓ | The shape of x_scale should be a subsample of the shape of input |
-| Dropout | ai.onnx(7-9, 10-11, 12, 13-21, 22+) | identity | ✓ | ✓ | Only supports test mode |
-| Einsum | ai.onnx(12+) | reshape, transpose, matmul, reduceSum, mul, triangular | ✓ | ✓ | |
-| Elu | ai.onnx(7+) | elu | ✓ | ✓ | WebNN CPU backend only supports 'alpha' value is 1.0 |
-| Equal | ai.onnx(7-10, 11-12, 13-18, 19+) | equal | ✓ | ✓ | |
-| Erf | ai.onnx(7-9, 10-12, 13+) | erf | ✓ | ✓ | |
-| Exp | ai.onnx(7-12, 13+) | exp | ✓ | ✓ | |
-| Expand | ai.onnx(8-12, 13+) | expand | ✓ | ✓ | 'shape' input should be a constant |
-| Flatten | ai.onnx(7-8, 9-10, 11-12, 13-20, 21+) | reshape | ✓ | ✓ | |
-| Floor | ai.onnx(7-12, 13+) | floor | ✓ | ✓ | |
-| Gather | ai.onnx(7-10, 11-12, 13+) | gather | ✓ | ✓ | |
-| GatherElements | ai.onnx(11-12, 13+) | gatherElements | ✗ | ✓ | |
-| GatherND | ai.onnx(11, 12, 13+) | gatherND | ✓ | ✓ | Only supports 'batch_dims' == 0 |
-| Gelu | ai.onnx(20+) | gelu | ✓ | ✓ | |
-| Gemm | ai.onnx(7-8, 9-10, 11-12, 13+) | gemm | ✓ | ✓ | Only supports 1-D 'C' input |
-| GlobalAveragePool | ai.onnx(7+) | averagePool2d | ✓ | ✓ | Only supports 4-D input |
-| GlobalMaxPool | ai.onnx(7+) | maxPool2d | ✓ | ✓ | Only supports 4-D input |
-| GlobalLpPool| ai.onnx(7+) | l2Pool2d | ✗ | ✓ | Only supports 4-D input, 'p' value is 2 |
-| Greater | ai.onnx(7-8, 9-12, 13+) | greater | ✓ | ✓ | |
-| GreaterOrEqual | ai.onnx(12-15, 16+) | greaterOrEqual | ✓ | ✓ | |
-| GRU | ai.onnx(7-13, 14-21, 22+) | gru | ✓ | ✓ | Only supports 'layout' == 0. 'clip' is not supported. The activation functions in 'activations' must be one of 'Relu', 'Tanh', 'Sigmoid'. Forward and backward activations must be the same if bidirectional. 'sequence_lens' if present should be constant with values equal to the first dimension length of input 'X' |
-| HardSigmoid | ai.onnx(7+) | hardSigmoid | ✓ | ✓ | |
-| HardSwish | ai.onnx(14+) | hardSwish | ✓ | ✓ | |
-| Identity | ai.onnx(7-13, 14-15, 16-18, 19-20, 21+) | identity | ✓ | ✓ | |
-| InstanceNormalization | ai.onnx(7+) | instanceNormalization | ✓ | ✓ | |
-| LayerNormalization | ai.onnx(7-16, 17+) | layerNormalization | ✓ | ✓ | |
-| LeakyRelu | ai.onnx(7-15, 16+) | leakyRelu | ✓ | ✓ | |
-| Less | ai.onnx(7-8, 9-12, 13+) | lesser | ✓ | ✓ | |
-| LessOrEqual | ai.onnx(12-15, 16+) | lesserOrEqual | ✓ | ✓ | |
-| Log | ai.onnx(7-12, 13+) | log | ✓ | ✓ | |
-| LpPool | ai.onnx(7-10, 11-17, 18+) | l2Pool2d | ✗ | ✓ | Only supports 4-D input, 2-D 'kernel_shape', 'p' value is 2 |
-| LRN | ai.onnx(7-12, 13+) | pad, averagePool2d, transpose, add, mul, pow, div | ✓ | ✓ | |
-| LSTM | ai.onnx(7-13, 14-21, 22+) | lstm | ✓ | ✓ | Only supports 'layout' == 0, 'input_forget' == 0. 'clip' is not supported. The activation functions in 'activations' must be one of 'Relu', 'Tanh', 'Sigmoid'. Forward and backward activations must be the same if bidirectional. 'sequence_lens' if present should be constant with values equal to the first dimension length of input 'X' |
-| MatMul | ai.onnx(7-8, 9-12, 13+) | matmul | ✓ | ✓ | |
-| Max | ai.onnx(7, 8-11, 12, 13+) | max | ✓ | ✓ | |
-| MaxPool | ai.onnx(7, 8-9, 10, 11, 12+) | maxPool2d | ✓ | ✓ | Only supports 4-D input, 2-D 'kernel_shape', 'storage_order' != 1, one output |
-| Min | ai.onnx(7, 8-11, 12, 13+) | min | ✓ | ✓ | |
-| Mul | ai.onnx(7-12, 13, 14+) | mul | ✓ | ✓ | |
-| Neg | ai.onnx(7-12, 13+) | neg | ✓ | ✓ | |
-| Not | ai.onnx(7+) | logicalNot | ✓ | ✓ | |
-| Or | ai.onnx(7+) | logicalOr | ✗ | ✓ | |
-| Pad | ai.onnx(7-10, 11-12, 13-17, 18, 19-20, 21+) | pad | ✓ | ✓ | modes == 'wrap' is not supported |
-| Pow | ai.onnx(7-11, 12, 13-14, 15+) | pow | ✓ | ✓ | |
-| PRelu | ai.onnx(7-8, 9-15, 16+) | prelu | ✓ | ✓ | WebNN CPU backend restricts the last dimension of input and slope to be same (Chromium issue: https://issues.chromium.org/issues/335517470) |
-| QuantizeLinear | ai.onnx(10-12, 13-18, 19-20, 21-22, 23+) | quantizeLinear | ✓ | ✓ | The shape of x_scale should be a subsample of the shape of input |
-| Reciprocal | ai.onnx(7-12, 13+) | reciprocal | ✓ | ✓ | |
-| ReduceL1 | ai.onnx(7-10, 11-12, 13-17, 18+) | reduceL1 | ✓ | ✓ | Input 'axes' if present should be a constant |
-| ReduceL2 | ai.onnx(7-10, 11-12, 13-17, 18+) | reduceL2 | ✓ | ✓ | Input 'axes' if present should be a constant |
-| ReduceLogSum| ai.onnx(7-10, 11-12, 13-17, 18+) | reduceLogSum| ✓ | ✓ | Input 'axes' if present should be a constant |
-| ReduceLogSumExp | ai.onnx(7-10, 11-12, 13-17, 18+) | reduceLogSumExp | ✓ | ✓ | Input 'axes' if present should be a constant |
-| ReduceMax | ai.onnx(7-10, 11, 12, 13-17, 18-19, 20+) | reduceMax | ✓ | ✓ | Input 'axes' if present should be a constant |
-| ReduceMean | ai.onnx(7-10, 11-12, 13-17, 18+) | reduceMean | ✓ | ✓ | Input 'axes' if present should be a constant |
-| ReduceMin | ai.onnx(7-10, 11, 12, 13-17, 18-19, 20+) | reduceMin | ✓ | ✓ | Input 'axes' if present should be a constant |
-| ReduceProd | ai.onnx(7-10, 11-12, 13-17, 18+) | reduceProduct | ✓ | ✓ | Input 'axes' if present should be a constant |
-| ReduceSum | ai.onnx(7-10, 11-12, 13+) | reduceSum | ✓ | ✓ | Input 'axes' if present should be a constant |
-| ReduceSumSquare | ai.onnx(7-10, 11-12, 13-17, 18+) | reduceSumSquare | ✓ | ✓ | Input 'axes' if present should be a constant |
-| Relu | ai.onnx(7-12, 13, 14+) | relu | ✓ | ✓ | |
-| Reshape | ai.onnx(7-12, 13, 14-18, 19-20, 21+) | reshape | ✓ | ✓ | Input 'shape' should be a constant, 0 dimension value in 'shape' is not supported |
-| Resize | ai.onnx(11-12, 13-17, 18, 19+) | resample2d | ✓ | ✓ | Only supports 4-D input, antialias == 0, exclude_outside == 0, keep_aspect_ratio_policy == 'stretch', 'linear' and 'nearest' modes, input 'scales' and 'sizes' if present must be a constant |
-| RotaryEmbedding | com.microsoft(1+) | add, concat, gather, mul, reshape, split | ✓ | ✓ | |
-| ScatterElements | ai.onnx(11-12, 13-15, 16-17, 18+) | scatterElements | ✗ | ✓ | Only supports 'reduction' == 'none' |
-| ScatterND | ai.onnx(11-12, 13-15, 16-17, 18+) | scatterND | ✗ | ✓ | Only supports 'reduction' == 'none' |
-| Shape | ai.onnx(7-12, 13-14, 15-18, 19-20, 21+) | slice | ✓ | ✓ | |
-| SimplifiedLayerNormalization | ai.onnx(1+) | pow, reduceMean, add, sqrt, div, mul | ✓ | ✓ | |
-| Sigmoid | ai.onnx(7-12, 13+) | sigmoid | ✓ | ✓ | |
-| Sign | ai.onnx(9-12, 13+) | sign | ✓ | ✓ | |
-| SkipSimplifiedLayerNormalization | com.microsoft(1+) | pow, reduceMean, add, sqrt, div, mul | ✓ | ✓ | |
-| Softplus | ai.onnx(7+) | softplus | ✓ | ✓ | |
-| Softsign | ai.onnx(7+) | softsign | ✓ | ✓ | |
-| Sin | ai.onnx(7+) | sin | ✓ | ✓ | |
-| Slice | ai.onnx(7-9, 10, 11-12, 13+) | slice, reverse | ✓ | ✓ | Input 'starts', 'ends', 'axes', and 'steps' if present must be a constant |
-| Softmax | ai.onnx(7-10, 11-12, 13+) | softmax | ✓ | ✓ | |
-| Split | ai.onnx(7-10, 11-12, 13-17, 18+) | split | ✓ | ✓ | Input 'split' if present should be a constant |
-| Sqrt | ai.onnx(7-12, 13+) | sqrt | ✓ | ✓ | |
-| Squeeze | ai.onnx(7-10, 11-12, 13-20, 21+) | reshape | ✓ | ✓ | Input 'axes' if present should be a constant |
-| Sub | ai.onnx(7-12, 13, 14+) | sub | ✓ | ✓ | |
-| Tan | ai.onnx(7+) | tan | ✓ | ✓ | |
-| Tanh | ai.onnx(7-12, 13+) | tanh | ✓ | ✓ | |
-| Tile | ai.onnx(7-12, 13+) | tile | ✗ | ✓ | Input 'repeats' should be a constant |
-| Transpose | ai.onnx(7-12, 13-20, 21+) | transpose | ✓ | ✓ | |
-| Trilu | ai.onnx(14+) | triangular | ✓ | ✓ | Input 'k' (option 'diagonal' for WebNN) if present should be a constant |
-| Unsqueeze | ai.onnx(7-10, 11-12, 13-20, 21+) | reshape | ✓ | ✓ | |
-| Where | ai.onnx(7-8, 9-15, 16+) | where | ✓ | ✓ | |
-| Xor | ai.onnx(7+) | logicalXor | ✗ | ✓ | |
+| Operator | Opset | WebNN API | Comments |
+|:------:|:------:|:------:|:------|
+| Abs | ai.onnx(7-12, 13+) | abs | |
+| Add | ai.onnx(7-12, 13, 14+) | add | |
+| And | ai.onnx(7+) | logicalAnd | |
+| ArgMax | ai.onnx(7-10, 11, 12, 13+) | argMax | |
+| ArgMin | ai.onnx(7-10, 11, 12, 13+) | argMin | |
+| AveragePool | ai.onnx(7-9, 10, 11, 12-18, 19+) | averagePool2d | Only supports 4-D input, 2-D 'kernel_shape', 'count_include_pad' value is 0 |
+| BatchNormalization | ai.onnx(7-8, 9-13, 14, 15+) | batchNormalization | Only supports 'training_mode' value is 0, one output |
+| Cast | ai.onnx(7-8, 9-12, 13-18, 19-20, 21+) | cast | |
+| Ceil | ai.onnx(7-12, 13+) | ceil | |
+| Clip | ai.onnx(7-10, 11, 12, 13+) | clamp | |
+| Concat | ai.onnx(7-10, 11-12, 13+) | concat | |
+| Conv | ai.onnx(7-10, 11+) | conv2d | Only supports 3-D or 4-D input and 'W' (weight) |
+| ConvTranspose | ai.onnx(7-10, 11+) | convTranspose2d | Only supports 3-D or 4-D input and 'W' (weight) |
+| Cos | ai.onnx(7+) | cos | |
+| CumSum | ai.onnx(11-13, 14+) | cumulativeSum | 'axis' input should be a constant |
+| Div | ai.onnx(7-12, 13, 14+) | div | |
+| DequantizeLinear | ai.onnx(10-12, 13-18, 19-20, 21-22, 23+) | dequantizeLinear | The shape of x_scale should be a subsample of the shape of input |
+| Dropout | ai.onnx(7-9, 10-11, 12, 13-21, 22+) | identity | Only supports test mode |
+| Einsum | ai.onnx(12+) | reshape, transpose, matmul, reduceSum, mul, triangular | |
+| Elu | ai.onnx(7+) | elu | |
+| Equal | ai.onnx(7-10, 11-12, 13-18, 19+) | equal | |
+| Erf | ai.onnx(7-9, 10-12, 13+) | erf | |
+| Exp | ai.onnx(7-12, 13+) | exp | |
+| Expand | ai.onnx(8-12, 13+) | expand | 'shape' input should be a constant |
+| Flatten | ai.onnx(7-8, 9-10, 11-12, 13-20, 21+) | reshape | |
+| Floor | ai.onnx(7-12, 13+) | floor | |
+| Gather | ai.onnx(7-10, 11-12, 13+) | gather | |
+| GatherElements | ai.onnx(11-12, 13+) | gatherElements | |
+| GatherND | ai.onnx(11, 12, 13+) | gatherND | Only supports 'batch_dims' == 0 |
+| Gelu | ai.onnx(20+) | gelu | |
+| Gemm | ai.onnx(7-8, 9-10, 11-12, 13+) | gemm | Only supports 1-D 'C' input |
+| GlobalAveragePool | ai.onnx(7+) | averagePool2d | Only supports 4-D input |
+| GlobalMaxPool | ai.onnx(7+) | maxPool2d | Only supports 4-D input |
+| GlobalLpPool| ai.onnx(7+) | l2Pool2d | Only supports 4-D input, 'p' value is 2 |
+| Greater | ai.onnx(7-8, 9-12, 13+) | greater | |
+| GreaterOrEqual | ai.onnx(12-15, 16+) | greaterOrEqual | |
+| GRU | ai.onnx(7-13, 14-21, 22+) | gru | Only supports 'layout' == 0. 'clip' is not supported. The activation functions in 'activations' must be one of 'Relu', 'Tanh', 'Sigmoid'. Forward and backward activations must be the same if bidirectional. 'sequence_lens' if present should be constant with values equal to the first dimension length of input 'X' |
+| HardSigmoid | ai.onnx(7+) | hardSigmoid | |
+| HardSwish | ai.onnx(14+) | hardSwish | |
+| Identity | ai.onnx(7-13, 14-15, 16-18, 19-20, 21+) | identity | |
+| InstanceNormalization | ai.onnx(7+) | instanceNormalization | |
+| LayerNormalization | ai.onnx(7-16, 17+) | layerNormalization | |
+| LeakyRelu | ai.onnx(7-15, 16+) | leakyRelu | |
+| Less | ai.onnx(7-8, 9-12, 13+) | lesser | |
+| LessOrEqual | ai.onnx(12-15, 16+) | lesserOrEqual | |
+| Log | ai.onnx(7-12, 13+) | log | |
+| LpPool | ai.onnx(7-10, 11-17, 18+) | l2Pool2d | Only supports 4-D input, 2-D 'kernel_shape', 'p' value is 2 |
+| LRN | ai.onnx(7-12, 13+) | pad, averagePool2d, transpose, add, mul, pow, div | |
+| LSTM | ai.onnx(7-13, 14-21, 22+) | lstm | Only supports 'layout' == 0, 'input_forget' == 0. 'clip' is not supported. The activation functions in 'activations' must be one of 'Relu', 'Tanh', 'Sigmoid'. Forward and backward activations must be the same if bidirectional. 'sequence_lens' if present should be constant with values equal to the first dimension length of input 'X' |
+| MatMul | ai.onnx(7-8, 9-12, 13+) | matmul | |
+| Max | ai.onnx(7, 8-11, 12, 13+) | max | |
+| MaxPool | ai.onnx(7, 8-9, 10, 11, 12+) | maxPool2d | Only supports 4-D input, 2-D 'kernel_shape', 'storage_order' != 1, one output |
+| Min | ai.onnx(7, 8-11, 12, 13+) | min | |
+| Mul | ai.onnx(7-12, 13, 14+) | mul | |
+| Neg | ai.onnx(7-12, 13+) | neg | |
+| Not | ai.onnx(7+) | logicalNot | |
+| Or | ai.onnx(7+) | logicalOr | |
+| Pad | ai.onnx(7-10, 11-12, 13-17, 18, 19-20, 21+) | pad | modes == 'wrap' is not supported |
+| Pow | ai.onnx(7-11, 12, 13-14, 15+) | pow | |
+| PRelu | ai.onnx(7-8, 9-15, 16+) | prelu | |
+| QuantizeLinear | ai.onnx(10-12, 13-18, 19-20, 21-22, 23+) | quantizeLinear | The shape of x_scale should be a subsample of the shape of input |
+| Reciprocal | ai.onnx(7-12, 13+) | reciprocal | |
+| ReduceL1 | ai.onnx(7-10, 11-12, 13-17, 18+) | reduceL1 | Input 'axes' if present should be a constant |
+| ReduceL2 | ai.onnx(7-10, 11-12, 13-17, 18+) | reduceL2 | Input 'axes' if present should be a constant |
+| ReduceLogSum| ai.onnx(7-10, 11-12, 13-17, 18+) | reduceLogSum | Input 'axes' if present should be a constant |
+| ReduceLogSumExp | ai.onnx(7-10, 11-12, 13-17, 18+) | reduceLogSumExp | Input 'axes' if present should be a constant |
+| ReduceMax | ai.onnx(7-10, 11, 12, 13-17, 18-19, 20+) | reduceMax | Input 'axes' if present should be a constant |
+| ReduceMean | ai.onnx(7-10, 11-12, 13-17, 18+) | reduceMean | Input 'axes' if present should be a constant |
+| ReduceMin | ai.onnx(7-10, 11, 12, 13-17, 18-19, 20+) | reduceMin | Input 'axes' if present should be a constant |
+| ReduceProd | ai.onnx(7-10, 11-12, 13-17, 18+) | reduceProduct | Input 'axes' if present should be a constant |
+| ReduceSum | ai.onnx(7-10, 11-12, 13+) | reduceSum | Input 'axes' if present should be a constant |
+| ReduceSumSquare | ai.onnx(7-10, 11-12, 13-17, 18+) | reduceSumSquare | Input 'axes' if present should be a constant |
+| Relu | ai.onnx(7-12, 13, 14+) | relu | |
+| Reshape | ai.onnx(7-12, 13, 14-18, 19-20, 21+) | reshape | Input 'shape' should be a constant, 0 dimension value in 'shape' is not supported |
+| Resize | ai.onnx(11-12, 13-17, 18, 19+) | resample2d | Only supports 4-D input, antialias == 0, exclude_outside == 0, keep_aspect_ratio_policy == 'stretch', 'linear' and 'nearest' modes, input 'scales' and 'sizes' if present must be a constant |
+| RotaryEmbedding | com.microsoft(1+) | add, concat, gather, mul, reshape, split | |
+| ScatterElements | ai.onnx(11-12, 13-15, 16-17, 18+) | scatterElements | Only supports 'reduction' == 'none' |
+| ScatterND | ai.onnx(11-12, 13-15, 16-17, 18+) | scatterND | Only supports 'reduction' == 'none' |
+| Shape | ai.onnx(7-12, 13-14, 15-18, 19-20, 21+) | slice | |
+| SimplifiedLayerNormalization | ai.onnx(1+) | pow, reduceMean, add, sqrt, div, mul | |
+| Sigmoid | ai.onnx(7-12, 13+) | sigmoid | |
+| Sign | ai.onnx(9-12, 13+) | sign | |
+| SkipSimplifiedLayerNormalization | com.microsoft(1+) | pow, reduceMean, add, sqrt, div, mul | |
+| Softplus | ai.onnx(7+) | softplus | |
+| Softsign | ai.onnx(7+) | softsign | |
+| Sin | ai.onnx(7+) | sin | |
+| Slice | ai.onnx(7-9, 10, 11-12, 13+) | slice, reverse | Input 'starts', 'ends', 'axes', and 'steps' if present must be a constant |
+| Softmax | ai.onnx(7-10, 11-12, 13+) | softmax | |
+| Split | ai.onnx(7-10, 11-12, 13-17, 18+) | split | Input 'split' if present should be a constant |
+| Sqrt | ai.onnx(7-12, 13+) | sqrt | |
+| Squeeze | ai.onnx(7-10, 11-12, 13-20, 21+) | reshape | Input 'axes' if present should be a constant |
+| Sub | ai.onnx(7-12, 13, 14+) | sub | |
+| Tan | ai.onnx(7+) | tan | |
+| Tanh | ai.onnx(7-12, 13+) | tanh | |
+| Tile | ai.onnx(7-12, 13+) | tile | Input 'repeats' should be a constant |
+| Transpose | ai.onnx(7-12, 13-20, 21+) | transpose | |
+| Trilu | ai.onnx(14+) | triangular | Input 'k' (option 'diagonal' for WebNN) if present should be a constant |
+| Unsqueeze | ai.onnx(7-10, 11-12, 13-20, 21+) | reshape | |
+| Where | ai.onnx(7-8, 9-15, 16+) | where | |
+| Xor | ai.onnx(7+) | logicalXor | |
diff --git a/onnxruntime/core/providers/webnn/builders/impl/activation_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/activation_op_builder.cc
index 781ddcb896..585fddfd1f 100644
--- a/onnxruntime/core/providers/webnn/builders/impl/activation_op_builder.cc
+++ b/onnxruntime/core/providers/webnn/builders/impl/activation_op_builder.cc
@@ -17,10 +17,6 @@ class ActivationOpBuilder : public BaseOpBuilder {
private:
Status AddToModelBuilderImpl(ModelBuilder& model_builder, const Node& node,
const logging::Logger& logger) const override ORT_MUST_USE_RESULT;
-
- // Operator support related.
- bool IsOpSupportedImpl(const InitializedTensorSet& initializers, const Node& node,
- WebnnDeviceType device_type, const logging::Logger& logger) const override;
};
// Add operator related.
@@ -68,30 +64,6 @@ Status ActivationOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder,
return Status::OK();
}
-// Operator support related.
-bool ActivationOpBuilder::IsOpSupportedImpl(const InitializedTensorSet& /* initializers */,
- const Node& node,
- WebnnDeviceType device_type,
- const logging::Logger& logger) const {
- const auto& input_defs = node.InputDefs();
- const auto& op_type = node.OpType();
-
- std::vector input_shape;
- if (!GetShape(*input_defs[0], input_shape, logger))
- return false;
-
- if (op_type == "Elu" && device_type == WebnnDeviceType::CPU) {
- NodeAttrHelper helper(node);
- float alpha = helper.Get("alpha", 1.0f);
- if (alpha != 1.0f) {
- LOGS(logger, VERBOSE) << "WebNN CPU backend only supports Elu's alpha == 1.0";
- return false;
- }
- }
-
- return true;
-}
-
void CreateActivationOpBuilder(const std::string& op_type, OpBuilderRegistrations& op_registrations) {
if (op_registrations.op_builder_map.count(op_type) > 0)
return;
diff --git a/onnxruntime/core/providers/webnn/builders/impl/binary_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/binary_op_builder.cc
index e14507e8f5..c5493f97fd 100644
--- a/onnxruntime/core/providers/webnn/builders/impl/binary_op_builder.cc
+++ b/onnxruntime/core/providers/webnn/builders/impl/binary_op_builder.cc
@@ -20,8 +20,6 @@ class BinaryOpBuilder : public BaseOpBuilder {
const logging::Logger& logger) const override ORT_MUST_USE_RESULT;
// Operator support related.
- bool IsOpSupportedImpl(const InitializedTensorSet& initializers, const Node& node,
- const WebnnDeviceType device_type, const logging::Logger& logger) const override;
bool HasSupportedInputsImpl(const InitializedTensorSet& /* initializers */, const Node& node,
const emscripten::val& wnn_limits, const logging::Logger& logger) const override;
};
@@ -59,33 +57,6 @@ Status BinaryOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, const
return Status::OK();
}
-bool BinaryOpBuilder::IsOpSupportedImpl(const InitializedTensorSet& initializers,
- const Node& node,
- const WebnnDeviceType device_type,
- const logging::Logger& logger) const {
- const auto& input_defs = node.InputDefs();
- const auto& op_type = node.OpType();
-
- std::vector input0_shape;
- std::vector input1_shape;
- if (!GetShape(*input_defs[0], input0_shape, logger) ||
- !GetShape(*input_defs[1], input1_shape, logger)) {
- return false;
- }
-
- // 'prelu' op in WebNN CPU backend restricts the last dimension of input and slope to be same.
- // TODO: Remove this workaround once the associated issue is resolved in Chromium:
- // https://issues.chromium.org/issues/335517470.
- if (op_type == "PRelu" && device_type == WebnnDeviceType::CPU) {
- if (input0_shape.back() != input1_shape.back()) {
- LOGS(logger, VERBOSE) << "The last dimension of input and slope for PRelu must be same for WebNN CPU backend.";
- return false;
- }
- }
-
- return true;
-}
-
bool BinaryOpBuilder::HasSupportedInputsImpl(const InitializedTensorSet& /* initializers */, const Node& node,
const emscripten::val& wnn_limits, const logging::Logger& logger) const {
const auto& input_defs = node.InputDefs();
diff --git a/onnxruntime/core/providers/webnn/builders/impl/clip_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/clip_op_builder.cc
index 374143c886..a244efdd9b 100644
--- a/onnxruntime/core/providers/webnn/builders/impl/clip_op_builder.cc
+++ b/onnxruntime/core/providers/webnn/builders/impl/clip_op_builder.cc
@@ -69,27 +69,7 @@ bool ClipOpBuilder::IsOpSupportedImpl(const InitializedTensorSet& initializers,
// can ensure initializers are constant. See #19401 for details of how this update was made to the NNAPI EP.
// GetClipMinMax(graph_viewer, node, minValue, maxValue, logger)
float min, max;
- if (GetClipMinMax(initializers, node, min, max, logger)) {
- // WebNN CPU backend only supports 3 specific ranges: [0.0, infinity], [-1.0, 1.0], [0.0, 6.0].
- // TODO: Remove this workaround once the associated issue is resolved in Chromium:
- // https://issues.chromium.org/issues/326156496.
- if (device_type == WebnnDeviceType::CPU) {
- if ((min == 0.0f && max == std::numeric_limits::infinity()) ||
- (min == -1.0f && max == 1.0f) ||
- (min == 0.0f && max == 6.0f)) {
- return true;
- } else {
- LOGS(logger, VERBOSE) << "Clip min and max values ("
- << min << ", "
- << max << ") are not supported for WebNN CPU backend";
- return false;
- }
- }
-
- return true;
- } else {
- return false;
- };
+ return GetClipMinMax(initializers, node, min, max, logger);
}
void CreateClipOpBuilder(const std::string& op_type, OpBuilderRegistrations& op_registrations) {
diff --git a/onnxruntime/core/providers/webnn/builders/impl/conv_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/conv_op_builder.cc
index 548e718b87..e623590e3b 100644
--- a/onnxruntime/core/providers/webnn/builders/impl/conv_op_builder.cc
+++ b/onnxruntime/core/providers/webnn/builders/impl/conv_op_builder.cc
@@ -378,22 +378,6 @@ bool ConvOpBuilder::IsOpSupportedImpl(const InitializedTensorSet& initializers,
return false;
}
- // WebNN CPU backend (TFLite) only supports default dilations and group.
- // https://source.chromium.org/chromium/chromium/src/+/main:services/webnn/tflite/graph_builder_tflite.cc;l=1040
- if (device_type == WebnnDeviceType::CPU && op_type == "ConvTranspose") {
- NodeAttrHelper helper(node);
- const auto dilations = helper.Get("dilations", std::vector{1, 1});
- const auto group = helper.Get("group", 1);
- if (dilations[0] != 1 || (dilations.size() > 1 && dilations[1] != 1)) {
- LOGS(logger, VERBOSE) << op_type << " for WebNN CPU backend only supports default dilation 1.";
- return false;
- }
- if (group != 1) {
- LOGS(logger, VERBOSE) << op_type << " for WebNN CPU backend only supports default group 1.";
- return false;
- }
- }
-
return true;
}