From e74b98227eee5eef1c3a7cded0f8fff147178864 Mon Sep 17 00:00:00 2001 From: rpkak Date: Tue, 7 Apr 2026 12:10:27 +0200 Subject: [PATCH 1/2] zigc: long double: call double function if long double and double are equivalent For some of these functions and most targets this changes nothing, either because long double and double are not equivalent or because llvm did function deduplication. But e.g. on aarch64-windows-gnu, ucrt provides hypot, but not hypotl. Now hypotl calls hypot from ucrt instead of including the std.math.hypot implementation in zigc. Very trivial functions (like nanl) are not changed, because a function call would probably make this function more complex. --- lib/c/math.zig | 45 ++++++++++++++++++++++++++++----------------- lib/std/c.zig | 8 ++++++++ 2 files changed, 36 insertions(+), 17 deletions(-) diff --git a/lib/c/math.zig b/lib/c/math.zig index 18ba8d9e755e4f74a6bc50d3cd178ffb2d1ed686..5eff669a9755975cc7423a203c15ecc6d5a199c6 100644 --- a/lib/c/math.zig +++ b/lib/c/math.zig @@ -116,13 +116,9 @@ fn atanf(x: f32) callconv(.c) f32 { } fn atanl(x: c_longdouble) callconv(.c) c_longdouble { - return switch (@typeInfo(@TypeOf(x)).float.bits) { - 16 => math.atan(@as(f16, @floatCast(x))), - 32 => math.atan(@as(f32, @floatCast(x))), - 64 => math.atan(@as(f64, @floatCast(x))), - 80 => math.atan(@as(f80, @floatCast(x))), - 128 => math.atan(@as(f128, @floatCast(x))), - else => unreachable, + return switch (@typeInfo(c_longdouble).float.bits) { + 64 => std.c.atan(x), + else => math.atan(x), }; } @@ -143,7 +139,10 @@ fn copysignf(x: f32, y: f32) callconv(.c) f32 { } fn copysignl(x: c_longdouble, y: c_longdouble) callconv(.c) c_longdouble { - return math.copysign(x, y); + return switch (@typeInfo(c_longdouble).float.bits) { + 64 => std.c.copysign(x, y), + else => math.copysign(x, y), + }; } fn cosh(x: f64) callconv(.c) f64 { @@ -183,15 +182,18 @@ fn fdimf(x: f32, y: f32) callconv(.c) f32 { } fn fdiml(x: c_longdouble, y: c_longdouble) callconv(.c) c_longdouble { - return fdimGeneric(c_longdouble, x, y); + return switch (@typeInfo(c_longdouble).float.bits) { + 64 => std.c.fdim(x, y), + else => fdimGeneric(c_longdouble, x, y), + }; } fn finite(x: f64) callconv(.c) c_int { - return if (math.isFinite(x)) 1 else 0; + return @intFromBool(math.isFinite(x)); } fn finitef(x: f32) callconv(.c) c_int { - return if (math.isFinite(x)) 1 else 0; + return @intFromBool(math.isFinite(x)); } fn frexpGeneric(comptime T: type, x: T, e: *c_int) T { @@ -222,7 +224,10 @@ fn frexpf(x: f32, e: *c_int) callconv(.c) f32 { } fn frexpl(x: c_longdouble, e: *c_int) callconv(.c) c_longdouble { - return frexpGeneric(c_longdouble, x, e); + return switch (@typeInfo(c_longdouble).float.bits) { + 64 => std.c.frexp(x, e), + else => frexpGeneric(c_longdouble, x, e), + }; } fn hypot(x: f64, y: f64) callconv(.c) f64 { @@ -234,19 +239,22 @@ fn hypotf(x: f32, y: f32) callconv(.c) f32 { } fn hypotl(x: c_longdouble, y: c_longdouble) callconv(.c) c_longdouble { - return math.hypot(x, y); + return switch (@typeInfo(c_longdouble).float.bits) { + 64 => std.c.hypot(x, y), + else => math.hypot(x, y), + }; } fn isnan(x: f64) callconv(.c) c_int { - return if (math.isNan(x)) 1 else 0; + return @intFromBool(math.isNan(x)); } fn isnanf(x: f32) callconv(.c) c_int { - return if (math.isNan(x)) 1 else 0; + return @intFromBool(math.isNan(x)); } fn isnanl(x: c_longdouble) callconv(.c) c_int { - return if (math.isNan(x)) 1 else 0; + return @intFromBool(math.isNan(x)); } fn lrint(x: f64) callconv(.c) c_long { @@ -290,7 +298,10 @@ fn modff(x: f32, iptr: *f32) callconv(.c) f32 { } fn modfl(x: c_longdouble, iptr: *c_longdouble) callconv(.c) c_longdouble { - return modfGeneric(c_longdouble, x, iptr); + return switch (@typeInfo(c_longdouble).float.bits) { + 64 => std.c.modf(x, iptr), + else => modfGeneric(c_longdouble, x, iptr), + }; } fn testModf(comptime T: type) !void { diff --git a/lib/std/c.zig b/lib/std/c.zig index f0b03917855a2261fad5352220329c6904f922dc..4e1bc6594339b4597058afbac119ae96c1218acb 100644 --- a/lib/std/c.zig +++ b/lib/std/c.zig @@ -11102,6 +11102,14 @@ pub const ioctl = switch (native_os) { else => private.ioctl, }; +// Math +pub extern "c" fn atan(x: f64) callconv(.c) f64; +pub extern "c" fn copysign(x: f64, y: f64) callconv(.c) f64; +pub extern "c" fn fdim(x: f64, y: f64) callconv(.c) f64; +pub extern "c" fn frexp(x: f64, e: *c_int) callconv(.c) f64; +pub extern "c" fn hypot(x: f64, y: f64) callconv(.c) f64; +pub extern "c" fn modf(x: f64, iptr: *f64) callconv(.c) f64; + // OS-specific bits. These are protected from being used on the wrong OS by // comptime assertions inside each OS-specific file. -- 2.54.0 From f564a7733cb20395a399caea21aac6fa54af50b3 Mon Sep 17 00:00:00 2001 From: rpkak Date: Wed, 8 Apr 2026 08:41:07 +0200 Subject: [PATCH 2/2] remove code, which is only reached if c_longdouble is only 16 or 32 bits big --- lib/compiler_rt/cos.zig | 2 -- lib/compiler_rt/exp.zig | 2 -- lib/compiler_rt/exp2.zig | 2 -- lib/compiler_rt/fabs.zig | 2 -- lib/compiler_rt/fma.zig | 2 -- lib/compiler_rt/fmax.zig | 2 -- lib/compiler_rt/fmin.zig | 2 -- lib/compiler_rt/fmod.zig | 2 -- lib/compiler_rt/log.zig | 2 -- lib/compiler_rt/log10.zig | 2 -- lib/compiler_rt/log2.zig | 2 -- lib/compiler_rt/round.zig | 2 -- lib/compiler_rt/sin.zig | 2 -- lib/compiler_rt/sincos.zig | 2 -- lib/compiler_rt/sqrt.zig | 2 -- lib/compiler_rt/tan.zig | 2 -- lib/compiler_rt/trunc.zig | 2 -- lib/std/Target.zig | 2 -- src/codegen/aarch64/Select.zig | 2 -- test/behavior/cast.zig | 2 -- 20 files changed, 40 deletions(-) diff --git a/lib/compiler_rt/cos.zig b/lib/compiler_rt/cos.zig index 3620e31835b20461f80a096c4ccc7a59365fd812..0bc02e32945fd33abd5a2c5b473398fe179c8ae2 100644 --- a/lib/compiler_rt/cos.zig +++ b/lib/compiler_rt/cos.zig @@ -173,8 +173,6 @@ pub fn cosq(x: f128) callconv(.c) f128 { pub fn cosl(x: c_longdouble) callconv(.c) c_longdouble { switch (@typeInfo(c_longdouble).float.bits) { - 16 => return cosh(x), - 32 => return cosf(x), 64 => return cos(x), 80 => return cosx(x), 128 => return cosq(x), diff --git a/lib/compiler_rt/exp.zig b/lib/compiler_rt/exp.zig index 3b0e593af0d3ccbed89b9e2e620134c6023405c9..ce2eadb7f1edfe49ca51562a8b3ec4432f2017eb 100644 --- a/lib/compiler_rt/exp.zig +++ b/lib/compiler_rt/exp.zig @@ -198,8 +198,6 @@ const expq = @import("exp_f128.zig").exp; pub fn expl(x: c_longdouble) callconv(.c) c_longdouble { switch (@typeInfo(c_longdouble).float.bits) { - 16 => return __exph(x), - 32 => return expf(x), 64 => return exp(x), 80 => return __expx(x), 128 => return expq(x), diff --git a/lib/compiler_rt/exp2.zig b/lib/compiler_rt/exp2.zig index 94f19bef2c919569b982ed5aea8e3ce1b58db14b..abcef881073619a860997766283c950cc702a3e6 100644 --- a/lib/compiler_rt/exp2.zig +++ b/lib/compiler_rt/exp2.zig @@ -165,8 +165,6 @@ pub const exp2q = @import("exp_f128.zig").exp2; pub fn exp2l(x: c_longdouble) callconv(.c) c_longdouble { switch (@typeInfo(c_longdouble).float.bits) { - 16 => return __exp2h(x), - 32 => return exp2f(x), 64 => return exp2(x), 80 => return __exp2x(x), 128 => return exp2q(x), diff --git a/lib/compiler_rt/fabs.zig b/lib/compiler_rt/fabs.zig index 8fcf36262a40ed89c2e3ae0be958eaadabfb2c91..3e2104da6af1f8263678f06127f1ee0eb9201136 100644 --- a/lib/compiler_rt/fabs.zig +++ b/lib/compiler_rt/fabs.zig @@ -38,8 +38,6 @@ pub fn fabsq(a: f128) callconv(.c) f128 { pub fn fabsl(x: c_longdouble) callconv(.c) c_longdouble { switch (@typeInfo(c_longdouble).float.bits) { - 16 => return __fabsh(x), - 32 => return fabsf(x), 64 => return fabs(x), 80 => return __fabsx(x), 128 => return fabsq(x), diff --git a/lib/compiler_rt/fma.zig b/lib/compiler_rt/fma.zig index 10926e9bde05d36d8cdf16661542df9821621e0c..61732585db2ece3fb84c3029293cab41662781d2 100644 --- a/lib/compiler_rt/fma.zig +++ b/lib/compiler_rt/fma.zig @@ -151,8 +151,6 @@ pub fn fmaq(x: f128, y: f128, z: f128) callconv(.c) f128 { pub fn fmal(x: c_longdouble, y: c_longdouble, z: c_longdouble) callconv(.c) c_longdouble { switch (@typeInfo(c_longdouble).float.bits) { - 16 => return __fmah(x, y, z), - 32 => return fmaf(x, y, z), 64 => return fma(x, y, z), 80 => return __fmax(x, y, z), 128 => return fmaq(x, y, z), diff --git a/lib/compiler_rt/fmax.zig b/lib/compiler_rt/fmax.zig index 606888d2d4f63a88a6a7de945239ddaca43f483d..0afdf9ee2be581c9296eac6d308f7f8fd7ecae35 100644 --- a/lib/compiler_rt/fmax.zig +++ b/lib/compiler_rt/fmax.zig @@ -39,8 +39,6 @@ pub fn fmaxq(x: f128, y: f128) callconv(.c) f128 { pub fn fmaxl(x: c_longdouble, y: c_longdouble) callconv(.c) c_longdouble { switch (@typeInfo(c_longdouble).float.bits) { - 16 => return __fmaxh(x, y), - 32 => return fmaxf(x, y), 64 => return fmax(x, y), 80 => return __fmaxx(x, y), 128 => return fmaxq(x, y), diff --git a/lib/compiler_rt/fmin.zig b/lib/compiler_rt/fmin.zig index bea1779476c89f2e4d174f5d5f381f4ac802dde6..60b58cef3a6793efd5a53c24b380ea2178243bc9 100644 --- a/lib/compiler_rt/fmin.zig +++ b/lib/compiler_rt/fmin.zig @@ -39,8 +39,6 @@ pub fn fminq(x: f128, y: f128) callconv(.c) f128 { pub fn fminl(x: c_longdouble, y: c_longdouble) callconv(.c) c_longdouble { switch (@typeInfo(c_longdouble).float.bits) { - 16 => return __fminh(x, y), - 32 => return fminf(x, y), 64 => return fmin(x, y), 80 => return __fminx(x, y), 128 => return fminq(x, y), diff --git a/lib/compiler_rt/fmod.zig b/lib/compiler_rt/fmod.zig index c2108abf3394d67d575ec124e23d61f19c5a5482..0279206f51b7977ff98c7007dfdf524320da3680 100644 --- a/lib/compiler_rt/fmod.zig +++ b/lib/compiler_rt/fmod.zig @@ -251,8 +251,6 @@ pub fn fmodq(a: f128, b: f128) callconv(.c) f128 { pub fn fmodl(a: c_longdouble, b: c_longdouble) callconv(.c) c_longdouble { switch (@typeInfo(c_longdouble).float.bits) { - 16 => return __fmodh(a, b), - 32 => return fmodf(a, b), 64 => return fmod(a, b), 80 => return __fmodx(a, b), 128 => return fmodq(a, b), diff --git a/lib/compiler_rt/log.zig b/lib/compiler_rt/log.zig index 926018f03d71a30ecd88052cbe3d456afb99926d..fb578c75e9244b885999cd8486520a76d7b259e0 100644 --- a/lib/compiler_rt/log.zig +++ b/lib/compiler_rt/log.zig @@ -443,8 +443,6 @@ pub fn logq(a: f128) callconv(.c) f128 { pub fn logl(x: c_longdouble) callconv(.c) c_longdouble { switch (@typeInfo(c_longdouble).float.bits) { - 16 => return __logh(x), - 32 => return logf(x), 64 => return log(x), 80 => return __logx(x), 128 => return logq(x), diff --git a/lib/compiler_rt/log10.zig b/lib/compiler_rt/log10.zig index ec4edac61860c7285879d13f0c1df4685774f370..6a3c46981555bca4b6f59ff431f3b69300a0467e 100644 --- a/lib/compiler_rt/log10.zig +++ b/lib/compiler_rt/log10.zig @@ -177,8 +177,6 @@ pub fn log10q(a: f128) callconv(.c) f128 { pub fn log10l(x: c_longdouble) callconv(.c) c_longdouble { switch (@typeInfo(c_longdouble).float.bits) { - 16 => return __log10h(x), - 32 => return log10f(x), 64 => return log10(x), 80 => return __log10x(x), 128 => return log10q(x), diff --git a/lib/compiler_rt/log2.zig b/lib/compiler_rt/log2.zig index ad17df7f653dbff49570203f79307049926dae74..d675fb172d159f3b5c658cba8696969f7abb48b1 100644 --- a/lib/compiler_rt/log2.zig +++ b/lib/compiler_rt/log2.zig @@ -170,8 +170,6 @@ pub fn log2q(a: f128) callconv(.c) f128 { pub fn log2l(x: c_longdouble) callconv(.c) c_longdouble { switch (@typeInfo(c_longdouble).float.bits) { - 16 => return __log2h(x), - 32 => return log2f(x), 64 => return log2(x), 80 => return __log2x(x), 128 => return log2q(x), diff --git a/lib/compiler_rt/round.zig b/lib/compiler_rt/round.zig index 8087fd6e1529fdc42012074257e12e5017de8dae..590b957922efdbf33ac4fea2728390daad82ee38 100644 --- a/lib/compiler_rt/round.zig +++ b/lib/compiler_rt/round.zig @@ -142,8 +142,6 @@ pub fn roundq(x_: f128) callconv(.c) f128 { pub fn roundl(x: c_longdouble) callconv(.c) c_longdouble { switch (@typeInfo(c_longdouble).float.bits) { - 16 => return __roundh(x), - 32 => return roundf(x), 64 => return round(x), 80 => return __roundx(x), 128 => return roundq(x), diff --git a/lib/compiler_rt/sin.zig b/lib/compiler_rt/sin.zig index 3f1509383bacbef90c8f81debc5a6eaeedbfdf7d..b3e46672eecc6276b5a24cdcec50f6a7f8c97018 100644 --- a/lib/compiler_rt/sin.zig +++ b/lib/compiler_rt/sin.zig @@ -189,8 +189,6 @@ pub fn sinq(x: f128) callconv(.c) f128 { pub fn sinl(x: c_longdouble) callconv(.c) c_longdouble { switch (@typeInfo(c_longdouble).float.bits) { - 16 => return sinh(x), - 32 => return sinf(x), 64 => return sin(x), 80 => return sinx(x), 128 => return sinq(x), diff --git a/lib/compiler_rt/sincos.zig b/lib/compiler_rt/sincos.zig index 7208325c2b86f65dd6736437572eea3c09235ff3..1ec9b81ac0c6b0611afe57c7b4176f257a3e3469 100644 --- a/lib/compiler_rt/sincos.zig +++ b/lib/compiler_rt/sincos.zig @@ -292,8 +292,6 @@ pub fn sincosq(x: f128, r_sin: *f128, r_cos: *f128) callconv(.c) void { pub fn sincosl(x: c_longdouble, r_sin: *c_longdouble, r_cos: *c_longdouble) callconv(.c) void { switch (@typeInfo(c_longdouble).float.bits) { - 16 => return sincosh(x, r_sin, r_cos), - 32 => return sincosf(x, r_sin, r_cos), 64 => return sincos(x, r_sin, r_cos), 80 => return sincosx(x, r_sin, r_cos), 128 => return sincosq(x, r_sin, r_cos), diff --git a/lib/compiler_rt/sqrt.zig b/lib/compiler_rt/sqrt.zig index e765414fb0f418ea9f6d1d71e03c4fa73ff36ca9..be2f58a12fd25213f2a1ebe7f8e150db18f92078 100644 --- a/lib/compiler_rt/sqrt.zig +++ b/lib/compiler_rt/sqrt.zig @@ -481,8 +481,6 @@ fn _Qp_sqrt(c: *f128, a: *f128) callconv(.c) void { pub fn sqrtl(x: c_longdouble) callconv(.c) c_longdouble { switch (@typeInfo(c_longdouble).float.bits) { - 16 => return __sqrth(x), - 32 => return sqrtf(x), 64 => return sqrt(x), 80 => return __sqrtx(x), 128 => return sqrtq(x), diff --git a/lib/compiler_rt/tan.zig b/lib/compiler_rt/tan.zig index 378491aad6d25de04a4cbeb15747eb20e118b25b..b9d996d8b94d2fc05cebdb213038be0c38a0e235 100644 --- a/lib/compiler_rt/tan.zig +++ b/lib/compiler_rt/tan.zig @@ -164,8 +164,6 @@ pub fn tanq(x: f128) callconv(.c) f128 { pub fn tanl(x: c_longdouble) callconv(.c) c_longdouble { switch (@typeInfo(c_longdouble).float.bits) { - 16 => return tanh(x), - 32 => return tanf(x), 64 => return tan(x), 80 => return tanx(x), 128 => return tanq(x), diff --git a/lib/compiler_rt/trunc.zig b/lib/compiler_rt/trunc.zig index b7846307034b667b5ae631d470689da9a3eb9b98..aa2eb560dfd8035f14aa07c8e51c5c117daad042 100644 --- a/lib/compiler_rt/trunc.zig +++ b/lib/compiler_rt/trunc.zig @@ -99,8 +99,6 @@ pub fn truncq(x: f128) callconv(.c) f128 { pub fn truncl(x: c_longdouble) callconv(.c) c_longdouble { switch (@typeInfo(c_longdouble).float.bits) { - 16 => return __trunch(x), - 32 => return truncf(x), 64 => return trunc(x), 80 => return __truncx(x), 128 => return truncq(x), diff --git a/lib/std/Target.zig b/lib/std/Target.zig index 03ca4a772be1f7a2b3bb763e9467c035ecfd8639..57c1779150abfc9a3f9255fe1b26828bc8c37eea 100644 --- a/lib/std/Target.zig +++ b/lib/std/Target.zig @@ -3049,8 +3049,6 @@ pub fn cTypeByteSize(t: *const Target, c_type: CType) u16 { => @divExact(cTypeBitSize(t, c_type), 8), .longdouble => switch (cTypeBitSize(t, c_type)) { - 16 => 2, - 32 => 4, 64 => 8, 80 => @intCast(std.mem.alignForward(usize, 10, cTypeAlignment(t, .longdouble))), 128 => 16, diff --git a/src/codegen/aarch64/Select.zig b/src/codegen/aarch64/Select.zig index 2bfb3c4a552c2d453a7612ea07ada56eae490308..4c45bb966766d02d79f067c005bef3d046b3e8a7 100644 --- a/src/codegen/aarch64/Select.zig +++ b/src/codegen/aarch64/Select.zig @@ -12381,8 +12381,6 @@ pub const CallAbiIterator = struct { .f128 => .quad, .c_longdouble => switch (zcu.getTarget().cTypeBitSize(.longdouble)) { else => unreachable, - 16 => .half, - 32 => .single, 64 => .double, 80 => null, 128 => .quad, diff --git a/test/behavior/cast.zig b/test/behavior/cast.zig index fcc6d7c6b992b7a120cee9104577107571ffb23c..63e6fa1b86cce326cf77dd1e6610d1980dced95b 100644 --- a/test/behavior/cast.zig +++ b/test/behavior/cast.zig @@ -1838,8 +1838,6 @@ test "coerce between pointers of compatible differently-named floats" { } const F = switch (@typeInfo(c_longdouble).float.bits) { - 16 => f16, - 32 => f32, 64 => f64, 80 => f80, 128 => f128, -- 2.54.0