def _check_reshape(op: Operator) -> bool:
    """check reshape [M, N] -> [M/D1, D1, D2, N/D2]
    D1 and D2 must be static. Also checks alignment here.

    Args:
        op (Operator): reshape op

    Returns:
        bool: True if can fuse
    """
    input_shapes = op._attrs["inputs"][0].shape()
    output_shapes = op._attrs["outputs"][0].shape()

    if len(input_shapes) != 2 or len(output_shapes) != 4:
        return False

    m, n = input_shapes
    m_d1, d1, d2, n_d2 = output_shapes

    if not isinstance(n, IntImm) or not isinstance(n_d2, IntImm):
        return False

    if not isinstance(d1, IntImm) or not isinstance(d2, IntImm):
        return False

    d1 = d1.value()
    d2 = d2.value()

    if len(m._attrs["values"]) != len(m_d1._attrs["values"]):
        return False

    if n.value() != n_d2.value() * d2:
        return False

    # check alignment
    if n_d2.value() % 2 == 1:
        return False

    return True
check reshape [M, N] -> [M/D1, D1, D2, N/D2]
D1 and D2 must be static. Also checks alignment here.

Args:
op (Operator): reshape op

Returns:
bool: True if can fuse
python/aitemplate/compiler/transform/fuse_mm_reshape_permute.py