| ... | @@ -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 | } |
| 4322 | | 4322 | |
| 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; |
| 4325 | | 4325 | |
| 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 | }; | | |
| 4335 | | 4329 | |
| 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 | }; | | |
| 4352 | | 4333 | |
| 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 | }; | | |
| 4391 | | 4357 | |
| 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, ""); |