// Original C++ solution (slower):
#include <vector>

#include <iostream>

#include <cmath>

#include <map>

#include <algorithm>

#include <fstream>

#include <unistd.h>

#include <string>

#include <numeric>

#include <queue>

#include <deque>

#include <sstream>

#include <iomanip>

#include <set>

using namespace std;

typedef long long ll;

typedef vector<int> vi;

typedef vector<ll> vl;

typedef vector<vl> vvl;

typedef vector<vi> vvi;

typedef vector<vvi> vvvi;

typedef vector<bool> vb;

typedef vector<vector<bool>> vvb;

typedef vector<string> vs;

typedef vector<vector<string>> vvs;

typedef vector<char> vc;

typedef vector<vector<char>> vvc;

typedef pair<int, int> P;

typedef pair<ll, ll> PL;

typedef vector<P> vp;

typedef vector<PL> vpl;

typedef vector<vector<P>> vvp;

typedef vector<vector<PL>> vvpl;

const int INF = 1001001001;

const ll LINF = 1e18;

const double pi = 3.1415926535897932;

const string endstr = "\n";

#define FOR(i, a, b) for(ll i = (a); i < b; i++)

#define REP(i, n) for(ll i = 0; i < n; i++)

#define FORMAP(it, m) for(auto it = m.begin(); it != m.end(); it++)

#define ff first

#define ss second

#define pb push_back



template <typename T>

T gcd(T a, T b) {

    return (a == 0) ? b : gcd(b%a, a);

}

template <typename T>

T lcm(T a, T b) {

    return a / gcd(a, b) * b;

}



bool p_comp_fs(const PL p1, const PL p2){ return p1.first < p2.first;};

bool p_comp_fg(const PL p1, const PL p2){ return p1.first > p2.first;};

bool p_comp_ss(const PL p1, const PL p2){ return p1.second < p2.second;};

bool p_comp_sg(const PL p1, const PL p2){ return p1.second > p2.second;};

template <typename T>

vector<T> uniquen(vector<T> vec){

    vec.erase(unique(vec.begin(), vec.end()), vec.end());

    return vec;

}



ll H, W;

vpl dpl = {PL(-1,0), PL(1,0), PL(0,1), PL(0,-1)};



bool valid(ll x, ll y){

    return x >= 0 && x < H && y >= 0 && y < W;

}



int main(){

    cin >> H >> W;

    ll w_count = 0;

    vvc s(H, vc(W));

    REP(i, H){

        string str; cin >> str;

        REP(j, W){

            s[i][j] = str[j];

            if(str[j] == '.') w_count++;

        }

    };

    vvl ds(H, vl(W, LINF)); ds[0][0] = 0;

    vvb used(H, vb(W, false));

    while(true){

        // dijkstra

        PL cur(-1,-1);

        REP(i, H) REP(j, W){

            if(!used[i][j] && (cur == PL(-1,-1) || ds[i][j] < ds[cur.ff][cur.ss])){

                cur = PL(i,j);

            }

        }

        if(cur == PL(-1,-1)) break;

        used[cur.ff][cur.ss] = true;

        for(PL d : dpl){

            ll nx = cur.ff + d.ff, ny = cur.ss + d.ss;

            if(valid(nx, ny) && s[nx][ny] == '.'){

                ds[nx][ny] = min(ds[nx][ny], ds[cur.ff][cur.ss] + 1);

            }

        }

    }

    cout << (ds[H-1][W-1] == LINF ? -1 : w_count - (ds[H-1][W-1] + 1)) << endstr;

    return 0;

}


// Optimized solution to the same problem (faster):
#include <vector>

#include <iostream>

#include <cmath>

#include <map>

#include <unordered_map>

#include <algorithm>

#include <fstream>

#include <unistd.h>

#include <string>

#include <numeric>

#include <queue>

#include <deque>

#include <sstream>

#include <iomanip>

#include <set>

#include <stack>

#include <cassert>

using namespace std;

typedef long long ll;

typedef vector<int> vi;

typedef vector<ll> vl;

typedef vector<vl> vvl;

typedef vector<vvl> vvvl;

typedef vector<vi> vvi;

typedef vector<vvi> vvvi;

typedef vector<bool> vb;

typedef vector<vector<bool>> vvb;

typedef vector<vvb> vvvb;

typedef vector<vvvb> vvvvb;

typedef vector<string> vs;

typedef vector<vector<string>> vvs;

typedef vector<char> vc;

typedef vector<vector<char>> vvc;

typedef vector<double> vd;

typedef vector<vd> vvd;

typedef vector<vvd> vvvd;

typedef pair<int, int> P;

typedef pair<ll, ll> PL;

typedef vector<P> vp;

typedef vector<PL> vpl;

typedef vector<vector<P>> vvp;

typedef vector<vector<PL>> vvpl;

const int INF = 1001001001;

const ll LINF = 1e16;

const double pi = 3.1415926535897932;

const string endstr = "\n";

#define FOR(i, a, b) for(ll i = (a); i < b; i++)

#define RFOR(i, a, b) for(ll i = (a); i > b; i--)

#define REP(i, n) for(ll i = 0; i < n; i++)

#define RREP(i, n) for(ll i = n-1; i > -1; i--)

#define FORMAP(it, m) for(auto it = m.begin(); it != m.end(); it++)

#define ff first

#define ss second

#define pb push_back

#define epb emplace_back



template <typename T>

T gcd(T a, T b) {

    return (a == 0) ? b : gcd(b%a, a);

}

template <typename T>

T lcm(T a, T b) {

    return a / gcd(a, b) * b;

}



bool p_comp_fs(const PL p1, const PL p2){ return p1.first < p2.first;};

bool p_comp_fg(const PL p1, const PL p2){ return p1.first > p2.first;};

bool p_comp_ss(const PL p1, const PL p2){ return p1.second < p2.second;};

bool p_comp_sg(const PL p1, const PL p2){ return p1.second > p2.second;};

template <typename T>

vector<T> uniquen(vector<T> vec){

    vec.erase(unique(vec.begin(), vec.end()), vec.end());

    return vec;

}



vl dx={-1,1,0,0};

vl dy={0,0,-1,1};



int main(){

    ll H, W; cin >> H >> W;

    vs S(H);

    REP(i, H) cin >> S[i];

    

    queue<PL> q;

    q.push({0,0});

    vvl dist(H, vl(W, -1)); dist[0][0] = 1;

    while(!q.empty()){

        PL now = q.front(); q.pop();

        REP(i, 4){

            ll nh = now.ff+dx[i], nw = now.ss+dy[i];

            if(0<=nh && nh < H && 0 <= nw && nw < W && dist[nh][nw] == -1 && S[nh][nw] == '.'){

                dist[nh][nw] = dist[now.ff][now.ss]+1;

                q.push({nh,nw});

            }

        }

    }

    if(dist[H-1][W-1] == -1) cout << -1 << endl;

    else{

        ll wcnt = 0;

        REP(i, H) REP(j, W) if(S[i][j] == '.') wcnt++;

        cout << wcnt - dist[H-1][W-1] << endl;

    }

    return 0;

}


// Fastest known solution for this problem: