def _add_recipe(node):
    r"""
    Case1: add has pre gemm node.
    Given  gemm     op             gemm         op                gemm       op
             \     /                 \         /                   \       /
              \   /       ==>    fake_quant (fake_quant?)     ==>   \   (fake_quant?)
               \ /                     \    /                        \   /
               add                       add                          add

          gemm     fp32_op          gemm     quantizable_op
    ==>    \        /                \         /
            \      /          or      \     fake_quant
             \    /                    \    /
              add                       add

    Case2: add doesn't have pre conv/gemm node.
    For this case, if one add input has one none-quantizable op, we will don't insert fake quant before it.
    """

    def reset_input_inf_dtype_to_orig_dtype(node, input_idx):
        if node.input_tensor_infos[input_idx] is not None:
            if (
                node.input_tensor_infos[input_idx]
                in node.pre_nodes[0].output_tensor_infos
            ):
                pre_node = node.pre_nodes[input_idx]
            elif (
                len(node.pre_nodes) == 2
                and node.input_tensor_infos[input_idx]
                in node.pre_nodes[1].output_tensor_infos
            ):
                pre_node = node.pre_nodes[1]
            else:
                pre_node = None
            if pre_node is not None:
                add_quantize_add_input_idx = _check_has_quantizable_node_before_node(
                    pre_node
                )
            else:
                add_quantize_add_input_idx = False
            if not add_quantize_add_input_idx:
                node.input_tensor_infos[input_idx].inf_dtype = node.input_tensor_infos[
                    input_idx
                ].orig_dtype
                node.input_tensor_force_inf_dtype[input_idx] = node.input_tensor_infos[
                    input_idx
                ].inf_dtype

    def force_reset_input_inf_dtype_to_orig_dtype(node, input_idx):
        if node.input_tensor_infos[input_idx] is not None:
            node.input_tensor_infos[input_idx].inf_dtype = node.input_tensor_infos[
                input_idx
            ].orig_dtype
            node.input_tensor_force_inf_dtype[input_idx] = node.input_tensor_infos[
                input_idx
            ].inf_dtype

    conv_gemm_node = _find_fused_node_with_cur_add(node, conv_gemm_ops)
    conv_node = _find_fused_node_with_cur_add(node, conv_ops)
    if conv_gemm_node is None:
        #  If pre_nodes don't have gemm node, need to check whether have quantizable node before it,
        #  if does't have quantizable node before it, we will not insert fake quant before add.
        # hoping all input nodes are quantizable node.
        if len(node.pre_nodes) > 0:
            add_1_has_pre_quantizable_op = _check_has_quantizable_node_before_node(
                node.pre_nodes[0]
            )
            add_2_has_pre_quantizable_op = False
            if len(node.pre_nodes) == 2:
                add_2_has_pre_quantizable_op = _check_has_quantizable_node_before_node(
                    node.pre_nodes[1]
                )

            # Generally, if add connected to 2 quantizable node, we will keep the fake quant
            # in the input edges of this add.
            if not (add_1_has_pre_quantizable_op and add_2_has_pre_quantizable_op):
                for idx, tensor_info in enumerate(node.input_tensor_infos):
                    tensor_info.inf_dtype = tensor_info.orig_dtype
                    node.input_tensor_force_inf_dtype[idx] = tensor_info.inf_dtype

            # A corner case is
            # add1    add2
            #  \     /
            #    add3
            # which exists in GPT-J, in this case, we need to remove the fake quant in
            # 2 inputs edge of add3
            if (
                (len(node.pre_nodes) == 2)
                and (node.pre_nodes[0].type in [str(torch.Tensor.add), str(torch.add)])
                and (node.pre_nodes[1].type in [str(torch.Tensor.add), str(torch.add)])
            ):
                for idx, tensor_info in enumerate(node.input_tensor_infos):
                    tensor_info.inf_dtype = tensor_info.orig_dtype
                    node.input_tensor_force_inf_dtype[idx] = tensor_info.inf_dtype
        else:
            for idx, tensor_info in enumerate(node.input_tensor_infos):
                tensor_info.inf_dtype = tensor_info.orig_dtype
                node.input_tensor_force_inf_dtype[idx] = tensor_info.inf_dtype
    else:
        # add can fused with gemm.
        if (
            node.input_tensor_infos[0] is not None
            and node.input_tensor_infos[0] in conv_gemm_node.output_tensor_infos
        ):
            node.input_tensor_infos[0].inf_dtype = node.input_tensor_infos[0].orig_dtype
            node.input_tensor_force_inf_dtype[0] = node.input_tensor_infos[0].inf_dtype
            # TODO: set another input's dtype for conv nodes when oneDNN is ready.
            if conv_node is None or not _check_has_quantizable_node_after_node(node):
                # set another input's dtype, if another's input is from non-quantizable op, we can remove the fake quant.
                if conv_node is None:
                    # For linear_add pattern, force reset add's extra input's inf_dtype to orig_dtype
                    force_reset_input_inf_dtype_to_orig_dtype(node, 1)
                else:
                    reset_input_inf_dtype_to_orig_dtype(node, 1)
        elif (
            node.input_tensor_infos[1] is not None
            and node.input_tensor_infos[1] in conv_gemm_node.output_tensor_infos
        ):
            node.input_tensor_infos[1].inf_dtype = node.input_tensor_infos[1].orig_dtype
            node.input_tensor_force_inf_dtype[1] = node.input_tensor_infos[1].inf_dtype
            # TODO: set another input's dtype for conv nodes when oneDNN is ready.
            if conv_node is None or not _check_has_quantizable_node_after_node(node):
                # set another input's dtype, if another's input is from non-quantizable op, we can remove the fake quant.
                if conv_node is None:
                    # For linear_add pattern, force reset add's extra input's inf_dtype to orig_dtype
                    force_reset_input_inf_dtype_to_orig_dtype(node, 0)
                else:
                    reset_input_inf_dtype_to_orig_dtype(node, 0)

    Case1: add has pre gemm node.
    Given  gemm     op             gemm         op                gemm       op
             \     /                 \         /                   \       /
              \   /       ==>    fake_quant (fake_quant?)     ==>   \   (fake_quant?)
               \ /                     \    /                        \   /
               add                       add                          add

          gemm     fp32_op          gemm     quantizable_op
    ==>    \        /                \         /
            \      /          or      \     fake_quant
             \    /                    \    /
              add                       add

    Case2: add doesn't have pre conv/gemm node.
    For this case, if one add input has one none-quantizable op, we will don't insert fake quant before it.
    
intel_extension_for_pytorch/quantization/_recipe.py