Skip to content

Commit 35ca858

Browse files
committed
[CIR] Add bit reverse and byte reverse operations
1 parent ba7d78a commit 35ca858

File tree

5 files changed

+196
-0
lines changed

5 files changed

+196
-0
lines changed

clang/include/clang/CIR/Dialect/IR/CIROps.td

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2661,6 +2661,55 @@ def BitPopcountOp : CIR_BitOpBase<"bit.popcnt",
26612661
}];
26622662
}
26632663

2664+
def BitReverseOp : CIR_BitOpBase<"bit.reverse", CIR_UIntOfWidths<[8, 16, 32, 64]>> {
2665+
let summary = "Reverse the bit pattern of the operand integer";
2666+
let description = [{
2667+
The `cir.bit.reverse` operation reverses the bits of the operand integer.
2668+
Its only argument must be of unsigned integer types of width 8, 16, 32, or
2669+
64.
2670+
2671+
This operation covers the C/C++ builtin function `__builtin_bitreverse`.
2672+
2673+
Example:
2674+
2675+
```mlir
2676+
%1 = cir.bit.reverse %0 : !u32i
2677+
```
2678+
}];
2679+
}
2680+
2681+
//===----------------------------------------------------------------------===//
2682+
// ByteswapOp
2683+
//===----------------------------------------------------------------------===//
2684+
2685+
def ByteSwapOp : CIR_Op<"bswap", [Pure, SameOperandsAndResultType]> {
2686+
let summary = "Reverse the bytes in the object representation of the operand";
2687+
let description = [{
2688+
The `cir.bswap` operation takes an integer as operand, reverse the bytes in
2689+
the object representation of the operand integer, and returns the result.
2690+
2691+
The operand integer must be an unsigned integer. Its widths must be either
2692+
16, 32, or 64.
2693+
2694+
Example:
2695+
2696+
```mlir
2697+
// %0 = 0x12345678
2698+
%0 = cir.const #cir.int<305419896> : !u32i
2699+
2700+
// %1 should be 0x78563412
2701+
%1 = cir.bswap(%0 : !u32i) : !u32i
2702+
```
2703+
}];
2704+
2705+
let results = (outs CIR_IntType:$result);
2706+
let arguments = (ins CIR_UIntOfWidths<[16, 32, 64]>:$input);
2707+
2708+
let assemblyFormat = [{
2709+
`(` $input `:` type($input) `)` `:` type($result) attr-dict
2710+
}];
2711+
}
2712+
26642713
//===----------------------------------------------------------------------===//
26652714
// Assume Operations
26662715
//===----------------------------------------------------------------------===//

clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,26 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl &gd, unsigned builtinID,
190190
expectedValue, probAttr);
191191
return RValue::get(result);
192192
}
193+
194+
case Builtin::BI__builtin_bswap16:
195+
case Builtin::BI__builtin_bswap32:
196+
case Builtin::BI__builtin_bswap64:
197+
case Builtin::BI_byteswap_ushort:
198+
case Builtin::BI_byteswap_ulong:
199+
case Builtin::BI_byteswap_uint64: {
200+
mlir::Value arg = emitScalarExpr(e->getArg(0));
201+
return RValue::get(
202+
builder.create<cir::ByteSwapOp>(getLoc(e->getSourceRange()), arg));
203+
}
204+
205+
case Builtin::BI__builtin_bitreverse8:
206+
case Builtin::BI__builtin_bitreverse16:
207+
case Builtin::BI__builtin_bitreverse32:
208+
case Builtin::BI__builtin_bitreverse64: {
209+
mlir::Value arg = emitScalarExpr(e->getArg(0));
210+
return RValue::get(
211+
builder.create<cir::BitReverseOp>(getLoc(e->getSourceRange()), arg));
212+
}
193213
}
194214

195215
cgm.errorNYI(e->getSourceRange(), "unimplemented builtin call");

clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -535,6 +535,13 @@ mlir::LogicalResult CIRToLLVMBitPopcountOpLowering::matchAndRewrite(
535535
return mlir::LogicalResult::success();
536536
}
537537

538+
mlir::LogicalResult CIRToLLVMBitReverseOpLowering::matchAndRewrite(
539+
cir::BitReverseOp op, OpAdaptor adaptor,
540+
mlir::ConversionPatternRewriter &rewriter) const {
541+
rewriter.replaceOpWithNewOp<mlir::LLVM::BitReverseOp>(op, adaptor.getInput());
542+
return mlir::success();
543+
}
544+
538545
mlir::LogicalResult CIRToLLVMBrCondOpLowering::matchAndRewrite(
539546
cir::BrCondOp brOp, OpAdaptor adaptor,
540547
mlir::ConversionPatternRewriter &rewriter) const {
@@ -551,6 +558,13 @@ mlir::LogicalResult CIRToLLVMBrCondOpLowering::matchAndRewrite(
551558
return mlir::success();
552559
}
553560

561+
mlir::LogicalResult CIRToLLVMByteSwapOpLowering::matchAndRewrite(
562+
cir::ByteSwapOp op, OpAdaptor adaptor,
563+
mlir::ConversionPatternRewriter &rewriter) const {
564+
rewriter.replaceOpWithNewOp<mlir::LLVM::ByteSwapOp>(op, adaptor.getInput());
565+
return mlir::LogicalResult::success();
566+
}
567+
554568
mlir::Type CIRToLLVMCastOpLowering::convertTy(mlir::Type ty) const {
555569
return getTypeConverter()->convertType(ty);
556570
}
@@ -2035,8 +2049,10 @@ void ConvertCIRToLLVMPass::runOnOperation() {
20352049
CIRToLLVMBitCtzOpLowering,
20362050
CIRToLLVMBitParityOpLowering,
20372051
CIRToLLVMBitPopcountOpLowering,
2052+
CIRToLLVMBitReverseOpLowering,
20382053
CIRToLLVMBrCondOpLowering,
20392054
CIRToLLVMBrOpLowering,
2055+
CIRToLLVMByteSwapOpLowering,
20402056
CIRToLLVMCallOpLowering,
20412057
CIRToLLVMCmpOpLowering,
20422058
CIRToLLVMComplexCreateOpLowering,

clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,16 @@ class CIRToLLVMBitPopcountOpLowering
9494
mlir::ConversionPatternRewriter &) const override;
9595
};
9696

97+
class CIRToLLVMBitReverseOpLowering
98+
: public mlir::OpConversionPattern<cir::BitReverseOp> {
99+
public:
100+
using mlir::OpConversionPattern<cir::BitReverseOp>::OpConversionPattern;
101+
102+
mlir::LogicalResult
103+
matchAndRewrite(cir::BitReverseOp op, OpAdaptor,
104+
mlir::ConversionPatternRewriter &) const override;
105+
};
106+
97107
class CIRToLLVMBrCondOpLowering
98108
: public mlir::OpConversionPattern<cir::BrCondOp> {
99109
public:
@@ -104,6 +114,16 @@ class CIRToLLVMBrCondOpLowering
104114
mlir::ConversionPatternRewriter &) const override;
105115
};
106116

117+
class CIRToLLVMByteSwapOpLowering
118+
: public mlir::OpConversionPattern<cir::ByteSwapOp> {
119+
public:
120+
using mlir::OpConversionPattern<cir::ByteSwapOp>::OpConversionPattern;
121+
122+
mlir::LogicalResult
123+
matchAndRewrite(cir::ByteSwapOp op, OpAdaptor,
124+
mlir::ConversionPatternRewriter &) const override;
125+
};
126+
107127
class CIRToLLVMCastOpLowering : public mlir::OpConversionPattern<cir::CastOp> {
108128
mlir::DataLayout const &dataLayout;
109129

clang/test/CIR/CodeGen/builtin_bit.cpp

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,3 +325,94 @@ int test_builtin_popcountg(unsigned x) {
325325

326326
// OGCG-LABEL: _Z22test_builtin_popcountgj
327327
// OGCG: %{{.+}} = call i32 @llvm.ctpop.i32(i32 %{{.+}})
328+
329+
unsigned char test_builtin_bitreverse8(unsigned char x) {
330+
return __builtin_bitreverse8(x);
331+
}
332+
333+
// CIR-LABEL: @_Z24test_builtin_bitreverse8h
334+
// CIR: %{{.+}} = cir.bit.reverse(%{{.+}} : !u8i) : !u8i
335+
336+
// LLVM-LABEL: @_Z24test_builtin_bitreverse8h
337+
// LLVM: %{{.+}} = call i8 @llvm.bitreverse.i8(i8 %{{.+}})
338+
339+
// OGCG-LABEL: @_Z24test_builtin_bitreverse8h
340+
// OGCG: %{{.+}} = call i8 @llvm.bitreverse.i8(i8 %{{.+}})
341+
342+
unsigned short test_builtin_bitreverse16(unsigned short x) {
343+
return __builtin_bitreverse16(x);
344+
}
345+
346+
// CIR-LABEL: @_Z25test_builtin_bitreverse16t
347+
// CIR: %{{.+}} = cir.bit.reverse(%{{.+}} : !u16i) : !u16i
348+
349+
// LLVM-LABEL: @_Z25test_builtin_bitreverse16t
350+
// LLVM: %{{.+}} = call i16 @llvm.bitreverse.i16(i16 %{{.+}})
351+
352+
// OGCG-LABEL: @_Z25test_builtin_bitreverse16t
353+
// OGCG: %{{.+}} = call i16 @llvm.bitreverse.i16(i16 %{{.+}})
354+
355+
unsigned test_builtin_bitreverse32(unsigned x) {
356+
return __builtin_bitreverse32(x);
357+
}
358+
359+
// CIR-LABEL: @_Z25test_builtin_bitreverse32j
360+
// CIR: %{{.+}} = cir.bit.reverse(%{{.+}} : !u32i) : !u32i
361+
362+
// LLVM-LABEL: @_Z25test_builtin_bitreverse32j
363+
// LLVM: %{{.+}} = call i32 @llvm.bitreverse.i32(i32 %{{.+}})
364+
365+
// OGCG-LABEL: @_Z25test_builtin_bitreverse32j
366+
// OGCG: %{{.+}} = call i32 @llvm.bitreverse.i32(i32 %{{.+}})
367+
368+
unsigned long long test_builtin_bitreverse64(unsigned long long x) {
369+
return __builtin_bitreverse64(x);
370+
}
371+
372+
// CIR-LABEL: @_Z25test_builtin_bitreverse64y
373+
// CIR: %{{.+}} = cir.bit.reverse(%{{.+}} : !u64i) : !u64i
374+
375+
// LLVM-LABEL: @_Z25test_builtin_bitreverse64y
376+
// LLVM: %{{.+}} = call i64 @llvm.bitreverse.i64(i64 %{{.+}})
377+
378+
// OGCG-LABEL: @_Z25test_builtin_bitreverse64y
379+
// OGCG: %{{.+}} = call i64 @llvm.bitreverse.i64(i64 %{{.+}})
380+
381+
unsigned short test_builtin_bswap16(unsigned short x) {
382+
return __builtin_bswap16(x);
383+
}
384+
385+
// CIR-LABEL: @_Z20test_builtin_bswap16t
386+
// CIR: %{{.+}} = cir.bswap(%{{.+}} : !u16i) : !u16i
387+
388+
// LLVM-LABEL: @_Z20test_builtin_bswap16t
389+
// LLVM: %{{.+}} = call i16 @llvm.bswap.i16(i16 %{{.+}})
390+
391+
// OGCG-LABEL: @_Z20test_builtin_bswap16t
392+
// OGCG: %{{.+}} = call i16 @llvm.bswap.i16(i16 %{{.+}})
393+
394+
unsigned test_builtin_bswap32(unsigned x) {
395+
return __builtin_bswap32(x);
396+
}
397+
398+
// CIR-LABEL: @_Z20test_builtin_bswap32j
399+
// CIR: %{{.+}} = cir.bswap(%{{.+}} : !u32i) : !u32i
400+
401+
// LLVM-LABEL: @_Z20test_builtin_bswap32j
402+
// LLVM: %{{.+}} = call i32 @llvm.bswap.i32(i32 %{{.+}})
403+
404+
// OGCG-LABEL: @_Z20test_builtin_bswap32j
405+
// OGCG: %{{.+}} = call i32 @llvm.bswap.i32(i32 %{{.+}})
406+
407+
unsigned long long test_builtin_bswap64(unsigned long long x) {
408+
return __builtin_bswap64(x);
409+
}
410+
411+
// CIR-LABEL: @_Z20test_builtin_bswap64y
412+
// CIR: %{{.+}} = cir.bswap(%{{.+}} : !u64i) : !u64i
413+
414+
// LLVM-LABEL: @_Z20test_builtin_bswap64y
415+
// LLVM: %{{.+}} = call i64 @llvm.bswap.i64(i64 %{{.+}})
416+
417+
// OGCG-LABEL: @_Z20test_builtin_bswap64y
418+
// OGCG: %{{.+}} = call i64 @llvm.bswap.i64(i64 %{{.+}})

0 commit comments

Comments
 (0)