Fix unaligned read/write in lpf_vertical_4_neon

Address of src buffer can only be 2-bytes aligned. Hence
replacing the operations by unaligned load/store functions.

BUG=aomedia:2186

Change-Id: Id56bbc1ff8ba533652c2668cbf4f4356a95d8495
diff --git a/aom_dsp/arm/loopfilter_neon.c b/aom_dsp/arm/loopfilter_neon.c
index bdc6762..aafac89 100644
--- a/aom_dsp/arm/loopfilter_neon.c
+++ b/aom_dsp/arm/loopfilter_neon.c
@@ -785,16 +785,15 @@
                              const uint8_t *limit, const uint8_t *thresh) {
   uint32x2x2_t p1q0_p0q1, p1q1_p0q0, p1p0_q1q0;
   uint32x2_t pq_rev;
-  uint8x8_t UNINITIALIZED_IS_SAFE(p1p0), q0q1, p0q0, p1q1;
+  uint8x8_t UNINITIALIZED_IS_SAFE(p1p0), UNINITIALIZED_IS_SAFE(q0q1);
+  uint8x8_t p0q0, p1q1;
 
   // row0: p1 p0 | q0 q1
   // row1: p1 p0 | q0 q1
   // row2: p1 p0 | q0 q1
   // row3: p1 p0 | q0 q1
-  load_u8_4x1(src - 2, &p1p0, 0);
-  load_u8_4x1((src - 2) + 1 * stride, &p1p0, 1);
-  load_u8_4x1((src - 2) + 2 * stride, &q0q1, 0);
-  load_u8_4x1((src - 2) + 3 * stride, &q0q1, 1);
+  load_unaligned_u8_4x4(src - 2, stride, (uint32x2_t *)&p1p0,
+                        (uint32x2_t *)&q0q1);
 
   transpose_u8_4x4(&p1p0, &q0q1);
 
@@ -815,10 +814,10 @@
 
   transpose_u8_4x4(&p1p0, &q0q1);
 
-  store_u8_4x1(src - 2, p1p0, 0);
-  store_u8_4x1((src - 2) + 1 * stride, q0q1, 0);
-  store_u8_4x1((src - 2) + 2 * stride, p1p0, 1);
-  store_u8_4x1((src - 2) + 3 * stride, q0q1, 1);
+  store_unaligned_u8_4x1(src - 2, p1p0, 0);
+  store_unaligned_u8_4x1((src - 2) + 1 * stride, q0q1, 0);
+  store_unaligned_u8_4x1((src - 2) + 2 * stride, p1p0, 1);
+  store_unaligned_u8_4x1((src - 2) + 3 * stride, q0q1, 1);
 }
 
 void aom_lpf_horizontal_14_neon(uint8_t *src, int stride, const uint8_t *blimit,
diff --git a/av1/common/arm/mem_neon.h b/av1/common/arm/mem_neon.h
index c4ae2e7..beae4ed 100644
--- a/av1/common/arm/mem_neon.h
+++ b/av1/common/arm/mem_neon.h
@@ -383,6 +383,15 @@
   *tu0 = vset_lane_u32(a, *tu0, 1);
 }
 
+/* These intrinsics require immediate values, so we must use #defines
+   to enforce that. */
+#define store_unaligned_u8_4x1(dst, src, lane)         \
+  do {                                                 \
+    uint32_t a;                                        \
+    a = vget_lane_u32(vreinterpret_u32_u8(src), lane); \
+    memcpy(dst, &a, 4);                                \
+  } while (0)
+
 static INLINE void load_unaligned_u8_2x2(const uint8_t *buf, int stride,
                                          uint16x4_t *tu0) {
   uint16_t a;