#include <iostream>
#include <string>
#include <cstdlib>
#include <cstdio>
#include <queue>
#include <stack>
#include <list>
#include <utility>
#include <vector>
#include <set>
#include <algorithm>
#include <cmath>
#include <climits>
#include <map>
#include <unordered_map>
#include <string.h>
#include<iomanip>
#include <iterator>
#include <locale>

#define all(a) a.begin(),a.end()
#define VV(T) vector<vector< T > >
#define rep(i,N) for(int i = 0; i <N; i++)
#define repsg(i,s,g) for(int i = s; i <g; i++)
#define name(x) #x
using namespace std;

const int INF = INT_MAX;
const long long INFL = 1LL<<40;
const double PI = atan(1)*4;
const int MOD = pow(10,9)+7;
int dy[]={0, 0, 1, -1, 0};
int dx[]={1, -1, 0, 0, 0};

typedef long long ll,LL;
typedef vector<int> vint;
typedef vector<vector<int> > vvint;
typedef vector<long long> vll, vLL;
typedef vector<vector<long long> > vvll, vvLL;
typedef pair<int,int> pii;
typedef pair<LL, LL> pLL;


// vector入力
template<typename T>
istream& operator >> (istream& is, vector<T>& vec){
    for(T& x: vec) is >> x;
    return is;
}
// vector出力
template<typename T>
ostream& operator << (ostream& os, vector<T>& vec){
    for(int i=0; i<vec.size(); i++){
        os << vec[i] << ( i+1 == vec.size() ? "" : " " );
    }
    return os;
}

template< typename T >
struct edge{
    int src, to;T cost;
    edge(int to,T cost) :src(-1),to(to),cost(cost){}
    edge(int src, int to, T cost) :src(src),to(to),cost(cost){}edge
    &operator=(const int &x){
        to =x;
        return *this;
    }
    operator int() const{ return to;}
};

template< typename T >
using Edges =vector< edge<T> >;
template< typename T >
using WeightedGraph =vector< Edges<T> >;
using UnWeightedGraph =vector< vector<int> >;
template< typename T >
using Matrix =vector< vector<T> >;


template< typename T >
vector< T > dijkstra(WeightedGraph< T > &g, int s) {
    // ダイクストラ法。O(E log V), All edges must have positive-weight
    // 無向グラフを使う場合は逆向きの辺を入れるのを忘れないように。
    
    /////////////////////////////////
    ////////////////////////////////
    /// ここをmainで。

    ////////////////////////////////
    //////////////////////////////
    
    const auto INF = numeric_limits< T >::max();
    vector< T > dist(g.size(), INF);
    
    using Pi = pair< T, int >;
    priority_queue< Pi, vector< Pi >, greater< Pi > > que;
    dist[s] = 0;
    que.emplace(dist[s], s);
    while(!que.empty()) {
        T cost;
        int idx;
        tie(cost, idx) = que.top();
        que.pop();
        if(dist[idx] < cost) continue;
        for(auto &e : g[idx]) {
            auto next_cost = cost + e.cost;
            if(dist[e.to] <= next_cost) continue;
            dist[e.to] = next_cost;
            que.emplace(dist[e.to], e.to);
        }
    }
    return dist;
}
int main() {

    int h,w;cin>>h>>w;
    WeightedGraph<ll> g((h+3)*(w+3));
    int c = 0;
    rep(i,h){
        string s;cin>>s;
        rep(j,w){
            
            if(s[j]=='.'){
                
                g[(w+2)*(i) + j+1].push_back(edge<ll>((w+2)*(i+1) + j+1,1));
                g[(w+2)*(i+2) + j+1].push_back(edge<ll>((w+2)*(i+1) + j+1,1));
                g[(w+2)*(i+1) + j].push_back(edge<ll>((w+2)*(i+1) + j+1,1));
                g[(w+2)*(i+1) + j+2].push_back(edge<ll>((w+2)*(i+1) + j+1,1));
                
                
            }else{
                c++;
            }
            
        }
    }
    auto dist = dijkstra(g,(w+2)*(1) + 1);
    if (dist[(w+2)*h + w] != numeric_limits<ll>::max()){
        cout << h*w - (1+dist[(w+2)*(h) + w]) - c<<endl;
    }else{
        cout << -1 << endl;
    }

    
    
    return 0;
}












Measured memory_bytes: 512