From 806147f2e09b609c773d34a4b1dc3a6272379427 Mon Sep 17 00:00:00 2001 From: Kirill Yansitov <36601354+YazZz1k@users.noreply.github.com> Date: Fri, 2 Feb 2024 04:51:21 +0300 Subject: [PATCH] [CIR][Lowering] Support conversion of cir.zero to dense consts (#413) 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. --- .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 39 +++++++++++++++++++ clang/test/CIR/Lowering/const.cir | 21 +++++++++- 2 files changed, 58 insertions(+), 2 deletions(-) diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index 0dfe1bcf29cb..ce5063285e0d 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -969,6 +969,39 @@ convertStringAttrToDenseElementsAttr(mlir::cir::ConstArrayAttr attr, llvm::ArrayRef(values)); } +template StorageTy getZeroInitFromType(mlir::Type Ty); + +template <> mlir::APInt getZeroInitFromType(mlir::Type Ty) { + assert(Ty.isa() && "expected int type"); + auto IntTy = Ty.cast(); + 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 x 1> +// it returns !s32i as return value and stores 3 to elemQuantity. +mlir::Type getNestedTypeAndElemQuantity(mlir::Type Ty, unsigned &elemQuantity) { + assert(Ty.isa() && "expected ArrayType"); + + elemQuantity = 1; + mlir::Type nestTy = Ty; + while (auto ArrTy = nestTy.dyn_cast()) { + nestTy = ArrTy.getEltType(); + elemQuantity *= ArrTy.getSize(); + } + + return nestTy; +} + template void convertToDenseElementsAttrImpl(mlir::cir::ConstArrayAttr attr, llvm::SmallVectorImpl &values) { @@ -979,6 +1012,12 @@ void convertToDenseElementsAttrImpl(mlir::cir::ConstArrayAttr attr, } else if (auto subArrayAttr = eltAttr.dyn_cast()) { convertToDenseElementsAttrImpl(subArrayAttr, values); + } else if (auto zeroAttr = eltAttr.dyn_cast()) { + unsigned numStoredZeros = 0; + auto nestTy = + getNestedTypeAndElemQuantity(zeroAttr.getType(), numStoredZeros); + values.insert(values.end(), numStoredZeros, + getZeroInitFromType(nestTy)); } else { llvm_unreachable("unknown element in ConstArrayAttr"); } diff --git a/clang/test/CIR/Lowering/const.cir b/clang/test/CIR/Lowering/const.cir index deca881e2e6a..7d0c63f8ccbb 100644 --- a/clang/test/CIR/Lowering/const.cir +++ b/clang/test/CIR/Lowering/const.cir @@ -1,10 +1,10 @@ // RUN: cir-opt %s -cir-to-llvm -o %t.mlir // RUN: FileCheck --input-file=%t.mlir %s -!s32i = !cir.int !s8i = !cir.int +!s32i = !cir.int +!s64i = !cir.int !ty_22anon2E122 = !cir.struct, !cir.int} #cir.record.decl.ast> - module { cir.func @testConstArrInit() { %0 = cir.const(#cir.const_array<"string\00" : !cir.array> : !cir.array) : !cir.array @@ -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, #cir.zero : !cir.array]> : !cir.array x 2>) : !cir.array x 2> + %1 = cir.const(#cir.const_array<[#cir.const_array<[#cir.int<1> : !s64i]> : !cir.array, #cir.zero : !cir.array]> : !cir.array x 2>) : !cir.array x 2> + %2 = cir.const(#cir.const_array<[#cir.const_array<[1.000000e+00 : f32]> : !cir.array, #cir.zero : !cir.array]> : !cir.array x 2>) : !cir.array x 2> + %3 = cir.const(#cir.const_array<[#cir.const_array<[1.000000e+00]> : !cir.array, #cir.zero : !cir.array]> : !cir.array x 2>) : !cir.array 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]> : !cir.array x 1>, #cir.zero : !cir.array x 1>]> : !cir.array x 1> x 2>) : !cir.array 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, cir.ptr >, ["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) : !cir.array