def test_conv1d_bias_fusion(self, backend, has_bias, bias_op_type):
        """
        After recomposing the shattered conv1d, conv1d optimization passes should work

        Input graph:
        input -> expand_dims -> conv2d -> squeeze -> add/sub a constant -> out

        Output graph:
        input -> conv1d -> out
        """
        N, L = 2, 8
        C_in, C_out = 3, 5
        K = 3

        strides = (1, 2)
        pad = (0, 0, 0, 1)
        dilations = (1, 2)

        # infer L_out with pad_type fixed to custom
        L_out = (L + pad[-2] + pad[-1] - dilations[-1] * (K - 1) - 1) // strides[-1] + 1

        conv_kwargs = {
            "weight": np.random.rand(C_out, C_in, 1, K),
            "strides": strides,
            "pad_type": "custom",
            "pad": pad,
            "dilations": dilations,
        }
        if has_bias:
            conv_kwargs["bias"] = np.random.rand(C_out)

        bias2 = np.random.rand(C_out, 1)

        @mb.program(input_specs=[mb.TensorSpec(shape=(N, C_in, L))])
        def prog(x):
            y_expand = mb.expand_dims(x=x, axes=(-2,))
            y_conv = mb.conv(x=y_expand, **conv_kwargs)
            y_squeeze = mb.squeeze(x=y_conv, axes=(-2,))
            y_bias2 = (
                mb.add(x=y_squeeze, y=bias2)
                if bias_op_type == "add"
                else mb.sub(x=y_squeeze, y=bias2)
            )
            return y_bias2

        assert get_op_types_in_program(prog) == ["expand_dims", "conv", "squeeze", bias_op_type]

        prev_prog, prev_block, block = apply_pass_and_basic_check(prog, "common::compose_conv1d")
        assert get_op_types_in_program(prog) == ["squeeze", "conv", bias_op_type]

        prev_prog, prev_block, block = apply_pass_and_basic_check(prog, "common::fuse_conv_bias")
        assert get_op_types_in_program(prog) == ["squeeze", "conv"]

        prev_prog, prev_block, block = apply_pass_and_basic_check(prog, "common::const_elimination")
        assert get_op_types_in_program(prog) == ["conv"]

        output_shape = (N, C_out, L_out)
        assert_model_is_valid(
            prog,
            {"x": (N, C_in, L)},
            expected_output_shapes={block.outputs[0].name: output_shape},
            backend=backend,
        )

        After recomposing the shattered conv1d, conv1d optimization passes should work

        Input graph:
        input -> expand_dims -> conv2d -> squeeze -> add/sub a constant -> out

        Output graph:
        input -> conv1d -> out
        
coremltools/converters/mil/mil/passes/tests/test_passes.py