def _match_pattern(reshape_op):
        """
        Given a ``reshape`` op,
        consider it as the head of a sequence of ``reshape`` ops, and
        then end the sequence at a non-removable ``reshape`` op.
        Return this sequence as a list.
        """
        res = []
        op = reshape_op

        while op.op_type == "reshape":
            res.append(op)

            # current reshape has 0 or 2+ child ops:
            # * no child: this is the end of graph
            # * 2+ children: only pattern of sequential reshape ops (1 child)
            #   is supported for now. For more general cases, please see TODO below
            if len(op.outputs[0].child_ops) != 1:
                break
            # current reshape output is a block output, so it is non-removable
            if op.outputs[0] in op.enclosing_block.outputs:
                break

            op = op.outputs[0].child_ops[0]

        return res

        Given a ``reshape`` op,
        consider it as the head of a sequence of ``reshape`` ops, and
        then end the sequence at a non-removable ``reshape`` op.
        Return this sequence as a list.
        
coremltools/converters/mil/mil/passes/defs/optimize_repeat_ops.py