diff --git a/src/plugins/intel_gpu/src/plugin/transformations/increase_position_ids_precision.cpp b/src/plugins/intel_gpu/src/plugin/transformations/increase_position_ids_precision.cpp index 5f2870231da..ca740480c62 100644 --- a/src/plugins/intel_gpu/src/plugin/transformations/increase_position_ids_precision.cpp +++ b/src/plugins/intel_gpu/src/plugin/transformations/increase_position_ids_precision.cpp @@ -481,22 +481,31 @@ IncreasePositionIdsPrecisionForGemma4::IncreasePositionIdsPrecisionForGemma4() { using namespace ov::pass::pattern; using ov::pass::pattern::op::Or; - // Gemma4 RoPE pattern: - // MatMul (f16) → Convert (f16→f32) → Transpose → Concat → Sin/Cos → Unsqueeze → RoPE - // The difference from base IncreasePositionIdsPrecisionForRoPE is that - // there is a Convert node between MatMul and Transpose. + // Gemma4 RoPE pattern (two variants): + // + // Original : + // MatMul → Convert → Transpose → Concat → Sin/Cos → Unsqueeze → RoPE + // + // Current (after upstream Unsqueeze→Reshape and Transpose→Reshape folding): + // MatMul → Reshape(Transpose) → Concat → Sin/Cos → Reshape(Unsqueeze) → RoPE + // auto matmul = wrap_type(); auto convert_after_matmul = wrap_type({matmul}); - auto transpose_m = wrap_type({convert_after_matmul, any_input()}); - auto concat = wrap_type({transpose_m, transpose_m}); + auto transpose_with_convert = wrap_type({convert_after_matmul, any_input()}); + auto transpose_direct = wrap_type({matmul, any_input()}); + auto reshape_transpose = wrap_type({matmul, any_input()}); + auto concat_input = std::make_shared(OutputVector{transpose_with_convert, transpose_direct, reshape_transpose}); + auto concat = wrap_type({concat_input, concat_input}); auto sin = wrap_type({concat}); auto cos = wrap_type({concat}); auto sin_unsqueeze = wrap_type({sin, wrap_type()}); auto cos_unsqueeze = wrap_type({cos, wrap_type()}); + auto sin_reshape = wrap_type({sin, any_input()}); + auto cos_reshape = wrap_type({cos, any_input()}); - auto rope_sin_input = std::make_shared(OutputVector{sin_unsqueeze, sin}); - auto rope_cos_input = std::make_shared(OutputVector{cos_unsqueeze, cos}); + auto rope_sin_input = std::make_shared(OutputVector{sin_unsqueeze, sin_reshape, sin}); + auto rope_cos_input = std::make_shared(OutputVector{cos_unsqueeze, cos_reshape, cos}); auto rope = wrap_type({any_input(), rope_cos_input, rope_sin_input}); @@ -504,7 +513,6 @@ IncreasePositionIdsPrecisionForGemma4::IncreasePositionIdsPrecisionForGemma4() { const auto& pattern_map = m.get_pattern_value_map(); auto matmul_node = ov::as_type_ptr(pattern_map.at(matmul).get_node_shared_ptr()); - auto convert_node = ov::as_type_ptr(pattern_map.at(convert_after_matmul).get_node_shared_ptr()); if (!matmul_node || transformation_callback(matmul_node)) return false; @@ -515,8 +523,6 @@ IncreasePositionIdsPrecisionForGemma4::IncreasePositionIdsPrecisionForGemma4() { return false; // Ensure both MatMul inputs are f32. - // - If input is a Convert node (e.g. Convert_3: i32→f16), replace it with i32→f32. - // - If input is not a Convert (e.g. Broadcast: f16), insert a new Convert(f16→f32) before it. for (auto& input : matmul_node->inputs()) { auto src_output = input.get_source_output(); auto src_node = src_output.get_node_shared_ptr(); @@ -537,10 +543,13 @@ IncreasePositionIdsPrecisionForGemma4::IncreasePositionIdsPrecisionForGemma4() { } } - // Remove the Convert after MatMul (f16→f32) since MatMul now outputs f32. - // Just replace it with MatMul's output directly. - if (convert_node) { - ov::replace_node(convert_node, matmul_node); + // Remove the Convert after MatMul if present (original pattern). + if (pattern_map.count(convert_after_matmul)) { + auto convert_node = ov::as_type_ptr( + pattern_map.at(convert_after_matmul).get_node_shared_ptr()); + if (convert_node) { + ov::replace_node(convert_node, matmul_node); + } } return true;