/// <summary>
        /// Determines whether it is safe to move 'expressionBeingMoved' past 'expr'
        /// </summary>
        bool IsSafeForInlineOver(ILExpression expr, ILExpression expressionBeingMoved)
        {
            switch (expr.Code)
            {
            case ILCode.Ldloc:
                ILVariable loadedVar = (ILVariable)expr.Operand;
                if (numLdloca.GetOrDefault(loadedVar) != 0)
                {
                    // abort, inlining is not possible
                    return(false);
                }
                foreach (ILExpression potentialStore in expressionBeingMoved.GetSelfAndChildrenRecursive <ILExpression>())
                {
                    if (potentialStore.Code == ILCode.Stloc && potentialStore.Operand == loadedVar)
                    {
                        return(false);
                    }
                }
                // the expression is loading a non-forbidden variable
                return(true);

            case ILCode.Ldloca:
            case ILCode.Ldflda:
            case ILCode.Ldsflda:
            case ILCode.Ldelema:
            case ILCode.AddressOf:
            case ILCode.ValueOf:
            case ILCode.NullableOf:
                // address-loading instructions are safe if their arguments are safe
                foreach (ILExpression arg in expr.Arguments)
                {
                    if (!IsSafeForInlineOver(arg, expressionBeingMoved))
                    {
                        return(false);
                    }
                }
                return(true);

            default:
                // instructions with no side-effects are safe (except for Ldloc and Ldloca which are handled separately)
                return(expr.HasNoSideEffects());
            }
        }