https://github.com/adams381 updated https://github.com/llvm/llvm-project/pull/203397
>From 234f14ae2a9f33f1ee96ff6e410980a8a886420d Mon Sep 17 00:00:00 2001 From: Adam Smith <[email protected]> Date: Thu, 11 Jun 2026 13:56:45 -0700 Subject: [PATCH 1/2] [CIR] Lower vector integer/float to bool casts An ext_vector integer-to-bool or float-to-bool conversion (for example __builtin_convertvector from an int4 to a bool4) crashed clang. emitScalarConversion only short-circuits the scalar bool case (dstType->isBooleanType()), so a vector-of-bool destination fell through to emitScalarCast, which unwrapped both vectors to their element types and hit llvm_unreachable("Cast to unexpected type") because its integer- and float-source branches handled only integer and floating-point destinations. Handle a bool element destination in those branches with the existing int_to_bool / float_to_bool cast kinds, mirroring the bool-source branch. In LowerToLLVM, build the comparison's zero operand with getZeroAttr so it splats for vector sources, and compare element widths in the bool_to_int lowering so the round trip also lowers for vectors. libcxx's vectorized comparison helpers reach this path; the conversion now lowers to an elementwise icmp ne / fcmp une against zero instead of crashing. --- clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp | 9 +++ .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 24 ++++--- .../test/CIR/CodeGen/vector-convert-to-bool.c | 63 +++++++++++++++++++ 3 files changed, 88 insertions(+), 8 deletions(-) create mode 100644 clang/test/CIR/CodeGen/vector-convert-to-bool.c diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp index d8b7fa062b845..47687ba00933e 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp @@ -539,6 +539,11 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> { castKind = cir::CastKind::integral; else if (mlir::isa<cir::FPTypeInterface>(dstTy)) castKind = cir::CastKind::int_to_float; + else if (mlir::isa<cir::BoolType>(dstTy)) + // Reached for vector-to-vector conversions whose element type is + // bool (e.g. __builtin_convertvector to an ext_vector of bool); + // the scalar bool case is handled in emitScalarConversion. + castKind = cir::CastKind::int_to_bool; else llvm_unreachable("Internal error: Cast to unexpected type"); } else if (mlir::isa<cir::FPTypeInterface>(srcTy)) { @@ -553,6 +558,10 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> { } else if (mlir::isa<cir::FPTypeInterface>(dstTy)) { // TODO: split this to createFPExt/createFPTrunc return builder.createFloatingCast(src, fullDstTy); + } else if (mlir::isa<cir::BoolType>(dstTy)) { + // Vector-to-vector conversion with bool element type (the scalar + // bool case is handled in emitScalarConversion). + castKind = cir::CastKind::float_to_bool; } else { llvm_unreachable("Internal error: Cast to unexpected type"); } diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index 67a2803e8ab81..37deb27038663 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -1271,8 +1271,12 @@ mlir::LogicalResult CIRToLLVMCastOpLowering::matchAndRewrite( } case cir::CastKind::int_to_bool: { mlir::Value llvmSrcVal = adaptor.getSrc(); + // getZeroAttr yields a splat for vector source types so this also + // handles element-wise int-to-bool conversions (e.g. an ext_vector + // __builtin_convertvector to bool). mlir::Value zeroInt = mlir::LLVM::ConstantOp::create( - rewriter, castOp.getLoc(), llvmSrcVal.getType(), 0); + rewriter, castOp.getLoc(), llvmSrcVal.getType(), + rewriter.getZeroAttr(llvmSrcVal.getType())); rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>( castOp, mlir::LLVM::ICmpPredicate::ne, llvmSrcVal, zeroInt); break; @@ -1335,10 +1339,12 @@ mlir::LogicalResult CIRToLLVMCastOpLowering::matchAndRewrite( mlir::Value llvmSrcVal = adaptor.getSrc(); auto kind = mlir::LLVM::FCmpPredicate::une; - // Check if float is not equal to zero. + // Check if float is not equal to zero. getZeroAttr yields a splat + // for vector source types so this also handles element-wise + // float-to-bool conversions. auto zeroFloat = mlir::LLVM::ConstantOp::create( rewriter, castOp.getLoc(), llvmSrcVal.getType(), - mlir::FloatAttr::get(llvmSrcVal.getType(), 0.0)); + rewriter.getZeroAttr(llvmSrcVal.getType())); // Extend comparison result to either bool (C++) or int (C). rewriter.replaceOpWithNewOp<mlir::LLVM::FCmpOp>(castOp, kind, llvmSrcVal, @@ -1347,13 +1353,15 @@ mlir::LogicalResult CIRToLLVMCastOpLowering::matchAndRewrite( return mlir::success(); } case cir::CastKind::bool_to_int: { - auto dstTy = mlir::cast<cir::IntType>(castOp.getType()); + mlir::Type dstTy = castOp.getType(); mlir::Value llvmSrcVal = adaptor.getSrc(); - auto llvmSrcTy = mlir::cast<mlir::IntegerType>(llvmSrcVal.getType()); - auto llvmDstTy = - mlir::cast<mlir::IntegerType>(getTypeConverter()->convertType(dstTy)); + mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy); + // Compare element widths so this also handles vector bool -> int casts. + auto srcElemTy = mlir::cast<mlir::IntegerType>( + elementTypeIfVector(llvmSrcVal.getType())); + auto dstElemTy = mlir::cast<cir::IntType>(elementTypeIfVector(dstTy)); - if (llvmSrcTy.getWidth() == llvmDstTy.getWidth()) + if (srcElemTy.getWidth() == dstElemTy.getWidth()) rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(castOp, llvmDstTy, llvmSrcVal); else diff --git a/clang/test/CIR/CodeGen/vector-convert-to-bool.c b/clang/test/CIR/CodeGen/vector-convert-to-bool.c new file mode 100644 index 0000000000000..273aa3b380c41 --- /dev/null +++ b/clang/test/CIR/CodeGen/vector-convert-to-bool.c @@ -0,0 +1,63 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir +// RUN: FileCheck --input-file=%t.cir %s -check-prefix=CIR +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t-cir.ll +// RUN: FileCheck --input-file=%t-cir.ll %s -check-prefix=LLVM +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t.ll +// RUN: FileCheck --input-file=%t.ll %s -check-prefix=LLVM + +typedef int int4 __attribute__((ext_vector_type(4))); +typedef long long2 __attribute__((ext_vector_type(2))); +typedef float float4 __attribute__((ext_vector_type(4))); +typedef _Bool bool4 __attribute__((ext_vector_type(4))); +typedef _Bool bool2 __attribute__((ext_vector_type(2))); + +// The bool vector is kept in registers (round-tripped back to an integer +// vector) so this isolates the element-wise int/float <-> bool casts. + +int4 int_to_bool_vec(int4 a) { + return __builtin_convertvector(__builtin_convertvector(a, bool4), int4); +} + +// CIR-LABEL: cir.func{{.*}} @int_to_bool_vec +// CIR: %[[M:.*]] = cir.cast int_to_bool %{{.+}} : !cir.vector<4 x !s32i> -> !cir.vector<4 x !cir.bool> +// CIR: cir.cast bool_to_int %[[M]] : !cir.vector<4 x !cir.bool> -> !cir.vector<4 x !s32i> + +// LLVM-LABEL: @int_to_bool_vec +// LLVM: %[[M:.*]] = icmp ne <4 x i32> %{{.+}}, zeroinitializer +// LLVM: zext <4 x i1> %[[M]] to <4 x i32> + +long2 long_to_bool_vec(long2 a) { + return __builtin_convertvector(__builtin_convertvector(a, bool2), long2); +} + +// CIR-LABEL: cir.func{{.*}} @long_to_bool_vec +// CIR: %[[M:.*]] = cir.cast int_to_bool %{{.+}} : !cir.vector<2 x !s64i> -> !cir.vector<2 x !cir.bool> +// CIR: cir.cast bool_to_int %[[M]] : !cir.vector<2 x !cir.bool> -> !cir.vector<2 x !s64i> + +// LLVM-LABEL: @long_to_bool_vec +// LLVM: %[[M:.*]] = icmp ne <2 x i64> %{{.+}}, zeroinitializer +// LLVM: zext <2 x i1> %[[M]] to <2 x i64> + +int4 float_to_bool_vec(float4 a) { + return __builtin_convertvector(__builtin_convertvector(a, bool4), int4); +} + +// CIR-LABEL: cir.func{{.*}} @float_to_bool_vec +// CIR: %[[M:.*]] = cir.cast float_to_bool %{{.+}} : !cir.vector<4 x !cir.float> -> !cir.vector<4 x !cir.bool> +// CIR: cir.cast bool_to_int %[[M]] : !cir.vector<4 x !cir.bool> -> !cir.vector<4 x !s32i> + +// LLVM-LABEL: @float_to_bool_vec +// LLVM: %[[M:.*]] = fcmp une <4 x float> %{{.+}}, zeroinitializer +// LLVM: zext <4 x i1> %[[M]] to <4 x i32> + +float4 bool_to_float_vec(int4 a) { + return __builtin_convertvector(__builtin_convertvector(a, bool4), float4); +} + +// CIR-LABEL: cir.func{{.*}} @bool_to_float_vec +// CIR: %[[M:.*]] = cir.cast int_to_bool %{{.+}} : !cir.vector<4 x !s32i> -> !cir.vector<4 x !cir.bool> +// CIR: cir.cast bool_to_float %[[M]] : !cir.vector<4 x !cir.bool> -> !cir.vector<4 x !cir.float> + +// LLVM-LABEL: @bool_to_float_vec +// LLVM: %[[M:.*]] = icmp ne <4 x i32> %{{.+}}, zeroinitializer +// LLVM: uitofp <4 x i1> %[[M]] to <4 x float> >From 82c83cb2d5251c1afbbd9d8e51650f161d6e31a2 Mon Sep 17 00:00:00 2001 From: Adam Smith <[email protected]> Date: Mon, 15 Jun 2026 11:57:14 -0700 Subject: [PATCH 2/2] [CIR] Drop redundant comments in emitScalarCast Remove the two explanatory comments on the int_to_bool and float_to_bool cast-kind branches in emitScalarCast, per review feedback on PR #203397. NFC. --- clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp index 47687ba00933e..6201d73851482 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp @@ -540,9 +540,6 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> { else if (mlir::isa<cir::FPTypeInterface>(dstTy)) castKind = cir::CastKind::int_to_float; else if (mlir::isa<cir::BoolType>(dstTy)) - // Reached for vector-to-vector conversions whose element type is - // bool (e.g. __builtin_convertvector to an ext_vector of bool); - // the scalar bool case is handled in emitScalarConversion. castKind = cir::CastKind::int_to_bool; else llvm_unreachable("Internal error: Cast to unexpected type"); @@ -559,8 +556,6 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> { // TODO: split this to createFPExt/createFPTrunc return builder.createFloatingCast(src, fullDstTy); } else if (mlir::isa<cir::BoolType>(dstTy)) { - // Vector-to-vector conversion with bool element type (the scalar - // bool case is handled in emitScalarConversion). castKind = cir::CastKind::float_to_bool; } else { llvm_unreachable("Internal error: Cast to unexpected type"); _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
