webnn: Support the layerNormalization operator in CoreML

Cq-Include-Trybots: luci.chromium.try:mac14-blink-rel,mac14.arm64-blink-rel
Bug: 41481333
Change-Id: If6afae9241608d9fb925b8fce1c72efbb61bd792
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5758541
Commit-Queue: Phillis Tang <phillis@chromium.org>
Reviewed-by: Austin Sullivan <asully@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1336359}
diff --git a/services/webnn/coreml/graph_builder_coreml.cc b/services/webnn/coreml/graph_builder_coreml.cc
index d959caf..42a6d76 100644
--- a/services/webnn/coreml/graph_builder_coreml.cc
+++ b/services/webnn/coreml/graph_builder_coreml.cc
@@ -125,6 +125,7 @@
 constexpr char kOpGatherTypeName[] = "gather_along_axis";
 constexpr char kOpHardSigmoidTypeName[] = "sigmoid_hard";
 constexpr char kOpInstanceNormalizationTypeName[] = "instance_norm";
+constexpr char kOpLayerNormalizationTypeName[] = "layer_norm";
 constexpr char kOpLeakyReluTypeName[] = "leaky_relu";
 constexpr char kOpMatmulTypeName[] = "matmul";
 constexpr char kOpPadTypeName[] = "pad";
@@ -187,10 +188,12 @@
     "upsample_nearest_neighbor";
 // General op params that are shared across multiple ops.
 constexpr char kOpParamAlpha[] = "alpha";
+constexpr char kOpParamAxes[] = "axes";
 constexpr char kOpParamAxis[] = "axis";
 constexpr char kOpParamBeta[] = "beta";
 constexpr char kOpParamDataTypeName[] = "dtype";
 constexpr char kOpParamEpsilon[] = "epsilon";
+constexpr char kOpParamGamma[] = "gamma";
 constexpr char kOpParamKeepDims[] = "keep_dims";
 constexpr char kOpParamPad[] = "pad";
 constexpr char kOpParamX[] = "x";
@@ -832,6 +835,11 @@
             *operation->get_instance_normalization(), block));
         break;
       }
+      case mojom::Operation::Tag::kLayerNormalization: {
+        RETURN_IF_ERROR(AddOperationForLayerNormalization(
+            *operation->get_layer_normalization(), block));
+        break;
+      }
       case mojom::Operation::Tag::kLeakyRelu: {
         RETURN_IF_ERROR(
             AddOperationForLeakyRelu(*operation->get_leaky_relu(), block));
@@ -930,7 +938,6 @@
       case mojom::Operation::Tag::kGelu:
       case mojom::Operation::Tag::kGru:
       case mojom::Operation::Tag::kGruCell:
-      case mojom::Operation::Tag::kLayerNormalization:
       case mojom::Operation::Tag::kLstm:
       case mojom::Operation::Tag::kLstmCell:
       case mojom::Operation::Tag::kPrelu:
@@ -1331,7 +1338,6 @@
 
   static constexpr char kParamMean[] = "mean";
   static constexpr char kParamVariance[] = "variance";
-  static constexpr char kParamGamma[] = "gamma";
 
   // TODO(crbug.com/338529226): These params must all be constant tensors.
   SetInputWithName(*op->mutable_inputs(), kParamMean,
@@ -1339,7 +1345,7 @@
   SetInputWithName(*op->mutable_inputs(), kParamVariance,
                    GetOperandInfo(operation.variance_operand_id).coreml_name);
   if (operation.scale_operand_id.has_value()) {
-    SetInputWithName(*op->mutable_inputs(), kParamGamma,
+    SetInputWithName(*op->mutable_inputs(), kOpParamGamma,
                      GetOperandInfo(*operation.scale_operand_id).coreml_name);
   }
   if (operation.bias_operand_id.has_value()) {
@@ -2061,11 +2067,9 @@
   SetInputWithName(*op->mutable_inputs(), kOpParamX,
                    input_operand_info.coreml_name);
 
-  static constexpr char kParamGamma[] = "gamma";
-
   // TODO(crbug.com/338529226): These params must all be constant tensors.
   if (operation.scale_operand_id.has_value()) {
-    SetInputWithName(*op->mutable_inputs(), kParamGamma,
+    SetInputWithName(*op->mutable_inputs(), kOpParamGamma,
                      GetOperandInfo(*operation.scale_operand_id).coreml_name);
   }
   if (operation.bias_operand_id.has_value()) {
@@ -2083,6 +2087,50 @@
 }
 
 base::expected<void, mojom::ErrorPtr>
+GraphBuilderCoreml::AddOperationForLayerNormalization(
+    const mojom::LayerNormalization& operation,
+    CoreML::Specification::MILSpec::Block& block) {
+  const OperandInfo& input_operand_info =
+      GetOperandInfo(operation.input_operand_id);
+  CHECK(kFloatDataTypes.contains(input_operand_info.mil_data_type));
+
+  // TODO: crbug.com/356905058: Figure out if unordered axes should be allowed.
+  if (!base::ranges::is_sorted(operation.axes)) {
+    return NewNotSupportedError("Axes must be ordered for layerNormalization.");
+  }
+
+  CoreML::Specification::MILSpec::Operation* op = block.add_operations();
+  op->set_type(kOpLayerNormalizationTypeName);
+  SetInputWithName(*op->mutable_inputs(), kOpParamX,
+                   input_operand_info.coreml_name);
+  std::vector<int32_t> axes;
+  base::ranges::transform(
+      operation.axes, std::back_inserter(axes),
+      [](uint32_t val) { return base::checked_cast<int32_t>(val); });
+
+  // TODO: crbug.com/338529226: These params must all be constant tensors.
+  if (operation.scale_operand_id.has_value()) {
+    SetInputWithName(
+        *op->mutable_inputs(), kOpParamGamma,
+        GetOperandInfo(operation.scale_operand_id.value()).coreml_name);
+  }
+  if (operation.bias_operand_id.has_value()) {
+    SetInputWithName(
+        *op->mutable_inputs(), kOpParamBeta,
+        GetOperandInfo(operation.bias_operand_id.value()).coreml_name);
+  }
+
+  SetInputsWithValues(
+      *op->mutable_inputs(),
+      {{kOpParamAxes, Create1DTensorImmediateValue<int32_t>(axes)},
+       {kOpParamEpsilon, CreateFloatValue(input_operand_info.mil_data_type,
+                                          operation.epsilon)}});
+
+  PopulateNamedValueType(operation.output_operand_id, *op->add_outputs());
+  return base::ok();
+}
+
+base::expected<void, mojom::ErrorPtr>
 GraphBuilderCoreml::AddOperationForLeakyRelu(
     const mojom::LeakyRelu& operation,
     CoreML::Specification::MILSpec::Block& block) {
@@ -2426,8 +2474,6 @@
         MILDataTypeToOperandType(input_operand_info.mil_data_type)));
   }
 
-  static constexpr char kParamAxes[] = "axes";
-
   std::vector<int32_t> axes;
 
   base::ranges::transform(
@@ -2435,7 +2481,7 @@
       [](uint32_t val) { return base::checked_cast<int32_t>(val); });
   SetInputsWithValues(
       *op->mutable_inputs(),
-      {{kParamAxes, Create1DTensorImmediateValue<int32_t>(axes)},
+      {{kOpParamAxes, Create1DTensorImmediateValue<int32_t>(axes)},
        {kOpParamKeepDims,
         CreateScalarImmediateValue(operation.keep_dimensions)}});
 
diff --git a/services/webnn/coreml/graph_builder_coreml.h b/services/webnn/coreml/graph_builder_coreml.h
index c9584c07..0774adc 100644
--- a/services/webnn/coreml/graph_builder_coreml.h
+++ b/services/webnn/coreml/graph_builder_coreml.h
@@ -248,6 +248,10 @@
   AddOperationForInstanceNormalization(
       const mojom::InstanceNormalization& operation,
       CoreML::Specification::MILSpec::Block& block);
+  [[nodiscard]] base::expected<void, mojom::ErrorPtr>
+  AddOperationForLayerNormalization(
+      const mojom::LayerNormalization& operation,
+      CoreML::Specification::MILSpec::Block& block);
   [[nodiscard]] base::expected<void, mojom::ErrorPtr> AddOperationForLeakyRelu(
       const mojom::LeakyRelu& operation,
       CoreML::Specification::MILSpec::Block& block);
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/layer_normalization.https.any.worker_cpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/layer_normalization.https.any.worker_cpu-expected.txt
index 339bb9d..5ed44c46 100644
--- a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/layer_normalization.https.any.worker_cpu-expected.txt
+++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/layer_normalization.https.any.worker_cpu-expected.txt
@@ -1,25 +1,7 @@
 This is a testharness.js-based test.
-[FAIL] layerNormalization float32 2D tensor default options
-  promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported operator layerNormalization."
-[FAIL] layerNormalization float32 3D tensor default options
-  promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported operator layerNormalization."
-[FAIL] layerNormalization float32 4D tensor default options
-  promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported operator layerNormalization."
-[FAIL] layerNormalization float32 5D tensor default options
-  promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported operator layerNormalization."
-[FAIL] layerNormalization float32 4D tensor options.scale
-  promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported operator layerNormalization."
-[FAIL] layerNormalization float32 4D tensor options.bias
-  promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported operator layerNormalization."
-[FAIL] layerNormalization float32 4D tensor options.axes=[2]
-  promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported operator layerNormalization."
-[FAIL] layerNormalization float32 4D tensor options.epsilon
-  promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported operator layerNormalization."
-[FAIL] layerNormalization float32 4D tensor options.scale and options.axes=[0, 2]
-  promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported operator layerNormalization."
 [FAIL] layerNormalization float32 4D tensor options.bias and options.axes=[3, 1, 2]
-  promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported operator layerNormalization."
+  promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Axes must be ordered for layerNormalization."
 [FAIL] layerNormalization float32 4D tensor all options
-  promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported operator layerNormalization."
+  promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Axes must be ordered for layerNormalization."
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/layer_normalization.https.any_cpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/layer_normalization.https.any_cpu-expected.txt
index 339bb9d..5ed44c46 100644
--- a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/layer_normalization.https.any_cpu-expected.txt
+++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/layer_normalization.https.any_cpu-expected.txt
@@ -1,25 +1,7 @@
 This is a testharness.js-based test.
-[FAIL] layerNormalization float32 2D tensor default options
-  promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported operator layerNormalization."
-[FAIL] layerNormalization float32 3D tensor default options
-  promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported operator layerNormalization."
-[FAIL] layerNormalization float32 4D tensor default options
-  promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported operator layerNormalization."
-[FAIL] layerNormalization float32 5D tensor default options
-  promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported operator layerNormalization."
-[FAIL] layerNormalization float32 4D tensor options.scale
-  promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported operator layerNormalization."
-[FAIL] layerNormalization float32 4D tensor options.bias
-  promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported operator layerNormalization."
-[FAIL] layerNormalization float32 4D tensor options.axes=[2]
-  promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported operator layerNormalization."
-[FAIL] layerNormalization float32 4D tensor options.epsilon
-  promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported operator layerNormalization."
-[FAIL] layerNormalization float32 4D tensor options.scale and options.axes=[0, 2]
-  promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported operator layerNormalization."
 [FAIL] layerNormalization float32 4D tensor options.bias and options.axes=[3, 1, 2]
-  promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported operator layerNormalization."
+  promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Axes must be ordered for layerNormalization."
 [FAIL] layerNormalization float32 4D tensor all options
-  promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported operator layerNormalization."
+  promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Axes must be ordered for layerNormalization."
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/layer_normalization.https.any.worker_gpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/layer_normalization.https.any.worker_gpu-expected.txt
index 339bb9d..5ed44c46 100644
--- a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/layer_normalization.https.any.worker_gpu-expected.txt
+++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/layer_normalization.https.any.worker_gpu-expected.txt
@@ -1,25 +1,7 @@
 This is a testharness.js-based test.
-[FAIL] layerNormalization float32 2D tensor default options
-  promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported operator layerNormalization."
-[FAIL] layerNormalization float32 3D tensor default options
-  promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported operator layerNormalization."
-[FAIL] layerNormalization float32 4D tensor default options
-  promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported operator layerNormalization."
-[FAIL] layerNormalization float32 5D tensor default options
-  promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported operator layerNormalization."
-[FAIL] layerNormalization float32 4D tensor options.scale
-  promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported operator layerNormalization."
-[FAIL] layerNormalization float32 4D tensor options.bias
-  promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported operator layerNormalization."
-[FAIL] layerNormalization float32 4D tensor options.axes=[2]
-  promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported operator layerNormalization."
-[FAIL] layerNormalization float32 4D tensor options.epsilon
-  promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported operator layerNormalization."
-[FAIL] layerNormalization float32 4D tensor options.scale and options.axes=[0, 2]
-  promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported operator layerNormalization."
 [FAIL] layerNormalization float32 4D tensor options.bias and options.axes=[3, 1, 2]
-  promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported operator layerNormalization."
+  promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Axes must be ordered for layerNormalization."
 [FAIL] layerNormalization float32 4D tensor all options
-  promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported operator layerNormalization."
+  promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Axes must be ordered for layerNormalization."
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/layer_normalization.https.any_gpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/layer_normalization.https.any_gpu-expected.txt
index 339bb9d..5ed44c46 100644
--- a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/layer_normalization.https.any_gpu-expected.txt
+++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/layer_normalization.https.any_gpu-expected.txt
@@ -1,25 +1,7 @@
 This is a testharness.js-based test.
-[FAIL] layerNormalization float32 2D tensor default options
-  promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported operator layerNormalization."
-[FAIL] layerNormalization float32 3D tensor default options
-  promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported operator layerNormalization."
-[FAIL] layerNormalization float32 4D tensor default options
-  promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported operator layerNormalization."
-[FAIL] layerNormalization float32 5D tensor default options
-  promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported operator layerNormalization."
-[FAIL] layerNormalization float32 4D tensor options.scale
-  promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported operator layerNormalization."
-[FAIL] layerNormalization float32 4D tensor options.bias
-  promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported operator layerNormalization."
-[FAIL] layerNormalization float32 4D tensor options.axes=[2]
-  promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported operator layerNormalization."
-[FAIL] layerNormalization float32 4D tensor options.epsilon
-  promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported operator layerNormalization."
-[FAIL] layerNormalization float32 4D tensor options.scale and options.axes=[0, 2]
-  promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported operator layerNormalization."
 [FAIL] layerNormalization float32 4D tensor options.bias and options.axes=[3, 1, 2]
-  promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported operator layerNormalization."
+  promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Axes must be ordered for layerNormalization."
 [FAIL] layerNormalization float32 4D tensor all options
-  promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported operator layerNormalization."
+  promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Axes must be ordered for layerNormalization."
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/layer_normalization.https.any.worker_npu-expected.txt b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/layer_normalization.https.any.worker_npu-expected.txt
index 339bb9d..5ed44c46 100644
--- a/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/layer_normalization.https.any.worker_npu-expected.txt
+++ b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/layer_normalization.https.any.worker_npu-expected.txt
@@ -1,25 +1,7 @@
 This is a testharness.js-based test.
-[FAIL] layerNormalization float32 2D tensor default options
-  promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported operator layerNormalization."
-[FAIL] layerNormalization float32 3D tensor default options
-  promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported operator layerNormalization."
-[FAIL] layerNormalization float32 4D tensor default options
-  promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported operator layerNormalization."
-[FAIL] layerNormalization float32 5D tensor default options
-  promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported operator layerNormalization."
-[FAIL] layerNormalization float32 4D tensor options.scale
-  promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported operator layerNormalization."
-[FAIL] layerNormalization float32 4D tensor options.bias
-  promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported operator layerNormalization."
-[FAIL] layerNormalization float32 4D tensor options.axes=[2]
-  promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported operator layerNormalization."
-[FAIL] layerNormalization float32 4D tensor options.epsilon
-  promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported operator layerNormalization."
-[FAIL] layerNormalization float32 4D tensor options.scale and options.axes=[0, 2]
-  promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported operator layerNormalization."
 [FAIL] layerNormalization float32 4D tensor options.bias and options.axes=[3, 1, 2]
-  promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported operator layerNormalization."
+  promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Axes must be ordered for layerNormalization."
 [FAIL] layerNormalization float32 4D tensor all options
-  promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported operator layerNormalization."
+  promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Axes must be ordered for layerNormalization."
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/layer_normalization.https.any_npu-expected.txt b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/layer_normalization.https.any_npu-expected.txt
index 339bb9d..5ed44c46 100644
--- a/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/layer_normalization.https.any_npu-expected.txt
+++ b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/layer_normalization.https.any_npu-expected.txt
@@ -1,25 +1,7 @@
 This is a testharness.js-based test.
-[FAIL] layerNormalization float32 2D tensor default options
-  promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported operator layerNormalization."
-[FAIL] layerNormalization float32 3D tensor default options
-  promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported operator layerNormalization."
-[FAIL] layerNormalization float32 4D tensor default options
-  promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported operator layerNormalization."
-[FAIL] layerNormalization float32 5D tensor default options
-  promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported operator layerNormalization."
-[FAIL] layerNormalization float32 4D tensor options.scale
-  promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported operator layerNormalization."
-[FAIL] layerNormalization float32 4D tensor options.bias
-  promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported operator layerNormalization."
-[FAIL] layerNormalization float32 4D tensor options.axes=[2]
-  promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported operator layerNormalization."
-[FAIL] layerNormalization float32 4D tensor options.epsilon
-  promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported operator layerNormalization."
-[FAIL] layerNormalization float32 4D tensor options.scale and options.axes=[0, 2]
-  promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported operator layerNormalization."
 [FAIL] layerNormalization float32 4D tensor options.bias and options.axes=[3, 1, 2]
-  promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported operator layerNormalization."
+  promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Axes must be ordered for layerNormalization."
 [FAIL] layerNormalization float32 4D tensor all options
-  promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported operator layerNormalization."
+  promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Axes must be ordered for layerNormalization."
 Harness: the test ran to completion.