https://github.com/Lancern created https://github.com/llvm/llvm-project/pull/147200
This patch adds support for the following two builtin functions: - `__builtin_bswap`, represented by the `cir.bswap` operation. - `__builtin_bitreverse`, represented by the `cir.bit.reverse` operation. >From 35ca85872ebc60f36f55c753c6aa33e00d94a91d Mon Sep 17 00:00:00 2001 From: Sirui Mu <msrlanc...@gmail.com> Date: Mon, 7 Jul 2025 00:45:48 +0800 Subject: [PATCH] [CIR] Add bit reverse and byte reverse operations --- clang/include/clang/CIR/Dialect/IR/CIROps.td | 49 ++++++++++ clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp | 20 ++++ .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 16 ++++ .../CIR/Lowering/DirectToLLVM/LowerToLLVM.h | 20 ++++ clang/test/CIR/CodeGen/builtin_bit.cpp | 91 +++++++++++++++++++ 5 files changed, 196 insertions(+) diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index 6529f1386599c..e26942d5cf511 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -2661,6 +2661,55 @@ def BitPopcountOp : CIR_BitOpBase<"bit.popcnt", }]; } +def BitReverseOp : CIR_BitOpBase<"bit.reverse", CIR_UIntOfWidths<[8, 16, 32, 64]>> { + let summary = "Reverse the bit pattern of the operand integer"; + let description = [{ + The `cir.bit.reverse` operation reverses the bits of the operand integer. + Its only argument must be of unsigned integer types of width 8, 16, 32, or + 64. + + This operation covers the C/C++ builtin function `__builtin_bitreverse`. + + Example: + + ```mlir + %1 = cir.bit.reverse %0 : !u32i + ``` + }]; +} + +//===----------------------------------------------------------------------===// +// ByteswapOp +//===----------------------------------------------------------------------===// + +def ByteSwapOp : CIR_Op<"bswap", [Pure, SameOperandsAndResultType]> { + let summary = "Reverse the bytes in the object representation of the operand"; + let description = [{ + The `cir.bswap` operation takes an integer as operand, reverse the bytes in + the object representation of the operand integer, and returns the result. + + The operand integer must be an unsigned integer. Its widths must be either + 16, 32, or 64. + + Example: + + ```mlir + // %0 = 0x12345678 + %0 = cir.const #cir.int<305419896> : !u32i + + // %1 should be 0x78563412 + %1 = cir.bswap(%0 : !u32i) : !u32i + ``` + }]; + + let results = (outs CIR_IntType:$result); + let arguments = (ins CIR_UIntOfWidths<[16, 32, 64]>:$input); + + let assemblyFormat = [{ + `(` $input `:` type($input) `)` `:` type($result) attr-dict + }]; +} + //===----------------------------------------------------------------------===// // Assume Operations //===----------------------------------------------------------------------===// diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp index fb046533a91b8..6c90bb7975630 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp @@ -190,6 +190,26 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl &gd, unsigned builtinID, expectedValue, probAttr); return RValue::get(result); } + + case Builtin::BI__builtin_bswap16: + case Builtin::BI__builtin_bswap32: + case Builtin::BI__builtin_bswap64: + case Builtin::BI_byteswap_ushort: + case Builtin::BI_byteswap_ulong: + case Builtin::BI_byteswap_uint64: { + mlir::Value arg = emitScalarExpr(e->getArg(0)); + return RValue::get( + builder.create<cir::ByteSwapOp>(getLoc(e->getSourceRange()), arg)); + } + + case Builtin::BI__builtin_bitreverse8: + case Builtin::BI__builtin_bitreverse16: + case Builtin::BI__builtin_bitreverse32: + case Builtin::BI__builtin_bitreverse64: { + mlir::Value arg = emitScalarExpr(e->getArg(0)); + return RValue::get( + builder.create<cir::BitReverseOp>(getLoc(e->getSourceRange()), arg)); + } } cgm.errorNYI(e->getSourceRange(), "unimplemented builtin call"); diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index 5ac42b6a63b09..acbaae1d227d0 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -535,6 +535,13 @@ mlir::LogicalResult CIRToLLVMBitPopcountOpLowering::matchAndRewrite( return mlir::LogicalResult::success(); } +mlir::LogicalResult CIRToLLVMBitReverseOpLowering::matchAndRewrite( + cir::BitReverseOp op, OpAdaptor adaptor, + mlir::ConversionPatternRewriter &rewriter) const { + rewriter.replaceOpWithNewOp<mlir::LLVM::BitReverseOp>(op, adaptor.getInput()); + return mlir::success(); +} + mlir::LogicalResult CIRToLLVMBrCondOpLowering::matchAndRewrite( cir::BrCondOp brOp, OpAdaptor adaptor, mlir::ConversionPatternRewriter &rewriter) const { @@ -551,6 +558,13 @@ mlir::LogicalResult CIRToLLVMBrCondOpLowering::matchAndRewrite( return mlir::success(); } +mlir::LogicalResult CIRToLLVMByteSwapOpLowering::matchAndRewrite( + cir::ByteSwapOp op, OpAdaptor adaptor, + mlir::ConversionPatternRewriter &rewriter) const { + rewriter.replaceOpWithNewOp<mlir::LLVM::ByteSwapOp>(op, adaptor.getInput()); + return mlir::LogicalResult::success(); +} + mlir::Type CIRToLLVMCastOpLowering::convertTy(mlir::Type ty) const { return getTypeConverter()->convertType(ty); } @@ -2035,8 +2049,10 @@ void ConvertCIRToLLVMPass::runOnOperation() { CIRToLLVMBitCtzOpLowering, CIRToLLVMBitParityOpLowering, CIRToLLVMBitPopcountOpLowering, + CIRToLLVMBitReverseOpLowering, CIRToLLVMBrCondOpLowering, CIRToLLVMBrOpLowering, + CIRToLLVMByteSwapOpLowering, CIRToLLVMCallOpLowering, CIRToLLVMCmpOpLowering, CIRToLLVMComplexCreateOpLowering, diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h index d9fb91066317b..83e692d6dcbac 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h @@ -94,6 +94,16 @@ class CIRToLLVMBitPopcountOpLowering mlir::ConversionPatternRewriter &) const override; }; +class CIRToLLVMBitReverseOpLowering + : public mlir::OpConversionPattern<cir::BitReverseOp> { +public: + using mlir::OpConversionPattern<cir::BitReverseOp>::OpConversionPattern; + + mlir::LogicalResult + matchAndRewrite(cir::BitReverseOp op, OpAdaptor, + mlir::ConversionPatternRewriter &) const override; +}; + class CIRToLLVMBrCondOpLowering : public mlir::OpConversionPattern<cir::BrCondOp> { public: @@ -104,6 +114,16 @@ class CIRToLLVMBrCondOpLowering mlir::ConversionPatternRewriter &) const override; }; +class CIRToLLVMByteSwapOpLowering + : public mlir::OpConversionPattern<cir::ByteSwapOp> { +public: + using mlir::OpConversionPattern<cir::ByteSwapOp>::OpConversionPattern; + + mlir::LogicalResult + matchAndRewrite(cir::ByteSwapOp op, OpAdaptor, + mlir::ConversionPatternRewriter &) const override; +}; + class CIRToLLVMCastOpLowering : public mlir::OpConversionPattern<cir::CastOp> { mlir::DataLayout const &dataLayout; diff --git a/clang/test/CIR/CodeGen/builtin_bit.cpp b/clang/test/CIR/CodeGen/builtin_bit.cpp index ba56c91ce7401..55377ce3b80fa 100644 --- a/clang/test/CIR/CodeGen/builtin_bit.cpp +++ b/clang/test/CIR/CodeGen/builtin_bit.cpp @@ -325,3 +325,94 @@ int test_builtin_popcountg(unsigned x) { // OGCG-LABEL: _Z22test_builtin_popcountgj // OGCG: %{{.+}} = call i32 @llvm.ctpop.i32(i32 %{{.+}}) + +unsigned char test_builtin_bitreverse8(unsigned char x) { + return __builtin_bitreverse8(x); +} + +// CIR-LABEL: @_Z24test_builtin_bitreverse8h +// CIR: %{{.+}} = cir.bit.reverse(%{{.+}} : !u8i) : !u8i + +// LLVM-LABEL: @_Z24test_builtin_bitreverse8h +// LLVM: %{{.+}} = call i8 @llvm.bitreverse.i8(i8 %{{.+}}) + +// OGCG-LABEL: @_Z24test_builtin_bitreverse8h +// OGCG: %{{.+}} = call i8 @llvm.bitreverse.i8(i8 %{{.+}}) + +unsigned short test_builtin_bitreverse16(unsigned short x) { + return __builtin_bitreverse16(x); +} + +// CIR-LABEL: @_Z25test_builtin_bitreverse16t +// CIR: %{{.+}} = cir.bit.reverse(%{{.+}} : !u16i) : !u16i + +// LLVM-LABEL: @_Z25test_builtin_bitreverse16t +// LLVM: %{{.+}} = call i16 @llvm.bitreverse.i16(i16 %{{.+}}) + +// OGCG-LABEL: @_Z25test_builtin_bitreverse16t +// OGCG: %{{.+}} = call i16 @llvm.bitreverse.i16(i16 %{{.+}}) + +unsigned test_builtin_bitreverse32(unsigned x) { + return __builtin_bitreverse32(x); +} + +// CIR-LABEL: @_Z25test_builtin_bitreverse32j +// CIR: %{{.+}} = cir.bit.reverse(%{{.+}} : !u32i) : !u32i + +// LLVM-LABEL: @_Z25test_builtin_bitreverse32j +// LLVM: %{{.+}} = call i32 @llvm.bitreverse.i32(i32 %{{.+}}) + +// OGCG-LABEL: @_Z25test_builtin_bitreverse32j +// OGCG: %{{.+}} = call i32 @llvm.bitreverse.i32(i32 %{{.+}}) + +unsigned long long test_builtin_bitreverse64(unsigned long long x) { + return __builtin_bitreverse64(x); +} + +// CIR-LABEL: @_Z25test_builtin_bitreverse64y +// CIR: %{{.+}} = cir.bit.reverse(%{{.+}} : !u64i) : !u64i + +// LLVM-LABEL: @_Z25test_builtin_bitreverse64y +// LLVM: %{{.+}} = call i64 @llvm.bitreverse.i64(i64 %{{.+}}) + +// OGCG-LABEL: @_Z25test_builtin_bitreverse64y +// OGCG: %{{.+}} = call i64 @llvm.bitreverse.i64(i64 %{{.+}}) + +unsigned short test_builtin_bswap16(unsigned short x) { + return __builtin_bswap16(x); +} + +// CIR-LABEL: @_Z20test_builtin_bswap16t +// CIR: %{{.+}} = cir.bswap(%{{.+}} : !u16i) : !u16i + +// LLVM-LABEL: @_Z20test_builtin_bswap16t +// LLVM: %{{.+}} = call i16 @llvm.bswap.i16(i16 %{{.+}}) + +// OGCG-LABEL: @_Z20test_builtin_bswap16t +// OGCG: %{{.+}} = call i16 @llvm.bswap.i16(i16 %{{.+}}) + +unsigned test_builtin_bswap32(unsigned x) { + return __builtin_bswap32(x); +} + +// CIR-LABEL: @_Z20test_builtin_bswap32j +// CIR: %{{.+}} = cir.bswap(%{{.+}} : !u32i) : !u32i + +// LLVM-LABEL: @_Z20test_builtin_bswap32j +// LLVM: %{{.+}} = call i32 @llvm.bswap.i32(i32 %{{.+}}) + +// OGCG-LABEL: @_Z20test_builtin_bswap32j +// OGCG: %{{.+}} = call i32 @llvm.bswap.i32(i32 %{{.+}}) + +unsigned long long test_builtin_bswap64(unsigned long long x) { + return __builtin_bswap64(x); +} + +// CIR-LABEL: @_Z20test_builtin_bswap64y +// CIR: %{{.+}} = cir.bswap(%{{.+}} : !u64i) : !u64i + +// LLVM-LABEL: @_Z20test_builtin_bswap64y +// LLVM: %{{.+}} = call i64 @llvm.bswap.i64(i64 %{{.+}}) + +// OGCG-LABEL: @_Z20test_builtin_bswap64y +// OGCG: %{{.+}} = call i64 @llvm.bswap.i64(i64 %{{.+}}) _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits