#include <vector>
#include <math.h>
#include <iostream>
#include <string>
#include <algorithm>
#include <queue>
#include <iomanip>
#include <deque>
 
using namespace std;
using uint = unsigned int;
using ll = long long;
using ull = unsigned long long;
template <class T> using V = vector<T>;
template <class T> using VV = V<V<T>>;
#define rep(i, n) for(int i = 0; i<n; i++)
#define rep_s(i, start, n) for(int i= start;  i<n; i++)
#define ALL(a) (a).begin(), (a).end()
string alphabet_upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
string alphabet_lower  = "abcdefghijklmnopqrstuvwxyz";
 
/*
using edge = struct {int to; ll cost;};
vector<edge> tree[limit];
ll depth[limit];
*/
int  root[60][60][4] = {0}, depth[60][60], visited[60][60] = {0};
char s[60][60];
int W, H;
 
void dfs(int h, int w,  int d){
  visited[h][w]++;
  //if (W-1 == w && H-1 == h) cout << "depth[i][j]: " << d << endl;
  depth[h][w]=min(depth[h][w], d);
  //cout <<"h:" << h << ", w: " << w << ", d: " << d <<endl;
  rep(i, 4){
    if (root[h][w][i]) {
      if (i == 0) {if(depth[h-1][w]>d+1)dfs(h-1, w, d+1);}
      else if (i == 1) {if(depth[h][w-1]>d+1) dfs(h, w-1, d+1);}
      else if (i == 2) {if(depth[h+1][w]>d+1) dfs(h+1, w, d+1);}
      else if (i == 3) {if(depth[h][w+1]>d+1) dfs(h, w+1, d+1);}
    } 
  }
}
/*
void dfs(int h, int w,  int d){
  visited[h][w]++;
  //if (W-1 == w && H-1 == h) cout << "depth[i][j]: " << d << endl;
  depth[h][w]=min(depth[h][w], d);
  cout <<"h:" << h << ", w: " << w << ", d: " << d <<endl;
  rep(i, 4){
    if (root[h][w][i]) {
      if (i == 0) if(visited[h-1][w])dfs(h-1, w, d+1);
      else if (i == 1) if(visited[h][w-1]) dfs(h, w-1, d+1);
      else if (i == 2) if(visited[h+1][w]) dfs(h+1, w, d+1);
      else if (i == 3) if(visited[h][w+1]) dfs(h, w+1, d+1);
    } 
  }
}
*/
/*
void dfs(int h, int w,  int d){
  visited[h][w]++;
  //if (W-1 == w && H-1 == h) cout << "depth[i][j]: " << d << endl;
  depth[h][w]=min(depth[h][w], d);
  cout <<"h:" << h << ", w: " << w << ", d: " << d <<endl;
  rep(i, 4){
    if (root[h][w][i]) {
      if (i == 0) {if(!visited[h-1][w]) dfs(h-1, w, d+1);}
      else if (i == 1) {if(!visited[h][w-1]) dfs(h, w-1, d+1);}
      else if (i == 2) {if(!visited[h+1][w]) dfs(h+1, w, d+1);}
      else if (i == 3) {if(!visited[h][w+1]) dfs(h, w+1, d+1);}
    } 
  }
}
*/
int keta_sum(int num){
  int dig, sum = 0;
  while(num){
    dig = num % 10;
    sum = sum + dig;
    num = num / 10;
  }
  return sum;
}
 
 
int main(void){
 
  cin >> H >> W;
  
  int count = 0;
  rep(i, H) {
    rep(j, W) {
    	cin>>s[i][j];
        if (s[i][j]=='.') count++;
    }
  }
  int inf = 1e+5;
  rep(i, H) rep(j, W){
    depth[i][j] = inf;
    if (s[i][j] == '#') continue;
    if (i!= 0) if(s[i-1][j] == '.') {root[i][j][0]=1;}
    if (j!= 0) if(s[i][j-1] == '.') {root[i][j][1]=1;}
    if (i != H-1) if(s[i+1][j] == '.') {root[i][j][2]=1;}
    if (j != W-1) if(s[i][j+1] == '.') {root[i][j][3]=1;}
  }
  /*
  rep(i, H) {
    rep(j, W){
      cout << s[i][j] << " ";
    }
    cout << endl;
  }
  */
  //rep(i, 4) cout <<"root[0][0][i]: " <<root[0][0][i] << endl;
  //rep(i, 4) cout <<"root[0][1][i]: " <<root[0][1][i] << endl;
 
  dfs(0, 0, 1);
  //cout << "count: " << count << endl;
  int ans = count-depth[H-1][W-1];
  if (ans >-1) cout << ans << endl;
  else cout << -1 << endl;
  //cout << depth[H-1][W-1]<< endl;
}

Measured memory_bytes: 512