// Original C++ solution (slower):
#include <bits/stdc++.h>

using namespace std;

using ll = long long;

using Edge = pair<int, int>;

using Graph = vector<vector<Edge>>;

#define REP(i, n) for (int i = 0; i < (n); ++i)

#define SORT(v) sort((v).begin(), (v).end())

#define RSORT(v) sort((v).rbegin(), (v).rend())

const ll MOD = 1000000007;

const ll nmax = 8;

const ll INF = 1e9;

bool graph[nmax][nmax];

vector<vector<ll>> dist = vector<vector<ll>>(nmax, vector<ll>(nmax, INF));

void warshall_floyd(ll n)

{

    for (size_t i = 0; i < n; i++)

    {

        for (size_t j = 0; j < n; j++)

        {

            for (size_t k = 0; k < n; k++)

            {

                dist[j][k] = min(dist[j][k], dist[j][i] + dist[i][k]);

            }

        }

    }

}



class UnionFind

{

public:

    vector<ll> Parent;



    UnionFind(ll N)

    {

        Parent = vector<ll>(N, -1);

    }

    ll find(ll A)

    {

        if (Parent[A] < 0)

            return A;

        return Parent[A] = find(Parent[A]);

    }



    ll size(ll A)

    {

        return -Parent[find(A)];

    }



    bool Union(ll A, ll B)

    {

        A = find(A);

        B = find(B);

        if (A == B)

        {

            return false;

        }

        if (size(A) < size(B))

            swap(A, B);



        Parent[A] += Parent[B];

        Parent[B] = A;



        return true;

    }

};



ll gcd(ll a, ll b)

{

    if (b == 0)

        return a;

    return gcd(b, a % b);

}



ll lcm(ll a, ll b)

{

    ll g = gcd(a, b);

    return a / g * b;

}



ll mulMod(ll a, ll b)

{

    return (((a % MOD) * (b % MOD)) % MOD);

}



ll powMod(ll a, ll p)

{

    if (p == 0)

    {

        return 1;

    }

    else if (p % 2 == 0)

    {

        ll half = powMod(a, p / 2);

        return mulMod(half, half);

    }

    else

    {

        return mulMod(powMod(a, p - 1), a);

    }

}



ll ceil(ll a, ll b)

{

    return (a + b - 1) / b;

}

// 四方向への移動ベクトル

const int dx[4] = {1, 0, -1, 0};

const int dy[4] = {0, 1, 0, -1};

ll H, W;

int seen[510][510];

char math[510][510];



int main()

{



    cin >> H >> W;



    ll cnt_white = 0;



    for (int i = 0; i < H; i++)

    {

        string str;

        cin >> str;

        for (int j = 0; j < W; j++)

        {

            if (str[j] == '.')

                cnt_white++;

            math[i][j] = str[j];

        }

    }

    memset(seen, -1, sizeof(seen));



    queue<pair<int, int>> que;



    que.push(make_pair(0, 0));

    seen[0][0] = 1;

    while (!que.empty())

    {

        pair<int, int> current_pos = que.front();

        int x = current_pos.first;

        int y = current_pos.second;

        que.pop();



        for (int dir = 0; dir < 4; dir++)

        {

            int nh = x + dx[dir];

            int nw = y + dy[dir];



            if (nh < 0 || nw < 0 || nh >= H || nw >= W)

                continue;



            if (math[nh][nw] == '#')

                continue;



            if (seen[nh][nw] != -1)

                continue;



            if(seen[nh][nw] == -1){

                que.push(make_pair(nh,nw));

                seen[nh][nw] = seen[x][y] + 1;

            }

        }

    }

    if (seen[H - 1][W - 1] == -1)

    {

        cout << -1 << endl;

    }

    else

    {

        cout << cnt_white - seen[H - 1][W - 1] << endl;

    }

    return 0;

}


// Optimized solution to the same problem (faster):
#include <bits/stdc++.h>

using namespace std;

using ll = long long;

using Edge = int;

using Graph = vector<vector<Edge>>;

#define REP(i, n) for (int i = 0; i < (n); ++i)

#define SORT(v) sort((v).begin(), (v).end())

#define RSORT(v) sort((v).rbegin(), (v).rend())

const ll MOD = 1000000007;

const ll nmax = 8;

const ll INF = 1e9;

bool graph[nmax][nmax];

vector<vector<ll>> dist = vector<vector<ll>>(nmax, vector<ll>(nmax, INF));

struct SegmentTree

{

private:

    ll n;

    vector<ll> node;



public:

    SegmentTree(vector<ll> v)

    {

        ll sz = v.size();

        n = 1;

        while (n < sz)

        {

            n *= 2;

        }

        node.resize(2 * n - 1, INF);



        for (ll i = 0; i < sz; i++)

        {

            node[i + n - 1] = v[i];

        }



        for (ll i = n - 2; i >= 0; i--)

        {

            node[i] = min(node[2 * i + 1], node[2 * i + 2]);

        }

    }

    void update(ll x, ll val)

    {

        x += (n - 1);

        node[x] = val;

        while (x > 0)

        {

            x = (x - 1) / 2;

            node[x] = min(node[2 * x + 1], node[2 * x + 2]);

        }

    }



    // findは半開区間で考える

    ll find(ll a, ll b, ll k = 0, ll l = 0, ll r = -1)

    {

        if (r < 0)

            r = n;



        if (r <= a || b <= l)

            return INF;



        if (a <= l && r <= b)

            return node[k];



        ll vl = find(a, b, 2 * k + 1, l, (l + r) / 2);

        ll vr = find(a, b, 2 * k + 2, (l + r) / 2, r);

        return min(vl, vr);

    }

};

void warshall_floyd(ll n)

{

    for (size_t i = 0; i < n; i++)

    {

        for (size_t j = 0; j < n; j++)

        {

            for (size_t k = 0; k < n; k++)

            {

                dist[j][k] = min(dist[j][k], dist[j][i] + dist[i][k]);

            }

        }

    }

}



class UnionFind

{

public:

    vector<ll> Parent;



    UnionFind(ll N)

    {

        Parent = vector<ll>(N, -1);

    }

    ll find(ll A)

    {

        if (Parent[A] < 0)

            return A;

        return Parent[A] = find(Parent[A]);

    }



    ll size(ll A)

    {

        return -Parent[find(A)];

    }



    bool Union(ll A, ll B)

    {

        A = find(A);

        B = find(B);

        if (A == B)

        {

            return false;

        }

        if (size(A) < size(B))

            swap(A, B);



        Parent[A] += Parent[B];

        Parent[B] = A;



        return true;

    }

};



ll gcd(ll a, ll b)

{

    if (b == 0)

        return a;

    return gcd(b, a % b);

}



ll lcm(ll a, ll b)

{

    ll g = gcd(a, b);

    return a / g * b;

}



ll mulMod(ll a, ll b)

{

    return (((a % MOD) * (b % MOD)) % MOD);

}



ll powMod(ll a, ll p)

{

    if (p == 0)

    {

        return 1;

    }

    else if (p % 2 == 0)

    {

        ll half = powMod(a, p / 2);

        return mulMod(half, half);

    }

    else

    {

        return mulMod(powMod(a, p - 1), a);

    }

}



ll ceil(ll a, ll b)

{

    return (a + b - 1) / b;

}



vector<ll> tsort(Graph G)

{

    ll N = G.size();

    vector<ll> in(N);

    for (auto &&edges : G)

    {

        for (auto &&edge : edges)

        {

            in[edge]++;

        }

    }



    queue<int> que;



    for (int i = 0; i < N; i++)

    {

        if (in[i] == 0)

        {

            que.push(i);

        }

    }

    int cnt = 0;

    vector<ll> ans;

    while (!que.empty())

    {

        int v = que.front();

        que.pop();

        ans.push_back(v);

        for (auto &&next : G[v])

        {



            in[next]--;

            if (in[next] == 0)

            {

                que.push(next);

            }

        }

    }

    return ans;

}



const int distX[4] = {-1, 0, 0, 1};

const int distY[4] = {0, 1, -1, 0};

int main()

{

    int H, W;

    cin >> H >> W;

    vector<string> map(H);

    for (int i = 0; i < H; i++)

    {

        string str;

        cin >> str;

        map[i] = str;

    }

    ll cnt = 0;

    for (int i = 0; i < H; i++)

    {

        for (int j = 0; j < W; j++)

        {

            if (map[i][j] == '.')

            {

                cnt++;

            }

        }

    }



    queue<pair<int, int>> que;

    vector<vector<ll>> dist(H, vector<ll>(W, -1));

    dist[0][0] = 0;



    que.push(make_pair(0, 0));



    while (!que.empty())

    {

        pair<int, int> p = que.front();

        int x = p.first;

        int y = p.second;

        que.pop();



        for (int i = 0; i < 4; i++)

        {

            int newX = x + distX[i];

            int newY = y + distY[i];

            if (newX < 0 || newX >= H || newY < 0 || newY >= W)

            {

                continue;

            }



            if (dist[newX][newY] != -1)

            {

                continue;

            }

            if (map[newX][newY] == '#')

            {

                continue;

            }

            dist[newX][newY] = dist[x][y] + 1;

            que.push(make_pair(newX, newY));

        }

    }



    if (dist[H - 1][W - 1] == -1)

    {

        cout << -1 << endl;

    }

    else

    {

        cout << cnt - dist[H - 1][W - 1] - 1 << endl;

    }

    return 0;

}


// Fastest known solution for this problem: