[clang] [CIR] Add bit reverse and byte reverse operations (PR #147200)
llvm-ci wrote: LLVM Buildbot has detected a new failure on builder `llvm-clang-aarch64-darwin` running on `doug-worker-4` while building `clang` at step 6 "test-build-unified-tree-check-all". Full details are available at: https://lab.llvm.org/buildbot/#/builders/190/builds/23350 Here is the relevant piece of the build log for the reference ``` Step 6 (test-build-unified-tree-check-all) failure: test (failure) TEST 'Clang-Unit :: ./AllClangUnitTests/15/48' FAILED Script(shard): -- GTEST_OUTPUT=json:/Users/buildbot/buildbot-root/aarch64-darwin/build/tools/clang/unittests/./AllClangUnitTests-Clang-Unit-70875-15-48.json GTEST_SHUFFLE=0 GTEST_TOTAL_SHARDS=48 GTEST_SHARD_INDEX=15 /Users/buildbot/buildbot-root/aarch64-darwin/build/tools/clang/unittests/./AllClangUnitTests -- Script: -- /Users/buildbot/buildbot-root/aarch64-darwin/build/tools/clang/unittests/./AllClangUnitTests --gtest_filter=DirectoryWatcherTest.AddFiles -- /Users/buildbot/buildbot-root/aarch64-darwin/llvm-project/clang/unittests/DirectoryWatcher/DirectoryWatcherTest.cpp:257: Failure Value of: WaitForExpectedStateResult.wait_for(EventualResultTimeout) == std::future_status::ready Actual: false Expected: true The expected result state wasn't reached before the time-out. /Users/buildbot/buildbot-root/aarch64-darwin/llvm-project/clang/unittests/DirectoryWatcher/DirectoryWatcherTest.cpp:260: Failure Value of: TestConsumer.result().has_value() Actual: false Expected: true /Users/buildbot/buildbot-root/aarch64-darwin/llvm-project/clang/unittests/DirectoryWatcher/DirectoryWatcherTest.cpp:257 Value of: WaitForExpectedStateResult.wait_for(EventualResultTimeout) == std::future_status::ready Actual: false Expected: true The expected result state wasn't reached before the time-out. /Users/buildbot/buildbot-root/aarch64-darwin/llvm-project/clang/unittests/DirectoryWatcher/DirectoryWatcherTest.cpp:260 Value of: TestConsumer.result().has_value() Actual: false Expected: true ``` https://github.com/llvm/llvm-project/pull/147200 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] Add bit reverse and byte reverse operations (PR #147200)
https://github.com/Lancern closed https://github.com/llvm/llvm-project/pull/147200 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] Add bit reverse and byte reverse operations (PR #147200)
Lancern wrote: I'm going to merge this and I'll send another patch to resolve the various nits in the comments. https://github.com/llvm/llvm-project/pull/147200 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] Add bit reverse and byte reverse operations (PR #147200)
@@ -2661,6 +2661,45 @@ 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): !u32i
+```
+ }];
+}
+
+def ByteSwapOp : CIR_BitOpBase<"bit.byte_swap", CIR_UIntOfWidths<[16, 32,
64]>> {
+ 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.bit.bswap(%0 : !u32i) : !u32i
Lancern wrote:
Changed its name to `cir.byte_swap`.
https://github.com/llvm/llvm-project/pull/147200
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] Add bit reverse and byte reverse operations (PR #147200)
https://github.com/Lancern updated
https://github.com/llvm/llvm-project/pull/147200
>From fb556207b6a0504e0b767dd655ae5df146a70f30 Mon Sep 17 00:00:00 2001
From: Sirui Mu
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 | 39
clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp | 36 +---
.../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 16
.../CIR/Lowering/DirectToLLVM/LowerToLLVM.h | 20
clang/test/CIR/CodeGen/builtin_bit.cpp| 91 +++
5 files changed, 191 insertions(+), 11 deletions(-)
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td
b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 6529f1386599c..cdbe3c51c8d5f 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -2661,6 +2661,45 @@ 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): !u32i
+```
+ }];
+}
+
+def ByteSwapOp : CIR_BitOpBase<"byte_swap", CIR_UIntOfWidths<[16, 32, 64]>> {
+ let summary = "Reverse the bytes in the object representation of the
operand";
+ let description = [{
+The `cir.byte_swap` 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.byte_swap(%0 : !u32i) : !u32i
+```
+ }];
+}
+
//===--===//
// Assume Operations
//===--===//
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
index fb046533a91b8..25be6f35df501 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
@@ -60,15 +60,15 @@ static RValue emitBuiltinBitOp(CIRGenFunction &cgf, const
CallExpr *e,
RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl &gd, unsigned
builtinID,
const CallExpr *e,
ReturnValueSlot returnValue) {
+ mlir::Location loc = getLoc(e->getSourceRange());
+
// See if we can constant fold this builtin. If so, don't emit it at all.
// TODO: Extend this handling to all builtin calls that we can constant-fold.
Expr::EvalResult result;
if (e->isPRValue() && e->EvaluateAsRValue(result, cgm.getASTContext()) &&
!result.hasSideEffects()) {
-if (result.Val.isInt()) {
- return RValue::get(builder.getConstInt(getLoc(e->getSourceRange()),
- result.Val.getInt()));
-}
+if (result.Val.isInt())
+ return RValue::get(builder.getConstInt(loc, result.Val.getInt()));
if (result.Val.isFloat()) {
// Note: we are using result type of CallExpr to determine the type of
// the constant. Classic codegen uses the result value to determine the
@@ -76,8 +76,7 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl &gd,
unsigned builtinID,
// hard to imagine a builtin function evaluates to a value that
// over/underflows its own defined type.
mlir::Type type = convertType(e->getType());
- return RValue::get(builder.getConstFP(getLoc(e->getExprLoc()), type,
-result.Val.getFloat()));
+ return RValue::get(builder.getConstFP(loc, type, result.Val.getFloat()));
}
}
@@ -101,8 +100,6 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl
&gd, unsigned builtinID,
assert(!cir::MissingFeatures::builtinCallMathErrno());
assert(!cir::MissingFeatures::builtinCall());
- mlir::Location loc = getLoc(e->getExprLoc());
-
switch (builtinIDIfNoAsmLabel) {
default:
break;
@@ -185,11 +182,28 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl
&gd, unsigned builtinID,
probability);
}
-auto result = builder.create(getLoc(e->getSourceRange()),
-argValue.getType(), argValue,
-expectedValue, probAttr);
+auto result = builder.create(
+
[clang] [CIR] Add bit reverse and byte reverse operations (PR #147200)
@@ -2661,6 +2661,45 @@ 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): !u32i
+```
+ }];
+}
+
+def ByteSwapOp : CIR_BitOpBase<"bit.byte_swap", CIR_UIntOfWidths<[16, 32,
64]>> {
+ 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.bit.bswap(%0 : !u32i) : !u32i
andykaylor wrote:
This is out of sync now.
@xlauko Based on your other comments, I got the impression that you would like
these to be `cir.bitreverse` and `cir.bswap`. Is that correct? If so, that
makes sense to me, and I don't see a reason to merge these with the `.bit`
prefix only to remove it in a subsequent change when the prefix is removed from
other bit operations.
https://github.com/llvm/llvm-project/pull/147200
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] Add bit reverse and byte reverse operations (PR #147200)
@@ -2661,6 +2661,45 @@ 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): !u32i
+```
+ }];
+}
+
+def ByteSwapOp : CIR_BitOpBase<"bit.bswap", CIR_UIntOfWidths<[16, 32, 64]>> {
Lancern wrote:
> Can we maybe spell it out, `bit.byte_swap`?
Updated.
https://github.com/llvm/llvm-project/pull/147200
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] Add bit reverse and byte reverse operations (PR #147200)
https://github.com/Lancern updated
https://github.com/llvm/llvm-project/pull/147200
>From cf2bf0bf66f22e8fdc35baf8d4176aa5af6588d2 Mon Sep 17 00:00:00 2001
From: Sirui Mu
Date: Mon, 7 Jul 2025 00:45:48 +0800
Subject: [PATCH 1/2] [CIR] Add bit reverse and byte reverse operations
---
clang/include/clang/CIR/Dialect/IR/CIROps.td | 39
clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp | 36 +---
.../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 16
.../CIR/Lowering/DirectToLLVM/LowerToLLVM.h | 20
clang/test/CIR/CodeGen/builtin_bit.cpp| 91 +++
5 files changed, 191 insertions(+), 11 deletions(-)
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td
b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 6529f1386599c..48b54c8335b19 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -2661,6 +2661,45 @@ 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): !u32i
+```
+ }];
+}
+
+def ByteSwapOp : CIR_BitOpBase<"bit.bswap", CIR_UIntOfWidths<[16, 32, 64]>> {
+ 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.bit.bswap(%0 : !u32i) : !u32i
+```
+ }];
+}
+
//===--===//
// Assume Operations
//===--===//
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
index fb046533a91b8..25be6f35df501 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
@@ -60,15 +60,15 @@ static RValue emitBuiltinBitOp(CIRGenFunction &cgf, const
CallExpr *e,
RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl &gd, unsigned
builtinID,
const CallExpr *e,
ReturnValueSlot returnValue) {
+ mlir::Location loc = getLoc(e->getSourceRange());
+
// See if we can constant fold this builtin. If so, don't emit it at all.
// TODO: Extend this handling to all builtin calls that we can constant-fold.
Expr::EvalResult result;
if (e->isPRValue() && e->EvaluateAsRValue(result, cgm.getASTContext()) &&
!result.hasSideEffects()) {
-if (result.Val.isInt()) {
- return RValue::get(builder.getConstInt(getLoc(e->getSourceRange()),
- result.Val.getInt()));
-}
+if (result.Val.isInt())
+ return RValue::get(builder.getConstInt(loc, result.Val.getInt()));
if (result.Val.isFloat()) {
// Note: we are using result type of CallExpr to determine the type of
// the constant. Classic codegen uses the result value to determine the
@@ -76,8 +76,7 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl &gd,
unsigned builtinID,
// hard to imagine a builtin function evaluates to a value that
// over/underflows its own defined type.
mlir::Type type = convertType(e->getType());
- return RValue::get(builder.getConstFP(getLoc(e->getExprLoc()), type,
-result.Val.getFloat()));
+ return RValue::get(builder.getConstFP(loc, type, result.Val.getFloat()));
}
}
@@ -101,8 +100,6 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl
&gd, unsigned builtinID,
assert(!cir::MissingFeatures::builtinCallMathErrno());
assert(!cir::MissingFeatures::builtinCall());
- mlir::Location loc = getLoc(e->getExprLoc());
-
switch (builtinIDIfNoAsmLabel) {
default:
break;
@@ -185,11 +182,28 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl
&gd, unsigned builtinID,
probability);
}
-auto result = builder.create(getLoc(e->getSourceRange()),
-argValue.getType(), argValue,
-expectedValue, probAttr);
+auto result = builder.create(
+
[clang] [CIR] Add bit reverse and byte reverse operations (PR #147200)
@@ -2661,6 +2661,45 @@ 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): !u32i
+```
+ }];
+}
+
+def ByteSwapOp : CIR_BitOpBase<"bit.bswap", CIR_UIntOfWidths<[16, 32, 64]>> {
Lancern wrote:
> For the same reason, I’d like to eliminate the bit. prefix entirely and use
> the builtin names directly, like bitreverse (This can be, and probably should
> be done as separate PR).
I'll send a separate PR for this after this PR lands.
https://github.com/llvm/llvm-project/pull/147200
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] Add bit reverse and byte reverse operations (PR #147200)
@@ -2661,6 +2661,45 @@ 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): !u32i
+```
+ }];
+}
+
+def ByteSwapOp : CIR_BitOpBase<"bit.bswap", CIR_UIntOfWidths<[16, 32, 64]>> {
xlauko wrote:
Same here — I’d also prefer to keep the names as close as possible to Clang
builtins. Using similar names reduces cognitive load and makes it easier to
trace things through the entire pipeline.
For the same reason, I’d like to eliminate the `bit.` prefix entirely and use
the builtin names directly, like `bitreverse` (This can be, and probably should
be done as separate PR). I tend to interpret dot-separated names as namespaces,
so using them just for readability feels a bit off. Grouping things like
`complex.` or `libc.` makes sense, as they are in a way subdialects, but when
the goal is simply improved readability, I’d lean toward using underscores
instead in general.
https://github.com/llvm/llvm-project/pull/147200
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] Add bit reverse and byte reverse operations (PR #147200)
@@ -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]> {
Lancern wrote:
Updated. Also the mnemonic is updated to `cir.bit.bswap` to match the naming
convention for `CIR_BitOpBase`.
https://github.com/llvm/llvm-project/pull/147200
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] Add bit reverse and byte reverse operations (PR #147200)
https://github.com/Lancern updated
https://github.com/llvm/llvm-project/pull/147200
>From cf2bf0bf66f22e8fdc35baf8d4176aa5af6588d2 Mon Sep 17 00:00:00 2001
From: Sirui Mu
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 | 39
clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp | 36 +---
.../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 16
.../CIR/Lowering/DirectToLLVM/LowerToLLVM.h | 20
clang/test/CIR/CodeGen/builtin_bit.cpp| 91 +++
5 files changed, 191 insertions(+), 11 deletions(-)
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td
b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 6529f1386599c..48b54c8335b19 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -2661,6 +2661,45 @@ 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): !u32i
+```
+ }];
+}
+
+def ByteSwapOp : CIR_BitOpBase<"bit.bswap", CIR_UIntOfWidths<[16, 32, 64]>> {
+ 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.bit.bswap(%0 : !u32i) : !u32i
+```
+ }];
+}
+
//===--===//
// Assume Operations
//===--===//
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
index fb046533a91b8..25be6f35df501 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
@@ -60,15 +60,15 @@ static RValue emitBuiltinBitOp(CIRGenFunction &cgf, const
CallExpr *e,
RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl &gd, unsigned
builtinID,
const CallExpr *e,
ReturnValueSlot returnValue) {
+ mlir::Location loc = getLoc(e->getSourceRange());
+
// See if we can constant fold this builtin. If so, don't emit it at all.
// TODO: Extend this handling to all builtin calls that we can constant-fold.
Expr::EvalResult result;
if (e->isPRValue() && e->EvaluateAsRValue(result, cgm.getASTContext()) &&
!result.hasSideEffects()) {
-if (result.Val.isInt()) {
- return RValue::get(builder.getConstInt(getLoc(e->getSourceRange()),
- result.Val.getInt()));
-}
+if (result.Val.isInt())
+ return RValue::get(builder.getConstInt(loc, result.Val.getInt()));
if (result.Val.isFloat()) {
// Note: we are using result type of CallExpr to determine the type of
// the constant. Classic codegen uses the result value to determine the
@@ -76,8 +76,7 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl &gd,
unsigned builtinID,
// hard to imagine a builtin function evaluates to a value that
// over/underflows its own defined type.
mlir::Type type = convertType(e->getType());
- return RValue::get(builder.getConstFP(getLoc(e->getExprLoc()), type,
-result.Val.getFloat()));
+ return RValue::get(builder.getConstFP(loc, type, result.Val.getFloat()));
}
}
@@ -101,8 +100,6 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl
&gd, unsigned builtinID,
assert(!cir::MissingFeatures::builtinCallMathErrno());
assert(!cir::MissingFeatures::builtinCall());
- mlir::Location loc = getLoc(e->getExprLoc());
-
switch (builtinIDIfNoAsmLabel) {
default:
break;
@@ -185,11 +182,28 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl
&gd, unsigned builtinID,
probability);
}
-auto result = builder.create(getLoc(e->getSourceRange()),
-argValue.getType(), argValue,
-expectedValue, probAttr);
+auto result = builder.create(
+l
[clang] [CIR] Add bit reverse and byte reverse operations (PR #147200)
@@ -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(getLoc(e->getSourceRange()), arg));
Lancern wrote:
Updated.
https://github.com/llvm/llvm-project/pull/147200
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] Add bit reverse and byte reverse operations (PR #147200)
https://github.com/Lancern updated
https://github.com/llvm/llvm-project/pull/147200
>From 2dc9775f797f944cb0f12f68bc914a0b4bb89609 Mon Sep 17 00:00:00 2001
From: Sirui Mu
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 | 36 +---
.../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 16
.../CIR/Lowering/DirectToLLVM/LowerToLLVM.h | 20
clang/test/CIR/CodeGen/builtin_bit.cpp| 91 +++
5 files changed, 201 insertions(+), 11 deletions(-)
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td
b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 6529f1386599c..c74bbb7dc88cd 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): !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..25be6f35df501 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
@@ -60,15 +60,15 @@ static RValue emitBuiltinBitOp(CIRGenFunction &cgf, const
CallExpr *e,
RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl &gd, unsigned
builtinID,
const CallExpr *e,
ReturnValueSlot returnValue) {
+ mlir::Location loc = getLoc(e->getSourceRange());
+
// See if we can constant fold this builtin. If so, don't emit it at all.
// TODO: Extend this handling to all builtin calls that we can constant-fold.
Expr::EvalResult result;
if (e->isPRValue() && e->EvaluateAsRValue(result, cgm.getASTContext()) &&
!result.hasSideEffects()) {
-if (result.Val.isInt()) {
- return RValue::get(builder.getConstInt(getLoc(e->getSourceRange()),
- result.Val.getInt()));
-}
+if (result.Val.isInt())
+ return RValue::get(builder.getConstInt(loc, result.Val.getInt()));
if (result.Val.isFloat()) {
// Note: we are using result type of CallExpr to determine the type of
// the constant. Classic codegen uses the result value to determine the
@@ -76,8 +76,7 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl &gd,
unsigned builtinID,
// hard to imagine a builtin function evaluates to a value that
// over/underflows its own defined type.
mlir::Type type = convertType(e->getType());
- return RValue::get(builder.getConstFP(getLoc(e->getExprLoc()), type,
-result.Val.getFloat()));
+ return RValue::get(builder.getConstFP(loc, type, result.Val.getFloat()));
}
}
@@ -101,8 +100,6 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl
&gd, unsigned builtinID,
assert(!cir::MissingFeatures::builtinCallMathErrno());
assert(!cir::MissingFeatures::builtinCall());
- mlir::Location loc = getLoc(e->getExprLoc());
-
switch (builtinIDIfNoAsmLabel) {
default:
break;
@@ -185,11 +182,28 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl
[clang] [CIR] Add bit reverse and byte reverse operations (PR #147200)
@@ -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
Lancern wrote:
It looks like we don't have to spell `!u32i` twice since all bit operations are
`SameOperandsAndResultType`. I'll make a patch to simplify this later.
https://github.com/llvm/llvm-project/pull/147200
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] Add bit reverse and byte reverse operations (PR #147200)
@@ -2661,6 +2661,55 @@ def BitPopcountOp : CIR_BitOpBase<"bit.popcnt",
}];
}
+def BitReverseOp : CIR_BitOpBase<"bit.reverse", CIR_UIntOfWidths<[8, 16, 32,
64]>> {
Lancern wrote:
Well I think we need to think about what the exact scope of `CIR_BitOpBase` is
and whether the bit reverse operation should be one of it. I'm naming it
`bit.reverse` because I think it should follow the `CIR_BitOpBase` convention.
https://github.com/llvm/llvm-project/pull/147200
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] Add bit reverse and byte reverse operations (PR #147200)
https://github.com/xlauko edited https://github.com/llvm/llvm-project/pull/147200 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] Add bit reverse and byte reverse operations (PR #147200)
@@ -2661,6 +2661,55 @@ def BitPopcountOp : CIR_BitOpBase<"bit.popcnt",
}];
}
+def BitReverseOp : CIR_BitOpBase<"bit.reverse", CIR_UIntOfWidths<[8, 16, 32,
64]>> {
xlauko wrote:
These are inherited from `CIR_BitOpBase`.
https://github.com/llvm/llvm-project/pull/147200
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] Add bit reverse and byte reverse operations (PR #147200)
@@ -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]> {
xlauko wrote:
```suggestion
def CIR_ByteSwapOp : CIR_Op<"bswap", [Pure, SameOperandsAndResultType]> {
```
https://github.com/llvm/llvm-project/pull/147200
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] Add bit reverse and byte reverse operations (PR #147200)
@@ -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]> {
xlauko wrote:
This operation has same format results and arguments as `CIR_BitOpBase`.
It can be used here too.
https://github.com/llvm/llvm-project/pull/147200
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] Add bit reverse and byte reverse operations (PR #147200)
@@ -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(getLoc(e->getSourceRange()), arg));
xlauko wrote:
Lets pull out `mlir::Location loc = getLoc(e->getSourceRange())` to the
beginning of the function and use it throughout the function. This will reduce
a lot of unnecessary indent.
https://github.com/llvm/llvm-project/pull/147200
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] Add bit reverse and byte reverse operations (PR #147200)
@@ -2661,6 +2661,55 @@ def BitPopcountOp : CIR_BitOpBase<"bit.popcnt",
}];
}
+def BitReverseOp : CIR_BitOpBase<"bit.reverse", CIR_UIntOfWidths<[8, 16, 32,
64]>> {
xlauko wrote:
I would also suggest to rename to `bitreverse` to mirror builtins name. Also
dot slightly implies some "namespace".
https://github.com/llvm/llvm-project/pull/147200
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] Add bit reverse and byte reverse operations (PR #147200)
@@ -2661,6 +2661,55 @@ def BitPopcountOp : CIR_BitOpBase<"bit.popcnt",
}];
}
+def BitReverseOp : CIR_BitOpBase<"bit.reverse", CIR_UIntOfWidths<[8, 16, 32,
64]>> {
xlauko wrote:
```suggestion
def CIR_BitReverseOp : CIR_BitOpBase<"bit.reverse",
CIR_UIntOfWidths<[8, 16, 32, 64]>
> {
```
https://github.com/llvm/llvm-project/pull/147200
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] Add bit reverse and byte reverse operations (PR #147200)
@@ -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
xlauko wrote:
```suggestion
%1 = cir.bit.reverse( %0 : !u32i) : !u32i
```
https://github.com/llvm/llvm-project/pull/147200
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] Add bit reverse and byte reverse operations (PR #147200)
llvmbot wrote:
@llvm/pr-subscribers-clang
@llvm/pr-subscribers-clangir
Author: Sirui Mu (Lancern)
Changes
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.
---
Full diff: https://github.com/llvm/llvm-project/pull/147200.diff
5 Files Affected:
- (modified) clang/include/clang/CIR/Dialect/IR/CIROps.td (+49)
- (modified) clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp (+20)
- (modified) clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp (+16)
- (modified) clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h (+20)
- (modified) clang/test/CIR/CodeGen/builtin_bit.cpp (+91)
``diff
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(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(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(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::Logi
[clang] [CIR] Add bit reverse and byte reverse operations (PR #147200)
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
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(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(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(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
CIRToLLV
