@@ -268,61 +268,82 @@ struct SubViewOpInterface
268268 MemRefType sourceType = subView.getSource ().getType ();
269269
270270 // For each dimension, assert that:
271- // 0 <= offset < dim_size
272- // 0 <= offset + (size - 1) * stride < dim_size
271+ // For empty slices (size == 0) : 0 <= offset <= dim_size
272+ // For non-empty slices (size > 0): 0 <= offset < dim_size
273+ // 0 <= offset + (size - 1) * stride
274+ // dim_size
273275 Value zero = arith::ConstantIndexOp::create (builder, loc, 0 );
274276 Value one = arith::ConstantIndexOp::create (builder, loc, 1 );
277+
275278 auto metadataOp =
276279 ExtractStridedMetadataOp::create (builder, loc, subView.getSource ());
280+
277281 for (int64_t i : llvm::seq<int64_t >(0 , sourceType.getRank ())) {
278- // Reset insertion point to before the operation for each dimension
282+ // Reset insertion point to before the operation for each dimension.
279283 builder.setInsertionPoint (subView);
284+
280285 Value offset = getValueOrCreateConstantIndexOp (
281286 builder, loc, subView.getMixedOffsets ()[i]);
282287 Value size = getValueOrCreateConstantIndexOp (builder, loc,
283288 subView.getMixedSizes ()[i]);
284289 Value stride = getValueOrCreateConstantIndexOp (
285290 builder, loc, subView.getMixedStrides ()[i]);
286-
287- // Verify that offset is in-bounds.
288291 Value dimSize = metadataOp.getSizes ()[i];
289- Value offsetInBounds =
290- generateInBoundsCheck (builder, loc, offset, zero, dimSize);
291- cf::AssertOp::create (builder, loc, offsetInBounds,
292+
293+ // Verify that offset is in-bounds (conditional on slice size).
294+ Value sizeIsZero = arith::CmpIOp::create (
295+ builder, loc, arith::CmpIPredicate::eq, size, zero);
296+ auto offsetCheckIf = scf::IfOp::create (
297+ builder, loc, sizeIsZero,
298+ [&](OpBuilder &b, Location loc) {
299+ // For empty slices, offset can be at the boundary: 0 <= offset <=
300+ // dimSize.
301+ Value offsetGEZero = arith::CmpIOp::create (
302+ b, loc, arith::CmpIPredicate::sge, offset, zero);
303+ Value offsetLEDimSize = arith::CmpIOp::create (
304+ b, loc, arith::CmpIPredicate::sle, offset, dimSize);
305+ Value emptyOffsetValid =
306+ arith::AndIOp::create (b, loc, offsetGEZero, offsetLEDimSize);
307+ scf::YieldOp::create (b, loc, emptyOffsetValid);
308+ },
309+ [&](OpBuilder &b, Location loc) {
310+ // For non-empty slices, offset must be a valid index: 0 <= offset
311+ // dimSize.
312+ Value offsetInBounds =
313+ generateInBoundsCheck (b, loc, offset, zero, dimSize);
314+ scf::YieldOp::create (b, loc, offsetInBounds);
315+ });
316+
317+ Value offsetCondition = offsetCheckIf.getResult (0 );
318+ cf::AssertOp::create (builder, loc, offsetCondition,
292319 generateErrorMessage (op, " offset " +
293320 std::to_string (i) +
294321 " is out-of-bounds" ));
295322
296- // Only verify if size > 0
323+ // Verify that the slice endpoint is in-bounds (only for non-empty
324+ // slices).
297325 Value sizeIsNonZero = arith::CmpIOp::create (
298326 builder, loc, arith::CmpIPredicate::sgt, size, zero);
327+ auto ifOp = scf::IfOp::create (
328+ builder, loc, sizeIsNonZero,
329+ [&](OpBuilder &b, Location loc) {
330+ // Verify that slice does not run out-of-bounds.
331+ Value sizeMinusOne = arith::SubIOp::create (b, loc, size, one);
332+ Value sizeMinusOneTimesStride =
333+ arith::MulIOp::create (b, loc, sizeMinusOne, stride);
334+ Value lastPos =
335+ arith::AddIOp::create (b, loc, offset, sizeMinusOneTimesStride);
336+ Value lastPosInBounds =
337+ generateInBoundsCheck (b, loc, lastPos, zero, dimSize);
338+ scf::YieldOp::create (b, loc, lastPosInBounds);
339+ },
340+ [&](OpBuilder &b, Location loc) {
341+ Value trueVal =
342+ arith::ConstantOp::create (b, loc, b.getBoolAttr (true ));
343+ scf::YieldOp::create (b, loc, trueVal);
344+ });
299345
300- auto ifOp = scf::IfOp::create (builder, loc, builder.getI1Type (),
301- sizeIsNonZero, /* withElseRegion=*/ true );
302-
303- // Populate the "then" region (for size > 0).
304- builder.setInsertionPointToStart (&ifOp.getThenRegion ().front ());
305-
306- // Verify that slice does not run out-of-bounds.
307- Value sizeMinusOne = arith::SubIOp::create (builder, loc, size, one);
308- Value sizeMinusOneTimesStride =
309- arith::MulIOp::create (builder, loc, sizeMinusOne, stride);
310- Value lastPos =
311- arith::AddIOp::create (builder, loc, offset, sizeMinusOneTimesStride);
312- Value lastPosInBounds =
313- generateInBoundsCheck (builder, loc, lastPos, zero, dimSize);
314-
315- scf::YieldOp::create (builder, loc, lastPosInBounds);
316-
317- // Populate the "else" region (for size == 0).
318- builder.setInsertionPointToStart (&ifOp.getElseRegion ().front ());
319- Value trueVal =
320- arith::ConstantOp::create (builder, loc, builder.getBoolAttr (true ));
321- scf::YieldOp::create (builder, loc, trueVal);
322-
323- builder.setInsertionPointAfter (ifOp);
324346 Value finalCondition = ifOp.getResult (0 );
325-
326347 cf::AssertOp::create (
327348 builder, loc, finalCondition,
328349 generateErrorMessage (op,
0 commit comments