authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2026-07-16 12:48:14-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2026-07-27 14:44:41-04:00
log556e9a455c1372d39bf7e73513d879aa199acc07
tree689fb0884fa48a4c51aa01ac341bad03a07025bf
parente03056d45a864c8176cdd897d771457005ead592

llvm: work around bizarre upstream llvm behavior


1 files changed, 33 insertions(+), 17 deletions(-)

src/codegen/llvm/FuncGen.zig+33-17
......@@ -2040,7 +2040,7 @@ fn airFloatFromInt(fg: *FuncGen, inst: Air.Inst.Index) TodoError!Builder.Value {
20402040 const dest_scalar_ty = dest_ty.scalarType(zcu);
20412041 const target = zcu.getTarget();
20422042
2043 if (intrinsicsAllowed(dest_scalar_ty, target))
2043 if (intrinsicsAllowed(.compiler_rt, dest_scalar_ty, target))
20442044 return fg.wip.conv(.fromStdLang(operand_scalar_info.signedness), operand, try o.lowerType(dest_ty, .as_value), "");
20452045
20462046 const rt_int_ty = compilerRtPromoteInt(operand_scalar_info) orelse {
......@@ -2093,7 +2093,7 @@ fn airIntFromFloat(
20932093 const dest_llvm_ty = try o.lowerType(dest_ty, .as_value);
20942094 const dest_scalar_info = dest_scalar_ty.intInfo(zcu);
20952095
2096 if (intrinsicsAllowed(operand_scalar_ty, target)) {
2096 if (intrinsicsAllowed(.compiler_rt, operand_scalar_ty, target)) {
20972097 // TODO set fast math flag
20982098 return fg.wip.conv(.fromStdLang(dest_scalar_info.signedness), operand, dest_llvm_ty, "");
20992099 }
......@@ -3888,7 +3888,7 @@ fn buildFloatCmp(
38883888 const target = zcu.getTarget();
38893889 const scalar_ty = ty.scalarType(zcu);
38903890
3891 if (intrinsicsAllowed(scalar_ty, target)) {
3891 if (intrinsicsAllowed(.compiler_rt, scalar_ty, target)) {
38923892 const cond: Builder.FloatCondition = switch (pred) {
38933893 .eq => .oeq,
38943894 .neq => .une,
......@@ -3968,10 +3968,14 @@ fn buildFloatOp(
39683968 const target = zcu.getTarget();
39693969 const scalar_ty = ty.scalarType(zcu);
39703970
3971 if (op != .tan and intrinsicsAllowed(scalar_ty, target)) switch (op) {
3971 switch (op) {
39723972 // Some operations are dedicated LLVM instructions, not available as intrinsics
3973 .neg => return fg.wip.un(.fneg, params[0], ""),
3974 .add, .sub, .mul, .div, .fmod => return fg.wip.bin(switch (fast) {
3973 .neg => if (intrinsicsAllowed(.compiler_rt, scalar_ty, target)) return fg.wip.un(.fneg, params[0], ""),
3974 .add, .sub, .mul, .div, .fmod => if (intrinsicsAllowed(switch (op) {
3975 else => unreachable,
3976 .add, .sub, .mul, .div => .compiler_rt,
3977 .fmod => .libc,
3978 }, scalar_ty, target)) return fg.wip.bin(switch (fast) {
39753979 .normal => switch (op) {
39763980 .add => .fadd,
39773981 .sub => .fsub,
......@@ -3989,6 +3993,7 @@ fn buildFloatOp(
39893993 else => unreachable,
39903994 },
39913995 }, params[0], params[1], ""),
3996 .fma,
39923997 .fmax,
39933998 .fmin,
39943999 .ceil,
......@@ -4003,9 +4008,10 @@ fn buildFloatOp(
40034008 .round,
40044009 .sin,
40054010 .sqrt,
4011 .tan,
40064012 .trunc,
4007 .fma,
4008 => return fg.wip.callIntrinsic(fast, .none, switch (op) {
4013 => if (intrinsicsAllowed(.libc, scalar_ty, target)) return fg.wip.callIntrinsic(fast, .none, switch (op) {
4014 .fma => .fma,
40094015 .fmax => .maxnum,
40104016 .fmin => .minnum,
40114017 .ceil => .ceil,
......@@ -4020,12 +4026,11 @@ fn buildFloatOp(
40204026 .round => .round,
40214027 .sin => .sin,
40224028 .sqrt => .sqrt,
4029 .tan => .tan,
40234030 .trunc => .trunc,
4024 .fma => .fma,
40254031 else => unreachable,
40264032 }, &.{try o.lowerType(ty, .as_value)}, &params, ""),
4027 .tan => unreachable,
4028 };
4033 }
40294034
40304035 const float_bits = scalar_ty.floatBits(target);
40314036 const fn_name = switch (op) {
......@@ -4589,7 +4594,8 @@ fn airFptrunc(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Valu
45894594 const dest_scalar_ty = dest_ty.scalarType(zcu);
45904595 const target = zcu.getTarget();
45914596
4592 if (intrinsicsAllowed(dest_scalar_ty, target) and intrinsicsAllowed(operand_scalar_ty, target))
4597 if (intrinsicsAllowed(.compiler_rt, dest_scalar_ty, target) and
4598 intrinsicsAllowed(.compiler_rt, operand_scalar_ty, target))
45934599 return self.wip.cast(.fptrunc, operand, try o.lowerType(dest_ty, .as_value), "");
45944600 const dest_bits = dest_scalar_ty.floatBits(target);
45954601 const src_bits = operand_scalar_ty.floatBits(target);
......@@ -4610,7 +4616,8 @@ fn airFpext(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value
46104616 const dest_scalar_ty = dest_ty.scalarType(zcu);
46114617 const target = zcu.getTarget();
46124618
4613 if (intrinsicsAllowed(dest_scalar_ty, target) and intrinsicsAllowed(operand_scalar_ty, target))
4619 if (intrinsicsAllowed(.compiler_rt, dest_scalar_ty, target) and
4620 intrinsicsAllowed(.compiler_rt, operand_scalar_ty, target))
46144621 return self.wip.cast(.fpext, operand, try o.lowerType(dest_ty, .as_value), "");
46154622 const dest_bits = dest_scalar_ty.floatBits(target);
46164623 const src_bits = operand_scalar_ty.floatBits(target);
......@@ -6161,7 +6168,7 @@ fn airReduce(fg: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) All
61616168 .@"vector.reduce.umax",
61626169 else => unreachable,
61636170 }, &.{try o.lowerType(operand_ty, .as_value)}, &.{operand}, ""),
6164 .float => if (intrinsicsAllowed(scalar_ty, target))
6171 .float => if (intrinsicsAllowed(.libc, scalar_ty, target))
61656172 return fg.wip.callIntrinsic(fast, .none, switch (reduce.operation) {
61666173 .Min => .@"vector.reduce.fmin",
61676174 .Max => .@"vector.reduce.fmax",
......@@ -6175,7 +6182,7 @@ fn airReduce(fg: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) All
61756182 .Mul => .@"vector.reduce.mul",
61766183 else => unreachable,
61776184 }, &.{try o.lowerType(operand_ty, .as_value)}, &.{operand}, ""),
6178 .float => if (intrinsicsAllowed(scalar_ty, target))
6185 .float => if (intrinsicsAllowed(.compiler_rt, scalar_ty, target))
61796186 return fg.wip.callIntrinsic(fast, .none, switch (reduce.operation) {
61806187 .Add => .@"vector.reduce.fadd",
61816188 .Mul => .@"vector.reduce.fmul",
......@@ -7936,9 +7943,18 @@ fn appendConstraints(
79367943
79377944/// LLVM does not support all relevant intrinsics for all targets, so we
79387945/// may need to manually generate a compiler-rt call using a soft type.
7939fn intrinsicsAllowed(scalar_ty: Type, target: *const std.Target) bool {
7946fn intrinsicsAllowed(kind: enum { compiler_rt, libc }, scalar_ty: Type, target: *const std.Target) bool {
79407947 if (!scalar_ty.isRuntimeFloat()) return true;
7941 return switch (std.zig.target.compilerRtFloatAbi(target, scalar_ty.floatBits(target))) {
7948 const bits = scalar_ty.floatBits(target);
7949 // Since upstream musl/msvc do not actually define the *f128 functions, llvm decides
7950 // that it is a much better idea to just emit a call to the entirely wrong function as
7951 // a fallback. We wouldn't want any linker errors when trying to perform an operation
7952 // that isn't actually implemented anywhere, now would we!
7953 if (bits == 128 and target.cpu.arch.isX86() and !target.abi.isGnu()) return switch (kind) {
7954 .compiler_rt => true,
7955 .libc => false,
7956 };
7957 return switch (std.zig.target.compilerRtFloatAbi(target, bits)) {
79427958 .hard => true,
79437959 .soft => false,
79447960 };