Skip to content

Commit 91f1871

Browse files
committed
[MooreToCore] Handle empty array creation and slices
Lower zero-element array creation and static array slices without constructing empty array_create/array_concat or mismatched bitcasts. Negative-low padding is clamped to the requested slice size.
1 parent 2aaa416 commit 91f1871

4 files changed

Lines changed: 131 additions & 25 deletions

File tree

lib/Conversion/MooreToCore/MooreToCore.cpp

Lines changed: 43 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1402,46 +1402,56 @@ struct ExtractOpConversion : public OpConversionPattern<ExtractOp> {
14021402
if (elementWidth < 0)
14031403
return failure();
14041404

1405-
int32_t high = low + resArrTy.getNumElements();
1406-
int32_t resWidth = resArrTy.getNumElements();
1405+
int64_t high = int64_t(low) + resArrTy.getNumElements();
1406+
int64_t resWidth = resArrTy.getNumElements();
1407+
if (resWidth == 0) {
1408+
Value zero = createZeroValue(resultType, op.getLoc(), rewriter);
1409+
if (!zero)
1410+
return failure();
1411+
rewriter.replaceOp(op, zero);
1412+
return success();
1413+
}
1414+
1415+
auto createZeroArray = [&](int64_t numElements) -> Value {
1416+
Value constZero = hw::ConstantOp::create(
1417+
rewriter, op.getLoc(), APInt(numElements * elementWidth, 0));
1418+
return rewriter.createOrFold<hw::BitcastOp>(
1419+
op.getLoc(),
1420+
hw::ArrayType::get(arrTy.getElementType(), numElements),
1421+
constZero);
1422+
};
14071423

14081424
SmallVector<Value> toConcat;
1425+
int64_t prefixElements = 0;
14091426
if (low < 0) {
1410-
Value val = hw::ConstantOp::create(
1411-
rewriter, op.getLoc(),
1412-
APInt(std::min((-low) * elementWidth, resWidth * elementWidth),
1413-
0));
1414-
Value res = rewriter.createOrFold<hw::BitcastOp>(
1415-
op.getLoc(), hw::ArrayType::get(arrTy.getElementType(), -low),
1416-
val);
1417-
toConcat.push_back(res);
1427+
prefixElements = std::min<int64_t>(-int64_t(low), resWidth);
1428+
if (prefixElements > 0)
1429+
toConcat.push_back(createZeroArray(prefixElements));
14181430
}
14191431

1432+
int64_t middleElements = 0;
14201433
if (low < inputWidth && high > 0) {
1421-
int32_t lowIdx = std::max(0, low);
1434+
int64_t lowIdx = std::max<int64_t>(0, low);
1435+
middleElements =
1436+
std::min<int64_t>(resWidth - prefixElements,
1437+
std::min<int64_t>(inputWidth, high) - lowIdx);
14221438
Value lowIdxVal = hw::ConstantOp::create(
14231439
rewriter, op.getLoc(), rewriter.getIntegerType(width), lowIdx);
14241440
Value middle = rewriter.createOrFold<hw::ArraySliceOp>(
14251441
op.getLoc(),
1426-
hw::ArrayType::get(
1427-
arrTy.getElementType(),
1428-
std::min(resWidth, std::min(inputWidth, high) - lowIdx)),
1442+
hw::ArrayType::get(arrTy.getElementType(), middleElements),
14291443
adaptor.getInput(), lowIdxVal);
14301444
toConcat.push_back(middle);
14311445
}
14321446

1433-
int32_t diff = high - inputWidth;
1434-
if (diff > 0) {
1435-
Value constZero = hw::ConstantOp::create(
1436-
rewriter, op.getLoc(), APInt(diff * elementWidth, 0));
1437-
Value val = hw::BitcastOp::create(
1438-
rewriter, op.getLoc(),
1439-
hw::ArrayType::get(arrTy.getElementType(), diff), constZero);
1440-
toConcat.push_back(val);
1441-
}
1447+
int64_t suffixElements = resWidth - prefixElements - middleElements;
1448+
if (suffixElements > 0)
1449+
toConcat.push_back(createZeroArray(suffixElements));
14421450

1443-
Value concat =
1444-
rewriter.createOrFold<hw::ArrayConcatOp>(op.getLoc(), toConcat);
1451+
Value concat = toConcat.size() == 1
1452+
? toConcat.front()
1453+
: rewriter.createOrFold<hw::ArrayConcatOp>(
1454+
op.getLoc(), toConcat);
14451455
rewriter.replaceOp(op, concat);
14461456
return success();
14471457
}
@@ -1613,6 +1623,14 @@ struct ArrayCreateOpConversion : public OpConversionPattern<ArrayCreateOp> {
16131623
matchAndRewrite(ArrayCreateOp op, OpAdaptor adaptor,
16141624
ConversionPatternRewriter &rewriter) const override {
16151625
Type resultType = typeConverter->convertType(op.getResult().getType());
1626+
if (adaptor.getElements().empty()) {
1627+
Value zero = createZeroValue(resultType, op.getLoc(), rewriter);
1628+
if (!zero)
1629+
return failure();
1630+
rewriter.replaceOp(op, zero);
1631+
return success();
1632+
}
1633+
16161634
rewriter.replaceOpWithNewOp<hw::ArrayCreateOp>(op, resultType,
16171635
adaptor.getElements());
16181636
return success();
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// RUN: circt-opt %s --convert-moore-to-core | FileCheck %s
2+
3+
// CHECK-LABEL: func.func @empty_packed_array_create
4+
// CHECK-NOT: hw.array_create
5+
// CHECK: %[[ZERO0:.+]] = hw.constant 0 : i0
6+
// CHECK: %[[ARRAY0:.+]] = hw.bitcast %[[ZERO0]] : (i0) -> !hw.array<0xi8>
7+
// CHECK: return %[[ARRAY0]] : !hw.array<0xi8>
8+
// CHECK-NOT: hw.array_create
9+
func.func @empty_packed_array_create() -> !moore.array<0 x !moore.i8> {
10+
%0 = "moore.array_create"() : () -> !moore.array<0 x !moore.i8>
11+
return %0 : !moore.array<0 x !moore.i8>
12+
}
13+
14+
// CHECK-LABEL: func.func @empty_unpacked_array_create
15+
// CHECK-NOT: hw.array_create
16+
// CHECK: %[[ZERO1:.+]] = hw.constant 0 : i0
17+
// CHECK: %[[ARRAY1:.+]] = hw.bitcast %[[ZERO1]] : (i0) -> !hw.array<0xi8>
18+
// CHECK: return %[[ARRAY1]] : !hw.array<0xi8>
19+
// CHECK-NOT: hw.array_create
20+
func.func @empty_unpacked_array_create() -> !moore.uarray<0 x !moore.i8> {
21+
%0 = "moore.array_create"() : () -> !moore.uarray<0 x !moore.i8>
22+
return %0 : !moore.uarray<0 x !moore.i8>
23+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// RUN: circt-opt --convert-moore-to-core %s | FileCheck %s
2+
3+
// CHECK-LABEL: func.func @negative_low_array_slice
4+
// CHECK-SAME: (%arg0: !hw.array<4xi8>) -> !hw.array<2xi8>
5+
// CHECK: %[[ZERO:.*]] = hw.constant 0 : i16
6+
// CHECK-NEXT: %[[PADDING:.*]] = hw.bitcast %[[ZERO]] : (i16) -> !hw.array<2xi8>
7+
// CHECK-NEXT: return %[[PADDING]] : !hw.array<2xi8>
8+
func.func @negative_low_array_slice(%arg0: !moore.array<4 x !moore.i8>) -> !moore.array<2 x !moore.i8> {
9+
%0 = moore.extract %arg0 from -3 : !moore.array<4 x !moore.i8> -> !moore.array<2 x !moore.i8>
10+
return %0 : !moore.array<2 x !moore.i8>
11+
}
12+
13+
// CHECK-LABEL: func.func @negative_low_i32_min_array_slice
14+
// CHECK-SAME: (%arg0: !hw.array<4xi8>) -> !hw.array<2xi8>
15+
// CHECK: %[[ZERO:.*]] = hw.constant 0 : i16
16+
// CHECK-NEXT: %[[PADDING:.*]] = hw.bitcast %[[ZERO]] : (i16) -> !hw.array<2xi8>
17+
// CHECK-NEXT: return %[[PADDING]] : !hw.array<2xi8>
18+
func.func @negative_low_i32_min_array_slice(%arg0: !moore.array<4 x !moore.i8>) -> !moore.array<2 x !moore.i8> {
19+
%0 = moore.extract %arg0 from -2147483648 : !moore.array<4 x !moore.i8> -> !moore.array<2 x !moore.i8>
20+
return %0 : !moore.array<2 x !moore.i8>
21+
}
22+
23+
// CHECK-LABEL: func.func @negative_low_i32_min_uarray_slice
24+
// CHECK-SAME: (%arg0: !hw.array<4xi8>) -> !hw.array<2xi8>
25+
// CHECK: %[[ZERO:.*]] = hw.constant 0 : i16
26+
// CHECK-NEXT: %[[PADDING:.*]] = hw.bitcast %[[ZERO]] : (i16) -> !hw.array<2xi8>
27+
// CHECK-NEXT: return %[[PADDING]] : !hw.array<2xi8>
28+
func.func @negative_low_i32_min_uarray_slice(%arg0: !moore.uarray<4 x !moore.i8>) -> !moore.uarray<2 x !moore.i8> {
29+
%0 = moore.extract %arg0 from -2147483648 : !moore.uarray<4 x !moore.i8> -> !moore.uarray<2 x !moore.i8>
30+
return %0 : !moore.uarray<2 x !moore.i8>
31+
}
32+
33+
// CHECK-LABEL: func.func @negative_low_partial_array_slice
34+
// CHECK-SAME: (%arg0: !hw.array<4xi8>) -> !hw.array<3xi8>
35+
// CHECK: %[[ZERO:.*]] = hw.constant 0 : i8
36+
// CHECK-NEXT: %[[PADDING:.*]] = hw.bitcast %[[ZERO]] : (i8) -> !hw.array<1xi8>
37+
// CHECK-NEXT: %[[LOW:.*]] = hw.constant 0 : i2
38+
// CHECK-NEXT: %[[SLICE:.*]] = hw.array_slice %arg0[%[[LOW]]] : (!hw.array<4xi8>) -> !hw.array<2xi8>
39+
// CHECK-NEXT: %[[RESULT:.*]] = hw.array_concat %[[PADDING]], %[[SLICE]] : !hw.array<1xi8>, !hw.array<2xi8>
40+
// CHECK-NEXT: return %[[RESULT]] : !hw.array<3xi8>
41+
func.func @negative_low_partial_array_slice(%arg0: !moore.array<4 x !moore.i8>) -> !moore.array<3 x !moore.i8> {
42+
%0 = moore.extract %arg0 from -1 : !moore.array<4 x !moore.i8> -> !moore.array<3 x !moore.i8>
43+
return %0 : !moore.array<3 x !moore.i8>
44+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// RUN: circt-opt --convert-moore-to-core %s | FileCheck %s
2+
3+
// CHECK-LABEL: func.func @zero_packed_array_slice
4+
// CHECK-NOT: hw.array_concat
5+
// CHECK: %[[ZERO:.*]] = hw.constant 0 : i0
6+
// CHECK-NEXT: %[[ARR:.*]] = hw.bitcast %[[ZERO]] : (i0) -> !hw.array<0xi8>
7+
// CHECK-NEXT: return %[[ARR]] : !hw.array<0xi8>
8+
func.func @zero_packed_array_slice(%arg0: !moore.array<0 x !moore.i8>) -> !moore.array<0 x !moore.i8> {
9+
%0 = moore.extract %arg0 from 0 : !moore.array<0 x !moore.i8> -> !moore.array<0 x !moore.i8>
10+
return %0 : !moore.array<0 x !moore.i8>
11+
}
12+
13+
// CHECK-LABEL: func.func @zero_unpacked_array_slice
14+
// CHECK-NOT: hw.array_concat
15+
// CHECK: %[[ZERO:.*]] = hw.constant 0 : i0
16+
// CHECK-NEXT: %[[ARR:.*]] = hw.bitcast %[[ZERO]] : (i0) -> !hw.array<0xi8>
17+
// CHECK-NEXT: return %[[ARR]] : !hw.array<0xi8>
18+
func.func @zero_unpacked_array_slice(%arg0: !moore.uarray<0 x !moore.i8>) -> !moore.uarray<0 x !moore.i8> {
19+
%0 = moore.extract %arg0 from 0 : !moore.uarray<0 x !moore.i8> -> !moore.uarray<0 x !moore.i8>
20+
return %0 : !moore.uarray<0 x !moore.i8>
21+
}

0 commit comments

Comments
 (0)