Commit 807edd2234

John Schmidt <3405586+schmee@users.noreply.github.com>
2022-02-15 03:52:12
LLVM backend: refactor LLVM bitcount ops (#10882)
Use `llvm.getIntrinsic` instead of `llvm.getNamedFunction`
1 parent 7b93876
Changed files (1)
src
codegen
src/codegen/llvm.zig
@@ -2203,8 +2203,8 @@ pub const FuncGen = struct {
                 .memcpy         => try self.airMemcpy(inst),
                 .set_union_tag  => try self.airSetUnionTag(inst),
                 .get_union_tag  => try self.airGetUnionTag(inst),
-                .clz            => try self.airClzCtz(inst, "ctlz"),
-                .ctz            => try self.airClzCtz(inst, "cttz"),
+                .clz            => try self.airClzCtz(inst, "llvm.ctlz"),
+                .ctz            => try self.airClzCtz(inst, "llvm.cttz"),
                 .popcount       => try self.airPopCount(inst),
                 .tag_name       => try self.airTagName(inst),
                 .error_name     => try self.airErrorName(inst),
@@ -4320,40 +4320,24 @@ pub const FuncGen = struct {
         return self.builder.buildCall(fn_val, &params, params.len, .C, .Auto, "");
     }
 
-    fn airClzCtz(self: *FuncGen, inst: Air.Inst.Index, prefix: [*:0]const u8) !?*const llvm.Value {
+    fn airClzCtz(self: *FuncGen, inst: Air.Inst.Index, llvm_fn_name: []const u8) !?*const llvm.Value {
         if (self.liveness.isUnused(inst)) return null;
 
         const ty_op = self.air.instructions.items(.data)[inst].ty_op;
         const operand_ty = self.air.typeOf(ty_op.operand);
         const operand = try self.resolveInst(ty_op.operand);
-        const target = self.dg.module.getTarget();
-        const bits = operand_ty.intInfo(target).bits;
-        const vec_len: ?u32 = switch (operand_ty.zigTypeTag()) {
-            .Vector => operand_ty.vectorLen(),
-            else => null,
-        };
 
-        var fn_name_buf: [100]u8 = undefined;
-        const llvm_fn_name = if (vec_len) |len|
-            std.fmt.bufPrintZ(&fn_name_buf, "llvm.{s}.v{d}i{d}", .{
-                prefix, len, bits,
-            }) catch unreachable
-        else
-            std.fmt.bufPrintZ(&fn_name_buf, "llvm.{s}.i{d}", .{
-                prefix, bits,
-            }) catch unreachable;
         const llvm_i1 = self.context.intType(1);
-        const fn_val = self.dg.object.llvm_module.getNamedFunction(llvm_fn_name) orelse blk: {
-            const operand_llvm_ty = try self.dg.llvmType(operand_ty);
-            const param_types = [_]*const llvm.Type{ operand_llvm_ty, llvm_i1 };
-            const fn_type = llvm.functionType(operand_llvm_ty, &param_types, param_types.len, .False);
-            break :blk self.dg.object.llvm_module.addFunction(llvm_fn_name, fn_type);
-        };
+        const operand_llvm_ty = try self.dg.llvmType(operand_ty);
+        const fn_val = self.getIntrinsic(llvm_fn_name, &.{operand_llvm_ty});
 
         const params = [_]*const llvm.Value{ operand, llvm_i1.constNull() };
         const wrong_size_result = self.builder.buildCall(fn_val, &params, params.len, .C, .Auto, "");
         const result_ty = self.air.typeOfIndex(inst);
         const result_llvm_ty = try self.dg.llvmType(result_ty);
+
+        const target = self.dg.module.getTarget();
+        const bits = operand_ty.intInfo(target).bits;
         const result_bits = result_ty.intInfo(target).bits;
         if (bits > result_bits) {
             return self.builder.buildTrunc(wrong_size_result, result_llvm_ty, "");
@@ -4370,29 +4354,17 @@ pub const FuncGen = struct {
         const ty_op = self.air.instructions.items(.data)[inst].ty_op;
         const operand_ty = self.air.typeOf(ty_op.operand);
         const operand = try self.resolveInst(ty_op.operand);
-        const target = self.dg.module.getTarget();
-        const bits = operand_ty.intInfo(target).bits;
-        const vec_len: ?u32 = switch (operand_ty.zigTypeTag()) {
-            .Vector => operand_ty.vectorLen(),
-            else => null,
-        };
-
-        var fn_name_buf: [100]u8 = undefined;
-        const llvm_fn_name = if (vec_len) |len|
-            std.fmt.bufPrintZ(&fn_name_buf, "llvm.ctpop.v{d}i{d}", .{ len, bits }) catch unreachable
-        else
-            std.fmt.bufPrintZ(&fn_name_buf, "llvm.ctpop.i{d}", .{bits}) catch unreachable;
-        const fn_val = self.dg.object.llvm_module.getNamedFunction(llvm_fn_name) orelse blk: {
-            const operand_llvm_ty = try self.dg.llvmType(operand_ty);
-            const param_types = [_]*const llvm.Type{operand_llvm_ty};
-            const fn_type = llvm.functionType(operand_llvm_ty, &param_types, param_types.len, .False);
-            break :blk self.dg.object.llvm_module.addFunction(llvm_fn_name, fn_type);
-        };
 
         const params = [_]*const llvm.Value{operand};
+        const operand_llvm_ty = try self.dg.llvmType(operand_ty);
+        const fn_val = self.getIntrinsic("llvm.ctpop", &.{operand_llvm_ty});
+
         const wrong_size_result = self.builder.buildCall(fn_val, &params, params.len, .C, .Auto, "");
         const result_ty = self.air.typeOfIndex(inst);
         const result_llvm_ty = try self.dg.llvmType(result_ty);
+
+        const target = self.dg.module.getTarget();
+        const bits = operand_ty.intInfo(target).bits;
         const result_bits = result_ty.intInfo(target).bits;
         if (bits > result_bits) {
             return self.builder.buildTrunc(wrong_size_result, result_llvm_ty, "");