class_docstr: Base TestCase to be used for all conv-bn[-relu] fusion patterns.
class_docstr_tok: ["Base","TestCase","to","be","used","for","all","conv-bn","[","-relu","]","fusion","patterns","."]
docstr: Test the case where the placeholder node for the [conv - bn - getitem] pattern
  is also a getitem node:
  
    some_op -> unrelated_getitem -> conv -> bn -> conv_bn_getitem
  
  We want the metadata to be copied from the `conv_bn_getitem` node, not from
  the `unrelated_getitem` node, which is not part of the conv-bn pattern but
  is returned as part of the match anyway (as a placeholder).
docstr_tok: ["Test","the","case","where","the","placeholder","node","for","the","[","conv","-","bn","-","getitem","]","pattern","is","also","a","getitem","node",":","some_op","-",">","unrelated_getitem","-",">","conv","-",">","bn","-",">","conv_bn_getitem","We","want","the","metadata","to","be","copied","from","the","`","conv_bn_getitem","`","node",",","not","from","the","`","unrelated_getitem","`","node",",","which","is","not","part","of","the","conv-bn","pattern","but","is","returned","as","part","of","the","match","anyway","(","as","a","placeholder",")","."]
code: def test_prepare_qat_conv_bn_fusion_getitem_placeholder(self):
      """
      Test the case where the placeholder node for the [conv - bn - getitem] pattern
      is also a getitem node:
  
        some_op -> unrelated_getitem -> conv -> bn -> conv_bn_getitem
  
      We want the metadata to be copied from the `conv_bn_getitem` node, not from
      the `unrelated_getitem` node, which is not part of the conv-bn pattern but
      is returned as part of the match anyway (as a placeholder).
      """
  
      class M(torch.nn.Module):
          def __init__(self, conv_class, bn_class):
              super().__init__()
              self.bn1 = bn_class(3)
              self.conv = conv_class(3, 3, 3)
              self.bn2 = bn_class(3)
  
          def forward(self, x):
              x = self.bn1(x)
              x = self.conv(x)
              x = self.bn2(x)
              return x
  
      def _get_getitem_nodes(m: torch.fx.GraphModule):
          """
          Return a 2-tuple of (unrelated_getitem_node, conv_bn_getitem_node) from the graph.
          """
          unrelated_getitem_node, conv_bn_getitem_node = None, None
          for node in m.graph.nodes:
              if (
                  node.target != operator.getitem
                  or node.args[0].target
                  != torch.ops.aten._native_batch_norm_legit.default
              ):
                  continue
              if node.args[0].args[0].op == "placeholder":
                  unrelated_getitem_node = node
              else:
                  conv_bn_getitem_node = node
          assert (
              unrelated_getitem_node is not None
          ), "did not find unrelated getitem node, bad test setup"
          assert (
              conv_bn_getitem_node is not None
          ), "did not find conv bn getitem node, bad test setup"
          return (unrelated_getitem_node, conv_bn_getitem_node)
  
      # Program capture
      m = M(self.conv_class, self.bn_class)
      m = capture_pre_autograd_graph(m, self.example_inputs)
      m.graph.eliminate_dead_code()
      m.recompile()
      (_, original_conv_bn_getitem_node) = _get_getitem_nodes(m)
  
      # Prepare QAT
      quantizer = XNNPACKQuantizer()
      quantizer.set_global(
          get_symmetric_quantization_config(
              is_per_channel=False, is_qat=True
          )
      )
      m = prepare_qat_pt2e(m, quantizer)
      (
          unrelated_getitem_node,
          conv_bn_getitem_node,
      ) = _get_getitem_nodes(m)
  
      # Verify that the metadata was copied from `conv_bn_getitem`, not `unrelated_getitem`
      original_conv_bn_getitem_meta = (
          original_conv_bn_getitem_node.meta["quantization_annotation"]
      )
      conv_bn_getitem_meta = conv_bn_getitem_node.meta[
          "quantization_annotation"
      ]
      self.assertEqual(
          conv_bn_getitem_meta, original_conv_bn_getitem_meta
      )
      self.assertTrue(
          "quantization_annotation" not in unrelated_getitem_node.meta
      )
  
imports: import copy
  import operator
  import unittest
  from typing import Any, Optional, Tuple, Type
  import torch
  from torch._export import capture_pre_autograd_graph
  from torch.ao.quantization import default_fake_quant, FusedMovingAvgObsFakeQuantize, MovingAverageMinMaxObserver, MovingAveragePerChannelMinMaxObserver, QConfigMapping
  from torch.ao.quantization.backend_config import get_qnnpack_backend_config
  from torch.ao.quantization.qconfig import default_per_channel_symmetric_qnnpack_qat_qconfig, default_symmetric_qnnpack_qat_qconfig
  from torch.ao.quantization.quantize_fx import prepare_qat_fx
  from torch.ao.quantization.quantize_pt2e import _convert_to_reference_decomposed_fx, convert_pt2e, prepare_pt2e, prepare_qat_pt2e
  from torch.ao.quantization.quantizer import DerivedQuantizationSpec, QuantizationAnnotation, QuantizationSpec, Quantizer
  from torch.ao.quantization.quantizer.xnnpack_quantizer import get_symmetric_quantization_config, XNNPACKQuantizer
  from torch.testing._internal.common_cuda import TEST_CUDA
  from torch.testing._internal.common_quantization import NodeSpec, QuantizationTestCase, skip_if_no_torchvision, skipIfNoQNNPACK
  from torch.testing._internal.common_quantized import override_quantized_engine
label_desc: Use image node_id 11 for calling the TestQuantizePT2EQAT_ConvBn_Base obj's underlying member method code with example usage: obj.test_prepare_qat_conv_bn_fusion_getitem_placeholder() and returns: unrelated_getitem_node,  conv_bn_getitem_node, x