using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using Library;
using static Library.Input;

namespace AtCoderTemplate {
    class ProgramF {
        private class Point {
            public int X {get;set;}
            public int Y {get;set;}
            public int Value {get;set;}
        }

        static void Main () {
            int H = NextInt, W = NextInt;
            var matrix = Enumerable.Range(0, H).Select(_ => Line).ToArray();
            var distance = Enumerable.Range(0, H).Select(_ => Enumerable.Repeat(-1, W).ToArray()).ToArray();

            var queue = new Queue<Point>();
            queue.Enqueue(new Point{Y = 0, X = 0, Value = 1});

            while (queue.Any() && distance[H - 1][W - 1] == -1)
            {
                var tmp = queue.Dequeue();

                if (distance[tmp.Y][tmp.X] == -1)
                {
                    distance[tmp.Y][tmp.X] = tmp.Value;

                    if (tmp.X > 0 && matrix[tmp.Y][tmp.X - 1] == '.') queue.Enqueue(new Point{Y = tmp.Y, X = tmp.X - 1, Value = tmp.Value + 1});
                    if (tmp.Y > 0 && matrix[tmp.Y - 1][tmp.X] == '.') queue.Enqueue(new Point{Y = tmp.Y - 1, X = tmp.X, Value = tmp.Value + 1});
                    if (tmp.X + 1 < W && matrix[tmp.Y][tmp.X + 1] == '.') queue.Enqueue(new Point{Y = tmp.Y, X = tmp.X + 1, Value = tmp.Value + 1});
                    if (tmp.Y + 1 < H && matrix[tmp.Y + 1][tmp.X] == '.') queue.Enqueue(new Point{Y = tmp.Y + 1, X = tmp.X, Value = tmp.Value + 1});
                }
            }

            if (distance[H - 1][W - 1] == -1) System.Console.WriteLine(-1);
            else System.Console.WriteLine(matrix.Sum(s => s.Count(c => c == '.')) - distance[H - 1][W - 1]);
        }
    }

}

namespace Library {
    class Input {
        static IEnumerator<string> enumerator = new string[] { }.AsEnumerable ().GetEnumerator ();

        public static string Line => Console.ReadLine ();

        public static string[] StrArr => Line.Split (' ');

        public static int NextInt => int.Parse (NextWord ());

        public static long NextLong => long.Parse (NextWord ());

        public static List<int> IntList => StrArr.Select (int.Parse).ToList ();

        public static List<long> LongList => StrArr.Select (long.Parse).ToList ();

        public static IEnumerable<long[]> TakeLine (int N) {
            return Enumerable.Repeat (0, N).Select (_ => Console.ReadLine ().Split (' ').Select (long.Parse).ToArray ());
        }

        public static string NextWord () {
            while (!enumerator.MoveNext ()) {
                enumerator = StrArr.AsEnumerable ().GetEnumerator ();
            }
            return enumerator.Current;
        }
    }
}

namespace Library {
    
    class Modular {
        public const int mod = 1000000007;
        public readonly long value;
        public Modular (long value) { this.value = value; }
        public static implicit operator Modular (long a) {
            var m = a % mod;
            return new Modular ((m < 0) ? m + mod : m);
        }
        public static Modular operator + (Modular a, Modular b) {
            return a.value + b.value;
        }
        public static Modular operator - (Modular a, Modular b) {
            return a.value - b.value;
        }
        public static Modular operator * (Modular a, Modular b) {
            return a.value * b.value;
        }
        public static Modular Pow (Modular a, int n) {
            switch (n) {
                case 0:
                    return 1;
                case 1:
                    return a;
                default:
                    var p = Pow (a, n / 2);
                    return p * p * Pow (a, n % 2);
            }
        }
        public static Modular operator / (Modular a, Modular b) {
            return a * Pow (b, mod - 2);
        }
        private static readonly List<int> facs = new List<int> { 1 };
        private static Modular Fac (int n) {
            for (int i = facs.Count; i <= n; ++i) {
                facs.Add ((int) (Math.BigMul (facs.Last (), i) % mod));
            }
            return facs[n];
        }
        public static Modular Ncr (int n, int r) {
            return (n < r) ? 0 :
                (n == r) ? 1 :
                Fac (n) / (Fac (r) * Fac (n - r));
        }
        public static explicit operator int (Modular a) {
            return (int) a.value;
        }
    }

}
namespace Library {
    class MyMath {
        public static long Gcd (long a, long b) {
            return b == 0 ? a : Gcd (b, a % b);
        }

        public static long Sqrt (long n) {
            if (n < 0) return 0;
            long a = 0, tmp = 0, b = 0;
            for (int i = 62; i >= 0; i -= 2) {
                tmp = (b << 1) + 1 <= (n >> i) ? 1 : 0;
                a = a << 1 | tmp;
                n -= (((b << 1) + 1) * tmp) << i;
                b = (b << 1) + tmp + tmp;
            }
            return a;
        }

        public static long Nck (int n, int k) {
            if (k == 0) return 1;
            if (n == 0) return 0;
            return n * Nck (n - 1, k - 1) / k;
        }
    }
}

namespace Library {
        public class PriorityQueue<T> {

        readonly List<T> _heap = new List<T> ();
        readonly Comparison<T> _comparison;

        public PriorityQueue (Comparison<T> comparison) {
            _comparison = comparison;
        }

        public PriorityQueue () : this (Comparer<T>.Default.Compare) { }

        public PriorityQueue (IComparer<T> comparer) : this (comparer.Compare) { }

        public void Enqueue (T item) {
            _heap.Add (item);

            int childID = _heap.Count - 1;
            int parentID = (childID - 1) / 2;

            while (childID > 0 && _comparison (_heap[parentID], _heap[childID]) > 0) {
                Swap (parentID, childID);
                childID = parentID;
                parentID = (parentID - 1) / 2;
            }
        }

        public T Dequeue () {
            var first = _heap.First ();
            _heap[0] = _heap.Last ();
            _heap.RemoveAt (_heap.Count - 1);

            int parentID = 0;
            int childID = parentID * 2 + 2;
            if (childID >= _heap.Count || _comparison (_heap[childID], _heap[childID - 1]) > 0) childID--;

            while (childID < _heap.Count && _comparison (_heap[parentID], _heap[childID]) > 0) {
                Swap (parentID, childID);
                parentID = childID;
                childID = parentID * 2 + 2;
                if (childID >= _heap.Count || _comparison (_heap[childID], _heap[childID - 1]) > 0) childID--;
            }

            return first;
        }

        void Swap (int parent, int child) {
            var tmp = _heap[parent];
            _heap[parent] = _heap[child];
            _heap[child] = tmp;
        }

        public T Peek () { return _heap[0]; }
        public int Count => _heap.Count;
        public bool Any () { return _heap.Any (); }
        public List<T> Data => _heap;
    }
}

namespace Library {
    
    public class UnionFind {
        public int[] Parents { get; set; }
        public UnionFind (int size) {
            Parents = Enumerable.Repeat (-1, size).ToArray ();
        }

        public int Find (int num) {
            if (Parents[num] < 0) return num;

            Parents[num] = Find (Parents[num]);
            return Parents[num];
        }

        public int Size (int num) {
            return -Parents[Find (num)];
        }

        public bool Same (int a, int b) {
            return Find (a) == Find (b);
        }

        public void Unite (int a, int b) {
            int x = Find (a), y = Find (b);

            if (Size (x) > Size (y)) {
                Parents[x] += Parents[y];
                Parents[y] = x;
            } else {
                Parents[y] += Parents[x];
                Parents[x] = y;
            }
        }
    }
}


Measured memory_bytes: 13652