def select_input_output_channel_axis(op: "Operation") -> Tuple[Optional[int], Optional[int]]:
    """
    Here are some representative ops:
    - linear: [D_out, D_in]
    - matmul's y: [..., D_in, D_out] if transpose_y is False, else [..., D_out, D_in]
    - conv: [C_out, C_in_div_group, KH, KW]
    - conv_transpose: [C_in, C_out_div_group, KH, KW]

    The input output channel axis selection criteria is:
    - For conv_transpose the output channel is 1 and input channel is 0.
    - For matmul's y:
        - When transpose_y=False, output channel is -1 and input channel is -2
        - When transpose_y=True, output channel is -2 and input channel is -1
    - For matmul's x:
        - When transpose_x=False, output channel is -2 and input channel is -1
        - When transpose_y=True, output channel is -1 and input channel is -2
    - For all other ops, output channel is 0 and input channel is 1.

    If cannot determine the input/output axis, return None to denote unknown.
    """
    var = op.outputs[0]

    # The op could be fed into multiple ops, so we traverse all children ops to see if they
    # have consistent input/output axis, otherwise set the axis to None.
    output_channel_axis_set = set()
    input_channel_axis_set = set()
    for child_op in var.child_ops:
        # By default, output channel axis is 0 and input channel axis is 1.
        output_channel_axis, input_channel_axis = 0, 1

        if child_op.op_type == "conv_transpose":
            output_channel_axis = 1
            input_channel_axis = 0
        elif child_op.op_type == "matmul":
            if child_op.y == var:
                if child_op.transpose_y.val:
                    output_channel_axis = -2
                    input_channel_axis = -1
                else:
                    output_channel_axis = -1
                    input_channel_axis = -2
            else:  # var is used as matmul's x.
                if child_op.transpose_x.val:
                    output_channel_axis = -1
                    input_channel_axis = -2
                else:
                    output_channel_axis = -2
                    input_channel_axis = -1
        elif child_op.op_type.startswith("constexpr_"):
            # In joint compression constexpr op could be chained together.
            input_channel_axis, output_channel_axis = select_input_output_channel_axis(child_op)

        if output_channel_axis < 0:
            output_channel_axis += var.rank
        if input_channel_axis < 0:
            input_channel_axis += var.rank
        output_channel_axis_set.add(output_channel_axis)
        input_channel_axis_set.add(input_channel_axis)

    output_channel_axis, input_channel_axis = 0, 1
    if len(output_channel_axis_set) > 1:
        _logger.warning(
            f"Can't decide output axis for op {op.name}, because it's fed "
            f"into multiple downstream ops which require different output axes."
        )
        output_channel_axis = None
    elif len(output_channel_axis_set) == 1:
        output_channel_axis = output_channel_axis_set.pop()

    if len(input_channel_axis_set) > 1:
        _logger.warning(
            f"Can't decide input axis for op {op.name}, because it's fed "
            f"into multiple downstream ops which require different input axes."
        )
        input_channel_axis = None
    elif len(input_channel_axis_set) == 1:
        input_channel_axis = input_channel_axis_set.pop()

    return input_channel_axis, output_channel_axis

    Here are some representative ops:
    - linear: [D_out, D_in]
    - matmul's y: [..., D_in, D_out] if transpose_y is False, else [..., D_out, D_in]
    - conv: [C_out, C_in_div_group, KH, KW]
    - conv_transpose: [C_in, C_out_div_group, KH, KW]

    The input output channel axis selection criteria is:
    - For conv_transpose the output channel is 1 and input channel is 0.
    - For matmul's y:
        - When transpose_y=False, output channel is -1 and input channel is -2
        - When transpose_y=True, output channel is -2 and input channel is -1
    - For matmul's x:
        - When transpose_x=False, output channel is -2 and input channel is -1
        - When transpose_y=True, output channel is -1 and input channel is -2
    - For all other ops, output channel is 0 and input channel is 1.

    If cannot determine the input/output axis, return None to denote unknown.
    
coremltools/optimize/_utils.py