def instancenorm_or_layernorm(x):
        """
        Identify the pattern:

        y = gamma * (x - mean) / sqrt(variance + epsilon) + beta

        y = x * [gamma * rsqrt(variance + eps)] + (beta - mean * [gamma * rsqrt(variance + eps)])

        x --> main_reduce --> sub --> square --> reduce_mean_2 --> add(epsilon) --> rsqrt
        |             |        ^                                                      |
        |             |        |                                                      V
        |-----------------------                                                mul (gamma)
        |             |                                                             |
        |             |                                                     --------|---------
        |             |                                                     |                |
        |             |                                                     |                V
        |             |------------------------------------------------------------------>  mul_3
        |                                                                   |                |
        |                                                                   V                |
        |----------------------------------------------------------------> mul_2             |
                                                                            |                V
                                                                            |              sub (beta) --> add_2 --> [...]
                                                                            |                              ^
                                                                            |-------------------------------

        This pattern corresponds to either layer_norm or instance_norm.

        It is instance_norm if all of the following are true:
            - input is rank 4
            - axes of reduce_mean is [-2, -1] or [-3, -2]
              (when [-3, -2], a channel first to channel last transpose would be inserted)
            - gamma and beta are rank 1, after squeeze

        It is layer_norm if all of the following are true:
            - axes is either [-1] or [-1, -2] or [-1, -2, -3] and so on
            - rank of gamma and beta is equal to the length of the axes
        """
        main_reduce = mb.reduce_mean(x=x, axes=[2, 3], keep_dims=True, name="main_reduce")
        sub = mb.sub(x=x, y=main_reduce, name="sub")
        square = mb.square(x=sub, name="square")
        reduce_mean_2 = mb.reduce_mean(x=square, axes=[2, 3], keep_dims=True, name="reduce_mean_2")
        add_epsilon = mb.add(x=reduce_mean_2, y=1e-5, name="add_epsilon")
        rsqrt = mb.rsqrt(x=add_epsilon, epsilon=1e-12, name="rsqrt")
        mul_gamma = mb.mul(x=rsqrt, y=np.random.rand(1, 5, 1, 1), name="mul_gamma")
        mul_2 = mb.mul(x=x, y=mul_gamma, name="mul_2")
        mul_3 = mb.mul(x=main_reduce, y=mul_gamma, name="mul_3")
        sub_beta = mb.sub(x=np.random.rand(1, 5, 1, 1), y=mul_3, name="sub_beta")
        add_2 = mb.add(x=sub_beta, y=mul_2, name="add_2")
        return add_2

        Identify the pattern:

        y = gamma * (x - mean) / sqrt(variance + epsilon) + beta

        y = x * [gamma * rsqrt(variance + eps)] + (beta - mean * [gamma * rsqrt(variance + eps)])

        x --> main_reduce --> sub --> square --> reduce_mean_2 --> add(epsilon) --> rsqrt
        |             |        ^                                                      |
        |             |        |                                                      V
        |-----------------------                                                mul (gamma)
        |             |                                                             |
        |             |                                                     --------|---------
        |             |                                                     |                |
        |             |                                                     |                V
        |             |------------------------------------------------------------------>  mul_3
        |                                                                   |                |
        |                                                                   V                |
        |----------------------------------------------------------------> mul_2             |
                                                                            |                V
                                                                            |              sub (beta) --> add_2 --> [...]
                                                                            |                              ^
                                                                            |-------------------------------

        This pattern corresponds to either layer_norm or instance_norm.

        It is instance_norm if all of the following are true:
            - input is rank 4
            - axes of reduce_mean is [-2, -1] or [-3, -2]
              (when [-3, -2], a channel first to channel last transpose would be inserted)
            - gamma and beta are rank 1, after squeeze

        It is layer_norm if all of the following are true:
            - axes is either [-1] or [-1, -2] or [-1, -2, -3] and so on
            - rank of gamma and beta is equal to the length of the axes
        
coremltools/converters/mil/experimental/passes/generic_layernorm_instancenorm_pattern_fusion.py