LLVM backend: refactor LLVM bitcount ops (#10882)

Use `llvm.getIntrinsic` instead of `llvm.getNamedFunction`
This commit is contained in:
John Schmidt 2022-02-15 03:52:12 +01:00 committed by GitHub
parent 7b938767bb
commit 807edd2234
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -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, "");