def test_cast_ops_fusion_negative_smoke_2(self):
        """
        Input graph:
        input(int32) --> cast(dtype="uint8") --> cast(dtype="int8") --> out

        Output graph:
        input --> cast --> cast --> out

        This pattern should not be fused, since the data range results from uint8 -> int8
        is [0, 127], while a single cast(int8) produces [-128, 127]. The data point between [-128, 0] will have wrong numerical result.
        """

        @mb.program(
            input_specs=[mb.TensorSpec(shape=(1,), dtype=types.int32)],
            opset_version=ct.target.iOS17,
        )
        def prog(x):
            x = mb.cast(x=x, dtype="uint8")
            x = mb.cast(x=x, dtype="int8")
            return x

        apply_pass_and_basic_check(prog, "common::cast_optimization")
        _, _, block = apply_pass_and_basic_check(prog, "common::dead_code_elimination")

        assert get_op_types_in_program(prog) == ["cast", "cast"]
        cast_ops = block.find_ops(op_type="cast")
        assert cast_ops[0].outputs[0].dtype == types.uint8
        assert cast_ops[1].outputs[0].dtype == types.int8
        assert block.outputs[0].dtype == types.int8

        Input graph:
        input(int32) --> cast(dtype="uint8") --> cast(dtype="int8") --> out

        Output graph:
        input --> cast --> cast --> out

        This pattern should not be fused, since the data range results from uint8 -> int8
        is [0, 127], while a single cast(int8) produces [-128, 127]. The data point between [-128, 0] will have wrong numerical result.
        
coremltools/converters/mil/mil/passes/tests/test_passes.py