Commit 86f61a9d26

antlilja <liljaanton2001@gmail.com>
2023-08-06 00:58:10
Implement bitop intrinsics in new LLVM IR builder
* llvm.bitreverse * llvm.bswap * llvm.ctpop * llvm.ctlz * llvm.cttz
1 parent 2b4ac7c
Changed files (4)
src/codegen/llvm/bindings.zig
@@ -1065,6 +1065,21 @@ pub const Builder = opaque {
     pub const buildFTrunc = ZigLLVMBuildFTrunc;
     extern fn ZigLLVMBuildFTrunc(builder: *Builder, V: *Value, name: [*:0]const u8) *Value;
 
+    pub const buildBitReverse = ZigLLVMBuildBitReverse;
+    extern fn ZigLLVMBuildBitReverse(builder: *Builder, V: *Value, name: [*:0]const u8) *Value;
+
+    pub const buildBSwap = ZigLLVMBuildBSwap;
+    extern fn ZigLLVMBuildBSwap(builder: *Builder, V: *Value, name: [*:0]const u8) *Value;
+
+    pub const buildCTPop = ZigLLVMBuildCTPop;
+    extern fn ZigLLVMBuildCTPop(builder: *Builder, V: *Value, name: [*:0]const u8) *Value;
+
+    pub const buildCTLZ = ZigLLVMBuildCTLZ;
+    extern fn ZigLLVMBuildCTLZ(builder: *Builder, LHS: *Value, RHS: *Value, name: [*:0]const u8) *Value;
+
+    pub const buildCTTZ = ZigLLVMBuildCTTZ;
+    extern fn ZigLLVMBuildCTTZ(builder: *Builder, LHS: *Value, RHS: *Value, name: [*:0]const u8) *Value;
+
     pub const buildFMA = ZigLLVMBuildFMA;
     extern fn ZigLLVMBuildFMA(builder: *Builder, a: *Value, b: *Value, c: *Value, name: [*:0]const u8) *Value;
 
src/codegen/llvm/Builder.zig
@@ -2430,6 +2430,11 @@ pub const Function = struct {
             @"llvm.sqrt.",
             @"llvm.trunc.",
             @"llvm.fma.",
+            @"llvm.bitreverse.",
+            @"llvm.bswap.",
+            @"llvm.ctpop.",
+            @"llvm.ctlz.",
+            @"llvm.cttz.",
             @"llvm.sadd.sat.",
             @"llvm.smax.",
             @"llvm.smin.",
@@ -2572,6 +2577,8 @@ pub const Function = struct {
                     .@"fsub fast",
                     .@"llvm.maxnum.",
                     .@"llvm.minnum.",
+                    .@"llvm.ctlz.",
+                    .@"llvm.cttz.",
                     .@"llvm.sadd.sat.",
                     .@"llvm.smax.",
                     .@"llvm.smin.",
@@ -2716,6 +2723,9 @@ pub const Function = struct {
                     .@"llvm.sin.",
                     .@"llvm.sqrt.",
                     .@"llvm.trunc.",
+                    .@"llvm.bitreverse.",
+                    .@"llvm.bswap.",
+                    .@"llvm.ctpop.",
                     => @as(Value, @enumFromInt(instruction.data)).typeOfWip(wip),
                     .getelementptr,
                     .@"getelementptr inbounds",
@@ -2783,6 +2793,8 @@ pub const Function = struct {
                     .@"fsub fast",
                     .@"llvm.maxnum.",
                     .@"llvm.minnum.",
+                    .@"llvm.ctlz.",
+                    .@"llvm.cttz.",
                     .@"llvm.sadd.sat.",
                     .@"llvm.smax.",
                     .@"llvm.smin.",
@@ -2928,6 +2940,9 @@ pub const Function = struct {
                     .@"llvm.sin.",
                     .@"llvm.sqrt.",
                     .@"llvm.trunc.",
+                    .@"llvm.bitreverse.",
+                    .@"llvm.bswap.",
+                    .@"llvm.ctpop.",
                     => @as(Value, @enumFromInt(instruction.data)).typeOf(function_index, builder),
                     .getelementptr,
                     .@"getelementptr inbounds",
@@ -3486,6 +3501,10 @@ pub const WipFunction = struct {
             .@"llvm.sqrt.",
             .@"llvm.trunc.",
             => assert(val.typeOfWip(self).scalarType(self.builder).isFloatingPoint()),
+            .@"llvm.bitreverse.",
+            .@"llvm.bswap.",
+            .@"llvm.ctpop.",
+            => assert(val.typeOfWip(self).scalarType(self.builder).isInteger(self.builder)),
             else => unreachable,
         }
         try self.ensureUnusedExtraCapacity(1, NoExtra, 0);
@@ -3507,6 +3526,9 @@ pub const WipFunction = struct {
                 .@"llvm.sin.",
                 .@"llvm.sqrt.",
                 .@"llvm.trunc.",
+                .@"llvm.bitreverse.",
+                .@"llvm.bswap.",
+                .@"llvm.ctpop.",
                 => {},
                 else => unreachable,
             }
@@ -3525,6 +3547,9 @@ pub const WipFunction = struct {
                 .@"llvm.sin." => &llvm.Builder.buildSin,
                 .@"llvm.sqrt." => &llvm.Builder.buildSqrt,
                 .@"llvm.trunc." => &llvm.Builder.buildFTrunc,
+                .@"llvm.bitreverse." => &llvm.Builder.buildBitReverse,
+                .@"llvm.bswap." => &llvm.Builder.buildBSwap,
+                .@"llvm.ctpop." => &llvm.Builder.buildCTPop,
                 else => unreachable,
             }(self.llvm.builder, val.toLlvm(self), instruction.llvmName(self)));
         }
@@ -3602,6 +3627,9 @@ pub const WipFunction = struct {
             .urem,
             .xor,
             => assert(lhs.typeOfWip(self) == rhs.typeOfWip(self)),
+            .@"llvm.ctlz.",
+            .@"llvm.cttz.",
+            => assert(lhs.typeOfWip(self).scalarType(self.builder).isInteger(self.builder) and rhs.typeOfWip(self) == .i1),
             else => unreachable,
         }
         try self.ensureUnusedExtraCapacity(1, Instruction.Binary, 0);
@@ -3639,6 +3667,8 @@ pub const WipFunction = struct {
                 .fsub, .@"fsub fast" => &llvm.Builder.buildFSub,
                 .@"llvm.maxnum." => &llvm.Builder.buildMaxNum,
                 .@"llvm.minnum." => &llvm.Builder.buildMinNum,
+                .@"llvm.ctlz." => &llvm.Builder.buildCTLZ,
+                .@"llvm.cttz." => &llvm.Builder.buildCTTZ,
                 .@"llvm.sadd.sat." => &llvm.Builder.buildSAddSat,
                 .@"llvm.smax." => &llvm.Builder.buildSMax,
                 .@"llvm.smin." => &llvm.Builder.buildSMin,
@@ -4669,6 +4699,8 @@ pub const WipFunction = struct {
                     .@"icmp ult",
                     .@"llvm.maxnum.",
                     .@"llvm.minnum.",
+                    .@"llvm.ctlz.",
+                    .@"llvm.cttz.",
                     .@"llvm.sadd.sat.",
                     .@"llvm.smax.",
                     .@"llvm.smin.",
@@ -4809,6 +4841,9 @@ pub const WipFunction = struct {
                     .@"llvm.sin.",
                     .@"llvm.sqrt.",
                     .@"llvm.trunc.",
+                    .@"llvm.bitreverse.",
+                    .@"llvm.bswap.",
+                    .@"llvm.ctpop.",
                     => instruction.data = @intFromEnum(instructions.map(@enumFromInt(instruction.data))),
                     .getelementptr,
                     .@"getelementptr inbounds",
@@ -7706,6 +7741,9 @@ pub fn printUnbuffered(
                         .@"llvm.sin.",
                         .@"llvm.sqrt.",
                         .@"llvm.trunc.",
+                        .@"llvm.bitreverse.",
+                        .@"llvm.bswap.",
+                        .@"llvm.ctpop.",
                         => |tag| {
                             const val: Value = @enumFromInt(instruction.data);
                             try writer.print("  {s} {%}\n", .{
@@ -7762,6 +7800,8 @@ pub fn printUnbuffered(
                         },
                         .@"llvm.maxnum.",
                         .@"llvm.minnum.",
+                        .@"llvm.ctlz.",
+                        .@"llvm.cttz.",
                         .@"llvm.sadd.sat.",
                         .@"llvm.smax.",
                         .@"llvm.smin.",
src/zig_llvm.cpp
@@ -546,6 +546,31 @@ LLVMValueRef ZigLLVMBuildFTrunc(LLVMBuilderRef B, LLVMValueRef V, const char *na
     return wrap(call_inst);
 }
 
+LLVMValueRef ZigLLVMBuildBitReverse(LLVMBuilderRef B, LLVMValueRef V, const char *name) {
+    CallInst *call_inst = unwrap(B)->CreateUnaryIntrinsic(Intrinsic::bitreverse, unwrap(V), nullptr, name);
+    return wrap(call_inst);
+}
+
+LLVMValueRef ZigLLVMBuildBSwap(LLVMBuilderRef B, LLVMValueRef V, const char *name) {
+    CallInst *call_inst = unwrap(B)->CreateUnaryIntrinsic(Intrinsic::bswap, unwrap(V), nullptr, name);
+    return wrap(call_inst);
+}
+
+LLVMValueRef ZigLLVMBuildCTPop(LLVMBuilderRef B, LLVMValueRef V, const char *name) {
+    CallInst *call_inst = unwrap(B)->CreateUnaryIntrinsic(Intrinsic::ctpop, unwrap(V), nullptr, name);
+    return wrap(call_inst);
+}
+
+LLVMValueRef ZigLLVMBuildCTLZ(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name) {
+    CallInst *call_inst = unwrap(B)->CreateBinaryIntrinsic(Intrinsic::ctlz, unwrap(LHS), unwrap(RHS), nullptr, name);
+    return wrap(call_inst);
+}
+
+LLVMValueRef ZigLLVMBuildCTTZ(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name) {
+    CallInst *call_inst = unwrap(B)->CreateBinaryIntrinsic(Intrinsic::cttz, unwrap(LHS), unwrap(RHS), nullptr, name);
+    return wrap(call_inst);
+}
+
 LLVMValueRef ZigLLVMBuildFMA(LLVMBuilderRef builder, LLVMValueRef A, LLVMValueRef B, LLVMValueRef C, const char *name) {
     llvm::Type* types[1] = {
         unwrap(A)->getType(),
src/zig_llvm.h
@@ -155,6 +155,13 @@ ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildSin(LLVMBuilderRef builder, LLVMValueRef V
 ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildSqrt(LLVMBuilderRef builder, LLVMValueRef V, const char* name);
 ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildFTrunc(LLVMBuilderRef builder, LLVMValueRef V, const char* name);
 
+ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildBitReverse(LLVMBuilderRef builder, LLVMValueRef V, const char* name);
+ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildBSwap(LLVMBuilderRef builder, LLVMValueRef V, const char* name);
+ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildCTPop(LLVMBuilderRef builder, LLVMValueRef V, const char* name);
+
+ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildCTLZ(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, const char* name);
+ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildCTTZ(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, const char* name);
+
 ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildFMA(LLVMBuilderRef builder, LLVMValueRef A, LLVMValueRef B, LLVMValueRef C, const char* name);
 
 ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildMaxNum(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, const char* name);