#include <iostream>
#include <vector>
using namespace std;

struct Node {
  char col;
  // ダイクストラ法のためのデータ
  bool done;  // 確定ノードか否か
  int cost;   // このノードへの現時点で判明している最小コスト
  struct Node *p;
};

int main(){
  int H, W, i, j, tmpcost;
  int wcount = 0;

  cin >> H >> W;
  struct Node Nodes[H][W];
  for (i = 0; i < H; i++){
    for(j = 0; j < W; j++){
      cin >> Nodes[i][j].col;
      if(Nodes[i][j].col == '.'){
        wcount++;
      }
      Nodes[i][j].done = false;
      Nodes[i][j].cost = -1;
    }
  }

  Nodes[0][0].cost = 0;
  Nodes[0][0].p = NULL;
  while(true){
    int process_i = -1;
    int process_j = -1;

    for(i = 0; i < H; i++){
      for(j = 0; j < W; j++){
        if(Nodes[i][j].done || Nodes[i][j].cost < 0){
          continue;
        }

        if(process_i == -1){
          process_i = i;
          process_j = j;
          continue;
        }

        if(Nodes[i][j].cost < Nodes[process_i][process_j].cost){
          process_i = i;
          process_j = j;
        }
      }
    }

    if(process_i == -1){
      break;
    }

    Nodes[process_i][process_j].done = true;

    //cout << "pro i = " << process_i << ", pro j = " << process_j << endl;

    if(process_j != (W - 1) && Nodes[process_i][process_j + 1].col == '.'){
      tmpcost = Nodes[process_i][process_j].cost + 1;
      if (Nodes[process_i][process_j + 1].cost < 0 || Nodes[process_i][process_j + 1].cost > tmpcost){
        Nodes[process_i][process_j + 1].cost = tmpcost;
        Nodes[process_i][process_j + 1].p = &Nodes[process_i][process_j];
//        cout << "-> Nodes[" << process_i << "][" << process_j + 1 << "].cost = " << tmpcost << endl;
      }
    }
    if(process_i != (H - 1) && Nodes[process_i + 1][process_j].col == '.'){    
      tmpcost = Nodes[process_i][process_j].cost + 1;
      if (Nodes[process_i + 1][process_j].cost < 0 || Nodes[process_i + 1][process_j].cost > tmpcost){
        Nodes[process_i + 1][process_j].cost = tmpcost;
        Nodes[process_i + 1][process_j].p = &Nodes[process_i][process_j];
//        cout << "| Nodes[" << process_i + 1 << "][" << process_j << "].cost = " << tmpcost << endl;
      }
    }
    if(process_j != 0 && Nodes[process_i][process_j - 1].col == '.'){
      tmpcost = Nodes[process_i][process_j].cost + 1;
      if (Nodes[process_i][process_j - 1].cost < 0 || Nodes[process_i][process_j - 1].cost > tmpcost){
        Nodes[process_i][process_j - 1].cost = tmpcost;
        Nodes[process_i][process_j - 1].p = &Nodes[process_i][process_j];
//        cout << "<- Nodes[" << process_i << "][" << process_j - 1 << "].cost = " << tmpcost << endl;
      }
    }
    if(process_i != 0 && Nodes[process_i - 1][process_j].col == '.'){    
      tmpcost = Nodes[process_i][process_j].cost + 1;
      if (Nodes[process_i - 1][process_j].cost < 0 || Nodes[process_i - 1][process_j].cost > tmpcost){
        Nodes[process_i - 1][process_j].cost = tmpcost;
        Nodes[process_i - 1][process_j].p = &Nodes[process_i][process_j];
//        cout << "^ Nodes[" << process_i - 1 << "][" << process_j << "].cost = " << tmpcost << endl;
      }
    }
  }

  if(Nodes[H - 1][W - 1].cost < 0){
    cout << -1 << endl;
    return 0;
  }

  int count = 2;
  struct Node *pare = Nodes[H - 1][W - 1].p;
//  cout << pare->cost << endl;
  while(true){
    pare = pare->p;
    count++;
    if(pare->cost == 0){
      break;
    }
  }
  
  cout << wcount - count << endl;
  
  /*
  for (i = 0; i < H; i++){
    for(j = 0; j < W; j++){
      cout << Nodes[i][j].col << " ";
    }
    cout << endl;
  }
  */

  return 0;
}

Measured memory_bytes: 256