https://github.com/AmrDeveloper updated https://github.com/llvm/llvm-project/pull/139444
>From 46d3b466df954eee87a5e5e7df5cb03802d468c7 Mon Sep 17 00:00:00 2001 From: AmrDeveloper <am...@programmer.net> Date: Sat, 10 May 2025 20:37:05 +0200 Subject: [PATCH 1/2] [CIR] Upstream unary operators for VectorType --- .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 48 +++++++++++----- clang/test/CIR/CodeGen/vector-ext.cpp | 57 +++++++++++++++++++ clang/test/CIR/CodeGen/vector.cpp | 57 +++++++++++++++++++ 3 files changed, 148 insertions(+), 14 deletions(-) diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index a1066cfe67ef9..dc632867d863c 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -1043,12 +1043,11 @@ mlir::LogicalResult CIRToLLVMUnaryOpLowering::matchAndRewrite( mlir::ConversionPatternRewriter &rewriter) const { assert(op.getType() == op.getInput().getType() && "Unary operation's operand type and result type are different"); - mlir::Type type = op.getType(); - mlir::Type elementType = type; - bool isVector = false; - assert(!cir::MissingFeatures::vectorType()); - mlir::Type llvmType = getTypeConverter()->convertType(type); - mlir::Location loc = op.getLoc(); + const mlir::Type type = op.getType(); + const mlir::Type elementType = elementTypeIfVector(type); + const bool isVector = mlir::isa<cir::VectorType>(type); + const mlir::Type llvmType = getTypeConverter()->convertType(type); + const mlir::Location loc = op.getLoc(); // Integer unary operations: + - ~ ++ -- if (mlir::isa<cir::IntType>(elementType)) { @@ -1076,20 +1075,41 @@ mlir::LogicalResult CIRToLLVMUnaryOpLowering::matchAndRewrite( rewriter.replaceOp(op, adaptor.getInput()); return mlir::success(); case cir::UnaryOpKind::Minus: { - assert(!isVector && - "Add vector handling when vector types are supported"); - mlir::LLVM::ConstantOp zero = rewriter.create<mlir::LLVM::ConstantOp>( - loc, llvmType, mlir::IntegerAttr::get(llvmType, 0)); + mlir::Value zero; + if (isVector) + zero = rewriter.create<mlir::LLVM::ZeroOp>(loc, llvmType); + else + zero = rewriter.create<mlir::LLVM::ConstantOp>( + loc, llvmType, mlir::IntegerAttr::get(llvmType, 0)); rewriter.replaceOpWithNewOp<mlir::LLVM::SubOp>( op, llvmType, zero, adaptor.getInput(), maybeNSW); return mlir::success(); } case cir::UnaryOpKind::Not: { // bit-wise compliment operator, implemented as an XOR with -1. - assert(!isVector && - "Add vector handling when vector types are supported"); - mlir::LLVM::ConstantOp minusOne = rewriter.create<mlir::LLVM::ConstantOp>( - loc, llvmType, mlir::IntegerAttr::get(llvmType, -1)); + mlir::Value minusOne; + if (isVector) { + // Creating a vector object with all -1 values is easier said than + // done. It requires a series of insertelement ops. + const mlir::Type llvmElementType = + getTypeConverter()->convertType(elementType); + const mlir::Value minusOneInt = rewriter.create<mlir::LLVM::ConstantOp>( + loc, llvmElementType, mlir::IntegerAttr::get(llvmElementType, -1)); + minusOne = rewriter.create<mlir::LLVM::UndefOp>(loc, llvmType); + + const uint64_t numElements = + mlir::dyn_cast<cir::VectorType>(type).getSize(); + for (uint64_t i = 0; i < numElements; ++i) { + const mlir::Value indexValue = + rewriter.create<mlir::LLVM::ConstantOp>(loc, + rewriter.getI64Type(), i); + minusOne = rewriter.create<mlir::LLVM::InsertElementOp>( + loc, minusOne, minusOneInt, indexValue); + } + } else { + minusOne = rewriter.create<mlir::LLVM::ConstantOp>( + loc, llvmType, mlir::IntegerAttr::get(llvmType, -1)); + } rewriter.replaceOpWithNewOp<mlir::LLVM::XOrOp>( op, llvmType, adaptor.getInput(), minusOne); return mlir::success(); diff --git a/clang/test/CIR/CodeGen/vector-ext.cpp b/clang/test/CIR/CodeGen/vector-ext.cpp index a16ef42f113df..504a13d9bb237 100644 --- a/clang/test/CIR/CodeGen/vector-ext.cpp +++ b/clang/test/CIR/CodeGen/vector-ext.cpp @@ -337,6 +337,63 @@ void foo7() { // OGCG: %[[NEW_VEC:.*]] = insertelement <4 x i32> %[[TMP2]], i32 %[[RES]], i32 2 // OGCG: store <4 x i32> %[[NEW_VEC]], ptr %[[VEC]], align 16 + +void foo8() { + vi4 a = { 1, 2, 3, 4 }; + vi4 plus_res = +a; + vi4 minus_res = -a; + vi4 not_res = ~a; +} + +// CIR: %[[VEC:.*]] = cir.alloca !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>>, ["a", init] +// CIR: %[[PLUS_RES:.*]] = cir.alloca !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>>, ["plus_res", init] +// CIR: %[[MINUS_RES:.*]] = cir.alloca !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>>, ["minus_res", init] +// CIR: %[[NOT_RES:.*]] = cir.alloca !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>>, ["not_res", init] +// CIR: %[[CONST_1:.*]] = cir.const #cir.int<1> : !s32i +// CIR: %[[CONST_2:.*]] = cir.const #cir.int<2> : !s32i +// CIR: %[[CONST_3:.*]] = cir.const #cir.int<3> : !s32i +// CIR: %[[CONST_4:.*]] = cir.const #cir.int<4> : !s32i +// CIR: %[[VEC_VAL:.*]] = cir.vec.create(%[[CONST_1]], %[[CONST_2]], %[[CONST_3]], %[[CONST_4]] : +// CIR-SAME: !s32i, !s32i, !s32i, !s32i) : !cir.vector<4 x !s32i> +// CIR: cir.store %[[VEC_VAL]], %[[VEC]] : !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>> +// CIR: %[[TMP1:.*]] = cir.load %[[VEC]] : !cir.ptr<!cir.vector<4 x !s32i>>, !cir.vector<4 x !s32i> +// CIR: %[[PLUS:.*]] = cir.unary(plus, %[[TMP1]]) : !cir.vector<4 x !s32i>, !cir.vector<4 x !s32i> +// CIR: cir.store %[[PLUS]], %[[PLUS_RES]] : !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>> +// CIR: %[[TMP2:.*]] = cir.load %[[VEC]] : !cir.ptr<!cir.vector<4 x !s32i>>, !cir.vector<4 x !s32i> +// CIR: %[[MINUS:.*]] = cir.unary(minus, %[[TMP2]]) : !cir.vector<4 x !s32i>, !cir.vector<4 x !s32i> +// CIR: cir.store %[[MINUS]], %[[MINUS_RES]] : !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>> +// CIR: %[[TMP3:.*]] = cir.load %[[VEC]] : !cir.ptr<!cir.vector<4 x !s32i>>, !cir.vector<4 x !s32i> +// CIR: %[[NOT:.*]] = cir.unary(not, %[[TMP3]]) : !cir.vector<4 x !s32i>, !cir.vector<4 x !s32i> +// CIR: cir.store %[[NOT]], %[[NOT_RES]] : !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>> + +// LLVM: %[[VEC:.*]] = alloca <4 x i32>, i64 1, align 16 +// LLVM: %[[PLUS_RES:.*]] = alloca <4 x i32>, i64 1, align 16 +// LLVM: %[[MINUS_RES:.*]] = alloca <4 x i32>, i64 1, align 16 +// LLVM: %[[NOT_RES:.*]] = alloca <4 x i32>, i64 1, align 16 +// LLVM: store <4 x i32> <i32 1, i32 2, i32 3, i32 4>, ptr %[[VEC]], align 16 +// LLVM: %[[TMP1:.*]] = load <4 x i32>, ptr %[[VEC]], align 16 +// LLVM: store <4 x i32> %[[TMP1]], ptr %[[PLUS_RES]], align 16 +// LLVM: %[[TMP2:.*]] = load <4 x i32>, ptr %[[VEC]], align 16 +// LLVM: %[[SUB:.*]] = sub <4 x i32> zeroinitializer, %[[TMP2]] +// LLVM: store <4 x i32> %[[SUB]], ptr %[[MINUS_RES]], align 16 +// LLVM: %[[TMP3:.*]] = load <4 x i32>, ptr %[[VEC]], align 16 +// LLVM: %[[NOT:.*]] = xor <4 x i32> %[[TMP3]], splat (i32 -1) +// LLVM: store <4 x i32> %[[NOT]], ptr %[[NOT_RES]], align 16 + +// OGCG: %[[VEC:.*]] = alloca <4 x i32>, align 16 +// OGCG: %[[PLUS_RES:.*]] = alloca <4 x i32>, align 16 +// OGCG: %[[MINUS_RES:.*]] = alloca <4 x i32>, align 16 +// OGCG: %[[NOT_RES:.*]] = alloca <4 x i32>, align 16 +// OGCG: store <4 x i32> <i32 1, i32 2, i32 3, i32 4>, ptr %[[VEC]], align 16 +// OGCG: %[[TMP1:.*]] = load <4 x i32>, ptr %[[VEC]], align 16 +// OGCG: store <4 x i32> %[[TMP1]], ptr %[[PLUS_RES]], align 16 +// OGCG: %[[TMP2:.*]] = load <4 x i32>, ptr %[[VEC]], align 16 +// OGCG: %[[SUB:.*]] = sub <4 x i32> zeroinitializer, %[[TMP2]] +// OGCG: store <4 x i32> %[[SUB]], ptr %[[MINUS_RES]], align 16 +// OGCG: %[[TMP3:.*]] = load <4 x i32>, ptr %[[VEC]], align 16 +// OGCG: %[[NOT:.*]] = xor <4 x i32> %[[TMP3]], splat (i32 -1) +// OGCG: store <4 x i32> %[[NOT]], ptr %[[NOT_RES]], align 16 + void foo9() { vi4 a = {1, 2, 3, 4}; vi4 b = {5, 6, 7, 8}; diff --git a/clang/test/CIR/CodeGen/vector.cpp b/clang/test/CIR/CodeGen/vector.cpp index 4546215865095..ad5641121d852 100644 --- a/clang/test/CIR/CodeGen/vector.cpp +++ b/clang/test/CIR/CodeGen/vector.cpp @@ -325,6 +325,63 @@ void foo7() { // OGCG: %[[NEW_VEC:.*]] = insertelement <4 x i32> %[[TMP2]], i32 %[[RES]], i32 2 // OGCG: store <4 x i32> %[[NEW_VEC]], ptr %[[VEC]], align 16 + +void foo8() { + vi4 a = { 1, 2, 3, 4 }; + vi4 plus_res = +a; + vi4 minus_res = -a; + vi4 not_res = ~a; +} + +// CIR: %[[VEC:.*]] = cir.alloca !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>>, ["a", init] +// CIR: %[[PLUS_RES:.*]] = cir.alloca !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>>, ["plus_res", init] +// CIR: %[[MINUS_RES:.*]] = cir.alloca !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>>, ["minus_res", init] +// CIR: %[[NOT_RES:.*]] = cir.alloca !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>>, ["not_res", init] +// CIR: %[[CONST_1:.*]] = cir.const #cir.int<1> : !s32i +// CIR: %[[CONST_2:.*]] = cir.const #cir.int<2> : !s32i +// CIR: %[[CONST_3:.*]] = cir.const #cir.int<3> : !s32i +// CIR: %[[CONST_4:.*]] = cir.const #cir.int<4> : !s32i +// CIR: %[[VEC_VAL:.*]] = cir.vec.create(%[[CONST_1]], %[[CONST_2]], %[[CONST_3]], %[[CONST_4]] : +// CIR-SAME: !s32i, !s32i, !s32i, !s32i) : !cir.vector<4 x !s32i> +// CIR: cir.store %[[VEC_VAL]], %[[VEC]] : !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>> +// CIR: %[[TMP1:.*]] = cir.load %[[VEC]] : !cir.ptr<!cir.vector<4 x !s32i>>, !cir.vector<4 x !s32i> +// CIR: %[[PLUS:.*]] = cir.unary(plus, %[[TMP1]]) : !cir.vector<4 x !s32i>, !cir.vector<4 x !s32i> +// CIR: cir.store %[[PLUS]], %[[PLUS_RES]] : !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>> +// CIR: %[[TMP2:.*]] = cir.load %[[VEC]] : !cir.ptr<!cir.vector<4 x !s32i>>, !cir.vector<4 x !s32i> +// CIR: %[[MINUS:.*]] = cir.unary(minus, %[[TMP2]]) : !cir.vector<4 x !s32i>, !cir.vector<4 x !s32i> +// CIR: cir.store %[[MINUS]], %[[MINUS_RES]] : !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>> +// CIR: %[[TMP3:.*]] = cir.load %[[VEC]] : !cir.ptr<!cir.vector<4 x !s32i>>, !cir.vector<4 x !s32i> +// CIR: %[[NOT:.*]] = cir.unary(not, %[[TMP3]]) : !cir.vector<4 x !s32i>, !cir.vector<4 x !s32i> +// CIR: cir.store %[[NOT]], %[[NOT_RES]] : !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>> + +// LLVM: %[[VEC:.*]] = alloca <4 x i32>, i64 1, align 16 +// LLVM: %[[PLUS_RES:.*]] = alloca <4 x i32>, i64 1, align 16 +// LLVM: %[[MINUS_RES:.*]] = alloca <4 x i32>, i64 1, align 16 +// LLVM: %[[NOT_RES:.*]] = alloca <4 x i32>, i64 1, align 16 +// LLVM: store <4 x i32> <i32 1, i32 2, i32 3, i32 4>, ptr %[[VEC]], align 16 +// LLVM: %[[TMP1:.*]] = load <4 x i32>, ptr %[[VEC]], align 16 +// LLVM: store <4 x i32> %[[TMP1]], ptr %[[PLUS_RES]], align 16 +// LLVM: %[[TMP2:.*]] = load <4 x i32>, ptr %[[VEC]], align 16 +// LLVM: %[[SUB:.*]] = sub <4 x i32> zeroinitializer, %[[TMP2]] +// LLVM: store <4 x i32> %[[SUB]], ptr %[[MINUS_RES]], align 16 +// LLVM: %[[TMP3:.*]] = load <4 x i32>, ptr %[[VEC]], align 16 +// LLVM: %[[NOT:.*]] = xor <4 x i32> %[[TMP3]], splat (i32 -1) +// LLVM: store <4 x i32> %[[NOT]], ptr %[[NOT_RES]], align 16 + +// OGCG: %[[VEC:.*]] = alloca <4 x i32>, align 16 +// OGCG: %[[PLUS_RES:.*]] = alloca <4 x i32>, align 16 +// OGCG: %[[MINUS_RES:.*]] = alloca <4 x i32>, align 16 +// OGCG: %[[NOT_RES:.*]] = alloca <4 x i32>, align 16 +// OGCG: store <4 x i32> <i32 1, i32 2, i32 3, i32 4>, ptr %[[VEC]], align 16 +// OGCG: %[[TMP1:.*]] = load <4 x i32>, ptr %[[VEC]], align 16 +// OGCG: store <4 x i32> %[[TMP1]], ptr %[[PLUS_RES]], align 16 +// OGCG: %[[TMP2:.*]] = load <4 x i32>, ptr %[[VEC]], align 16 +// OGCG: %[[SUB:.*]] = sub <4 x i32> zeroinitializer, %[[TMP2]] +// OGCG: store <4 x i32> %[[SUB]], ptr %[[MINUS_RES]], align 16 +// OGCG: %[[TMP3:.*]] = load <4 x i32>, ptr %[[VEC]], align 16 +// OGCG: %[[NOT:.*]] = xor <4 x i32> %[[TMP3]], splat (i32 -1) +// OGCG: store <4 x i32> %[[NOT]], ptr %[[NOT_RES]], align 16 + void foo9() { vi4 a = {1, 2, 3, 4}; vi4 b = {5, 6, 7, 8}; >From 92f23e11707af38c94a29054aa16857970e95d23 Mon Sep 17 00:00:00 2001 From: AmrDeveloper <am...@programmer.net> Date: Thu, 15 May 2025 21:14:39 +0200 Subject: [PATCH 2/2] Address code review comments --- .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 31 ++++++------------- 1 file changed, 10 insertions(+), 21 deletions(-) diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index dc632867d863c..ba22f2cc6ba98 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -57,7 +57,7 @@ namespace { mlir::Type elementTypeIfVector(mlir::Type type) { return llvm::TypeSwitch<mlir::Type, mlir::Type>(type) .Case<cir::VectorType, mlir::VectorType>( - [](auto p) { return p->getElementType(); }) + [](auto p) { return p.getElementType(); }) .Default([](mlir::Type p) { return p; }); } } // namespace @@ -1043,11 +1043,11 @@ mlir::LogicalResult CIRToLLVMUnaryOpLowering::matchAndRewrite( mlir::ConversionPatternRewriter &rewriter) const { assert(op.getType() == op.getInput().getType() && "Unary operation's operand type and result type are different"); - const mlir::Type type = op.getType(); - const mlir::Type elementType = elementTypeIfVector(type); - const bool isVector = mlir::isa<cir::VectorType>(type); - const mlir::Type llvmType = getTypeConverter()->convertType(type); - const mlir::Location loc = op.getLoc(); + mlir::Type type = op.getType(); + mlir::Type elementType = elementTypeIfVector(type); + bool isVector = mlir::isa<cir::VectorType>(type); + mlir::Type llvmType = getTypeConverter()->convertType(type); + mlir::Location loc = op.getLoc(); // Integer unary operations: + - ~ ++ -- if (mlir::isa<cir::IntType>(elementType)) { @@ -1089,23 +1089,12 @@ mlir::LogicalResult CIRToLLVMUnaryOpLowering::matchAndRewrite( // bit-wise compliment operator, implemented as an XOR with -1. mlir::Value minusOne; if (isVector) { - // Creating a vector object with all -1 values is easier said than - // done. It requires a series of insertelement ops. - const mlir::Type llvmElementType = - getTypeConverter()->convertType(elementType); - const mlir::Value minusOneInt = rewriter.create<mlir::LLVM::ConstantOp>( - loc, llvmElementType, mlir::IntegerAttr::get(llvmElementType, -1)); - minusOne = rewriter.create<mlir::LLVM::UndefOp>(loc, llvmType); - const uint64_t numElements = mlir::dyn_cast<cir::VectorType>(type).getSize(); - for (uint64_t i = 0; i < numElements; ++i) { - const mlir::Value indexValue = - rewriter.create<mlir::LLVM::ConstantOp>(loc, - rewriter.getI64Type(), i); - minusOne = rewriter.create<mlir::LLVM::InsertElementOp>( - loc, minusOne, minusOneInt, indexValue); - } + std::vector<int32_t> values(numElements, -1); + mlir::DenseIntElementsAttr denseVec = rewriter.getI32VectorAttr(values); + minusOne = + rewriter.create<mlir::LLVM::ConstantOp>(loc, llvmType, denseVec); } else { minusOne = rewriter.create<mlir::LLVM::ConstantOp>( loc, llvmType, mlir::IntegerAttr::get(llvmType, -1)); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits