https://github.com/AmrDeveloper updated https://github.com/llvm/llvm-project/pull/142393
>From 030af8ea55d123d4b32d6a935c6288ea76973897 Mon Sep 17 00:00:00 2001 From: AmrDeveloper <am...@programmer.net> Date: Mon, 2 Jun 2025 15:11:17 +0200 Subject: [PATCH 1/3] [CIR] Upstream TernaryOp for VectorType --- clang/include/clang/CIR/Dialect/IR/CIROps.td | 36 +++++++++++++++++++ clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp | 30 ++++++++++++++++ clang/lib/CIR/Dialect/IR/CIRDialect.cpp | 18 ++++++++++ .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 17 ++++++++- .../CIR/Lowering/DirectToLLVM/LowerToLLVM.h | 10 ++++++ clang/test/CIR/CodeGen/vector-ext.cpp | 15 ++++++++ clang/test/CIR/CodeGen/vector.cpp | 17 ++++++++- 7 files changed, 141 insertions(+), 2 deletions(-) diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index 237daed32532a..d6a9bda0c04ea 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -2194,4 +2194,40 @@ def VecShuffleDynamicOp : CIR_Op<"vec.shuffle.dynamic", let hasVerifier = 1; } +//===----------------------------------------------------------------------===// +// VecTernaryOp +//===----------------------------------------------------------------------===// + +def VecTernaryOp : CIR_Op<"vec.ternary", + [Pure, AllTypesMatch<["result", "vec1", "vec2"]>]> { + let summary = "The `cond ? a : b` ternary operator for vector types"; + let description = [{ + The `cir.vec.ternary` operation represents the C/C++ ternary operator, + `?:`, for vector types, which does a `select` on individual elements of the + vectors. Unlike a regular `?:` operator, there is no short circuiting. All + three arguments are always evaluated. Because there is no short + circuiting, there are no regions in this operation, unlike cir.ternary. + + The first argument is a vector of integral type. The second and third + arguments are vectors of the same type and have the same number of elements + as the first argument. + + The result is a vector of the same type as the second and third arguments. + Each element of the result is `(bool)a[n] ? b[n] : c[n]`. + }]; + + let arguments = (ins + IntegerVector:$cond, + CIR_VectorType:$vec1, + CIR_VectorType:$vec2 + ); + + let results = (outs CIR_VectorType:$result); + let assemblyFormat = [{ + `(` $cond `,` $vec1 `,` $vec2 `)` `:` qualified(type($cond)) `,` + qualified(type($vec1)) attr-dict + }]; + let hasVerifier = 1; +} + #endif // CLANG_CIR_DIALECT_IR_CIROPS_TD diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp index b33bb71c99c90..94e331d4ef652 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp @@ -193,6 +193,36 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> { e->getSourceRange().getBegin()); } + mlir::Value + VisitAbstractConditionalOperator(const AbstractConditionalOperator *e) { + mlir::Location loc = cgf.getLoc(e->getSourceRange()); + Expr *condExpr = e->getCond(); + Expr *lhsExpr = e->getTrueExpr(); + Expr *rhsExpr = e->getFalseExpr(); + + // OpenCL: If the condition is a vector, we can treat this condition like + // the select function. + if ((cgf.getLangOpts().OpenCL && condExpr->getType()->isVectorType()) || + condExpr->getType()->isExtVectorType()) { + cgf.getCIRGenModule().errorNYI(loc, + "TernaryOp OpenCL VectorType condition"); + return {}; + } + + if (condExpr->getType()->isVectorType() || + condExpr->getType()->isSveVLSBuiltinType()) { + assert(condExpr->getType()->isVectorType() && "?: op for SVE vector NYI"); + mlir::Value condValue = Visit(condExpr); + mlir::Value lhsValue = Visit(lhsExpr); + mlir::Value rhsValue = Visit(rhsExpr); + return builder.create<cir::VecTernaryOp>(loc, condValue, lhsValue, + rhsValue); + } + + cgf.getCIRGenModule().errorNYI(loc, "TernaryOp for non vector types"); + return {}; + } + mlir::Value VisitMemberExpr(MemberExpr *e); mlir::Value VisitInitListExpr(InitListExpr *e); diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp index 36f050de9f8bb..1236c455304a9 100644 --- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp @@ -1589,6 +1589,24 @@ LogicalResult cir::VecShuffleDynamicOp::verify() { return success(); } +//===----------------------------------------------------------------------===// +// VecTernaryOp +//===----------------------------------------------------------------------===// + +LogicalResult cir::VecTernaryOp::verify() { + // Verify that the condition operand has the same number of elements as the + // other operands. (The automatic verification already checked that all + // operands are vector types and that the second and third operands are the + // same type.) + if (mlir::cast<cir::VectorType>(getCond().getType()).getSize() != + getVec1().getType().getSize()) { + return emitOpError() << ": the number of elements in " + << getCond().getType() << " and " + << getVec1().getType() << " don't match"; + } + return success(); +} + //===----------------------------------------------------------------------===// // TableGen'd op method definitions //===----------------------------------------------------------------------===// diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index b07e61638c3b4..e5a26260dc8cc 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -1708,7 +1708,8 @@ void ConvertCIRToLLVMPass::runOnOperation() { CIRToLLVMVecExtractOpLowering, CIRToLLVMVecInsertOpLowering, CIRToLLVMVecCmpOpLowering, - CIRToLLVMVecShuffleDynamicOpLowering + CIRToLLVMVecShuffleDynamicOpLowering, + CIRToLLVMVecTernaryOpLowering // clang-format on >(converter, patterns.getContext()); @@ -1916,6 +1917,20 @@ mlir::LogicalResult CIRToLLVMVecShuffleDynamicOpLowering::matchAndRewrite( return mlir::success(); } +mlir::LogicalResult CIRToLLVMVecTernaryOpLowering::matchAndRewrite( + cir::VecTernaryOp op, OpAdaptor adaptor, + mlir::ConversionPatternRewriter &rewriter) const { + // Convert `cond` into a vector of i1, then use that in a `select` op. + mlir::Value bitVec = rewriter.create<mlir::LLVM::ICmpOp>( + op.getLoc(), mlir::LLVM::ICmpPredicate::ne, adaptor.getCond(), + rewriter.create<mlir::LLVM::ZeroOp>( + op.getCond().getLoc(), + typeConverter->convertType(op.getCond().getType()))); + rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>( + op, bitVec, adaptor.getVec1(), adaptor.getVec2()); + return mlir::success(); +} + std::unique_ptr<mlir::Pass> createConvertCIRToLLVMPass() { return std::make_unique<ConvertCIRToLLVMPass>(); } diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h index 6b8862db2c8be..ed369ff15a710 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h @@ -363,6 +363,16 @@ class CIRToLLVMVecShuffleDynamicOpLowering mlir::ConversionPatternRewriter &) const override; }; +class CIRToLLVMVecTernaryOpLowering + : public mlir::OpConversionPattern<cir::VecTernaryOp> { +public: + using mlir::OpConversionPattern<cir::VecTernaryOp>::OpConversionPattern; + + mlir::LogicalResult + matchAndRewrite(cir::VecTernaryOp op, OpAdaptor, + mlir::ConversionPatternRewriter &) const override; +}; + } // namespace direct } // namespace cir diff --git a/clang/test/CIR/CodeGen/vector-ext.cpp b/clang/test/CIR/CodeGen/vector-ext.cpp index 8a0479fc1d088..53258845c2169 100644 --- a/clang/test/CIR/CodeGen/vector-ext.cpp +++ b/clang/test/CIR/CodeGen/vector-ext.cpp @@ -1091,3 +1091,18 @@ void foo17() { // OGCG: %[[VEC_A:.*]] = alloca <2 x double>, align 16 // OGCG: %[[TMP:.*]] = load <2 x double>, ptr %[[VEC_A]], align 16 // OGCG: %[[RES:.*]]= fptoui <2 x double> %[[TMP]] to <2 x i16> + +void foo20() { + vi4 a; + vi4 b; + vi4 c; + vi4 r = c ? a : b; +} + +// CIR: %[[RES:.*]] = cir.vec.ternary({{.*}}, {{.*}}, {{.*}}) : !cir.vector<4 x !s32i>, !cir.vector<4 x !s32i> + +// LLVM: %[[VEC_COND:.*]] = icmp ne <4 x i32> {{.*}}, zeroinitializer +// LLVM: %[[RES:.*]] = select <4 x i1> %[[VEC_COND]], <4 x i32> {{.*}}, <4 x i32> {{.*}} + +// OGCG: %[[VEC_COND:.*]] = icmp ne <4 x i32> {{.*}}, zeroinitializer +// OGCG: %[[RES:.*]] = select <4 x i1> %[[VEC_COND]], <4 x i32> {{.*}}, <4 x i32> {{.*}} diff --git a/clang/test/CIR/CodeGen/vector.cpp b/clang/test/CIR/CodeGen/vector.cpp index 4c50f68a56162..49f142d110a81 100644 --- a/clang/test/CIR/CodeGen/vector.cpp +++ b/clang/test/CIR/CodeGen/vector.cpp @@ -1069,4 +1069,19 @@ void foo17() { // OGCG: %[[VEC_A:.*]] = alloca <2 x double>, align 16 // OGCG: %[[TMP:.*]] = load <2 x double>, ptr %[[VEC_A]], align 16 -// OGCG: %[[RES:.*]]= fptoui <2 x double> %[[TMP]] to <2 x i16> \ No newline at end of file +// OGCG: %[[RES:.*]]= fptoui <2 x double> %[[TMP]] to <2 x i16> + +void foo20() { + vi4 a; + vi4 b; + vi4 c; + vi4 r = c ? a : b; +} + +// CIR: %[[RES:.*]] = cir.vec.ternary({{.*}}, {{.*}}, {{.*}}) : !cir.vector<4 x !s32i>, !cir.vector<4 x !s32i> + +// LLVM: %[[VEC_COND:.*]] = icmp ne <4 x i32> {{.*}}, zeroinitializer +// LLVM: %[[RES:.*]] = select <4 x i1> %[[VEC_COND]], <4 x i32> {{.*}}, <4 x i32> {{.*}} + +// OGCG: %[[VEC_COND:.*]] = icmp ne <4 x i32> {{.*}}, zeroinitializer +// OGCG: %[[RES:.*]] = select <4 x i1> %[[VEC_COND]], <4 x i32> {{.*}}, <4 x i32> {{.*}} >From 4aa56e8e4b4dfcf5835c0d35d99462a352efbeae Mon Sep 17 00:00:00 2001 From: AmrDeveloper <am...@programmer.net> Date: Mon, 2 Jun 2025 22:47:35 +0200 Subject: [PATCH 2/3] Update with main & Address code review comments --- clang/include/clang/CIR/Dialect/IR/CIROps.td | 2 +- clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp | 20 ++++++++++++-------- clang/lib/CIR/Dialect/IR/CIRDialect.cpp | 3 +-- clang/test/CIR/CodeGen/vector-ext.cpp | 15 --------------- 4 files changed, 14 insertions(+), 26 deletions(-) diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index d6a9bda0c04ea..746583985d4c5 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -2217,7 +2217,7 @@ def VecTernaryOp : CIR_Op<"vec.ternary", }]; let arguments = (ins - IntegerVector:$cond, + CIR_VectorOfIntType:$cond, CIR_VectorType:$vec1, CIR_VectorType:$vec2 ); diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp index 94e331d4ef652..fd2718c57dbca 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp @@ -200,18 +200,22 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> { Expr *lhsExpr = e->getTrueExpr(); Expr *rhsExpr = e->getFalseExpr(); + QualType condType = condExpr->getType(); + // OpenCL: If the condition is a vector, we can treat this condition like // the select function. - if ((cgf.getLangOpts().OpenCL && condExpr->getType()->isVectorType()) || - condExpr->getType()->isExtVectorType()) { - cgf.getCIRGenModule().errorNYI(loc, - "TernaryOp OpenCL VectorType condition"); + if ((cgf.getLangOpts().OpenCL && condType->isVectorType()) || + condType->isExtVectorType()) { + cgf.cgm.errorNYI(loc, "TernaryOp OpenCL VectorType condition"); return {}; } - if (condExpr->getType()->isVectorType() || - condExpr->getType()->isSveVLSBuiltinType()) { - assert(condExpr->getType()->isVectorType() && "?: op for SVE vector NYI"); + if (condType->isVectorType() || condType->isSveVLSBuiltinType()) { + if (!condExpr->getType()->isVectorType()) { + cgf.cgm.errorNYI(loc, "TernaryOp for SVE vector"); + return {}; + } + mlir::Value condValue = Visit(condExpr); mlir::Value lhsValue = Visit(lhsExpr); mlir::Value rhsValue = Visit(rhsExpr); @@ -219,7 +223,7 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> { rhsValue); } - cgf.getCIRGenModule().errorNYI(loc, "TernaryOp for non vector types"); + cgf.cgm.errorNYI(loc, "TernaryOp for non vector types"); return {}; } diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp index 1236c455304a9..7dd4a8ec0c7ef 100644 --- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp @@ -1598,8 +1598,7 @@ LogicalResult cir::VecTernaryOp::verify() { // other operands. (The automatic verification already checked that all // operands are vector types and that the second and third operands are the // same type.) - if (mlir::cast<cir::VectorType>(getCond().getType()).getSize() != - getVec1().getType().getSize()) { + if (getCond().getType().getSize() != getVec1().getType().getSize()) { return emitOpError() << ": the number of elements in " << getCond().getType() << " and " << getVec1().getType() << " don't match"; diff --git a/clang/test/CIR/CodeGen/vector-ext.cpp b/clang/test/CIR/CodeGen/vector-ext.cpp index 53258845c2169..8a0479fc1d088 100644 --- a/clang/test/CIR/CodeGen/vector-ext.cpp +++ b/clang/test/CIR/CodeGen/vector-ext.cpp @@ -1091,18 +1091,3 @@ void foo17() { // OGCG: %[[VEC_A:.*]] = alloca <2 x double>, align 16 // OGCG: %[[TMP:.*]] = load <2 x double>, ptr %[[VEC_A]], align 16 // OGCG: %[[RES:.*]]= fptoui <2 x double> %[[TMP]] to <2 x i16> - -void foo20() { - vi4 a; - vi4 b; - vi4 c; - vi4 r = c ? a : b; -} - -// CIR: %[[RES:.*]] = cir.vec.ternary({{.*}}, {{.*}}, {{.*}}) : !cir.vector<4 x !s32i>, !cir.vector<4 x !s32i> - -// LLVM: %[[VEC_COND:.*]] = icmp ne <4 x i32> {{.*}}, zeroinitializer -// LLVM: %[[RES:.*]] = select <4 x i1> %[[VEC_COND]], <4 x i32> {{.*}}, <4 x i32> {{.*}} - -// OGCG: %[[VEC_COND:.*]] = icmp ne <4 x i32> {{.*}}, zeroinitializer -// OGCG: %[[RES:.*]] = select <4 x i1> %[[VEC_COND]], <4 x i32> {{.*}}, <4 x i32> {{.*}} >From 85de642d07dee0f3ddf7eba535424040aba53a93 Mon Sep 17 00:00:00 2001 From: AmrDeveloper <am...@programmer.net> Date: Tue, 3 Jun 2025 00:27:44 +0200 Subject: [PATCH 3/3] Rename VecTernaryOp operands to mirror AST representation --- clang/include/clang/CIR/Dialect/IR/CIROps.td | 10 +++++----- clang/lib/CIR/Dialect/IR/CIRDialect.cpp | 6 +++--- clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index 746583985d4c5..853a321b29309 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -2199,7 +2199,7 @@ def VecShuffleDynamicOp : CIR_Op<"vec.shuffle.dynamic", //===----------------------------------------------------------------------===// def VecTernaryOp : CIR_Op<"vec.ternary", - [Pure, AllTypesMatch<["result", "vec1", "vec2"]>]> { + [Pure, AllTypesMatch<["result", "lhs", "rhs"]>]> { let summary = "The `cond ? a : b` ternary operator for vector types"; let description = [{ The `cir.vec.ternary` operation represents the C/C++ ternary operator, @@ -2218,14 +2218,14 @@ def VecTernaryOp : CIR_Op<"vec.ternary", let arguments = (ins CIR_VectorOfIntType:$cond, - CIR_VectorType:$vec1, - CIR_VectorType:$vec2 + CIR_VectorType:$lhs, + CIR_VectorType:$rhs ); let results = (outs CIR_VectorType:$result); let assemblyFormat = [{ - `(` $cond `,` $vec1 `,` $vec2 `)` `:` qualified(type($cond)) `,` - qualified(type($vec1)) attr-dict + `(` $cond `,` $lhs`,` $rhs `)` `:` qualified(type($cond)) `,` + qualified(type($lhs)) attr-dict }]; let hasVerifier = 1; } diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp index 7dd4a8ec0c7ef..5c41211d130bf 100644 --- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp @@ -1598,10 +1598,10 @@ LogicalResult cir::VecTernaryOp::verify() { // other operands. (The automatic verification already checked that all // operands are vector types and that the second and third operands are the // same type.) - if (getCond().getType().getSize() != getVec1().getType().getSize()) { + if (getCond().getType().getSize() != getLhs().getType().getSize()) { return emitOpError() << ": the number of elements in " - << getCond().getType() << " and " - << getVec1().getType() << " don't match"; + << getCond().getType() << " and " << getLhs().getType() + << " don't match"; } return success(); } diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index e5a26260dc8cc..2a73b23802ae4 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -1927,7 +1927,7 @@ mlir::LogicalResult CIRToLLVMVecTernaryOpLowering::matchAndRewrite( op.getCond().getLoc(), typeConverter->convertType(op.getCond().getType()))); rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>( - op, bitVec, adaptor.getVec1(), adaptor.getVec2()); + op, bitVec, adaptor.getLhs(), adaptor.getRhs()); return mlir::success(); } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits