From b911c2038eeaf0d63ba790ccaad07e6102aef369 Mon Sep 17 00:00:00 2001 From: Guojin He Date: Mon, 2 Dec 2024 23:34:46 -0500 Subject: [PATCH 1/3] [CIR][CIRGen][Builtin][Neon] Lower neon_vqmovns_s32 and add CIR PoisonOp --- clang/include/clang/CIR/Dialect/IR/CIROps.td | 24 ++++++++++++ .../lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp | 37 ++++++++++++++++++- clang/test/CIR/CodeGen/AArch64/neon.c | 26 +++++++++---- clang/test/CIR/IR/cir-ops.cir | 10 +++++ 4 files changed, 87 insertions(+), 10 deletions(-) diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index dcb433aedaaa..21aaa22df2d4 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -379,6 +379,30 @@ def PtrStrideOp : CIR_Op<"ptr_stride", let hasVerifier = 0; } +//===----------------------------------------------------------------------===// +// PoisonOp +//===----------------------------------------------------------------------===// +def PoisonOp : CIR_Op<"poison", [Pure]> { + let summary = "Creates a poison value of CIR type"; + + let description = [{ + Unlike LLVM IR, MLIR does not have first-class poison values. Such values + must be created as SSA values using a dialect operation. This operation + has no operands or attributes. It creates a poison value of the specified + CIR type. + + Example: + + ```mlir + %0 = cir.poison : !cir.vector + ``` + }]; + + let results = (outs CIR_AnyType:$res); + let assemblyFormat = "attr-dict `:` type($res)"; + let llvmOp = "PoisonOp"; +} + //===----------------------------------------------------------------------===// // ConstantOp //===----------------------------------------------------------------------===// diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp index 01269b92a45d..a3b413c75ec4 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp @@ -2265,6 +2265,30 @@ static mlir::Value emitNeonRShiftImm(CIRGenFunction &cgf, mlir::Value shiftVec, false /* right shift */); } +/// Vectorize value, usually for argument of a neon SISD intrinsic call. +static void vecExtendIntValue(CIRGenFunction &cgf, cir::VectorType argVTy, + mlir::Value &arg, mlir::Location loc) { + CIRGenBuilderTy &builder = cgf.getBuilder(); + cir::IntType eltTy = mlir::dyn_cast(argVTy.getEltType()); + assert(mlir::isa(arg.getType()) && eltTy); + // The constant argument to an _n_ intrinsic always has Int32Ty, so truncate + // it before inserting. + arg = builder.createIntCast(arg, eltTy); + arg = builder.create( + loc, builder.create(loc, argVTy), arg, + builder.getConstInt(loc, cgf.SizeTy, 0)); +} + +/// Reduce vector type value to scalar, usually for result of a +/// neon SISD intrinsic call +static mlir::Value vecReduceIntValue(CIRGenFunction &cgf, mlir::Value val, + mlir::Location loc) { + CIRGenBuilderTy &builder = cgf.getBuilder(); + assert(mlir::isa(val.getType())); + return builder.create( + loc, val, builder.getConstInt(loc, cgf.SizeTy, 0)); +} + mlir::Value emitNeonCall(CIRGenBuilderTy &builder, llvm::SmallVector argTypes, llvm::SmallVectorImpl &args, @@ -2853,8 +2877,17 @@ static mlir::Value emitCommonNeonSISDBuiltinExpr( llvm_unreachable(" neon_vqmovnh_s16 NYI "); case NEON::BI__builtin_neon_vqmovnh_u16: llvm_unreachable(" neon_vqmovnh_u16 NYI "); - case NEON::BI__builtin_neon_vqmovns_s32: - llvm_unreachable(" neon_vqmovns_s32 NYI "); + case NEON::BI__builtin_neon_vqmovns_s32: { + mlir::Location loc = cgf.getLoc(expr->getExprLoc()); + cir::VectorType argVecTy = + cir::VectorType::get(&(cgf.getMLIRContext()), cgf.SInt32Ty, 4); + cir::VectorType resVecTy = + cir::VectorType::get(&(cgf.getMLIRContext()), cgf.SInt16Ty, 4); + vecExtendIntValue(cgf, argVecTy, ops[0], loc); + mlir::Value result = emitNeonCall(builder, {argVecTy}, ops, + "aarch64.neon.sqxtn", resVecTy, loc); + return vecReduceIntValue(cgf, result, loc); + } case NEON::BI__builtin_neon_vqmovns_u32: llvm_unreachable(" neon_vqmovns_u32 NYI "); case NEON::BI__builtin_neon_vqmovund_s64: diff --git a/clang/test/CIR/CodeGen/AArch64/neon.c b/clang/test/CIR/CodeGen/AArch64/neon.c index 3ddaea58f163..c155be9048f2 100644 --- a/clang/test/CIR/CodeGen/AArch64/neon.c +++ b/clang/test/CIR/CodeGen/AArch64/neon.c @@ -14611,14 +14611,24 @@ void test_vst1q_s64(int64_t *a, int64x2_t b) { // return (int8_t)vqmovnh_s16(a); // } -// NYI-LABEL: @test_vqmovns_s32( -// NYI: [[TMP0:%.*]] = insertelement <4 x i32> poison, i32 %a, i64 0 -// NYI: [[VQMOVNS_S32_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.sqxtn.v4i16(<4 x i32> [[TMP0]]) -// NYI: [[TMP1:%.*]] = extractelement <4 x i16> [[VQMOVNS_S32_I]], i64 0 -// NYI: ret i16 [[TMP1]] -// int16_t test_vqmovns_s32(int32_t a) { -// return (int16_t)vqmovns_s32(a); -// } +int16_t test_vqmovns_s32(int32_t a) { + return (int16_t)vqmovns_s32(a); + + // CIR-LABEL: vqmovns_s32 + // CIR: [[A:%.*]] = cir.load {{.*}} : !cir.ptr, !s32i + // CIR-NEXT: [[POISON:%.*]] = cir.poison : !cir.vector + // CIR-NEXT: [[VQMOVNS_S32_ZERO1:%.*]] = cir.const #cir.int<0> : !u64i + // CIR-NEXT: [[TMP0:%.*]] = cir.vec.insert [[A]], [[POISON]][[[VQMOVNS_S32_ZERO1]] : !u64i] : !cir.vector + // CIR: [[VQMOVNS_S32_I:%.*]] = cir.llvm.intrinsic "aarch64.neon.sqxtn" [[TMP0]] : (!cir.vector) -> !cir.vector + // CIR: [[VQMOVNS_S32_ZERO2:%.*]] = cir.const #cir.int<0> : !u64i + // CIR: [[TMP1:%.*]] = cir.vec.extract [[VQMOVNS_S32_I]][[[VQMOVNS_S32_ZERO2]] : !u64i] : !cir.vector loc(#loc4503) + + // LLVM: {{.*}}@test_vqmovns_s32(i32{{.*}}[[a:%.*]]) + // LLVM: [[TMP0:%.*]] = insertelement <4 x i32> poison, i32 [[a]], i64 0 + // LLVM: [[VQMOVNS_S32_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.sqxtn.v4i16(<4 x i32> [[TMP0]]) + // LLVM: [[TMP1:%.*]] = extractelement <4 x i16> [[VQMOVNS_S32_I]], i64 0 + // LLVM: ret i16 [[TMP1]] +} // NYI-LABEL: @test_vqmovnd_s64( // NYI: [[VQMOVND_S64_I:%.*]] = call i32 @llvm.aarch64.neon.scalar.sqxtn.i32.i64(i64 %a) diff --git a/clang/test/CIR/IR/cir-ops.cir b/clang/test/CIR/IR/cir-ops.cir index 2c2d137ab92e..7417f71873c3 100644 --- a/clang/test/CIR/IR/cir-ops.cir +++ b/clang/test/CIR/IR/cir-ops.cir @@ -65,6 +65,11 @@ module { %3 = cir.shift(left, %1 : !cir.vector, %2 : !cir.vector) -> !cir.vector cir.return } + + cir.func @poisonvalue() { + %0 = cir.poison : !cir.vector + cir.return + } } // CHECK: module { @@ -118,4 +123,9 @@ module { // CHECK-NEXT: cir.return // CHECK-NEXT: } +// CHECK: cir.func @poisonvalue() { +// CHECK-NEXT: %0 = cir.poison : !cir.vector +// CHECK-NEXT: cir.return +// CHECK-NEXT: } + // CHECK: } From 06a8d183a7f5ca4b48f565ab1c717a57c2596f34 Mon Sep 17 00:00:00 2001 From: Guojin He Date: Tue, 3 Dec 2024 09:57:42 -0500 Subject: [PATCH 2/3] Fix code to make generated CIR consistent on different OS --- clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp | 4 ++-- clang/test/CIR/CodeGen/AArch64/neon.c | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp index a3b413c75ec4..b86ec5fd9be0 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp @@ -2274,9 +2274,9 @@ static void vecExtendIntValue(CIRGenFunction &cgf, cir::VectorType argVTy, // The constant argument to an _n_ intrinsic always has Int32Ty, so truncate // it before inserting. arg = builder.createIntCast(arg, eltTy); + mlir::Value zero = builder.getConstInt(loc, cgf.SizeTy, 0); arg = builder.create( - loc, builder.create(loc, argVTy), arg, - builder.getConstInt(loc, cgf.SizeTy, 0)); + loc, builder.create(loc, argVTy), arg, zero); } /// Reduce vector type value to scalar, usually for result of a diff --git a/clang/test/CIR/CodeGen/AArch64/neon.c b/clang/test/CIR/CodeGen/AArch64/neon.c index c155be9048f2..e6b706e9ef35 100644 --- a/clang/test/CIR/CodeGen/AArch64/neon.c +++ b/clang/test/CIR/CodeGen/AArch64/neon.c @@ -14616,9 +14616,9 @@ int16_t test_vqmovns_s32(int32_t a) { // CIR-LABEL: vqmovns_s32 // CIR: [[A:%.*]] = cir.load {{.*}} : !cir.ptr, !s32i - // CIR-NEXT: [[POISON:%.*]] = cir.poison : !cir.vector - // CIR-NEXT: [[VQMOVNS_S32_ZERO1:%.*]] = cir.const #cir.int<0> : !u64i - // CIR-NEXT: [[TMP0:%.*]] = cir.vec.insert [[A]], [[POISON]][[[VQMOVNS_S32_ZERO1]] : !u64i] : !cir.vector + // CIR: [[VQMOVNS_S32_ZERO1:%.*]] = cir.const #cir.int<0> : !u64i + // CIR: [[POISON:%.*]] = cir.poison : !cir.vector + // CIR: [[TMP0:%.*]] = cir.vec.insert [[A]], [[POISON]][[[VQMOVNS_S32_ZERO1]] : !u64i] : !cir.vector // CIR: [[VQMOVNS_S32_I:%.*]] = cir.llvm.intrinsic "aarch64.neon.sqxtn" [[TMP0]] : (!cir.vector) -> !cir.vector // CIR: [[VQMOVNS_S32_ZERO2:%.*]] = cir.const #cir.int<0> : !u64i // CIR: [[TMP1:%.*]] = cir.vec.extract [[VQMOVNS_S32_I]][[[VQMOVNS_S32_ZERO2]] : !u64i] : !cir.vector loc(#loc4503) From e6e5e25d38844a72d2fd08d09ecc24b4d961cee0 Mon Sep 17 00:00:00 2001 From: Guojin He Date: Tue, 10 Dec 2024 09:18:31 -0500 Subject: [PATCH 3/3] Use PoisonAttr --- .../include/clang/CIR/Dialect/IR/CIRAttrs.td | 15 +++++++++ clang/include/clang/CIR/Dialect/IR/CIROps.td | 24 -------------- .../lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp | 4 ++- clang/lib/CIR/Dialect/IR/CIRDialect.cpp | 6 ++++ .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 33 +++++++++++++++++-- clang/test/CIR/CodeGen/AArch64/neon.c | 7 ++-- clang/test/CIR/IR/cir-ops.cir | 10 ------ clang/test/CIR/IR/invalid.cir | 6 ++++ clang/test/CIR/Lowering/const.cir | 2 ++ 9 files changed, 66 insertions(+), 41 deletions(-) diff --git a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td index 0cfbf84fa58a..b375b624ccc5 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td +++ b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td @@ -169,6 +169,21 @@ def UndefAttr : CIR_Attr<"Undef", "undef", [TypedAttrInterface]> { let assemblyFormat = [{}]; } +//===----------------------------------------------------------------------===// +// PoisonAttr +//===----------------------------------------------------------------------===// + +def PoisonAttr : CIR_Attr<"Poison", "poison", [TypedAttrInterface]> { + let summary = "Represent an poison constant"; + let description = [{ + The PoisonAttr represents an poison constant, corresponding to LLVM's notion + of poison. + }]; + + let parameters = (ins AttributeSelfTypeParameter<"">:$type); + let assemblyFormat = [{}]; +} + //===----------------------------------------------------------------------===// // ConstArrayAttr //===----------------------------------------------------------------------===// diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index 21aaa22df2d4..dcb433aedaaa 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -379,30 +379,6 @@ def PtrStrideOp : CIR_Op<"ptr_stride", let hasVerifier = 0; } -//===----------------------------------------------------------------------===// -// PoisonOp -//===----------------------------------------------------------------------===// -def PoisonOp : CIR_Op<"poison", [Pure]> { - let summary = "Creates a poison value of CIR type"; - - let description = [{ - Unlike LLVM IR, MLIR does not have first-class poison values. Such values - must be created as SSA values using a dialect operation. This operation - has no operands or attributes. It creates a poison value of the specified - CIR type. - - Example: - - ```mlir - %0 = cir.poison : !cir.vector - ``` - }]; - - let results = (outs CIR_AnyType:$res); - let assemblyFormat = "attr-dict `:` type($res)"; - let llvmOp = "PoisonOp"; -} - //===----------------------------------------------------------------------===// // ConstantOp //===----------------------------------------------------------------------===// diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp index b86ec5fd9be0..33a5a12cd4ba 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp @@ -2275,8 +2275,10 @@ static void vecExtendIntValue(CIRGenFunction &cgf, cir::VectorType argVTy, // it before inserting. arg = builder.createIntCast(arg, eltTy); mlir::Value zero = builder.getConstInt(loc, cgf.SizeTy, 0); + mlir::Value poison = builder.create( + loc, eltTy, builder.getAttr(eltTy)); arg = builder.create( - loc, builder.create(loc, argVTy), arg, zero); + loc, builder.create(loc, argVTy, poison), arg, zero); } /// Reduce vector type value to scalar, usually for result of a diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp index a2b22679296e..d98d75589518 100644 --- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp @@ -389,6 +389,12 @@ static LogicalResult checkConstantTypes(mlir::Operation *op, mlir::Type opType, return op->emitOpError("undef expects non-void type"); } + if (isa(attrType)) { + if (!::mlir::isa(opType)) + return success(); + return op->emitOpError("poison expects non-void type"); + } + if (mlir::isa(attrType)) { if (!mlir::isa(opType)) return op->emitOpError("result type (") diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index 939d92eead41..b81d5e1511d4 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -425,6 +425,16 @@ lowerCirAttrAsValue(mlir::Operation *parentOp, cir::UndefAttr undefAttr, loc, converter->convertType(undefAttr.getType())); } +/// PoisonAttr visitor. +static mlir::Value +lowerCirAttrAsValue(mlir::Operation *parentOp, cir::PoisonAttr poisonAttr, + mlir::ConversionPatternRewriter &rewriter, + const mlir::TypeConverter *converter) { + auto loc = parentOp->getLoc(); + return rewriter.create( + loc, converter->convertType(poisonAttr.getType())); +} + /// ConstStruct visitor. static mlir::Value lowerCirAttrAsValue(mlir::Operation *parentOp, cir::ConstStructAttr constStruct, @@ -644,6 +654,8 @@ mlir::Value lowerCirAttrAsValue(mlir::Operation *parentOp, mlir::Attribute attr, return lowerCirAttrAsValue(parentOp, zeroAttr, rewriter, converter); if (const auto undefAttr = mlir::dyn_cast(attr)) return lowerCirAttrAsValue(parentOp, undefAttr, rewriter, converter); + if (const auto poisonAttr = mlir::dyn_cast(attr)) + return lowerCirAttrAsValue(parentOp, poisonAttr, rewriter, converter); if (const auto globalAttr = mlir::dyn_cast(attr)) return lowerCirAttrAsValue(parentOp, globalAttr, rewriter, converter); if (const auto vtableAttr = mlir::dyn_cast(attr)) @@ -1555,6 +1567,14 @@ mlir::LogicalResult CIRToLLVMConstantOpLowering::matchAndRewrite( mlir::ConversionPatternRewriter &rewriter) const { mlir::Attribute attr = op.getValue(); + // Regardless of the type, we should lower the constant of poison value + // into PoisonOp. + if (mlir::isa(attr)) { + rewriter.replaceOp( + op, lowerCirAttrAsValue(op, attr, rewriter, getTypeConverter())); + return mlir::success(); + } + if (mlir::isa(op.getType())) { // Verified cir.const operations cannot actually be of these types, but the // lowering pass may generate temporary cir.const operations with these @@ -1695,6 +1715,7 @@ mlir::LogicalResult CIRToLLVMVecCreateOpLowering::matchAndRewrite( mlir::Value result = rewriter.create(loc, llvmTy); assert(vecTy.getSize() == op.getElements().size() && "cir.vec.create op count doesn't match vector type elements count"); + for (uint64_t i = 0; i < vecTy.getSize(); ++i) { mlir::Value indexValue = rewriter.create(loc, rewriter.getI64Type(), i); @@ -1745,15 +1766,21 @@ mlir::LogicalResult CIRToLLVMVecSplatOpLowering::matchAndRewrite( assert(vecTy && "result type of cir.vec.splat op is not VectorType"); auto llvmTy = typeConverter->convertType(vecTy); auto loc = op.getLoc(); - mlir::Value undef = rewriter.create(loc, llvmTy); + mlir::Value poison = rewriter.create(loc, llvmTy); mlir::Value indexValue = rewriter.create(loc, rewriter.getI64Type(), 0); mlir::Value elementValue = adaptor.getValue(); + if (mlir::isa(elementValue.getDefiningOp())) { + // If the splat value is poison, then we can just use poison value + // for the entire vector. + rewriter.replaceOp(op, poison); + return mlir::success(); + } mlir::Value oneElement = rewriter.create( - loc, undef, elementValue, indexValue); + loc, poison, elementValue, indexValue); SmallVector zeroValues(vecTy.getSize(), 0); mlir::Value shuffled = rewriter.create( - loc, oneElement, undef, zeroValues); + loc, oneElement, poison, zeroValues); rewriter.replaceOp(op, shuffled); return mlir::success(); } diff --git a/clang/test/CIR/CodeGen/AArch64/neon.c b/clang/test/CIR/CodeGen/AArch64/neon.c index e6b706e9ef35..487778d3778f 100644 --- a/clang/test/CIR/CodeGen/AArch64/neon.c +++ b/clang/test/CIR/CodeGen/AArch64/neon.c @@ -14617,11 +14617,12 @@ int16_t test_vqmovns_s32(int32_t a) { // CIR-LABEL: vqmovns_s32 // CIR: [[A:%.*]] = cir.load {{.*}} : !cir.ptr, !s32i // CIR: [[VQMOVNS_S32_ZERO1:%.*]] = cir.const #cir.int<0> : !u64i - // CIR: [[POISON:%.*]] = cir.poison : !cir.vector - // CIR: [[TMP0:%.*]] = cir.vec.insert [[A]], [[POISON]][[[VQMOVNS_S32_ZERO1]] : !u64i] : !cir.vector + // CIR: [[POISON:%.*]] = cir.const #cir.poison : !s32i + // CIR: [[POISON_VEC:%.*]] = cir.vec.splat [[POISON]] : !s32i, !cir.vector + // CIR: [[TMP0:%.*]] = cir.vec.insert [[A]], [[POISON_VEC]][[[VQMOVNS_S32_ZERO1]] : !u64i] : !cir.vector // CIR: [[VQMOVNS_S32_I:%.*]] = cir.llvm.intrinsic "aarch64.neon.sqxtn" [[TMP0]] : (!cir.vector) -> !cir.vector // CIR: [[VQMOVNS_S32_ZERO2:%.*]] = cir.const #cir.int<0> : !u64i - // CIR: [[TMP1:%.*]] = cir.vec.extract [[VQMOVNS_S32_I]][[[VQMOVNS_S32_ZERO2]] : !u64i] : !cir.vector loc(#loc4503) + // CIR: [[TMP1:%.*]] = cir.vec.extract [[VQMOVNS_S32_I]][[[VQMOVNS_S32_ZERO2]] : !u64i] : !cir.vector // LLVM: {{.*}}@test_vqmovns_s32(i32{{.*}}[[a:%.*]]) // LLVM: [[TMP0:%.*]] = insertelement <4 x i32> poison, i32 [[a]], i64 0 diff --git a/clang/test/CIR/IR/cir-ops.cir b/clang/test/CIR/IR/cir-ops.cir index 7417f71873c3..2c2d137ab92e 100644 --- a/clang/test/CIR/IR/cir-ops.cir +++ b/clang/test/CIR/IR/cir-ops.cir @@ -65,11 +65,6 @@ module { %3 = cir.shift(left, %1 : !cir.vector, %2 : !cir.vector) -> !cir.vector cir.return } - - cir.func @poisonvalue() { - %0 = cir.poison : !cir.vector - cir.return - } } // CHECK: module { @@ -123,9 +118,4 @@ module { // CHECK-NEXT: cir.return // CHECK-NEXT: } -// CHECK: cir.func @poisonvalue() { -// CHECK-NEXT: %0 = cir.poison : !cir.vector -// CHECK-NEXT: cir.return -// CHECK-NEXT: } - // CHECK: } diff --git a/clang/test/CIR/IR/invalid.cir b/clang/test/CIR/IR/invalid.cir index 1a6c2f503dfd..aaeb46e770b5 100644 --- a/clang/test/CIR/IR/invalid.cir +++ b/clang/test/CIR/IR/invalid.cir @@ -393,6 +393,12 @@ module { // ----- +module { + cir.global external @v = #cir.poison : !cir.void // expected-error {{poison expects non-void type}} +} + +// ----- + !s32i = !cir.int cir.func @vec_op_size() { %0 = cir.const #cir.int<1> : !s32i diff --git a/clang/test/CIR/Lowering/const.cir b/clang/test/CIR/Lowering/const.cir index 43e635226000..ae78b8387fc5 100644 --- a/clang/test/CIR/Lowering/const.cir +++ b/clang/test/CIR/Lowering/const.cir @@ -17,6 +17,8 @@ module { // CHECK: llvm.mlir.zero : !llvm.array<3 x i32> %5 = cir.const #cir.undef : !cir.array // CHECK: llvm.mlir.undef : !llvm.array<3 x i32> + %6 = cir.const #cir.poison : !s32i + // CHECK: llvm.mlir.poison : i32 cir.return }