void main(){
  import std.stdio, std.string, std.conv, std.algorithm;
  import std.exception, std.typecons, std.container;

  int h, w; rd(h, w);
  auto c=new char[][](h, w);
  foreach(i; 0..h) c[i]=readln.chomp.to!(char[]);

  auto n=h*w;
  alias E=Tuple!(int, "to", int, "cost");
  auto g=new E[][](n);
  auto dir=[[1, 0], [-1, 0], [0, 1], [0, -1]];
  foreach(i; 0..h)foreach(j; 0..w){
    if(c[i][j]=='#') continue;
    foreach(dd; dir){
      auto ai=i+dd[0], aj=j+dd[1];
      if(ai<0 || ai>=h || aj<0 || aj>=w) continue;
      if(c[ai][aj]=='.'){
        g[i*w+j]~=E(ai*w+aj, 1);
        g[ai*w+aj]~=E(i*w+j, 1);
      }
    }
  }
  auto d=new int[](n);
  const int inf=1e9.to!(int);
  fill(d, inf);
  alias P=Tuple!(int, "v", int, "dist");
  auto Q=new RedBlackTree!(P, "a.dist<b.dist", true);
  d[0]=0; Q.insert(P(0, 0));
  while(Q.empty==false){
    auto cur=Q.front; Q.removeFront;
    foreach(e; g[cur.v]){
      if(d[e.to]<=d[cur.v]+e.cost) continue;
      d[e.to]=d[cur.v]+e.cost;
      Q.insert(P(e.to, d[e.to]));
    }
  }
  if(d[n-1]==inf){writeln(-1); return;}

  int bk=0;
  foreach(i; 0..h) bk+=count(c[i], '#');
  auto res=n-bk-(d[n-1]+1);
  enforce(res>=0);
  writeln(res);
}
void rd(T...)(ref T x){
  import std.stdio, std.string, std.conv;
  auto l=readln.split;
  assert(l.length==x.length);
  foreach(i, ref e; x){
    e=l[i].to!(typeof(e));
  }
}