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
