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

Reply via email to