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
signaturebadge-question-mark 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 {...@@ -2203,8 +2203,8 @@ pub const FuncGen = struct {
2203 .memcpy => try self.airMemcpy(inst),2203 .memcpy => try self.airMemcpy(inst),
2204 .set_union_tag => try self.airSetUnionTag(inst),2204 .set_union_tag => try self.airSetUnionTag(inst),
2205 .get_union_tag => try self.airGetUnionTag(inst),2205 .get_union_tag => try self.airGetUnionTag(inst),
2206 .clz => try self.airClzCtz(inst, "ctlz"),2206 .clz => try self.airClzCtz(inst, "llvm.ctlz"),
2207 .ctz => try self.airClzCtz(inst, "cttz"),2207 .ctz => try self.airClzCtz(inst, "llvm.cttz"),
2208 .popcount => try self.airPopCount(inst),2208 .popcount => try self.airPopCount(inst),
2209 .tag_name => try self.airTagName(inst),2209 .tag_name => try self.airTagName(inst),
2210 .error_name => try self.airErrorName(inst),2210 .error_name => try self.airErrorName(inst),
...@@ -4320,40 +4320,24 @@ pub const FuncGen = struct {...@@ -4320,40 +4320,24 @@ pub const FuncGen = struct {
4320 return self.builder.buildCall(fn_val, &params, params.len, .C, .Auto, "");4320 return self.builder.buildCall(fn_val, &params, params.len, .C, .Auto, "");
4321 }4321 }
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 {
4324 if (self.liveness.isUnused(inst)) return null;4324 if (self.liveness.isUnused(inst)) return null;
43254325
4326 const ty_op = self.air.instructions.items(.data)[inst].ty_op;4326 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
4327 const operand_ty = self.air.typeOf(ty_op.operand);4327 const operand_ty = self.air.typeOf(ty_op.operand);
4328 const operand = try self.resolveInst(ty_op.operand);4328 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;
4345 const llvm_i1 = self.context.intType(1);4330 const llvm_i1 = self.context.intType(1);
4346 const fn_val = self.dg.object.llvm_module.getNamedFunction(llvm_fn_name) orelse blk: {4331 const operand_llvm_ty = try self.dg.llvmType(operand_ty);
4347 const operand_llvm_ty = try self.dg.llvmType(operand_ty);4332 const fn_val = self.getIntrinsic(llvm_fn_name, &.{operand_llvm_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 };
43524333
4353 const params = [_]*const llvm.Value{ operand, llvm_i1.constNull() };4334 const params = [_]*const llvm.Value{ operand, llvm_i1.constNull() };
4354 const wrong_size_result = self.builder.buildCall(fn_val, &params, params.len, .C, .Auto, "");4335 const wrong_size_result = self.builder.buildCall(fn_val, &params, params.len, .C, .Auto, "");
4355 const result_ty = self.air.typeOfIndex(inst);4336 const result_ty = self.air.typeOfIndex(inst);
4356 const result_llvm_ty = try self.dg.llvmType(result_ty);4337 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;
4357 const result_bits = result_ty.intInfo(target).bits;4341 const result_bits = result_ty.intInfo(target).bits;
4358 if (bits > result_bits) {4342 if (bits > result_bits) {
4359 return self.builder.buildTrunc(wrong_size_result, result_llvm_ty, "");4343 return self.builder.buildTrunc(wrong_size_result, result_llvm_ty, "");
...@@ -4370,29 +4354,17 @@ pub const FuncGen = struct {...@@ -4370,29 +4354,17 @@ pub const FuncGen = struct {
4370 const ty_op = self.air.instructions.items(.data)[inst].ty_op;4354 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
4371 const operand_ty = self.air.typeOf(ty_op.operand);4355 const operand_ty = self.air.typeOf(ty_op.operand);
4372 const operand = try self.resolveInst(ty_op.operand);4356 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
4392 const params = [_]*const llvm.Value{operand};4358 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
4393 const wrong_size_result = self.builder.buildCall(fn_val, &params, params.len, .C, .Auto, "");4362 const wrong_size_result = self.builder.buildCall(fn_val, &params, params.len, .C, .Auto, "");
4394 const result_ty = self.air.typeOfIndex(inst);4363 const result_ty = self.air.typeOfIndex(inst);
4395 const result_llvm_ty = try self.dg.llvmType(result_ty);4364 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;
4396 const result_bits = result_ty.intInfo(target).bits;4368 const result_bits = result_ty.intInfo(target).bits;
4397 if (bits > result_bits) {4369 if (bits > result_bits) {
4398 return self.builder.buildTrunc(wrong_size_result, result_llvm_ty, "");4370 return self.builder.buildTrunc(wrong_size_result, result_llvm_ty, "");