#include <iostream>
#include <algorithm>
#include <functional>
#include <string>
#include <vector>
#include <set>
#include <queue>
#include <stack>
#include <numeric>
#include <bitset>
#include <map>
#include <set>
#include <list>
#include <unordered_set>
#include <unordered_map>
#include <iomanip>
#include <limits>

using namespace std;

using i64 = int64_t;
using P = pair<i64, i64>;

struct edge {
    i64 from, to, cost;
    edge(i64 from, i64 to) : from(from), to(to), cost(1) {}
    edge(i64 from, i64 to, i64 cost) : from(from), to(to), cost(cost) {}
};
using Graph = vector<vector<edge>>;

constexpr i64 INF = std::numeric_limits<i64>::max();
constexpr i64 SINF = std::numeric_limits<i64>::max() / 10;
const i64 MOD = 1000000007;
//const i64 dx[4] = { 0,1,0,-1 }, dy[4] = { -1,0,1,0 };
//const i64 dx[5] = {-1,0,0,0,1}, dy[5] = {0,-1,0,1,0};
//const i64 dx[8] = {-1,0,1,1,1,0,-1,-1}, dy[8] = {1,1,1,0,-1,-1,-1,0};
//const i64 dx[9] = {-1,0,1,1,1,0,-1,-1,0}, dy[9] = {1,1,1,0,-1,-1,-1,0,0};

// http://beet-aizu.hatenablog.com/entry/2018/04/08/145516
template<typename T>
vector<T> make_v(size_t a) { return vector<T>(a); }

template<typename T, typename... Ts>
auto make_v(size_t a, Ts... ts) {
    return vector<decltype(make_v<T>(ts...))>(a, make_v<T>(ts...));
}

template<typename T, typename V>
typename enable_if<is_class<T>::value == 0>::type
fill_v(T& t, const V& v) { t = v; }

template<typename T, typename V>
typename enable_if<is_class<T>::value != 0>::type
fill_v(T& t, const V& v) {
    for (auto& e : t) fill_v(e, v);
}

struct Combination{
    int64_t mod;
    vector< int64_t > mfact, rfact;

    Combination(int64_t sz, int64_t mod) : mfact(sz + 1), rfact(sz + 1), mod(mod){
        mfact[0] = 1;
        for (int64_t i = 1; i < mfact.size(); i++) {
            mfact[i] = mfact[i - 1] * i % mod;
        }
        rfact[sz] = inv(mfact[sz]);
        for (int64_t i = sz - 1; i >= 0; i--) {
            rfact[i] = rfact[i + 1] * (i + 1) % mod;
        }
    }

    int64_t fact(int64_t k){
        return (mfact[k]);
    }

    int64_t pow(int64_t x, int64_t n){
        int64_t ret = 1;
        while (n > 0) {
            if (n & 1) (ret *= x) %= mod;
            (x *= x) %= mod;
            n >>= 1;
        }
        return (ret);
    }

    int64_t inv(int64_t x){
        return (pow(x, mod - 2));
    }

    int64_t P(int64_t n, int64_t r){
        if (r < 0 || n < r) return (0);
        return (mfact[n] * rfact[n - r] % mod);
    }

    int64_t C(int64_t p, int64_t q){
        if (q < 0 || p < q) return (0);
        return (mfact[p] * rfact[q] % mod * rfact[p - q] % mod);
    }

    int64_t H(int64_t n, int64_t r){
        if (n < 0 || r < 0) return (0);
        return (r == 0 ? 1 : C(n + r - 1, r));
    }
};

vector<int64_t> dijkstra(Graph G, int64_t s) {
    vector<int64_t> dist(G.size(), INF);
    dist[s] = 0;
    priority_queue<P, vector<P>, greater<P>> que;
    que.emplace(0, s);
    while (!que.empty()) {
        int64_t cost, idx;
        tie(cost, idx) = que.top(); que.pop();
        if (dist[idx] < cost) continue;
        for (edge e : G[idx]) {
            int64_t next_cost = cost + e.cost;
            if (dist[e.to] <= next_cost) continue;
            dist[e.to] = next_cost;
            que.emplace(dist[e.to], e.to);
        }
    }
    return dist;
}

vector<vector<i64>> grid_bfs(vector<vector<i64>> G, i64 sx, i64 sy) {
    const i64 dx4[4] = { 0,1,0,-1 }, dy4[4] = { -1,0,1,0 };
    i64 h = G.size(), w = G[0].size();
    vector<vector<i64>> d(h, vector<i64>(w, -1));
    d[sx][sy] = 0;
    queue<P> que;
    que.emplace(sx, sy);
    if(G[sx][sy] == 1) return d;
    while (!que.empty()) {
        i64 x, y;
        tie(x, y) = que.front(); que.pop();
        for (int idx = 0; idx < 4; ++idx) {
            i64 nx = x + dx4[idx], ny = y + dy4[idx];
            if(nx < 0 || ny < 0 || nx >= h || ny >= w || G[nx][ny] == 1 || d[nx][ny] != -1) continue;
            d[nx][ny] = d[x][y] + 1;
            que.emplace(nx, ny);
        }
    }
    return d;
}

int main() {
    i64 h, w;
    cin >> h >> w;
    vector<vector<i64>> mas(h, vector<i64>(w));
    i64 cnt = 0;
    for (int i = 0; i < h; ++i) {
        for (int j = 0; j < w; ++j) {
            char c;
            cin >> c;
            if(c == '.') mas[i][j] = 0;
            else{
                mas[i][j] = 1;
                ++cnt;
            }
        }
    }
    auto d = grid_bfs(mas, 0, 0);
    if(d[h - 1][w - 1] == -1) cout << -1 << endl;
    else cout << h * w - cnt - d[h - 1][w - 1] - 1 << endl;
}

Measured memory_bytes: 256