authorgravatar for 3405586+schmee@users.noreply.github.comJohn Schmidt <3405586+schmee@users.noreply.github.com> 2022-02-15 03:52:12+01:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-02-14 21:52:12-05:00
log807edd2234b016cd5470c51ac2bac451554c614d
tree8ef308a0e0b082361acb82c075b3af16962364d6
parent7b938767bb18535a870d0460c9f4d9e3d93ab053
signature Signed by PGP key 4AEE18F83AFDEB23

LLVM backend: refactor LLVM bitcount ops (#10882)

Use `llvm.getIntrinsic` instead of `llvm.getNamedFunction`

1 files changed, 14 insertions(+), 42 deletions(-)

src/codegen/llvm.zig+14-42
......@@ -2203,8 +2203,8 @@ pub const FuncGen = struct {
22032203 .memcpy => try self.airMemcpy(inst),
22042204 .set_union_tag => try self.airSetUnionTag(inst),
22052205 .get_union_tag => try self.airGetUnionTag(inst),
2206 .clz => try self.airClzCtz(inst, "ctlz"),
2207 .ctz => try self.airClzCtz(inst, "cttz"),
2206 .clz => try self.airClzCtz(inst, "llvm.ctlz"),
2207 .ctz => try self.airClzCtz(inst, "llvm.cttz"),
22082208 .popcount => try self.airPopCount(inst),
22092209 .tag_name => try self.airTagName(inst),
22102210 .error_name => try self.airErrorName(inst),
......@@ -4320,40 +4320,24 @@ pub const FuncGen = struct {
43204320 return self.builder.buildCall(fn_val, &params, params.len, .C, .Auto, "");
43214321 }
43224322
4323 fn airClzCtz(self: *FuncGen, inst: Air.Inst.Index, prefix: [*:0]const u8) !?*const llvm.Value {
4323 fn airClzCtz(self: *FuncGen, inst: Air.Inst.Index, llvm_fn_name: []const u8) !?*const llvm.Value {
43244324 if (self.liveness.isUnused(inst)) return null;
43254325
43264326 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
43274327 const operand_ty = self.air.typeOf(ty_op.operand);
43284328 const operand = try self.resolveInst(ty_op.operand);
4329 const target = self.dg.module.getTarget();
4330 const bits = operand_ty.intInfo(target).bits;
4331 const vec_len: ?u32 = switch (operand_ty.zigTypeTag()) {
4332 .Vector => operand_ty.vectorLen(),
4333 else => null,
4334 };
43354329
4336 var fn_name_buf: [100]u8 = undefined;
4337 const llvm_fn_name = if (vec_len) |len|
4338 std.fmt.bufPrintZ(&fn_name_buf, "llvm.{s}.v{d}i{d}", .{
4339 prefix, len, bits,
4340 }) catch unreachable
4341 else
4342 std.fmt.bufPrintZ(&fn_name_buf, "llvm.{s}.i{d}", .{
4343 prefix, bits,
4344 }) catch unreachable;
43454330 const llvm_i1 = self.context.intType(1);
4346 const fn_val = self.dg.object.llvm_module.getNamedFunction(llvm_fn_name) orelse blk: {
4347 const operand_llvm_ty = try self.dg.llvmType(operand_ty);
4348 const param_types = [_]*const llvm.Type{ operand_llvm_ty, llvm_i1 };
4349 const fn_type = llvm.functionType(operand_llvm_ty, &param_types, param_types.len, .False);
4350 break :blk self.dg.object.llvm_module.addFunction(llvm_fn_name, fn_type);
4351 };
4331 const operand_llvm_ty = try self.dg.llvmType(operand_ty);
4332 const fn_val = self.getIntrinsic(llvm_fn_name, &.{operand_llvm_ty});
43524333
43534334 const params = [_]*const llvm.Value{ operand, llvm_i1.constNull() };
43544335 const wrong_size_result = self.builder.buildCall(fn_val, &params, params.len, .C, .Auto, "");
43554336 const result_ty = self.air.typeOfIndex(inst);
43564337 const result_llvm_ty = try self.dg.llvmType(result_ty);
4338
4339 const target = self.dg.module.getTarget();
4340 const bits = operand_ty.intInfo(target).bits;
43574341 const result_bits = result_ty.intInfo(target).bits;
43584342 if (bits > result_bits) {
43594343 return self.builder.buildTrunc(wrong_size_result, result_llvm_ty, "");
......@@ -4370,29 +4354,17 @@ pub const FuncGen = struct {
43704354 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
43714355 const operand_ty = self.air.typeOf(ty_op.operand);
43724356 const operand = try self.resolveInst(ty_op.operand);
4373 const target = self.dg.module.getTarget();
4374 const bits = operand_ty.intInfo(target).bits;
4375 const vec_len: ?u32 = switch (operand_ty.zigTypeTag()) {
4376 .Vector => operand_ty.vectorLen(),
4377 else => null,
4378 };
4379
4380 var fn_name_buf: [100]u8 = undefined;
4381 const llvm_fn_name = if (vec_len) |len|
4382 std.fmt.bufPrintZ(&fn_name_buf, "llvm.ctpop.v{d}i{d}", .{ len, bits }) catch unreachable
4383 else
4384 std.fmt.bufPrintZ(&fn_name_buf, "llvm.ctpop.i{d}", .{bits}) catch unreachable;
4385 const fn_val = self.dg.object.llvm_module.getNamedFunction(llvm_fn_name) orelse blk: {
4386 const operand_llvm_ty = try self.dg.llvmType(operand_ty);
4387 const param_types = [_]*const llvm.Type{operand_llvm_ty};
4388 const fn_type = llvm.functionType(operand_llvm_ty, &param_types, param_types.len, .False);
4389 break :blk self.dg.object.llvm_module.addFunction(llvm_fn_name, fn_type);
4390 };
43914357
43924358 const params = [_]*const llvm.Value{operand};
4359 const operand_llvm_ty = try self.dg.llvmType(operand_ty);
4360 const fn_val = self.getIntrinsic("llvm.ctpop", &.{operand_llvm_ty});
4361
43934362 const wrong_size_result = self.builder.buildCall(fn_val, &params, params.len, .C, .Auto, "");
43944363 const result_ty = self.air.typeOfIndex(inst);
43954364 const result_llvm_ty = try self.dg.llvmType(result_ty);
4365
4366 const target = self.dg.module.getTarget();
4367 const bits = operand_ty.intInfo(target).bits;
43964368 const result_bits = result_ty.intInfo(target).bits;
43974369 if (bits > result_bits) {
43984370 return self.builder.buildTrunc(wrong_size_result, result_llvm_ty, "");