def broadcast_shapes(shape_x, shape_y):
    """
    Check and broadcast given input shapes.
    :param shape_x: tuple of int or symbols
        Shape of the first tensor (possibly symbolic).
    :param shape_y: tuple of int or symbols
        Shape of the second tensor (possibly symbolic).
    :return: tuple of int or symbols
        Result from broadcast.
    """

    def raise_incompatible_dim_exception():
        raise ValueError(
            "Incompatible dim {} in shapes {} vs. {}".format(
                i, shape_x, shape_y
            )
        )

    shape_x = tuple(shape_x)
    shape_y = tuple(shape_y)
    if len(shape_x) < len(shape_y):
        shape_x = tuple([1] * (len(shape_y) - len(shape_x))) + shape_x
    if len(shape_y) < len(shape_x):
        shape_y = tuple([1] * (len(shape_x) - len(shape_y))) + shape_y

    ret_shapes = list()
    for i in range(len(shape_x)):
        if shape_x[i] == shape_y[i]:
            ret_shapes.append(shape_x[i])
        else:
            is_x_unknown = is_symbolic(shape_x[i])
            is_y_unknown = is_symbolic(shape_y[i])
            if shape_x[i] == 1:
                ret_shapes.append(shape_y[i])
            elif shape_y[i] == 1:
                ret_shapes.append(shape_x[i])
            elif not is_y_unknown and shape_y[i] > 1:
                if not is_x_unknown and shape_x[i] != shape_y[i]:
                    raise_incompatible_dim_exception()
                ret_shapes.append(shape_y[i])
            elif not is_x_unknown and shape_x[i] > 1:
                if not is_y_unknown and shape_x[i] != shape_y[i]:
                    raise_incompatible_dim_exception()
                ret_shapes.append(shape_x[i])
            elif is_x_unknown or is_y_unknown:
                ret_shapes.append(get_new_symbol())
            else:
                raise_incompatible_dim_exception()

    return tuple(ret_shapes)

    Check and broadcast given input shapes.
    :param shape_x: tuple of int or symbols
        Shape of the first tensor (possibly symbolic).
    :param shape_y: tuple of int or symbols
        Shape of the second tensor (possibly symbolic).
    :return: tuple of int or symbols
        Result from broadcast.
    
coremltools/converters/mil/mil/ops/defs/_utils.py