#include <bits/stdc++.h>
using namespace std;
const int MOD = 1000000007;
void yes() {
  cout << "Yes"
       << "\n";
}
void no() {
  cout << "No"
       << "\n";
}
struct Sync_stdio {
  Sync_stdio() {
    cin.tie(NULL);
    ios_base::sync_with_stdio(false);
  }
} _sync_stdio;
struct FAIL {
  FAIL() {
    cout << "CHANGE!!!"
         << "\n";
  }
};
class BipartiteMatching {
 public:
  struct Edge {
    int first_part_vertex;
    int second_part_vertex;
  };
  struct Vertex {
    int vertex_id;
    int part;
  };
  BipartiteMatching(int size_first_, int size_second_)
      : size_first(size_first_), size_second(size_second_), graph(size_first) {}
  void add_edge(int first_part_vertex, int second_part_vertex) {
    graph[first_part_vertex].push_back(second_part_vertex);
  }
  vector<Edge> find_matching() {
    if (!calculated_matching) {
      calculate_matching();
    }
    vector<Edge> answer;
    for (int i = 0; i < size_second; ++i) {
      if (mt[i] != -1) {
        answer.push_back({mt[i], i});
      }
    }
    return answer;
  }
  vector<Vertex> find_minimum_vertex_cover() {
    if (!calculated_matching) {
      calculate_matching();
    }
    cerr << "Doesn't work"
         << "\n";
    return {};
  }

 private:
  bool try_kuhn(int vertex) {
    if (used[vertex]) {
      return false;
    }
    used[vertex] = true;
    for (int to : graph[vertex]) {
      if (mt[to] == -1 || try_kuhn(mt[to])) {
        mt[to] = vertex;
        return true;
      }
    }
    return false;
  }
  void calculate_matching() {
    mt.assign(size_second, -1);
    for (int i = 0; i < size_first; ++i) {
      used.assign(size_first, false);
      try_kuhn(i);
    }
    calculated_matching = true;
  }
  int size_first, size_second;
  int calculated_matching = false;
  vector<vector<int>> graph;
  vector<int> mt;
  vector<char> used;
};
bool can(int n, int m) {
  BipartiteMatching matching(n * m, n * m);
  for (int i1 = (0); i1 < (n); ++i1) {
    for (int j1 = (0); j1 < (m); ++j1) {
      for (int i2 = (0); i2 < (n); ++i2) {
        for (int j2 = (0); j2 < (m); ++j2) {
          if ((i1 + j1) % 2 && abs(i1 - i2) + abs(j1 - j2) == 3) {
            matching.add_edge(i1 * m + j1, i2 * m + j2);
          }
        }
      }
    }
  }
  return matching.find_matching().size() == n * m / 2;
}
void build_table(int n, int m) {
  vector<vector<int>> ans(n, vector<int>(m));
  for (int i = (0); i < (n); ++i) {
    for (int j = (0); j < (m); ++j) {
      ans[i][j] = can(i + 1, j + 1);
    }
  }
  for (int i = (0); i < (n); ++i) {
    for (int j = (0); j < (m); ++j) {
      cout << ans[i][j];
    }
    cout << "\n";
  }
}
int main() {
  long long n, m;
  cin >> n >> m;
  if (n > m) {
    swap(n, m);
  }
  if (n >= 3) {
    cout << n * m / 2 * 2;
    return 0;
  }
  if (n == 2) {
    if (m == 7) {
      cout << 12;
    } else if (m >= 4) {
      cout << n * m / 2 * 2;
    } else if (m == 3) {
      cout << 4;
    } else {
      cout << 0;
    }
    return 0;
  }
  cout << m / 6 * 6 + max((m % 6 - 3) * 2, 0LL);
}
