#include <bits/stdc++.h>
#define fst first
#define snd second
#define rep(n) for(lint I = 0; (I) < (lint)(n); ++(I))
#define repeat(i, n) for(lint i = 0; (i) < (lint)(n); ++(i))
#define repeat_to(i, n) for(lint i = 0; (i) <= (lint)(n); ++(i))
#define repeat_from(i, m, n) for(lint i = (m); (i) < (lint)(n); ++(i))
#define repeat_from_to(i, m, n) for(lint i = (m); (i) <= (lint)(n); ++(i))
#define repeat_reverse_from_to(i, m, n) for(lint i = (m); (i) >= (lint)(n); --(i))
#define el cout<<endl
#define dump(x) cout<<" "<<#x<<"="<<x
#define vdump(v) for(size_t I=0; I<v.size(); ++I){cout<<" "<<#v<<"["<<I<<"]="<<v[I];} cout<<endl
using namespace std;
using lint = long long;
using ld = long double;

/****************** グラフ ******************/
// 諸宣言
using Weight = lint;
using Flow = lint;
struct Edge {
    int src, dst;
    Weight weight;
    Flow cap;
    Edge() : src(0), dst(0), weight(0) {}
    Edge(int s, int d, Weight w) : src(s), dst(d), weight(w) {}
    Edge(int s, int d, Weight w, Flow c) : src(s), dst(d), weight(w), cap(c) {}
};
using Edges = vector<Edge>;
using Graph = vector<Edges>;
using Array = vector<Weight>;
using Matrix = vector<Array>;

void add_edge(Graph &g, int a, int b, Weight w = 1, Flow c = 1) {
    g[a].emplace_back(a, b, w, c);
    g[b].emplace_back(b, a, w, c);
}
void add_arc(Graph &g, int a, int b, Weight w = 1, Flow c = 1) {
    g[a].emplace_back(a, b, w, c);
}

// ダイクストラ法（プライオリティーキュー）O((E+V)logV)
vector<Weight> dijkstra(const Graph &g, int s) {
    const Weight INF = numeric_limits<Weight>::max() / 8;
    using state = tuple<Weight, int>;
    priority_queue<state> q;
    vector<Weight> dist(g.size(), INF);
    dist[s] = 0;
    q.emplace(0, s);
    while (q.size()) {
        Weight d;
        int v;
        tie(d, v) = q.top();
        q.pop();
        d *= -1;
        /* if(v == t) return d; */
        if (dist[v] < d) continue;
        for (auto &e : g[v]) {
            if (dist[e.dst] > dist[v] + e.weight) {
                dist[e.dst] = dist[v] + e.weight;
                q.emplace(-dist[e.dst], e.dst);
            }
        }
    }
    return dist;
}

int main(void) {
    int h, w;
    cin >> h >> w;
    vector<string> c(h+2);
    c[0] = c[h+1] = string(w+2, '#');
    repeat(i, h) {
        cin >> c[i+1];
        c[i+1] = "#" + c[i+1] + "#";
    }
    
    Graph g((h+2)*(w+2));
    
    auto nodenum = [&](int h1, int w1) -> int {
        return h1 * (w+2) + w1;
    };
    
    repeat_from_to (i, 1, h) {
        repeat_from_to (j, 1, w) {
            vector<int> dx {1, 0, -1, 0};
            vector<int> dy {0, 1, 0, -1};
            if (c[i][j] != '.') continue;
            repeat (k, 4) {
                if (c[i+dx[k]][j+dy[k]] == '.') {
                    int src = nodenum(i, j);
                    int dst = nodenum(i+dx[k], j+dy[k]);
                    add_edge(g, src, dst);
                }
            }
        }
    }
    
    auto res = dijkstra(g, nodenum(1, 1));
    int d = res[nodenum(h, w)];
 
    auto whitenum = [&](void) -> int {
        int ans = 0;
        repeat_from_to (i, 1, h) {
            repeat_from_to (j, 1, w) {
                if (c[i][j] == '.') ++ans;
            }
        }
        return ans;
    };
    
    if (d > 0) {
        cout << whitenum() - d - 1 << endl;
    }
    else {
        cout << -1 << endl;
    }
    
}

Measured memory_bytes: 896