41 static const uint8x8_t c0_x8 = vdup_n_u8(0);
42 static const uint8x16_t c0_x16 = vdupq_n_u8(0);
43 static const uint8x8_t c1_x8 = vdup_n_u8(1);
44 static const uint8x16_t c1_x16 = vdupq_n_u8(1);
45 static const uint32_t
step = 16;
46 static const uint32_t half_step =
step / 2;
48 void neon_logical_and(
const uint8_t *src0,
const uint8_t *src1, uint8_t *
dst, uint32_t len)
56 vst1q_u8(
dst, vandq_u8(vminq_u8(vld1q_u8(src0), c1_x16), vminq_u8(vld1q_u8(src1), c1_x16)));
62 for (; len >= half_step; len -= half_step)
64 vst1_u8(
dst, vand_u8(vmin_u8(vld1_u8(src0), c1_x8), vmin_u8(vld1_u8(src1), c1_x8)));
70 for (; len > 0; --len)
72 *
dst = (*src0) && (*src1);
79 void neon_logical_and_broadcast(
const uint8_t *
src, uint8_t broadcast_val, uint8_t *
dst, uint32_t len)
84 const auto broadcast_val_clamped_s = std::min<uint8_t>(broadcast_val, 1);
85 const auto broadcast_val_clamped_x16 = vdupq_n_u8(broadcast_val_clamped_s);
86 const auto broadcast_val_clamped_x8 = vdup_n_u8(broadcast_val_clamped_s);
90 vst1q_u8(
dst, vandq_u8(vminq_u8(vld1q_u8(
src), c1_x16), broadcast_val_clamped_x16));
95 for (; len >= half_step; len -= half_step)
97 vst1_u8(
dst, vand_u8(vmin_u8(vld1_u8(
src), c1_x8), broadcast_val_clamped_x8));
102 for (; len > 0; --len)
104 *
dst = (*src) && broadcast_val_clamped_s;
110 void neon_logical_or(
const uint8_t *src0,
const uint8_t *src1, uint8_t *
dst, uint32_t len)
118 vst1q_u8(
dst, vorrq_u8(vminq_u8(vld1q_u8(src0), c1_x16), vminq_u8(vld1q_u8(src1), c1_x16)));
124 for (; len >= half_step; len -= half_step)
126 vst1_u8(
dst, vorr_u8(vmin_u8(vld1_u8(src0), c1_x8), vmin_u8(vld1_u8(src1), c1_x8)));
132 for (; len > 0; --len)
134 *
dst = (*src0) || (*src1);
141 void neon_logical_or_broadcast(
const uint8_t *
src, uint8_t broadcast_val, uint8_t *
dst, uint32_t len)
146 const auto broadcast_val_clamped_s = std::min<uint8_t>(broadcast_val, 1);
147 const auto broadcast_val_clamped_x16 = vdupq_n_u8(broadcast_val_clamped_s);
148 const auto broadcast_val_clamped_x8 = vdup_n_u8(broadcast_val_clamped_s);
152 vst1q_u8(
dst, vorrq_u8(vminq_u8(vld1q_u8(
src), c1_x16), broadcast_val_clamped_x16));
157 for (; len >= half_step; len -= half_step)
159 vst1_u8(
dst, vorr_u8(vmin_u8(vld1_u8(
src), c1_x8), broadcast_val_clamped_x8));
164 for (; len > 0; --len)
166 *
dst = (*src) || broadcast_val_clamped_s;
172 void neon_logical_not(
const uint8_t *
src, uint8_t *
dst, uint32_t len)
179 vst1q_u8(
dst, vbslq_u8(vceqq_u8(vld1q_u8(
src), c0_x16), c1_x16, c0_x16));
184 for (; len >= half_step; len -= half_step)
186 vst1_u8(
dst, vbsl_u8(vceq_u8(vld1_u8(
src), c0_x8), c1_x8, c0_x8));
191 for (; len > 0; --len)
203 const auto len = window.
x().
end() - window.
x().
start();
209 win, [&](
const Coordinates &) { neon_logical_not(in.
ptr(), out.
ptr(), len); }, in, out);
221 const auto len = window.
x().
end() - window.
x().
start();
223 if (is_broadcast_across_x)
225 using LogicalBroadcastUKernelPtr = std::add_pointer<void(
const uint8_t *, uint8_t, uint8_t *, uint32_t)>
::type;
226 LogicalBroadcastUKernelPtr logical_func =
229 const bool is_broadcast_input_1 = src1_win.
x().
step() == 0;
230 Window broadcast_win = is_broadcast_input_1 ? src1_win : src0_win;
231 Window non_broadcast_win = !is_broadcast_input_1 ? src1_win : src0_win;
232 const ITensor *broadcast_tensor = is_broadcast_input_1 ? src1 : src0;
233 const ITensor *non_broadcast_tensor = !is_broadcast_input_1 ? src1 : src0;
236 Iterator broadcast_in(broadcast_tensor, broadcast_win);
237 Iterator non_broadcast_in(non_broadcast_tensor, non_broadcast_win);
244 const uint8_t broadcast_value = *broadcast_in.
ptr();
245 logical_func(non_broadcast_in.
ptr(), broadcast_value, out.
ptr(), len);
247 broadcast_in, non_broadcast_in, out);
251 using LogicalUKernelPtr = std::add_pointer<void(
const uint8_t *,
const uint8_t *, uint8_t *, uint32_t)>
::type;
252 LogicalUKernelPtr logical_func = op ==
LogicalOperation::Or ? &neon_logical_or : &neon_logical_and;
261 win, [&](
const Coordinates &) { logical_func(in0.
ptr(), in1.
ptr(), out.
ptr(), len); }, in0, in1, out);
267 return "NELogicalKernel";
288 ICPPKernel::configure(win);
312 if ((output !=
nullptr) && (output->
total_size() != 0))
338 run_binary(
window, src0, src1,
dst, _op);