Refactor av1_update_boundary_info function

- Split av1_update_boundary_info() into two functions to avoid
  unnecessarily checking which goes through each mi block.
- av1_setup_frame_boundary_info() sets up frame level boundary,
  i.e. non-tile case, which is called in frame level only.
- av1_setup_across_tile_boundary_info sets up tiles boundary,
  which is called per tile, in multiple tile case.
- Decoder running time reduction: 8.72% (1080p, 25 frames, 4Mbps).

Change-Id: I2fc42d4281c77bce4a7dab5d208347308cfbe579
diff --git a/av1/common/tile_common.c b/av1/common/tile_common.c
index cae4ce3..c4ffc26 100644
--- a/av1/common/tile_common.c
+++ b/av1/common/tile_common.c
@@ -75,64 +75,82 @@
   assert(*min_log2_tile_cols <= *max_log2_tile_cols);
 }
 
-void av1_update_boundary_info(const struct AV1Common *cm,
-                              const TileInfo *const tile_info, int mi_row,
-                              int mi_col) {
-  int row, col;
-  for (row = mi_row; ((row < (mi_row + cm->mib_size)) && (row < cm->mi_rows));
-       row++)
-    for (col = mi_col; ((col < (mi_col + cm->mib_size)) && (col < cm->mi_cols));
-         col++) {
-      MODE_INFO *const mi = cm->mi + row * cm->mi_stride + col;
-      mi->mbmi.boundary_info = 0;
+void av1_setup_frame_boundary_info(const AV1_COMMON *const cm) {
+  MODE_INFO *mi = cm->mi;
+  int col;
+  for (col = 0; col < cm->mi_cols; ++col) {
+    mi->mbmi.boundary_info |= FRAME_ABOVE_BOUNDARY | TILE_ABOVE_BOUNDARY;
+    mi += 1;
+  }
 
-      // If horizontal dependent tile is enabled, then the horizontal
-      // tile boundary is not treated as real tile boundary for loop
-      // filtering, only the horizontal tile group boundary is treated
-      // as tile boundary.
-      // Otherwise, tile group boundary is treated the same as tile boundary.
-      // Loop filtering operation is done based on the
-      // loopfilter_across_tiles_enabled flag for both tile boundary and tile
-      // group boundary.
-      // the tile boundary flag is updated only when
-      // loopfilter_across_tiles_enabled value is 0.
+  mi = cm->mi;
+  int row;
+  for (row = 0; row < cm->mi_rows; ++row) {
+    mi->mbmi.boundary_info |= FRAME_LEFT_BOUNDARY | TILE_LEFT_BOUNDARY;
+    mi += cm->mi_stride;
+  }
 
-      int lpf_across_tiles_enabled = 1;
+  mi = cm->mi + (cm->mi_rows - 1) * cm->mi_stride;
+  for (col = 0; col < cm->mi_cols; ++col) {
+    mi->mbmi.boundary_info |= FRAME_BOTTOM_BOUNDARY | TILE_BOTTOM_BOUNDARY;
+    mi += 1;
+  }
 
+  mi = cm->mi + cm->mi_cols - 1;
+  for (row = 0; row < cm->mi_rows; ++row) {
+    mi->mbmi.boundary_info |= FRAME_RIGHT_BOUNDARY | TILE_RIGHT_BOUNDARY;
+    mi += cm->mi_stride;
+  }
+}
+
+void av1_setup_across_tile_boundary_info(const AV1_COMMON *const cm,
+                                         const TileInfo *const tile_info) {
+  int lpf_across_tiles_enabled = 1;
 #if CONFIG_LOOPFILTERING_ACROSS_TILES
-      lpf_across_tiles_enabled = cm->loop_filter_across_tiles_enabled;
+  lpf_across_tiles_enabled = cm->loop_filter_across_tiles_enabled;
 #endif
+  if ((cm->tile_cols * cm->tile_rows > 1) && (!lpf_across_tiles_enabled)) {
+    const int mi_row = tile_info->mi_row_start;
+    const int mi_col = tile_info->mi_col_start;
+    MODE_INFO *const mi_start = cm->mi + mi_row * cm->mi_stride + mi_col;
+    MODE_INFO *mi = 0;
+    const int row_diff = tile_info->mi_row_end - tile_info->mi_row_start;
+    const int col_diff = tile_info->mi_col_end - tile_info->mi_col_start;
+    int row, col;
 
-      if ((cm->tile_cols * cm->tile_rows > 1) && (!lpf_across_tiles_enabled)) {
 #if CONFIG_DEPENDENT_HORZTILES
 #if CONFIG_TILE_GROUPS
-        if (row == tile_info->mi_row_start &&
-            (!cm->dependent_horz_tiles || tile_info->tg_horz_boundary))
+    if (!cm->dependent_horz_tiles || tile_info->tg_horz_boundary)
 #else
-        if (row == tile_info->mi_row_start && !cm->dependent_horz_tiles)
+    if (!cm->dependent_horz_tiles)
 #endif  // CONFIG_TILE_GROUPS
-#else
-        if (row == tile_info->mi_row_start)
 #endif  // CONFIG_DEPENDENT_HORZTILES
-
-          mi->mbmi.boundary_info |= TILE_ABOVE_BOUNDARY;
-        if (col == tile_info->mi_col_start)
-          mi->mbmi.boundary_info |= TILE_LEFT_BOUNDARY;
-        if ((row + 1) >= tile_info->mi_row_end)
-          mi->mbmi.boundary_info |= TILE_BOTTOM_BOUNDARY;
-        if ((col + 1) >= tile_info->mi_col_end)
-          mi->mbmi.boundary_info |= TILE_RIGHT_BOUNDARY;
+    {
+      mi = mi_start;
+      for (col = 0; col < col_diff; ++col) {
+        mi->mbmi.boundary_info |= TILE_ABOVE_BOUNDARY;
+        mi += 1;
       }
-      // Frame boundary is treated as tile boundary
-      if (row == 0)
-        mi->mbmi.boundary_info |= FRAME_ABOVE_BOUNDARY | TILE_ABOVE_BOUNDARY;
-      if (col == 0)
-        mi->mbmi.boundary_info |= FRAME_LEFT_BOUNDARY | TILE_LEFT_BOUNDARY;
-      if ((row + 1) >= cm->mi_rows)
-        mi->mbmi.boundary_info |= FRAME_BOTTOM_BOUNDARY | TILE_BOTTOM_BOUNDARY;
-      if ((col + 1) >= cm->mi_cols)
-        mi->mbmi.boundary_info |= FRAME_RIGHT_BOUNDARY | TILE_RIGHT_BOUNDARY;
     }
+
+    mi = mi_start;
+    for (row = 0; row < row_diff; ++row) {
+      mi->mbmi.boundary_info |= TILE_LEFT_BOUNDARY;
+      mi += cm->mi_stride;
+    }
+
+    mi = mi_start + (row_diff - 1) * cm->mi_stride;
+    for (col = 0; col < col_diff; ++col) {
+      mi->mbmi.boundary_info |= TILE_BOTTOM_BOUNDARY;
+      mi += 1;
+    }
+
+    mi = mi_start + col_diff - 1;
+    for (row = 0; row < row_diff; ++row) {
+      mi->mbmi.boundary_info |= TILE_RIGHT_BOUNDARY;
+      mi += cm->mi_stride;
+    }
+  }
 }
 
 #if CONFIG_LOOPFILTERING_ACROSS_TILES