import           Control.Monad
import qualified Data.Array.IO               as IO
import           Data.Bits
import qualified Data.ByteString.Char8       as BS
import           Data.Char
import           Data.Maybe
import qualified Data.Sequence               as Seq
import qualified Data.Vector.Unboxed         as V
import qualified Data.Vector.Unboxed.Mutable as VM

readInt = fst . fromJust . BS.readInt
readIntList = map readInt . BS.words
getInt = readInt <$> BS.getLine
getIntList = readIntList <$> BS.getLine
getIntVec n = V.unfoldrN n (BS.readInt . BS.dropWhile isSpace) <$> BS.getLine

readInteger = fst . fromJust . BS.readInteger
readIntegerList = map readInteger . BS.words
getInteger = readInteger <$> BS.getLine
getIntegerList = readIntegerList <$> BS.getLine

main = do
  [h, w] <- getIntList
  ss <- replicateM h getLine

  let getPos y x | y < 1 || y > h || x < 1 || x > w = '#'
                 | otherwise = (ss !! (y-1)) !! (x-1)

      inf = 10^9 :: Int

      nWhites = length $ concatMap (filter (== '.')) ss

  g <- IO.newArray ((0,0),(h+1,w+1)) inf :: IO (IO.IOUArray (Int,Int) Int)

  let bsf :: Seq.Seq (Int, Int) -> IO ()
      bsf q | Seq.null q = return ()
            | otherwise = do
                let (y, x) Seq.:< q' = Seq.viewl q
                if y == h && x == w
                  then return ()
                  else do
                  dist <- IO.readArray g (y, x)
                  ps <- forM [(0,-1),(0,1),(1,0),(-1,0)] $ \(dy,dx) -> do
                    let (y', x') = (y + dy, x + dx)
                    t <- IO.readArray g (y', x')
                    if dist < t && getPos y' x' == '.'
                      then do IO.writeArray g (y', x') (dist+1)
                              return [(y', x')]
                      else return []
                  let q'' = q' Seq.>< (Seq.fromList $ concat ps)
                  bsf q''

  IO.writeArray g (1,1) 0
  bsf (Seq.fromList [(1,1)])
  dist <- IO.readArray g (h, w)

  let ans = nWhites - (dist + 1)
  print $ if dist < inf then ans else -1
