-
Notifications
You must be signed in to change notification settings - Fork 14.6k
[CIR] Add folders for bit manipulation operations #150235
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@llvm/pr-subscribers-clangir Author: Sirui Mu (Lancern) ChangesThis patch adds folders for the bit manipulation operations, namely: Full diff: https://github.com/llvm/llvm-project/pull/150235.diff 4 Files Affected:
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 694e3691c9361..8d5d34782c9a8 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -2773,6 +2773,8 @@ class CIR_BitOpBase<string mnemonic, TypeConstraint operandTy>
let assemblyFormat = [{
$input `:` type($result) attr-dict
}];
+
+ let hasFolder = 1;
}
class CIR_BitZeroCountOpBase<string mnemonic, TypeConstraint operandTy>
@@ -2980,6 +2982,8 @@ def CIR_RotateOp : CIR_Op<"rotate", [Pure, SameOperandsAndResultType]> {
bool isRotateLeft() { return getRotateLeft(); }
bool isRotateRight() { return !getRotateLeft(); }
}];
+
+ let hasFolder = 1;
}
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index f0416b6aba6e4..8e13900043108 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -17,6 +17,7 @@
#include "mlir/Interfaces/ControlFlowInterfaces.h"
#include "mlir/Interfaces/FunctionImplementation.h"
+#include "mlir/Support/LLVM.h"
#include "clang/CIR/Dialect/IR/CIROpsDialect.cpp.inc"
#include "clang/CIR/Dialect/IR/CIROpsEnums.cpp.inc"
@@ -2132,6 +2133,117 @@ LogicalResult cir::ComplexImagPtrOp::verify() {
return success();
}
+//===----------------------------------------------------------------------===//
+// Bit manipulation operations
+//===----------------------------------------------------------------------===//
+
+template <typename F>
+static OpFoldResult foldUnaryBitOp(mlir::Attribute inputAttr, F func,
+ bool poisonZero = false) {
+ auto input = mlir::dyn_cast_if_present<IntAttr>(inputAttr);
+ if (!input)
+ return nullptr;
+
+ llvm::APInt inputValue = input.getValue();
+ if (poisonZero && inputValue.isZero()) {
+ // TODO(cir): maybe we should return a poison value here?
+ return nullptr;
+ }
+
+ auto resultValue = func(inputValue);
+ if constexpr (std::is_integral_v<decltype(resultValue)>)
+ return IntAttr::get(input.getType(), resultValue);
+ else
+ return IntAttr::get(input.getContext(), input.getType(), resultValue);
+}
+
+OpFoldResult BitClrsbOp::fold(FoldAdaptor adaptor) {
+ return foldUnaryBitOp(adaptor.getInput(), [](const llvm::APInt &inputValue) {
+ return inputValue.getBitWidth() - inputValue.getSignificantBits();
+ });
+}
+
+OpFoldResult BitClzOp::fold(FoldAdaptor adaptor) {
+ return foldUnaryBitOp(
+ adaptor.getInput(),
+ [](const llvm::APInt &inputValue) {
+ return inputValue.countLeadingZeros();
+ },
+ getPoisonZero());
+}
+
+OpFoldResult BitCtzOp::fold(FoldAdaptor adaptor) {
+ return foldUnaryBitOp(
+ adaptor.getInput(),
+ [](const llvm::APInt &inputValue) {
+ return inputValue.countTrailingZeros();
+ },
+ getPoisonZero());
+}
+
+OpFoldResult BitParityOp::fold(FoldAdaptor adaptor) {
+ return foldUnaryBitOp(adaptor.getInput(), [](const llvm::APInt &inputValue) {
+ return inputValue.popcount() % 2;
+ });
+}
+
+OpFoldResult BitPopcountOp::fold(FoldAdaptor adaptor) {
+ return foldUnaryBitOp(adaptor.getInput(), [](const llvm::APInt &inputValue) {
+ return inputValue.popcount();
+ });
+}
+
+OpFoldResult BitReverseOp::fold(FoldAdaptor adaptor) {
+ return foldUnaryBitOp(adaptor.getInput(), [](const llvm::APInt &inputValue) {
+ return inputValue.reverseBits();
+ });
+}
+
+OpFoldResult ByteSwapOp::fold(FoldAdaptor adaptor) {
+ return foldUnaryBitOp(adaptor.getInput(), [](const llvm::APInt &inputValue) {
+ return inputValue.byteSwap();
+ });
+}
+
+OpFoldResult RotateOp::fold(FoldAdaptor adaptor) {
+ auto input = mlir::dyn_cast_if_present<IntAttr>(adaptor.getInput());
+ auto amount = mlir::dyn_cast_if_present<IntAttr>(adaptor.getAmount());
+ if (!input && !amount)
+ return nullptr;
+
+ llvm::APInt inputValue;
+ if (input) {
+ inputValue = input.getValue();
+ if (inputValue.isZero() || inputValue.isAllOnes()) {
+ // An input value of all 0s or all 1s will not change after rotation
+ return input;
+ }
+ }
+
+ uint64_t amountValue;
+ if (amount) {
+ amountValue = amount.getValue().urem(getInput().getType().getWidth());
+ if (amountValue == 0) {
+ // A shift amount of 0 will not change the input value
+ return getInput();
+ }
+ }
+
+ if (!input || !amount)
+ return nullptr;
+
+ assert(inputValue.getBitWidth() == getInput().getType().getWidth() &&
+ "input value must have the same bit width as the input type");
+
+ llvm::APInt resultValue;
+ if (isRotateLeft())
+ resultValue = inputValue.rotl(amountValue);
+ else
+ resultValue = inputValue.rotr(amountValue);
+
+ return IntAttr::get(input.getContext(), input.getType(), resultValue);
+}
+
//===----------------------------------------------------------------------===//
// TableGen'd op method definitions
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/CIR/Dialect/Transforms/CIRCanonicalize.cpp b/clang/lib/CIR/Dialect/Transforms/CIRCanonicalize.cpp
index e505db50d3609..2143f167ba2c8 100644
--- a/clang/lib/CIR/Dialect/Transforms/CIRCanonicalize.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/CIRCanonicalize.cpp
@@ -143,7 +143,8 @@ void CIRCanonicalizePass::runOnOperation() {
if (isa<BrOp, BrCondOp, CastOp, ScopeOp, SwitchOp, SelectOp, UnaryOp,
ComplexCreateOp, ComplexImagOp, ComplexRealOp, VecCmpOp,
VecCreateOp, VecExtractOp, VecShuffleOp, VecShuffleDynamicOp,
- VecTernaryOp>(op))
+ VecTernaryOp, BitClrsbOp, BitClzOp, BitCtzOp, BitParityOp,
+ BitPopcountOp, BitReverseOp, ByteSwapOp, RotateOp>(op))
ops.push_back(op);
});
diff --git a/clang/test/CIR/Transforms/bit.cir b/clang/test/CIR/Transforms/bit.cir
new file mode 100644
index 0000000000000..df804fbef8981
--- /dev/null
+++ b/clang/test/CIR/Transforms/bit.cir
@@ -0,0 +1,129 @@
+// RUN: cir-opt -cir-canonicalize -cir-simplify -o %t.cir %s
+// RUN: FileCheck --input-file=%t.cir %s
+
+!s32i = !cir.int<s, 32>
+!u32i = !cir.int<u, 32>
+
+module {
+ cir.func @fold_clrsb() -> !s32i {
+ %0 = cir.const #cir.int<114514> : !s32i
+ %1 = cir.clrsb %0 : !s32i
+ cir.return %1 : !s32i
+ }
+ // CHECK-LABEL: @fold_clrsb
+ // CHECK-NEXT: %[[R:.+]] = cir.const #cir.int<14> : !s32i
+ // CHECK-NEXT: cir.return %[[R]] : !s32i
+ // CHECK-NEXT: }
+
+ cir.func @fold_clz() -> !u32i {
+ %0 = cir.const #cir.int<114514> : !u32i
+ %1 = cir.clz %0 : !u32i
+ cir.return %1 : !u32i
+ }
+ // CHECK-LABEL: @fold_clz
+ // CHECK-NEXT: %[[R:.+]] = cir.const #cir.int<15> : !u32i
+ // CHECK-NEXT: cir.return %[[R]] : !u32i
+ // CHECK-NEXT: }
+
+ cir.func @fold_ctz() -> !u32i {
+ %0 = cir.const #cir.int<114514> : !u32i
+ %1 = cir.ctz %0 : !u32i
+ cir.return %1 : !u32i
+ }
+ // CHECK-LABEL: @fold_ctz
+ // CHECK-NEXT: %[[R:.+]] = cir.const #cir.int<1> : !u32i
+ // CHECK-NEXT: cir.return %[[R]] : !u32i
+ // CHECK-NEXT: }
+
+ cir.func @fold_parity() -> !u32i {
+ %0 = cir.const #cir.int<114514> : !u32i
+ %1 = cir.parity %0 : !u32i
+ cir.return %1 : !u32i
+ }
+ // CHECK-LABEL: @fold_parity
+ // CHECK-NEXT: %[[R:.+]] = cir.const #cir.int<1> : !u32i
+ // CHECK-NEXT: cir.return %[[R]] : !u32i
+ // CHECK-NEXT: }
+
+ cir.func @fold_popcount() -> !u32i {
+ %0 = cir.const #cir.int<114514> : !u32i
+ %1 = cir.popcount %0 : !u32i
+ cir.return %1 : !u32i
+ }
+ // CHECK-LABEL: @fold_popcount
+ // CHECK-NEXT: %[[R:.+]] = cir.const #cir.int<11> : !u32i
+ // CHECK-NEXT: cir.return %[[R]] : !u32i
+ // CHECK-NEXT: }
+
+ cir.func @fold_bitreverse() -> !u32i {
+ %0 = cir.const #cir.int<114514> : !u32i
+ %1 = cir.bitreverse %0 : !u32i
+ cir.return %1 : !u32i
+ }
+ // CHECK-LABEL: @fold_bitreverse
+ // CHECK-NEXT: %[[R:.+]] = cir.const #cir.int<1258127360> : !u32i
+ // CHECK-NEXT: cir.return %[[R]] : !u32i
+ // CHECK-NEXT: }
+
+ cir.func @fold_byte_swap() -> !u32i {
+ %0 = cir.const #cir.int<114514> : !u32i
+ %1 = cir.byte_swap %0 : !u32i
+ cir.return %1 : !u32i
+ }
+ // CHECK-LABEL: @fold_byte_swap
+ // CHECK-NEXT: %[[R:.+]] = cir.const #cir.int<1388249344> : !u32i
+ // CHECK-NEXT: cir.return %[[R]] : !u32i
+ // CHECK-NEXT: }
+
+ cir.func @fold_rotate_input_all_zeros(%arg0 : !u32i) -> !u32i {
+ %0 = cir.const #cir.int<0> : !u32i
+ %1 = cir.rotate left %0, %arg0 : !u32i
+ cir.return %1 : !u32i
+ }
+ // CHECK-LABEL: @fold_rotate_input_all_zeros
+ // CHECK-NEXT: %[[R:.+]] = cir.const #cir.int<0> : !u32i
+ // CHECK-NEXT: cir.return %[[R]] : !u32i
+ // CHECK-NEXT: }
+
+ cir.func @fold_rotate_input_all_ones(%arg0 : !u32i) -> !u32i {
+ %0 = cir.const #cir.int<4294967295> : !u32i
+ %1 = cir.rotate left %0, %arg0 : !u32i
+ cir.return %1 : !u32i
+ }
+ // CHECK-LABEL: @fold_rotate_input_all_ones
+ // CHECK-NEXT: %[[R:.+]] = cir.const #cir.int<4294967295> : !u32i
+ // CHECK-NEXT: cir.return %[[R]] : !u32i
+ // CHECK-NEXT: }
+
+ cir.func @fold_rotate_zero_amount(%arg0 : !u32i) -> !u32i {
+ %0 = cir.const #cir.int<32> : !u32i
+ %1 = cir.rotate left %arg0, %0 : !u32i
+ cir.return %1 : !u32i
+ }
+ // CHECK-LABEL: @fold_rotate_zero_amount
+ // CHECK-SAME: (%[[R:.+]]: !u32i)
+ // CHECK-NEXT: cir.return %[[R]] : !u32i
+ // CHECK-NEXT: }
+
+ cir.func @fold_rotate_left() -> !u32i {
+ %0 = cir.const #cir.int<114514> : !u32i
+ %1 = cir.const #cir.int<7> : !u32i
+ %2 = cir.rotate left %0, %1 : !u32i
+ cir.return %2 : !u32i
+ }
+ // CHECK-LABEL: @fold_rotate_left
+ // CHECK-NEXT: %[[R:.+]] = cir.const #cir.int<14657792> : !u32i
+ // CHECK-NEXT: cir.return %[[R]] : !u32i
+ // CHECK-NEXT: }
+
+ cir.func @fold_rotate_right() -> !u32i {
+ %0 = cir.const #cir.int<114514> : !u32i
+ %1 = cir.const #cir.int<7> : !u32i
+ %2 = cir.rotate right %0, %1 : !u32i
+ cir.return %2 : !u32i
+ }
+ // CHECK-LABEL: @fold_rotate_right
+ // CHECK-NEXT: %[[R:.+]] = cir.const #cir.int<2751464318> : !u32i
+ // CHECK-NEXT: cir.return %[[R]] : !u32i
+ // CHECK-NEXT: }
+}
|
@llvm/pr-subscribers-clang Author: Sirui Mu (Lancern) ChangesThis patch adds folders for the bit manipulation operations, namely: Full diff: https://github.com/llvm/llvm-project/pull/150235.diff 4 Files Affected:
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 694e3691c9361..8d5d34782c9a8 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -2773,6 +2773,8 @@ class CIR_BitOpBase<string mnemonic, TypeConstraint operandTy>
let assemblyFormat = [{
$input `:` type($result) attr-dict
}];
+
+ let hasFolder = 1;
}
class CIR_BitZeroCountOpBase<string mnemonic, TypeConstraint operandTy>
@@ -2980,6 +2982,8 @@ def CIR_RotateOp : CIR_Op<"rotate", [Pure, SameOperandsAndResultType]> {
bool isRotateLeft() { return getRotateLeft(); }
bool isRotateRight() { return !getRotateLeft(); }
}];
+
+ let hasFolder = 1;
}
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index f0416b6aba6e4..8e13900043108 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -17,6 +17,7 @@
#include "mlir/Interfaces/ControlFlowInterfaces.h"
#include "mlir/Interfaces/FunctionImplementation.h"
+#include "mlir/Support/LLVM.h"
#include "clang/CIR/Dialect/IR/CIROpsDialect.cpp.inc"
#include "clang/CIR/Dialect/IR/CIROpsEnums.cpp.inc"
@@ -2132,6 +2133,117 @@ LogicalResult cir::ComplexImagPtrOp::verify() {
return success();
}
+//===----------------------------------------------------------------------===//
+// Bit manipulation operations
+//===----------------------------------------------------------------------===//
+
+template <typename F>
+static OpFoldResult foldUnaryBitOp(mlir::Attribute inputAttr, F func,
+ bool poisonZero = false) {
+ auto input = mlir::dyn_cast_if_present<IntAttr>(inputAttr);
+ if (!input)
+ return nullptr;
+
+ llvm::APInt inputValue = input.getValue();
+ if (poisonZero && inputValue.isZero()) {
+ // TODO(cir): maybe we should return a poison value here?
+ return nullptr;
+ }
+
+ auto resultValue = func(inputValue);
+ if constexpr (std::is_integral_v<decltype(resultValue)>)
+ return IntAttr::get(input.getType(), resultValue);
+ else
+ return IntAttr::get(input.getContext(), input.getType(), resultValue);
+}
+
+OpFoldResult BitClrsbOp::fold(FoldAdaptor adaptor) {
+ return foldUnaryBitOp(adaptor.getInput(), [](const llvm::APInt &inputValue) {
+ return inputValue.getBitWidth() - inputValue.getSignificantBits();
+ });
+}
+
+OpFoldResult BitClzOp::fold(FoldAdaptor adaptor) {
+ return foldUnaryBitOp(
+ adaptor.getInput(),
+ [](const llvm::APInt &inputValue) {
+ return inputValue.countLeadingZeros();
+ },
+ getPoisonZero());
+}
+
+OpFoldResult BitCtzOp::fold(FoldAdaptor adaptor) {
+ return foldUnaryBitOp(
+ adaptor.getInput(),
+ [](const llvm::APInt &inputValue) {
+ return inputValue.countTrailingZeros();
+ },
+ getPoisonZero());
+}
+
+OpFoldResult BitParityOp::fold(FoldAdaptor adaptor) {
+ return foldUnaryBitOp(adaptor.getInput(), [](const llvm::APInt &inputValue) {
+ return inputValue.popcount() % 2;
+ });
+}
+
+OpFoldResult BitPopcountOp::fold(FoldAdaptor adaptor) {
+ return foldUnaryBitOp(adaptor.getInput(), [](const llvm::APInt &inputValue) {
+ return inputValue.popcount();
+ });
+}
+
+OpFoldResult BitReverseOp::fold(FoldAdaptor adaptor) {
+ return foldUnaryBitOp(adaptor.getInput(), [](const llvm::APInt &inputValue) {
+ return inputValue.reverseBits();
+ });
+}
+
+OpFoldResult ByteSwapOp::fold(FoldAdaptor adaptor) {
+ return foldUnaryBitOp(adaptor.getInput(), [](const llvm::APInt &inputValue) {
+ return inputValue.byteSwap();
+ });
+}
+
+OpFoldResult RotateOp::fold(FoldAdaptor adaptor) {
+ auto input = mlir::dyn_cast_if_present<IntAttr>(adaptor.getInput());
+ auto amount = mlir::dyn_cast_if_present<IntAttr>(adaptor.getAmount());
+ if (!input && !amount)
+ return nullptr;
+
+ llvm::APInt inputValue;
+ if (input) {
+ inputValue = input.getValue();
+ if (inputValue.isZero() || inputValue.isAllOnes()) {
+ // An input value of all 0s or all 1s will not change after rotation
+ return input;
+ }
+ }
+
+ uint64_t amountValue;
+ if (amount) {
+ amountValue = amount.getValue().urem(getInput().getType().getWidth());
+ if (amountValue == 0) {
+ // A shift amount of 0 will not change the input value
+ return getInput();
+ }
+ }
+
+ if (!input || !amount)
+ return nullptr;
+
+ assert(inputValue.getBitWidth() == getInput().getType().getWidth() &&
+ "input value must have the same bit width as the input type");
+
+ llvm::APInt resultValue;
+ if (isRotateLeft())
+ resultValue = inputValue.rotl(amountValue);
+ else
+ resultValue = inputValue.rotr(amountValue);
+
+ return IntAttr::get(input.getContext(), input.getType(), resultValue);
+}
+
//===----------------------------------------------------------------------===//
// TableGen'd op method definitions
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/CIR/Dialect/Transforms/CIRCanonicalize.cpp b/clang/lib/CIR/Dialect/Transforms/CIRCanonicalize.cpp
index e505db50d3609..2143f167ba2c8 100644
--- a/clang/lib/CIR/Dialect/Transforms/CIRCanonicalize.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/CIRCanonicalize.cpp
@@ -143,7 +143,8 @@ void CIRCanonicalizePass::runOnOperation() {
if (isa<BrOp, BrCondOp, CastOp, ScopeOp, SwitchOp, SelectOp, UnaryOp,
ComplexCreateOp, ComplexImagOp, ComplexRealOp, VecCmpOp,
VecCreateOp, VecExtractOp, VecShuffleOp, VecShuffleDynamicOp,
- VecTernaryOp>(op))
+ VecTernaryOp, BitClrsbOp, BitClzOp, BitCtzOp, BitParityOp,
+ BitPopcountOp, BitReverseOp, ByteSwapOp, RotateOp>(op))
ops.push_back(op);
});
diff --git a/clang/test/CIR/Transforms/bit.cir b/clang/test/CIR/Transforms/bit.cir
new file mode 100644
index 0000000000000..df804fbef8981
--- /dev/null
+++ b/clang/test/CIR/Transforms/bit.cir
@@ -0,0 +1,129 @@
+// RUN: cir-opt -cir-canonicalize -cir-simplify -o %t.cir %s
+// RUN: FileCheck --input-file=%t.cir %s
+
+!s32i = !cir.int<s, 32>
+!u32i = !cir.int<u, 32>
+
+module {
+ cir.func @fold_clrsb() -> !s32i {
+ %0 = cir.const #cir.int<114514> : !s32i
+ %1 = cir.clrsb %0 : !s32i
+ cir.return %1 : !s32i
+ }
+ // CHECK-LABEL: @fold_clrsb
+ // CHECK-NEXT: %[[R:.+]] = cir.const #cir.int<14> : !s32i
+ // CHECK-NEXT: cir.return %[[R]] : !s32i
+ // CHECK-NEXT: }
+
+ cir.func @fold_clz() -> !u32i {
+ %0 = cir.const #cir.int<114514> : !u32i
+ %1 = cir.clz %0 : !u32i
+ cir.return %1 : !u32i
+ }
+ // CHECK-LABEL: @fold_clz
+ // CHECK-NEXT: %[[R:.+]] = cir.const #cir.int<15> : !u32i
+ // CHECK-NEXT: cir.return %[[R]] : !u32i
+ // CHECK-NEXT: }
+
+ cir.func @fold_ctz() -> !u32i {
+ %0 = cir.const #cir.int<114514> : !u32i
+ %1 = cir.ctz %0 : !u32i
+ cir.return %1 : !u32i
+ }
+ // CHECK-LABEL: @fold_ctz
+ // CHECK-NEXT: %[[R:.+]] = cir.const #cir.int<1> : !u32i
+ // CHECK-NEXT: cir.return %[[R]] : !u32i
+ // CHECK-NEXT: }
+
+ cir.func @fold_parity() -> !u32i {
+ %0 = cir.const #cir.int<114514> : !u32i
+ %1 = cir.parity %0 : !u32i
+ cir.return %1 : !u32i
+ }
+ // CHECK-LABEL: @fold_parity
+ // CHECK-NEXT: %[[R:.+]] = cir.const #cir.int<1> : !u32i
+ // CHECK-NEXT: cir.return %[[R]] : !u32i
+ // CHECK-NEXT: }
+
+ cir.func @fold_popcount() -> !u32i {
+ %0 = cir.const #cir.int<114514> : !u32i
+ %1 = cir.popcount %0 : !u32i
+ cir.return %1 : !u32i
+ }
+ // CHECK-LABEL: @fold_popcount
+ // CHECK-NEXT: %[[R:.+]] = cir.const #cir.int<11> : !u32i
+ // CHECK-NEXT: cir.return %[[R]] : !u32i
+ // CHECK-NEXT: }
+
+ cir.func @fold_bitreverse() -> !u32i {
+ %0 = cir.const #cir.int<114514> : !u32i
+ %1 = cir.bitreverse %0 : !u32i
+ cir.return %1 : !u32i
+ }
+ // CHECK-LABEL: @fold_bitreverse
+ // CHECK-NEXT: %[[R:.+]] = cir.const #cir.int<1258127360> : !u32i
+ // CHECK-NEXT: cir.return %[[R]] : !u32i
+ // CHECK-NEXT: }
+
+ cir.func @fold_byte_swap() -> !u32i {
+ %0 = cir.const #cir.int<114514> : !u32i
+ %1 = cir.byte_swap %0 : !u32i
+ cir.return %1 : !u32i
+ }
+ // CHECK-LABEL: @fold_byte_swap
+ // CHECK-NEXT: %[[R:.+]] = cir.const #cir.int<1388249344> : !u32i
+ // CHECK-NEXT: cir.return %[[R]] : !u32i
+ // CHECK-NEXT: }
+
+ cir.func @fold_rotate_input_all_zeros(%arg0 : !u32i) -> !u32i {
+ %0 = cir.const #cir.int<0> : !u32i
+ %1 = cir.rotate left %0, %arg0 : !u32i
+ cir.return %1 : !u32i
+ }
+ // CHECK-LABEL: @fold_rotate_input_all_zeros
+ // CHECK-NEXT: %[[R:.+]] = cir.const #cir.int<0> : !u32i
+ // CHECK-NEXT: cir.return %[[R]] : !u32i
+ // CHECK-NEXT: }
+
+ cir.func @fold_rotate_input_all_ones(%arg0 : !u32i) -> !u32i {
+ %0 = cir.const #cir.int<4294967295> : !u32i
+ %1 = cir.rotate left %0, %arg0 : !u32i
+ cir.return %1 : !u32i
+ }
+ // CHECK-LABEL: @fold_rotate_input_all_ones
+ // CHECK-NEXT: %[[R:.+]] = cir.const #cir.int<4294967295> : !u32i
+ // CHECK-NEXT: cir.return %[[R]] : !u32i
+ // CHECK-NEXT: }
+
+ cir.func @fold_rotate_zero_amount(%arg0 : !u32i) -> !u32i {
+ %0 = cir.const #cir.int<32> : !u32i
+ %1 = cir.rotate left %arg0, %0 : !u32i
+ cir.return %1 : !u32i
+ }
+ // CHECK-LABEL: @fold_rotate_zero_amount
+ // CHECK-SAME: (%[[R:.+]]: !u32i)
+ // CHECK-NEXT: cir.return %[[R]] : !u32i
+ // CHECK-NEXT: }
+
+ cir.func @fold_rotate_left() -> !u32i {
+ %0 = cir.const #cir.int<114514> : !u32i
+ %1 = cir.const #cir.int<7> : !u32i
+ %2 = cir.rotate left %0, %1 : !u32i
+ cir.return %2 : !u32i
+ }
+ // CHECK-LABEL: @fold_rotate_left
+ // CHECK-NEXT: %[[R:.+]] = cir.const #cir.int<14657792> : !u32i
+ // CHECK-NEXT: cir.return %[[R]] : !u32i
+ // CHECK-NEXT: }
+
+ cir.func @fold_rotate_right() -> !u32i {
+ %0 = cir.const #cir.int<114514> : !u32i
+ %1 = cir.const #cir.int<7> : !u32i
+ %2 = cir.rotate right %0, %1 : !u32i
+ cir.return %2 : !u32i
+ }
+ // CHECK-LABEL: @fold_rotate_right
+ // CHECK-NEXT: %[[R:.+]] = cir.const #cir.int<2751464318> : !u32i
+ // CHECK-NEXT: cir.return %[[R]] : !u32i
+ // CHECK-NEXT: }
+}
|
clang/test/CIR/Transforms/bit.cir
Outdated
|
||
module { | ||
cir.func @fold_clrsb() -> !s32i { | ||
%0 = cir.const #cir.int<114514> : !s32i |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was 114514
chosen for any particular reason? The test would be more readable if you chose a number for which the operations could be easily compute mentally and added a comment showing the hex representation of the number.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's randomly chosen w/o a specific reason. Updated with comments.
return nullptr; | ||
} | ||
|
||
auto resultValue = func(inputValue); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you use mlir::Value
rather than auto
? I don't think we want to allow functors that return other types.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I make it an llvm::APInt
.
7b5e3cd
to
d216fcd
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm -- thanks for the test updates!
d216fcd
to
169c89a
Compare
d431acf
to
b22e90b
Compare
This patch adds folders for the bit manipulation operations, namely:
clrsb
,clz
,ctz
,parity
,popcount
,bitreverse
,byte_swap
, androtate
.