H,W=list(map(int, input().split()))

grid=[]
S=""
for i in range(W+2):
    S = S+'#'
grid.append(S)
for i in range(H):
    grid.append('#'+input()+'#')
grid.append(S)

reached=[]
for i in range(H+2):
    reached.append([0*j for j in range(W+2)])

number_of_black_grid=0
for row in grid:
    number_of_black_grid += row.count('#')
s_x=1
s_y=1
g_x=W
g_y=H

# for i in range(H+2):
#     print(grid[i])
# for i in range(H+2):
#     print(reached[i])


def isGoal(x,y,g_x,g_y):
    if x==g_x and y==g_y:
        return True
    else:
        return False

def BFS_search(s_x, s_y, g_x, g_y):
    queue=[]
    queue.append([s_y, s_x, 0])
    reached[s_y][s_x]=0
    while len(queue)>0:
        v=queue.pop(0)
        if grid[v[0]+1][v[1]]=='.' and reached[v[0]+1][v[1]]==0 and [v[0]+1, v[1]]!=[s_y, s_x]:
            reached[v[0]+1][v[1]]=v[2]+1
            if isGoal(v[1], v[0]+1, g_x, g_y):
                break
            else:
                queue.append([v[0]+1, v[1], v[2]+1])
        if grid[v[0]][v[1]+1]=='.' and reached[v[0]][v[1]+1]==0 and [v[0], v[1]+1]!=[s_y, s_x]:
            reached[v[0]][v[1]+1]=v[2]+1
            if isGoal(v[1]+1, v[0], g_x, g_y):
                break
            else:
                queue.append([v[0], v[1]+1, v[2]+1])
        if grid[v[0]-1][v[1]]=='.' and reached[v[0]-1][v[1]]==0 and [v[0]-1, v[1]]!=[s_y, s_x]:
            reached[v[0]-1][v[1]]=v[2]+1
            if isGoal(v[1], v[0]-1, g_x, g_y):
                break
            else:
                queue.append([v[0]-1, v[1], v[2]+1])
        if grid[v[0]][v[1]-1]=='.' and reached[v[0]][v[1]-1]==0 and [v[0], v[1]-1]!=[s_y, s_x]:
            reached[v[0]][v[1]-1]=v[2]+1
            if isGoal(v[1]-1, v[0], g_x, g_y):
                break
            else:
                queue.append([v[0], v[1]-1, v[2]+1])

BFS_search(s_x, s_y, g_x, g_y)
# print(reached[g_y][g_x])
maximum_score = ((H+2)*(W+2)-number_of_black_grid)-(reached[g_x][g_y]+1)
print(maximum_score)


### FIXED CODE ###

H,W=list(map(int, input().split()))

grid=[]
S=""
for i in range(W+2):
    S = S+'#'
grid.append(S)
for i in range(H):
    grid.append('#'+input()+'#')
grid.append(S)

reached=[]
for i in range(H+2):
    reached.append([0*j for j in range(W+2)])

number_of_black_grid=0
for row in grid:
    number_of_black_grid += row.count('#')
s_x=1
s_y=1
g_x=W
g_y=H

def isGoal(x,y,g_x,g_y):
    if x==g_x and y==g_y:
        return True
    else:
        return False

def BFS_search(s_x, s_y, g_x, g_y):
    queue=[]
    queue.append([s_y, s_x, 0])
    reached[s_y][s_x]=0
    while len(queue)>0:
        v=queue.pop(0)
        if grid[v[0]+1][v[1]]=='.' and reached[v[0]+1][v[1]]==0 and [v[0]+1, v[1]]!=[s_y, s_x]:
            reached[v[0]+1][v[1]]=v[2]+1
            if isGoal(v[1], v[0]+1, g_x, g_y):
                break
            else:
                queue.append([v[0]+1, v[1], v[2]+1])
        if grid[v[0]][v[1]+1]=='.' and reached[v[0]][v[1]+1]==0 and [v[0], v[1]+1]!=[s_y, s_x]:
            reached[v[0]][v[1]+1]=v[2]+1
            if isGoal(v[1]+1, v[0], g_x, g_y):
                break
            else:
                queue.append([v[0], v[1]+1, v[2]+1])
        if grid[v[0]-1][v[1]]=='.' and reached[v[0]-1][v[1]]==0 and [v[0]-1, v[1]]!=[s_y, s_x]:
            reached[v[0]-1][v[1]]=v[2]+1
            if isGoal(v[1], v[0]-1, g_x, g_y):
                break
            else:
                queue.append([v[0]-1, v[1], v[2]+1])
        if grid[v[0]][v[1]-1]=='.' and reached[v[0]][v[1]-1]==0 and [v[0], v[1]-1]!=[s_y, s_x]:
            reached[v[0]][v[1]-1]=v[2]+1
            if isGoal(v[1]-1, v[0], g_x, g_y):
                break
            else:
                queue.append([v[0], v[1]-1, v[2]+1])

BFS_search(s_x, s_y, g_x, g_y)
if reached[g_y][g_x] == 0:
    print(-1)
else:
    maximum_score = ((H+2)*(W+2)-number_of_black_grid)-(reached[g_y][g_x]+1)
    print(maximum_score)