Skip to content

Commit

Permalink
[CIR][Lowering] Support conversion of cir.zero to dense consts (llvm#413
Browse files Browse the repository at this point in the history
)

Compiling the given c-code

```
void foo() {
  int      i [2][1] = { { 1 }, { 0 } };
  long int li[2][1] = { { 1 }, { 0 } };
  float    fl[2][1] = { { 1 }, { 0 } };
  double   d [2][1] = { { 1 }, { 0 } };
}
```

leads to compilation error

```
unknown element in ConstArrayAttr
UNREACHABLE executed at /home/huawei/cir/repo/van/llvm-project/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp:951!
```

PR implements conversion the cir.zero attr to dense constant and fixed
this error.
  • Loading branch information
YazZz1k authored and lanza committed Oct 12, 2024
1 parent e4acd04 commit c1dd99f
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 2 deletions.
39 changes: 39 additions & 0 deletions clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -969,6 +969,39 @@ convertStringAttrToDenseElementsAttr(mlir::cir::ConstArrayAttr attr,
llvm::ArrayRef(values));
}

template <typename StorageTy> StorageTy getZeroInitFromType(mlir::Type Ty);

template <> mlir::APInt getZeroInitFromType(mlir::Type Ty) {
assert(Ty.isa<mlir::cir::IntType>() && "expected int type");
auto IntTy = Ty.cast<mlir::cir::IntType>();
return mlir::APInt::getZero(IntTy.getWidth());
}

template <> mlir::APFloat getZeroInitFromType(mlir::Type Ty) {
assert((Ty.isF32() || Ty.isF64()) && "only float and double supported");
if (Ty.isF32())
return mlir::APFloat(0.f);
if (Ty.isF64())
return mlir::APFloat(0.0);
llvm_unreachable("NYI");
}

// return the nested type and quiantity of elements for cir.array type.
// e.g: for !cir.array<!cir.array<!s32i x 3> x 1>
// it returns !s32i as return value and stores 3 to elemQuantity.
mlir::Type getNestedTypeAndElemQuantity(mlir::Type Ty, unsigned &elemQuantity) {
assert(Ty.isa<mlir::cir::ArrayType>() && "expected ArrayType");

elemQuantity = 1;
mlir::Type nestTy = Ty;
while (auto ArrTy = nestTy.dyn_cast<mlir::cir::ArrayType>()) {
nestTy = ArrTy.getEltType();
elemQuantity *= ArrTy.getSize();
}

return nestTy;
}

template <typename AttrTy, typename StorageTy>
void convertToDenseElementsAttrImpl(mlir::cir::ConstArrayAttr attr,
llvm::SmallVectorImpl<StorageTy> &values) {
Expand All @@ -979,6 +1012,12 @@ void convertToDenseElementsAttrImpl(mlir::cir::ConstArrayAttr attr,
} else if (auto subArrayAttr =
eltAttr.dyn_cast<mlir::cir::ConstArrayAttr>()) {
convertToDenseElementsAttrImpl<AttrTy>(subArrayAttr, values);
} else if (auto zeroAttr = eltAttr.dyn_cast<mlir::cir::ZeroAttr>()) {
unsigned numStoredZeros = 0;
auto nestTy =
getNestedTypeAndElemQuantity(zeroAttr.getType(), numStoredZeros);
values.insert(values.end(), numStoredZeros,
getZeroInitFromType<StorageTy>(nestTy));
} else {
llvm_unreachable("unknown element in ConstArrayAttr");
}
Expand Down
21 changes: 19 additions & 2 deletions clang/test/CIR/Lowering/const.cir
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
// RUN: cir-opt %s -cir-to-llvm -o %t.mlir
// RUN: FileCheck --input-file=%t.mlir %s

!s32i = !cir.int<s, 32>
!s8i = !cir.int<s, 8>
!s32i = !cir.int<s, 32>
!s64i = !cir.int<s, 64>
!ty_22anon2E122 = !cir.struct<struct "anon.1" {!cir.int<s, 32>, !cir.int<s, 32>} #cir.record.decl.ast>

module {
cir.func @testConstArrInit() {
%0 = cir.const(#cir.const_array<"string\00" : !cir.array<!s8i x 7>> : !cir.array<!s8i x 7>) : !cir.array<!s8i x 7>
Expand All @@ -18,6 +18,23 @@ module {
cir.return
}

cir.func @testConvertConstArrayToDenseConst() {
%0 = cir.const(#cir.const_array<[#cir.const_array<[#cir.int<1> : !s32i]> : !cir.array<!s32i x 1>, #cir.zero : !cir.array<!s32i x 1>]> : !cir.array<!cir.array<!s32i x 1> x 2>) : !cir.array<!cir.array<!s32i x 1> x 2>
%1 = cir.const(#cir.const_array<[#cir.const_array<[#cir.int<1> : !s64i]> : !cir.array<!s64i x 1>, #cir.zero : !cir.array<!s64i x 1>]> : !cir.array<!cir.array<!s64i x 1> x 2>) : !cir.array<!cir.array<!s64i x 1> x 2>
%2 = cir.const(#cir.const_array<[#cir.const_array<[1.000000e+00 : f32]> : !cir.array<f32 x 1>, #cir.zero : !cir.array<f32 x 1>]> : !cir.array<!cir.array<f32 x 1> x 2>) : !cir.array<!cir.array<f32 x 1> x 2>
%3 = cir.const(#cir.const_array<[#cir.const_array<[1.000000e+00]> : !cir.array<f64 x 1>, #cir.zero : !cir.array<f64 x 1>]> : !cir.array<!cir.array<f64 x 1> x 2>) : !cir.array<!cir.array<f64 x 1> x 2>
%4 = cir.const(#cir.const_array<[#cir.const_array<[#cir.const_array<[#cir.int<1> : !s32i, #cir.int<1> : !s32i, #cir.int<1> : !s32i]> : !cir.array<!s32i x 3>]> : !cir.array<!cir.array<!s32i x 3> x 1>, #cir.zero : !cir.array<!cir.array<!s32i x 3> x 1>]> : !cir.array<!cir.array<!cir.array<!s32i x 3> x 1> x 2>) : !cir.array<!cir.array<!cir.array<!s32i x 3> x 1> x 2>

cir.return
}
// CHECK: llvm.func @testConvertConstArrayToDenseConst()
// CHECK: {{%.*}} = llvm.mlir.constant(dense<{{\[\[}}1], [0{{\]\]}}> : tensor<2x1xi32>) : !llvm.array<2 x array<1 x i32>>
// CHECK: {{%.*}} = llvm.mlir.constant(dense<{{\[\[}}1], [0{{\]\]}}> : tensor<2x1xi64>) : !llvm.array<2 x array<1 x i64>>
// CHECK: {{%.*}} = llvm.mlir.constant(dense<{{\[\[}}1.000000e+00], [0.000000e+00{{\]\]}}> : tensor<2x1xf32>) : !llvm.array<2 x array<1 x f32>>
// CHECK: {{%.*}} = llvm.mlir.constant(dense<{{\[\[}}1.000000e+00], [0.000000e+00{{\]\]}}> : tensor<2x1xf64>) : !llvm.array<2 x array<1 x f64>>
// CHECK: {{%.*}} = llvm.mlir.constant(dense<{{\[\[\[}}1, 1, 1{{\]\]}}, {{\[\[}}0, 0, 0{{\]\]\]}}> : tensor<2x1x3xi32>) : !llvm.array<2 x array<1 x array<3 x i32>>>
// CHECK: llvm.return

cir.func @testConstArrayOfStructs() {
%0 = cir.alloca !cir.array<!ty_22anon2E122 x 1>, cir.ptr <!cir.array<!ty_22anon2E122 x 1>>, ["a"] {alignment = 4 : i64}
%1 = cir.const(#cir.const_array<[#cir.const_struct<{#cir.int<0> : !s32i, #cir.int<1> : !s32i}> : !ty_22anon2E122]> : !cir.array<!ty_22anon2E122 x 1>) : !cir.array<!ty_22anon2E122 x 1>
Expand Down

0 comments on commit c1dd99f

Please sign in to comment.