#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define FOR(var, begin, end) for (int var = (begin); var <= (end); var++)
#define RFOR(var, begin, end) for (int var = (begin); var >= (end); var--)
#define REP(var, length) FOR(var, 0, length - 1)
#define RREP(var, length) RFOR(var, length - 1, 0)
#define EACH(value, var) for (auto value : var)
#define SORT(var) sort(var.begin(), var.end())
#define REVERSE(var) reverse(var.begin(), var.end())
#define RSORT(var) SORT(var); REVERSE(var)
#define OPTIMIZE_STDIO ios::sync_with_stdio(false);cin.tie(0);cout.precision(10);cout << fixed
#define endl '\n'

const int INF = 1e9;
const ll MOD = 1e9 + 7;
const ll LINF = 1e18;
struct mint {
    ll x;
    mint() : x(0) {}
    mint(ll x) : x((x % MOD + MOD) % MOD) {}
    mint& operator+=(const mint& r) { if ((x += r.x) >= MOD) { x -= MOD; } return *this; }
    mint& operator-=(const mint& r) { if ((x -= r.x) < 0) { x += MOD; } return *this; }
    mint& operator*=(const mint& r) { if ((x *= r.x) > MOD) { x %= MOD; } return *this; }
    mint& operator++() { if ((++x) >= MOD) { x -= MOD; } return *this; }
    mint operator++(int) { mint ret = x; if ((++x) >= MOD) { x-= MOD; } return ret; }
    mint& operator--() { if ((--x) < 0) { x += MOD; } return *this; }
    mint operator--(int) { mint ret = x; if ((--x) < 0) { x += MOD; } return ret; }
    mint operator+(const mint& r) { mint ret; return ret = x + r.x; }
    mint operator-(const mint& r) { mint ret; return ret = x - r.x; }
    mint operator*(const mint& r) { mint ret; return ret = x * r.x; }
    mint operator-() { return mint() - *this; }
    bool operator<(const mint& a) { return x < a.x; }
    bool operator>(const mint& a) { return x > a.x; }
    bool operator<=(const mint& a) { return x <= a.x; }
    bool operator>=(const mint& a) { return x >= a.x; }
    bool operator==(const mint& a) { return x == a.x; }
    bool operator!=(const mint& a) { return x != a.x; }
};
ostream& operator<<(ostream& os, const mint& r) { os << r.x; return os; }
ostream& operator>>(ostream& os, const mint& r) { os >> r.x; return os; }

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

void solve(istream& cin, ostream& cout) {
  int h, w;
  cin >> h >> w;
  char field[h][w];
  int white = 0;
  REP(i, h) REP(j, w) {
    cin >> field[i][j];
    if (i == 0 && j == 0 || i == h - 1 && j == w - 1) continue;
    if (field[i][j] == '.') white++;
  }
  bool flag = false;
  int dist[h][w];
  REP(i, h) REP(j, w) dist[i][j] = INF;
  queue<int> q;
  q.push(0);
  q.push(0);
  dist[0][0] = 0;
  while (!q.empty()) {
    int nx = q.front(); q.pop();
    int ny = q.front(); q.pop();
    if (field[nx][ny] == '#') continue;
    REP(i, 4) {
      int nh = nx + dx[i];
      int nw = ny + dy[i];
      if (nh < 0 || nh >= h || nw < 0 || nw >= w) continue;
      if (field[nh][nw] == '#') continue;
      if (dist[nh][nw] > dist[nx][ny] + 1) {
        dist[nh][nw] = dist[nx][ny] + 1;
        q.push(nh); q.push(nw);
      }
    }
  }
  if (dist[h - 1][w - 1] == INF) cout << -1 << endl;
  else {
    int ans = white - dist[h - 1][w - 1] + 1;
    cout << ans << endl;
  }
}

#ifndef TEST
int main() {
  OPTIMIZE_STDIO;
  solve(cin, cout);
}
#endif


Measured memory_bytes: 256