@@ -72,6 +72,55 @@ using namespace llvm;
72
72
73
73
namespace cir {
74
74
75
+ // / Given a type convertor and a data layout, convert the given type to a type
76
+ // / that is suitable for memory operations. For example, this can be used to
77
+ // / lower cir.bool accesses to i8.
78
+ static mlir::Type convertTypeForMemory (const mlir::TypeConverter &converter,
79
+ mlir::Type type) {
80
+ // TODO(cir): Handle other types similarly to clang's codegen
81
+ // convertTypeForMemory
82
+ if (isa<cir::BoolType>(type)) {
83
+ // TODO: Use datalayout to get the size of bool
84
+ return mlir::IntegerType::get (type.getContext (), 8 );
85
+ }
86
+
87
+ return converter.convertType (type);
88
+ }
89
+
90
+ // Create a reference to an MLIR type. This creates a memref of the element type
91
+ // with the requested shape except when it is a tensor because it represents a
92
+ // !cir.array which has to be blessed as a memref of the tensor element type
93
+ // instead.
94
+ static mlir::MemRefType convertToReferenceType (ArrayRef<int64_t > shape,
95
+ mlir::Type elementType) {
96
+ if (auto t = mlir::dyn_cast<mlir::TensorType>(elementType))
97
+ return mlir::MemRefType::get (t.getShape (), t.getElementType ());
98
+ return mlir::MemRefType::get (shape, elementType);
99
+ }
100
+
101
+ // Lower a cir.array either as a memref when it has a reference semantics or as
102
+ // a tensor when it has a value semantics (like inside a struct or union).
103
+ mlir::Type lowerArrayType (cir::ArrayType type, bool hasValueSemantics,
104
+ mlir::TypeConverter &converter) {
105
+ SmallVector<int64_t > shape;
106
+ mlir::Type curType = type;
107
+ while (auto arrayType = dyn_cast<cir::ArrayType>(curType)) {
108
+ shape.push_back (arrayType.getSize ());
109
+ curType = arrayType.getEltType ();
110
+ }
111
+ auto elementType = convertTypeForMemory (converter, curType);
112
+ // FIXME: The element type might not be converted.
113
+ if (!elementType)
114
+ return nullptr ;
115
+ // Arrays in C/C++ have a value semantics when in a struct, so use
116
+ // a tensor.
117
+ // TODO: tensors cannot contain most built-in types like memref.
118
+ if (hasValueSemantics)
119
+ return mlir::RankedTensorType::get (shape, elementType);
120
+ // Otherwise, go to a memref.
121
+ return convertToReferenceType (shape, elementType);
122
+ }
123
+
75
124
class CIRReturnLowering : public mlir ::OpConversionPattern<cir::ReturnOp> {
76
125
public:
77
126
using OpConversionPattern<cir::ReturnOp>::OpConversionPattern;
@@ -124,21 +173,6 @@ class CIRCallOpLowering : public mlir::OpConversionPattern<cir::CallOp> {
124
173
}
125
174
};
126
175
127
- // / Given a type convertor and a data layout, convert the given type to a type
128
- // / that is suitable for memory operations. For example, this can be used to
129
- // / lower cir.bool accesses to i8.
130
- static mlir::Type convertTypeForMemory (const mlir::TypeConverter &converter,
131
- mlir::Type type) {
132
- // TODO(cir): Handle other types similarly to clang's codegen
133
- // convertTypeForMemory
134
- if (isa<cir::BoolType>(type)) {
135
- // TODO: Use datalayout to get the size of bool
136
- return mlir::IntegerType::get (type.getContext (), 8 );
137
- }
138
-
139
- return converter.convertType (type);
140
- }
141
-
142
176
// / Emits the value from memory as expected by its users. Should be called when
143
177
// / the memory represetnation of a CIR type is not equal to its scalar
144
178
// / representation.
@@ -187,14 +221,7 @@ class CIRAllocaOpLowering : public mlir::OpConversionPattern<cir::AllocaOp> {
187
221
if (!mlirType)
188
222
return mlir::LogicalResult::failure ();
189
223
190
- auto memreftype = mlir::dyn_cast<mlir::MemRefType>(mlirType);
191
- if (memreftype && mlir::isa<cir::ArrayType>(adaptor.getAllocaType ())) {
192
- // if the type is an array,
193
- // we don't need to wrap with memref.
194
- } else {
195
- memreftype = mlir::MemRefType::get ({}, mlirType);
196
- }
197
-
224
+ auto memreftype = convertToReferenceType ({}, mlirType);
198
225
rewriter.replaceOpWithNewOp <mlir::memref::AllocaOp>(op, memreftype,
199
226
op.getAlignmentAttr ());
200
227
return mlir::LogicalResult::success ();
@@ -336,7 +363,7 @@ class CIRGetMemberOpLowering
336
363
auto flattenedMemRef = mlir::MemRefType::get (
337
364
linearizedSize, mlir::IntegerType::get (getContext (), 8 ));
338
365
// Use a special cast because normal memref cast cannot do such an extreme
339
- // cast.
366
+ // cast. Could be an UnrealizedCastOp instead?
340
367
auto bytesMemRef = rewriter.create <mlir::named_tuple::CastOp>(
341
368
op.getLoc (), mlir::TypeRange{flattenedMemRef},
342
369
mlir::ValueRange{adaptor.getAddr ()});
@@ -1062,7 +1089,7 @@ class CIRGlobalOpLowering : public mlir::OpConversionPattern<cir::GlobalOp> {
1062
1089
return mlir::failure ();
1063
1090
auto memrefType = dyn_cast<mlir::MemRefType>(convertedType);
1064
1091
if (!memrefType)
1065
- memrefType = mlir::MemRefType::get ({}, convertedType);
1092
+ memrefType = convertToReferenceType ({}, convertedType);
1066
1093
// Add an optional alignment to the global memref.
1067
1094
mlir::IntegerAttr memrefAlignment =
1068
1095
op.getAlignment ()
@@ -1475,27 +1502,6 @@ void populateCIRToMLIRConversionPatterns(mlir::RewritePatternSet &patterns,
1475
1502
cirDataLayout);
1476
1503
}
1477
1504
1478
- // Lower a cir.array either as a memref when it has a reference semantics or as
1479
- // a tensor when it has a value semantics (like inside a struct or union)
1480
- mlir::Type lowerArrayType (cir::ArrayType type, bool hasValueSemantics,
1481
- mlir::TypeConverter &converter) {
1482
- SmallVector<int64_t > shape;
1483
- mlir::Type curType = type;
1484
- while (auto arrayType = dyn_cast<cir::ArrayType>(curType)) {
1485
- shape.push_back (arrayType.getSize ());
1486
- curType = arrayType.getEltType ();
1487
- }
1488
- auto elementType = convertTypeForMemory (converter, curType);
1489
- // FIXME: The element type might not be converted
1490
- if (!elementType)
1491
- return nullptr ;
1492
- // Arrays in C/C++ have a reference semantics when not in a struct, so use
1493
- // a memref
1494
- if (hasValueSemantics)
1495
- return mlir::RankedTensorType::get (shape, elementType);
1496
- return mlir::MemRefType::get (shape, elementType);
1497
- }
1498
-
1499
1505
mlir::TypeConverter prepareTypeConverter (mlir::DataLayout &dataLayout) {
1500
1506
mlir::TypeConverter converter;
1501
1507
converter.addConversion ([&](cir::PointerType type) -> mlir::Type {
@@ -1504,12 +1510,8 @@ mlir::TypeConverter prepareTypeConverter(mlir::DataLayout &dataLayout) {
1504
1510
// converted (e.g. struct)
1505
1511
if (!ty)
1506
1512
return nullptr ;
1507
- if (isa<cir::ArrayType>(type.getPointee ()))
1508
- // An array is already lowered as a memref with reference semantics by
1509
- // default
1510
- return ty;
1511
1513
// Each level of pointer becomes a level of memref
1512
- return mlir::MemRefType::get ({}, ty);
1514
+ return convertToReferenceType ({}, ty);
1513
1515
});
1514
1516
converter.addConversion (
1515
1517
[&](mlir::IntegerType type) -> mlir::Type { return type; });
@@ -1547,23 +1549,15 @@ mlir::TypeConverter prepareTypeConverter(mlir::DataLayout &dataLayout) {
1547
1549
return mlir::BFloat16Type::get (type.getContext ());
1548
1550
});
1549
1551
converter.addConversion ([&](cir::ArrayType type) -> mlir::Type {
1550
- // Assume we are not in a class/struct/union context with value semantics,
1551
- // so lower it as a memref to provide reference semantics.
1552
- return lowerArrayType (type, /* hasValueSemantics */ false , converter);
1552
+ // Assume we are in a class/struct/union context with value semantics,
1553
+ // so lower it as a tensor to provide value semantics.
1554
+ return lowerArrayType (type, /* hasValueSemantics */ true , converter);
1553
1555
});
1554
1556
converter.addConversion ([&](cir::VectorType type) -> mlir::Type {
1555
1557
auto ty = converter.convertType (type.getEltType ());
1556
1558
return mlir::VectorType::get (type.getSize (), ty);
1557
1559
});
1558
1560
converter.addConversion ([&](cir::StructType type) -> mlir::Type {
1559
- auto convertWithValueSemanticsArray = [&](mlir::Type t) {
1560
- if (mlir::isa<cir::ArrayType>(t))
1561
- // Inside a class/struct/union, an array has value semantics and is
1562
- // lowered as a tensor.
1563
- return lowerArrayType (mlir::cast<cir::ArrayType>(t),
1564
- /* hasValueSemantics */ true , converter);
1565
- return converter.convertType (t);
1566
- };
1567
1561
// FIXME(cir): create separate unions, struct, and classes types.
1568
1562
// Convert struct members.
1569
1563
llvm::SmallVector<mlir::Type> mlirMembers;
@@ -1572,13 +1566,13 @@ mlir::TypeConverter prepareTypeConverter(mlir::DataLayout &dataLayout) {
1572
1566
// TODO(cir): This should be properly validated.
1573
1567
case cir::StructType::Struct:
1574
1568
for (auto ty : type.getMembers ())
1575
- mlirMembers.push_back (convertWithValueSemanticsArray (ty));
1569
+ mlirMembers.push_back (converter. convertType (ty));
1576
1570
break ;
1577
1571
// Unions are lowered as only the largest member.
1578
1572
case cir::StructType::Union: {
1579
1573
auto largestMember = type.getLargestMember (dataLayout);
1580
1574
if (largestMember)
1581
- mlirMembers.push_back (convertWithValueSemanticsArray (largestMember));
1575
+ mlirMembers.push_back (converter. convertType (largestMember));
1582
1576
break ;
1583
1577
}
1584
1578
}
0 commit comments