Use new LLVM builder API in buildFloatOP

This commit is contained in:
antlilja
2023-08-06 00:10:43 +02:00
parent 63dcffdf9f
commit 2b4ac7c6b3

View File

@@ -8282,8 +8282,7 @@ pub const FuncGen = struct {
const scalar_ty = ty.scalarType(mod);
const llvm_ty = try o.lowerType(ty);
const intrinsics_allowed = op != .tan and intrinsicsAllowed(scalar_ty, target);
const strat: FloatOpStrat = if (intrinsics_allowed) switch (op) {
if (op != .tan and intrinsicsAllowed(scalar_ty, target)) switch (op) {
// Some operations are dedicated LLVM instructions, not available as intrinsics
.neg => return self.wip.un(.fneg, params[0], ""),
.add => return self.wip.bin(.fadd, params[0], params[1], ""),
@@ -8293,83 +8292,84 @@ pub const FuncGen = struct {
.fmod => return self.wip.bin(.frem, params[0], params[1], ""),
.fmax => return self.wip.bin(.@"llvm.maxnum.", params[0], params[1], ""),
.fmin => return self.wip.bin(.@"llvm.minnum.", params[0], params[1], ""),
else => .{ .intrinsic = "llvm." ++ @tagName(op) },
} else b: {
const float_bits = scalar_ty.floatBits(target);
break :b switch (op) {
.neg => {
// In this case we can generate a softfloat negation by XORing the
// bits with a constant.
const int_ty = try o.builder.intType(@intCast(float_bits));
const cast_ty = try llvm_ty.changeScalar(int_ty, &o.builder);
const sign_mask = try o.builder.splatValue(
cast_ty,
try o.builder.intConst(int_ty, @as(u128, 1) << @intCast(float_bits - 1)),
);
const bitcasted_operand = try self.wip.cast(.bitcast, params[0], cast_ty, "");
const result = try self.wip.bin(.xor, bitcasted_operand, sign_mask, "");
return self.wip.cast(.bitcast, result, llvm_ty, "");
},
.add, .sub, .div, .mul => .{ .libc = try o.builder.fmt("__{s}{s}f3", .{
@tagName(op), compilerRtFloatAbbrev(float_bits),
}) },
.ceil,
.cos,
.exp,
.exp2,
.fabs,
.floor,
.fma,
.fmax,
.fmin,
.fmod,
.log,
.log10,
.log2,
.round,
.sin,
.sqrt,
.tan,
.trunc,
=> .{ .libc = try o.builder.fmt("{s}{s}{s}", .{
libcFloatPrefix(float_bits), @tagName(op), libcFloatSuffix(float_bits),
}) },
};
.ceil => return self.wip.un(.@"llvm.ceil.", params[0], ""),
.cos => return self.wip.un(.@"llvm.cos.", params[0], ""),
.exp => return self.wip.un(.@"llvm.exp.", params[0], ""),
.exp2 => return self.wip.un(.@"llvm.exp2.", params[0], ""),
.fabs => return self.wip.un(.@"llvm.fabs.", params[0], ""),
.floor => return self.wip.un(.@"llvm.floor.", params[0], ""),
.log => return self.wip.un(.@"llvm.log.", params[0], ""),
.log10 => return self.wip.un(.@"llvm.log10.", params[0], ""),
.log2 => return self.wip.un(.@"llvm.log2.", params[0], ""),
.round => return self.wip.un(.@"llvm.round.", params[0], ""),
.sin => return self.wip.un(.@"llvm.sin.", params[0], ""),
.sqrt => return self.wip.un(.@"llvm.sqrt.", params[0], ""),
.trunc => return self.wip.un(.@"llvm.trunc.", params[0], ""),
.fma => return self.wip.fusedMultiplyAdd(params[0], params[1], params[2]),
.tan => unreachable,
};
const llvm_fn = switch (strat) {
.intrinsic => |fn_name| try self.getIntrinsic(fn_name, &.{llvm_ty}),
.libc => |fn_name| b: {
const scalar_llvm_ty = llvm_ty.scalarType(&o.builder);
const libc_fn = try self.getLibcFunction(
fn_name,
([1]Builder.Type{scalar_llvm_ty} ** 3)[0..params.len],
scalar_llvm_ty,
const float_bits = scalar_ty.floatBits(target);
const fn_name = switch (op) {
.neg => {
// In this case we can generate a softfloat negation by XORing the
// bits with a constant.
const int_ty = try o.builder.intType(@intCast(float_bits));
const cast_ty = try llvm_ty.changeScalar(int_ty, &o.builder);
const sign_mask = try o.builder.splatValue(
cast_ty,
try o.builder.intConst(int_ty, @as(u128, 1) << @intCast(float_bits - 1)),
);
if (ty.zigTypeTag(mod) == .Vector) {
const result = try o.builder.poisonValue(llvm_ty);
return self.buildElementwiseCall(libc_fn, &params, result, ty.vectorLen(mod));
}
break :b libc_fn.toLlvm(&o.builder);
const bitcasted_operand = try self.wip.cast(.bitcast, params[0], cast_ty, "");
const result = try self.wip.bin(.xor, bitcasted_operand, sign_mask, "");
return self.wip.cast(.bitcast, result, llvm_ty, "");
},
.add, .sub, .div, .mul => try o.builder.fmt("__{s}{s}f3", .{
@tagName(op), compilerRtFloatAbbrev(float_bits),
}),
.ceil,
.cos,
.exp,
.exp2,
.fabs,
.floor,
.fma,
.fmax,
.fmin,
.fmod,
.log,
.log10,
.log2,
.round,
.sin,
.sqrt,
.tan,
.trunc,
=> try o.builder.fmt("{s}{s}{s}", .{
libcFloatPrefix(float_bits), @tagName(op), libcFloatSuffix(float_bits),
}),
};
const llvm_fn_ty = try o.builder.fnType(
llvm_ty,
([1]Builder.Type{llvm_ty} ** 3)[0..params.len],
.normal,
const scalar_llvm_ty = llvm_ty.scalarType(&o.builder);
const libc_fn = try self.getLibcFunction(
fn_name,
([1]Builder.Type{scalar_llvm_ty} ** 3)[0..params.len],
scalar_llvm_ty,
);
var llvm_params: [params_len]*llvm.Value = undefined;
for (&llvm_params, params) |*llvm_param, param| llvm_param.* = param.toLlvm(&self.wip);
return (try self.wip.unimplemented(llvm_ty, "")).finish(self.builder.buildCallOld(
llvm_fn_ty.toLlvm(&o.builder),
llvm_fn,
&llvm_params,
params_len,
.C,
.Auto,
if (ty.zigTypeTag(mod) == .Vector) {
const result = try o.builder.poisonValue(llvm_ty);
return self.buildElementwiseCall(libc_fn, &params, result, ty.vectorLen(mod));
}
return self.wip.call(
.normal,
.ccc,
.none,
libc_fn.typeOf(&o.builder),
libc_fn.toValue(&o.builder),
&params,
"",
), &self.wip);
);
}
fn airMulAdd(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {