#include <stdio.h>
#include <set>
#include <map>
#include <unordered_map>
#include <unordered_set>
#include <list>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <cstdio>
#include <vector>
#include <string>
#include <bitset>
#include <cctype>
#include <cstdlib>
#include <cstring>
#include <utility>
#include <numeric>
#include <complex>
#include <sstream>
#include <fstream>
#include <iomanip>
#include <cassert>
#include <iostream>
#include <iterator>
#include <algorithm>
#include <functional>
using namespace std;
typedef long long ll;
const double EPS = 1e-9;
typedef vector<int> vint;
typedef vector<vector<int>> v2int;
typedef vector<ll> vll;
typedef vector<vector<ll>> v2ll;
typedef list<int> liint;
typedef pair<int, int> pint;
const int INF = int(2e9);
const ll LINF = ll(2e9) * ll(2e9);
#define rep(i, n) REP(i, 0, n)
#define ALL(v) v.begin(), v.end()
#define MSG(a) cout << #a << " " << a << endl;
#define REP(i, x, n) for(int i = x; i < n; i++)
template<class T, class C> void chmax(T& a, C b) { a > b ? : a = b; }
template<class T, class C> void chmin(T& a, C b) { a < b ? : a = b; }

//vector<pair<int, int>> move_vec = { make_pair(1, 0), make_pair(0, 1), make_pair(-1, 0), make_pair(0, -1) };
//int dfs(vector<vector<char>>& field, int H, int W, pair<int, int>& now, set<pair<int, int>> visited, int d) {
//    if (now.first == H - 1 && now.second == W - 1) {
//        return d;
//    }
//    int res = INF;
//    for (auto& m : move_vec) {
//        auto nex = now;
//        nex.first += m.first;
//        nex.second += m.second;
//        if (nex.first < 0 || nex.first >= H || nex.second < 0 || nex.second >= W) continue;
//        if (field[nex.first][nex.second] == '#') continue;
//        if (visited.count(nex) != 0) continue;
//        visited.insert(nex);
//        res = min(res, dfs(field, H, W, nex, visited, d + 1));
//        //visited.erase(nex);
//    }
//
//    return res;
//}
vector<pair<int, int>> move_vec = { make_pair(1, 0), make_pair(0, 1), make_pair(-1, 0), make_pair(0, -1) };
int bfs(vector<vector<char>>& field, int H, int W,pair<int, int> start) {
  
    deque<pair<pair<int, int>, int>> que;
    que.push_back(make_pair(start, 1));
    set<pair<int, int>> visited;
    visited.insert(start);
    while (1) {
        if (que.size() <= 0) break;
        auto nd = que.front();
        que.pop_front();
        if (nd.first.first == H - 1 && nd.first.second == W - 1) {
            return nd.second;
        }
        for (auto& m : move_vec) {
            auto nex = nd;
            nex.first.first += m.first;
            nex.first.second += m.second;
            if (nex.first.first < 0 || nex.first.first >= H || nex.first.second < 0 || nex.first.second >= W) continue;
            if (field[nex.first.first][nex.first.second] == '#') continue;
            if (visited.count(nex.first) != 0) continue;

            nex.second += 1;
            que.push_back(nex);
            visited.insert(nex.first);
        }
    }
    return INF;
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    int H ,  W;
    cin >> H >> W;
    vector<vector<char>> field(H, vector<char>(W));
    ll ans = ll(H) * ll(W);
    int cnt = 0;
    rep(i, H) {
        rep(j, W) {
            cin >> field[i][j];
            if (field[i][j] == '#') cnt++;
        }
    }
    ans -= cnt;

    int dist = bfs(field, H, W, make_pair(0, 0));
    if (dist == INF) {
        cout << -1 << endl;
        return 0;
    }
    ans -= dist;
    cout << ans << endl;
    return 0;
}

Measured memory_bytes: 384