From 6bc6e47b1582a4538078c8f4e9b3dae386854d07 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 30 Jun 2022 00:02:00 -0700 Subject: stage2: lower float negation explicitly Rather than lowering float negation as `0.0 - x`. * Add AIR instruction for float negation. * Add compiler-rt functions for f128, f80 negation closes #11853 --- src/codegen/llvm.zig | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'src/codegen/llvm.zig') diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 2b320923ad..d5096e3fe5 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -4019,6 +4019,7 @@ pub const FuncGen = struct { .ceil => try self.airUnaryOp(inst, .ceil), .round => try self.airUnaryOp(inst, .round), .trunc_float => try self.airUnaryOp(inst, .trunc), + .neg => try self.airUnaryOp(inst, .neg), .cmp_eq => try self.airCmp(inst, .eq), .cmp_gt => try self.airCmp(inst, .gt), @@ -6545,13 +6546,14 @@ pub const FuncGen = struct { fabs, floor, fma, + fmax, + fmin, + fmod, log, log10, log2, - fmax, - fmin, mul, - fmod, + neg, round, sin, sqrt, @@ -6584,6 +6586,7 @@ pub const FuncGen = struct { var fn_name_buf: [64]u8 = undefined; const strat: FloatOpStrat = if (intrinsics_allowed) switch (op) { // Some operations are dedicated LLVM instructions, not available as intrinsics + .neg => return self.builder.buildFNeg(params[0], ""), .add => return self.builder.buildFAdd(params[0], params[1], ""), .sub => return self.builder.buildFSub(params[0], params[1], ""), .mul => return self.builder.buildFMul(params[0], params[1], ""), @@ -6595,6 +6598,11 @@ pub const FuncGen = struct { } else b: { const float_bits = scalar_ty.floatBits(target); break :b switch (op) { + .neg => FloatOpStrat{ + .libc = std.fmt.bufPrintZ(&fn_name_buf, "__neg{s}f2", .{ + compilerRtFloatAbbrev(float_bits), + }) catch unreachable, + }, .add, .sub, .div, .mul => FloatOpStrat{ .libc = std.fmt.bufPrintZ(&fn_name_buf, "__{s}{s}f3", .{ @tagName(op), compilerRtFloatAbbrev(float_bits), -- cgit v1.2.3 From b3b96b5e288ddf3694b4a0d203c684b9b8f6b49f Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 30 Jun 2022 11:48:37 -0700 Subject: LLVM: lower float negation with xor a constant Rather than a compiler-rt call in the case that LLVM does not support lowering the fneg instruction. --- src/codegen/llvm.zig | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'src/codegen/llvm.zig') diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index d5096e3fe5..37d6d2c52b 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -6598,10 +6598,16 @@ pub const FuncGen = struct { } else b: { const float_bits = scalar_ty.floatBits(target); break :b switch (op) { - .neg => FloatOpStrat{ - .libc = std.fmt.bufPrintZ(&fn_name_buf, "__neg{s}f2", .{ - compilerRtFloatAbbrev(float_bits), - }) catch unreachable, + .neg => { + // In this case we can generate a softfloat negation by XORing the + // bits with a constant. + const int_llvm_ty = self.dg.context.intType(float_bits); + const one = int_llvm_ty.constInt(1, .False); + const shift_amt = int_llvm_ty.constInt(float_bits - 1, .False); + const sign_mask = one.constShl(shift_amt); + const bitcasted_operand = self.builder.buildBitCast(params[0], int_llvm_ty, ""); + const result = self.builder.buildXor(bitcasted_operand, sign_mask, ""); + return self.builder.buildBitCast(result, llvm_ty, ""); }, .add, .sub, .div, .mul => FloatOpStrat{ .libc = std.fmt.bufPrintZ(&fn_name_buf, "__{s}{s}f3", .{ -- cgit v1.2.3