diff options
Diffstat (limited to 'src/codegen/llvm.zig')
| -rw-r--r-- | src/codegen/llvm.zig | 56 |
1 files changed, 14 insertions, 42 deletions
diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 493b895d5d..3d65829c1e 100644 --- a/src/codegen/llvm.zig +++ b/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, ¶ms, 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, ¶m_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, ¶ms, 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, ¶m_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, ¶ms, 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, ""); |
