diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2022-06-30 11:48:37 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2022-06-30 11:48:37 -0700 |
| commit | b3b96b5e288ddf3694b4a0d203c684b9b8f6b49f (patch) | |
| tree | 93ec35c7630bdfe44eb3cf4f27e9db286d1e2b32 /src/codegen | |
| parent | c8531faaf56612773ef860d341f8eebb36af4bf3 (diff) | |
| download | zig-b3b96b5e288ddf3694b4a0d203c684b9b8f6b49f.tar.gz zig-b3b96b5e288ddf3694b4a0d203c684b9b8f6b49f.zip | |
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.
Diffstat (limited to 'src/codegen')
| -rw-r--r-- | src/codegen/llvm.zig | 14 |
1 files changed, 10 insertions, 4 deletions
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", .{ |
