diff --git a/onnxruntime/core/optimizer/skip_layer_norm_fusion.cc b/onnxruntime/core/optimizer/skip_layer_norm_fusion.cc index 3727ac0918115..2541b4870486d 100644 --- a/onnxruntime/core/optimizer/skip_layer_norm_fusion.cc +++ b/onnxruntime/core/optimizer/skip_layer_norm_fusion.cc @@ -199,7 +199,11 @@ Status SkipLayerNormFusion::ApplyImpl(Graph& graph, bool& modified, int graph_le Format matched_format = Format::None; // Format 1 - std::vector format1_parent_path{ + // The matcher paths are compile-time constants, so make them function-local `static const`: + // built once (not per node iteration), and their destructors run at program exit rather than + // inlined into ApplyImpl, which sidesteps a GCC 15 -Wfree-nonheap-object false positive on the + // vector's destructor. + static const std::vector format1_parent_path{ {0, 0, "Add", {7, 13, 14}, kOnnxDomain}, {0, 0, "Add", {7, 13, 14}, kOnnxDomain}}; @@ -218,7 +222,7 @@ Status SkipLayerNormFusion::ApplyImpl(Graph& graph, bool& modified, int graph_le if (matched_format == Format::None) { // Format 2 - std::vector format2_parent_path{ + static const std::vector format2_parent_path{ {0, 0, "Add", {7, 13, 14}, kOnnxDomain}, {0, 1, "Add", {7, 13, 14}, kOnnxDomain}}; @@ -237,7 +241,7 @@ Status SkipLayerNormFusion::ApplyImpl(Graph& graph, bool& modified, int graph_le if (matched_format == Format::None) { // Format 3 - std::vector format3_parent_path{ + static const std::vector format3_parent_path{ {0, 0, "Add", {7, 13, 14}, kOnnxDomain}}; if (graph_utils::FindPath(ln_node, true, format3_parent_path, edges, logger)) { diff --git a/onnxruntime/test/providers/cpu/ml/zipmap_test.cc b/onnxruntime/test/providers/cpu/ml/zipmap_test.cc index e2e8ced73e565..d154a143a34ec 100644 --- a/onnxruntime/test/providers/cpu/ml/zipmap_test.cc +++ b/onnxruntime/test/providers/cpu/ml/zipmap_test.cc @@ -7,10 +7,14 @@ using namespace std; namespace onnxruntime { namespace test { template -void TestHelper(const std::vector& classes, +void TestHelper(std::initializer_list classes_init, const std::string& type, const vector& input_dims, OpTester::ExpectResult expect_result = OpTester::ExpectResult::kExpectSuccess) { + // Materialize the class list inside the helper rather than binding a braced std::vector temporary + // at each call site: keeps the vector's construction/destruction out of the inlined TEST body, + // where GCC 15 emits a -Wfree-nonheap-object false positive on the vector's destructor. + const std::vector classes(classes_init); OpTester test("ZipMap", 1, onnxruntime::kMLDomain); std::vector input{1.f, 0.f, 3.f, 44.f, 23.f, 11.3f}; diff --git a/onnxruntime/test/unittest_util/conversion.h b/onnxruntime/test/unittest_util/conversion.h index b0f0663f33dd7..5fa9860576619 100644 --- a/onnxruntime/test/unittest_util/conversion.h +++ b/onnxruntime/test/unittest_util/conversion.h @@ -3,6 +3,7 @@ #pragma once +#include #include #include "core/common/float16.h" @@ -10,29 +11,28 @@ namespace onnxruntime { namespace test { +// These converters use std::transform rather than an Eigen Map cast-assignment. The Eigen path +// vectorizes to a 16-wide _mm512_loadu_ps under -march=native, which GCC 15 mis-flags with a +// -Warray-bounds false positive when the helper is inlined into callers that pass small fixed-size +// buffers (it assumes the guarded packet load runs at input_size < 16). The element-wise transforms +// keep identical conversion semantics (Eigen::half round-to-nearest for float<->half; static_cast +// for the integer casts) without the vectorized load. inline void ConvertFloatToMLFloat16(const float* f_datat, MLFloat16* h_data, size_t input_size) { - auto in_vector = ConstEigenVectorMap(f_datat, input_size); - auto output_vector = EigenVectorMap(static_cast(static_cast(h_data)), input_size); - output_vector = in_vector.template cast(); + auto* h = static_cast(static_cast(h_data)); + std::transform(f_datat, f_datat + input_size, h, [](float f) { return static_cast(f); }); } inline void ConvertFloatToUint8_t(const float* f_datat, uint8_t* u8_data, size_t input_size) { - auto in_vector = ConstEigenVectorMap(f_datat, input_size); - auto output_vector = EigenVectorMap(static_cast(static_cast(u8_data)), input_size); - output_vector = in_vector.template cast(); + std::transform(f_datat, f_datat + input_size, u8_data, [](float f) { return static_cast(f); }); } inline void ConvertFloatToInt8_t(const float* f_datat, int8_t* i8_data, size_t input_size) { - auto in_vector = ConstEigenVectorMap(f_datat, input_size); - auto output_vector = EigenVectorMap(static_cast(static_cast(i8_data)), input_size); - output_vector = in_vector.template cast(); + std::transform(f_datat, f_datat + input_size, i8_data, [](float f) { return static_cast(f); }); } inline void ConvertMLFloat16ToFloat(const MLFloat16* h_data, float* f_data, size_t input_size) { - auto in_vector = - ConstEigenVectorMap(static_cast(static_cast(h_data)), input_size); - auto output_vector = EigenVectorMap(f_data, input_size); - output_vector = in_vector.template cast(); + const auto* h = static_cast(static_cast(h_data)); + std::transform(h, h + input_size, f_data, [](Eigen::half h) { return static_cast(h); }); } inline std::vector FloatsToMLFloat16s(const std::vector& f) {