https://github.com/aobolensk created 
https://github.com/llvm/llvm-project/pull/237750

Use a signed MSB test and bitcast operands to match its type

>From 41d5e05a402b7fae54c32f32c1db5c031dde9566 Mon Sep 17 00:00:00 2001
From: Arseniy Obolenskiy <[email protected]>
Date: Sun, 1 Nov 2026 17:21:34 +0100
Subject: [PATCH] [CIR][OpenCL] Fix vector ternary with unsigned condition or
 operands

Use a signed MSB test and bitcast operands to match its type
---
 clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp | 12 ++++++---
 clang/test/CIR/CodeGenOpenCL/vector.cl     | 31 ++++++++++++++++++++++
 2 files changed, 39 insertions(+), 4 deletions(-)

diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
index 8e6ded0527cc90..d047cf15e7e9d8 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
@@ -3347,19 +3347,23 @@ mlir::Value 
ScalarExprEmitter::VisitAbstractConditionalOperator(
     mlir::Value lhsValue = Visit(lhsExpr);
     mlir::Value rhsValue = Visit(rhsExpr);
 
-    mlir::Type vecTy = convertType(condType);
+    // Test the MSB with a signed compare, as classic codegen does.
+    auto condVecTy = cast<cir::VectorType>(convertType(condType));
+    auto condEltTy = cast<cir::IntType>(condVecTy.getElementType());
+    mlir::Type vecTy = cir::VectorType::get(
+        builder.getSIntNTy(condEltTy.getWidth()), condVecTy.getSize());
+    condValue = builder.createBitcast(condValue, vecTy);
     mlir::Value zeroVec = builder.getNullValue(vecTy, loc);
     auto testMSB = cir::VecCmpOp::create(
         builder, loc, vecTy, cir::CmpOpKind::lt, condValue, zeroVec);
     mlir::Value tmp = builder.createIntCast(testMSB, vecTy);
     mlir::Value tmp2 = builder.createNot(tmp);
 
-    // Cast float to int to perform ANDs if necessary.
+    // Bitcast float or differently signed operands to the condition type.
     mlir::Value rhsTmp = rhsValue;
     mlir::Value lhsTmp = lhsValue;
     bool wasCast = false;
-    auto rhsVecTy = cast<cir::VectorType>(rhsValue.getType());
-    if (cir::isAnyFloatingPointType(rhsVecTy.getElementType())) {
+    if (rhsValue.getType() != vecTy) {
       rhsTmp = builder.createBitcast(rhsValue, tmp2.getType());
       lhsTmp = builder.createBitcast(lhsValue, tmp.getType());
       wasCast = true;
diff --git a/clang/test/CIR/CodeGenOpenCL/vector.cl 
b/clang/test/CIR/CodeGenOpenCL/vector.cl
index 9e71e34da4724f..dfb493906d471f 100644
--- a/clang/test/CIR/CodeGenOpenCL/vector.cl
+++ b/clang/test/CIR/CodeGenOpenCL/vector.cl
@@ -9,6 +9,7 @@
 
 typedef __attribute__(( ext_vector_type(2) )) int int2;
 typedef __attribute__(( ext_vector_type(4) )) int int4;
+typedef __attribute__(( ext_vector_type(4) )) unsigned int uint4;
 typedef __attribute__(( ext_vector_type(4) )) float float4;
 
 int4 vec_ternary(int4 c, int4 a, int4 b) {
@@ -72,6 +73,36 @@ float4 vec_ternary_f4(int4 c, float4 a, float4 b) {
 // LLVM: %[[RESULT:.*]] = select <4 x i1> %[[IS_NEG]], <4 x float> %[[A:.*]], 
<4 x float> %[[B:.*]]
 // LLVM: ret <4 x float> %[[RESULT]]
 
+uint4 vec_ternary_u4(int4 c, uint4 a, uint4 b) {
+  return c ? a : b;
+}
+
+// CIR: cir.func {{.*}} @vec_ternary_u4
+// CIR: %[[C_CMP:.*]] = cir.vec.cmp(lt, %{{.*}}, %{{.*}}) : !cir.vector<4 x 
!s32i>, !cir.vector<4 x !s32i>
+// CIR: %[[C_CMP_NOT:.*]] = cir.not %[[C_CMP]] : !cir.vector<4 x !s32i>
+// CIR: %[[TMP_B_VI4:.*]] = cir.cast bitcast %{{.*}} : !cir.vector<4 x !u32i> 
-> !cir.vector<4 x !s32i>
+// CIR: %[[TMP_A_VI4:.*]] = cir.cast bitcast %{{.*}} : !cir.vector<4 x !u32i> 
-> !cir.vector<4 x !s32i>
+// CIR: %[[TMP_1:.*]] = cir.and %[[TMP_B_VI4]], %[[C_CMP_NOT]] : !cir.vector<4 
x !s32i>
+// CIR: %[[TMP_2:.*]] = cir.and %[[TMP_A_VI4]], %[[C_CMP]] : !cir.vector<4 x 
!s32i>
+// CIR: %[[TMP_1_1_OR:.*]] = cir.or %[[TMP_1]], %[[TMP_2]] : !cir.vector<4 x 
!s32i>
+// CIR: %{{.*}} = cir.cast bitcast %[[TMP_1_1_OR]] : !cir.vector<4 x !s32i> -> 
!cir.vector<4 x !u32i>
+
+// LLVM: %[[IS_NEG:.*]] = icmp slt <4 x i32> %[[COND:.*]], zeroinitializer
+// LLVM: %[[RESULT:.*]] = select <4 x i1> %[[IS_NEG]], <4 x i32> %[[A:.*]], <4 
x i32> %[[B:.*]]
+// LLVM: ret <4 x i32> %[[RESULT]]
+
+uint4 vec_ternary_ucond(uint4 c, uint4 a, uint4 b) {
+  return c ? a : b;
+}
+
+// CIR: cir.func {{.*}} @vec_ternary_ucond
+// CIR: %[[C_S:.*]] = cir.cast bitcast %{{.*}} : !cir.vector<4 x !u32i> -> 
!cir.vector<4 x !s32i>
+// CIR: %{{.*}} = cir.vec.cmp(lt, %[[C_S]], %{{.*}}) : !cir.vector<4 x !s32i>, 
!cir.vector<4 x !s32i>
+
+// LLVM: %[[IS_NEG:.*]] = icmp slt <4 x i32> %[[COND:.*]], zeroinitializer
+// LLVM: %[[RESULT:.*]] = select <4 x i1> %[[IS_NEG]], <4 x i32> %[[A:.*]], <4 
x i32> %[[B:.*]]
+// LLVM: ret <4 x i32> %[[RESULT]]
+
 int4 vec_unary_inc(int4 a) {
   ++a;
   return a;

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to