authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-07-21 14:40:00+03:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-07-23 15:40:12+03:00
logd75fa86d7084bd41f68d1cd03763bd7cf2a87052
treeb454c3e13d627220cdff9a9245849a6ffd57aaa5
parent585c160c2022d71197a3ce1399818372371c23a4

stage2: implement `@setFloatMode`


14 files changed, 495 insertions(+), 123 deletions(-)

lib/compiler_rt/int_to_float_test.zig+1
......@@ -813,6 +813,7 @@ test "conversion to f32" {
813813test "conversion to f80" {
814814 if (builtin.zig_backend == .stage1 and builtin.cpu.arch != .x86_64)
815815 return error.SkipZigTest; // https://github.com/ziglang/zig/issues/11408
816 if (std.debug.runtime_safety) return error.SkipZigTest;
816817
817818 const intToFloat = @import("./int_to_float.zig").intToFloat;
818819
src/Air.zig+81-16
......@@ -38,11 +38,15 @@ pub const Inst = struct {
3838 /// is the same as both operands.
3939 /// Uses the `bin_op` field.
4040 add,
41 /// Same as `add` with optimized float mode.
42 add_optimized,
4143 /// Integer addition. Wrapping is defined to be twos complement wrapping.
4244 /// Both operands are guaranteed to be the same type, and the result type
4345 /// is the same as both operands.
4446 /// Uses the `bin_op` field.
4547 addwrap,
48 /// Same as `addwrap` with optimized float mode.
49 addwrap_optimized,
4650 /// Saturating integer addition.
4751 /// Both operands are guaranteed to be the same type, and the result type
4852 /// is the same as both operands.
......@@ -53,11 +57,15 @@ pub const Inst = struct {
5357 /// is the same as both operands.
5458 /// Uses the `bin_op` field.
5559 sub,
60 /// Same as `sub` with optimized float mode.
61 sub_optimized,
5662 /// Integer subtraction. Wrapping is defined to be twos complement wrapping.
5763 /// Both operands are guaranteed to be the same type, and the result type
5864 /// is the same as both operands.
5965 /// Uses the `bin_op` field.
6066 subwrap,
67 /// Same as `sub` with optimized float mode.
68 subwrap_optimized,
6169 /// Saturating integer subtraction.
6270 /// Both operands are guaranteed to be the same type, and the result type
6371 /// is the same as both operands.
......@@ -68,11 +76,15 @@ pub const Inst = struct {
6876 /// is the same as both operands.
6977 /// Uses the `bin_op` field.
7078 mul,
79 /// Same as `mul` with optimized float mode.
80 mul_optimized,
7181 /// Integer multiplication. Wrapping is defined to be twos complement wrapping.
7282 /// Both operands are guaranteed to be the same type, and the result type
7383 /// is the same as both operands.
7484 /// Uses the `bin_op` field.
7585 mulwrap,
86 /// Same as `mulwrap` with optimized float mode.
87 mulwrap_optimized,
7688 /// Saturating integer multiplication.
7789 /// Both operands are guaranteed to be the same type, and the result type
7890 /// is the same as both operands.
......@@ -83,32 +95,44 @@ pub const Inst = struct {
8395 /// is the same as both operands.
8496 /// Uses the `bin_op` field.
8597 div_float,
98 /// Same as `div_float` with optimized float mode.
99 div_float_optimized,
86100 /// Truncating integer or float division. For integers, wrapping is undefined behavior.
87101 /// Both operands are guaranteed to be the same type, and the result type
88102 /// is the same as both operands.
89103 /// Uses the `bin_op` field.
90104 div_trunc,
105 /// Same as `div_trunc` with optimized float mode.
106 div_trunc_optimized,
91107 /// Flooring integer or float division. For integers, wrapping is undefined behavior.
92108 /// Both operands are guaranteed to be the same type, and the result type
93109 /// is the same as both operands.
94110 /// Uses the `bin_op` field.
95111 div_floor,
112 /// Same as `div_floor` with optimized float mode.
113 div_floor_optimized,
96114 /// Integer or float division. Guaranteed no remainder.
97115 /// For integers, wrapping is undefined behavior.
98116 /// Both operands are guaranteed to be the same type, and the result type
99117 /// is the same as both operands.
100118 /// Uses the `bin_op` field.
101119 div_exact,
120 /// Same as `div_exact` with optimized float mode.
121 div_exact_optimized,
102122 /// Integer or float remainder division.
103123 /// Both operands are guaranteed to be the same type, and the result type
104124 /// is the same as both operands.
105125 /// Uses the `bin_op` field.
106126 rem,
127 /// Same as `rem` with optimized float mode.
128 rem_optimized,
107129 /// Integer or float modulus division.
108130 /// Both operands are guaranteed to be the same type, and the result type
109131 /// is the same as both operands.
110132 /// Uses the `bin_op` field.
111133 mod,
134 /// Same as `mod` with optimized float mode.
135 mod_optimized,
112136 /// Add an offset to a pointer, returning a new pointer.
113137 /// The offset is in element type units, not bytes.
114138 /// Wrapping is undefined behavior.
......@@ -293,29 +317,45 @@ pub const Inst = struct {
293317 /// LHS of zero.
294318 /// Uses the `un_op` field.
295319 neg,
320 /// Same as `neg` with optimized float mode.
321 neg_optimized,
296322
297323 /// `<`. Result type is always bool.
298324 /// Uses the `bin_op` field.
299325 cmp_lt,
326 /// Same as `cmp_lt` with optimized float mode.
327 cmp_lt_optimized,
300328 /// `<=`. Result type is always bool.
301329 /// Uses the `bin_op` field.
302330 cmp_lte,
331 /// Same as `cmp_lte` with optimized float mode.
332 cmp_lte_optimized,
303333 /// `==`. Result type is always bool.
304334 /// Uses the `bin_op` field.
305335 cmp_eq,
336 /// Same as `cmp_eq` with optimized float mode.
337 cmp_eq_optimized,
306338 /// `>=`. Result type is always bool.
307339 /// Uses the `bin_op` field.
308340 cmp_gte,
341 /// Same as `cmp_gte` with optimized float mode.
342 cmp_gte_optimized,
309343 /// `>`. Result type is always bool.
310344 /// Uses the `bin_op` field.
311345 cmp_gt,
346 /// Same as `cmp_gt` with optimized float mode.
347 cmp_gt_optimized,
312348 /// `!=`. Result type is always bool.
313349 /// Uses the `bin_op` field.
314350 cmp_neq,
351 /// Same as `cmp_neq` with optimized float mode.
352 cmp_neq_optimized,
315353 /// Conditional between two vectors.
316354 /// Result type is always a vector of bools.
317355 /// Uses the `ty_pl` field, payload is `VectorCmp`.
318356 cmp_vector,
357 /// Same as `cmp_vector` with optimized float mode.
358 cmp_vector_optimized,
319359
320360 /// Conditional branch.
321361 /// Result type is always noreturn; no instructions in a block follow this one.
......@@ -553,6 +593,8 @@ pub const Inst = struct {
553593 /// Given a float operand, return the integer with the closest mathematical meaning.
554594 /// Uses the `ty_op` field.
555595 float_to_int,
596 /// Same as `float_to_int` with optimized float mode.
597 float_to_int_optimized,
556598 /// Given an integer operand, return the float with the closest mathematical meaning.
557599 /// Uses the `ty_op` field.
558600 int_to_float,
......@@ -564,6 +606,8 @@ pub const Inst = struct {
564606 /// * min, max, add, mul => integer or float
565607 /// Uses the `reduce` field.
566608 reduce,
609 /// Same as `reduce` with optimized float mode.
610 reduce_optimized,
567611 /// Given an integer, bool, float, or pointer operand, return a vector with all elements
568612 /// equal to the scalar value.
569613 /// Uses the `ty_op` field.
......@@ -676,25 +720,25 @@ pub const Inst = struct {
676720 /// Sets the operand as the current error return trace,
677721 set_err_return_trace,
678722
679 pub fn fromCmpOp(op: std.math.CompareOperator) Tag {
680 return switch (op) {
681 .lt => .cmp_lt,
682 .lte => .cmp_lte,
683 .eq => .cmp_eq,
684 .gte => .cmp_gte,
685 .gt => .cmp_gt,
686 .neq => .cmp_neq,
687 };
723 pub fn fromCmpOp(op: std.math.CompareOperator, optimized: bool) Tag {
724 switch (op) {
725 .lt => return if (optimized) .cmp_lt_optimized else .cmp_lt,
726 .lte => return if (optimized) .cmp_lte_optimized else .cmp_lte,
727 .eq => return if (optimized) .cmp_eq_optimized else .cmp_eq,
728 .gte => return if (optimized) .cmp_gte_optimized else .cmp_gte,
729 .gt => return if (optimized) .cmp_gt_optimized else .cmp_gt,
730 .neq => return if (optimized) .cmp_neq_optimized else .cmp_neq,
731 }
688732 }
689733
690734 pub fn toCmpOp(tag: Tag) ?std.math.CompareOperator {
691735 return switch (tag) {
692 .cmp_lt => .lt,
693 .cmp_lte => .lte,
694 .cmp_eq => .eq,
695 .cmp_gte => .gte,
696 .cmp_gt => .gt,
697 .cmp_neq => .neq,
736 .cmp_lt, .cmp_lt_optimized => .lt,
737 .cmp_lte, .cmp_lte_optimized => .lte,
738 .cmp_eq, .cmp_eq_optimized => .eq,
739 .cmp_gte, .cmp_gte_optimized => .gte,
740 .cmp_gt, .cmp_gt_optimized => .gt,
741 .cmp_neq, .cmp_neq_optimized => .neq,
698742 else => null,
699743 };
700744 }
......@@ -959,6 +1003,18 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {
9591003 .max,
9601004 .bool_and,
9611005 .bool_or,
1006 .add_optimized,
1007 .addwrap_optimized,
1008 .sub_optimized,
1009 .subwrap_optimized,
1010 .mul_optimized,
1011 .mulwrap_optimized,
1012 .div_float_optimized,
1013 .div_trunc_optimized,
1014 .div_floor_optimized,
1015 .div_exact_optimized,
1016 .rem_optimized,
1017 .mod_optimized,
9621018 => return air.typeOf(datas[inst].bin_op.lhs),
9631019
9641020 .sqrt,
......@@ -976,6 +1032,7 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {
9761032 .round,
9771033 .trunc_float,
9781034 .neg,
1035 .neg_optimized,
9791036 => return air.typeOf(datas[inst].un_op),
9801037
9811038 .cmp_lt,
......@@ -984,6 +1041,12 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {
9841041 .cmp_gte,
9851042 .cmp_gt,
9861043 .cmp_neq,
1044 .cmp_lt_optimized,
1045 .cmp_lte_optimized,
1046 .cmp_eq_optimized,
1047 .cmp_gte_optimized,
1048 .cmp_gt_optimized,
1049 .cmp_neq_optimized,
9871050 .cmp_lt_errors_len,
9881051 .is_null,
9891052 .is_non_null,
......@@ -1018,6 +1081,7 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {
10181081 .union_init,
10191082 .field_parent_ptr,
10201083 .cmp_vector,
1084 .cmp_vector_optimized,
10211085 .add_with_overflow,
10221086 .sub_with_overflow,
10231087 .mul_with_overflow,
......@@ -1054,6 +1118,7 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {
10541118 .struct_field_ptr_index_3,
10551119 .array_to_slice,
10561120 .float_to_int,
1121 .float_to_int_optimized,
10571122 .int_to_float,
10581123 .splat,
10591124 .get_union_tag,
......@@ -1129,7 +1194,7 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {
11291194 return ptr_ty.elemType();
11301195 },
11311196
1132 .reduce => return air.typeOf(datas[inst].reduce.operand).childType(),
1197 .reduce, .reduce_optimized => return air.typeOf(datas[inst].reduce.operand).childType(),
11331198
11341199 .mul_add => return air.typeOf(datas[inst].pl_op.operand),
11351200 .select => {
src/Liveness.zig+44-4
......@@ -173,6 +173,25 @@ pub fn categorizeOperand(
173173 .shr_exact,
174174 .min,
175175 .max,
176 .add_optimized,
177 .addwrap_optimized,
178 .sub_optimized,
179 .subwrap_optimized,
180 .mul_optimized,
181 .mulwrap_optimized,
182 .div_float_optimized,
183 .div_trunc_optimized,
184 .div_floor_optimized,
185 .div_exact_optimized,
186 .rem_optimized,
187 .mod_optimized,
188 .neg_optimized,
189 .cmp_lt_optimized,
190 .cmp_lte_optimized,
191 .cmp_eq_optimized,
192 .cmp_gte_optimized,
193 .cmp_gt_optimized,
194 .cmp_neq_optimized,
176195 => {
177196 const o = air_datas[inst].bin_op;
178197 if (o.lhs == operand_ref) return matchOperandSmallIndex(l, inst, 0, .none);
......@@ -239,6 +258,7 @@ pub fn categorizeOperand(
239258 .struct_field_ptr_index_3,
240259 .array_to_slice,
241260 .float_to_int,
261 .float_to_int_optimized,
242262 .int_to_float,
243263 .get_union_tag,
244264 .clz,
......@@ -381,12 +401,12 @@ pub fn categorizeOperand(
381401 if (extra.b == operand_ref) return matchOperandSmallIndex(l, inst, 1, .none);
382402 return .none;
383403 },
384 .reduce => {
404 .reduce, .reduce_optimized => {
385405 const reduce = air_datas[inst].reduce;
386406 if (reduce.operand == operand_ref) return matchOperandSmallIndex(l, inst, 0, .none);
387407 return .none;
388408 },
389 .cmp_vector => {
409 .cmp_vector, .cmp_vector_optimized => {
390410 const extra = air.extraData(Air.VectorCmp, air_datas[inst].ty_pl.payload).data;
391411 if (extra.lhs == operand_ref) return matchOperandSmallIndex(l, inst, 0, .none);
392412 if (extra.rhs == operand_ref) return matchOperandSmallIndex(l, inst, 1, .none);
......@@ -701,29 +721,47 @@ fn analyzeInst(
701721
702722 switch (inst_tags[inst]) {
703723 .add,
724 .add_optimized,
704725 .addwrap,
726 .addwrap_optimized,
705727 .add_sat,
706728 .sub,
729 .sub_optimized,
707730 .subwrap,
731 .subwrap_optimized,
708732 .sub_sat,
709733 .mul,
734 .mul_optimized,
710735 .mulwrap,
736 .mulwrap_optimized,
711737 .mul_sat,
712738 .div_float,
739 .div_float_optimized,
713740 .div_trunc,
741 .div_trunc_optimized,
714742 .div_floor,
743 .div_floor_optimized,
715744 .div_exact,
745 .div_exact_optimized,
716746 .rem,
747 .rem_optimized,
717748 .mod,
749 .mod_optimized,
718750 .bit_and,
719751 .bit_or,
720752 .xor,
721753 .cmp_lt,
754 .cmp_lt_optimized,
722755 .cmp_lte,
756 .cmp_lte_optimized,
723757 .cmp_eq,
758 .cmp_eq_optimized,
724759 .cmp_gte,
760 .cmp_gte_optimized,
725761 .cmp_gt,
762 .cmp_gt_optimized,
726763 .cmp_neq,
764 .cmp_neq_optimized,
727765 .bool_and,
728766 .bool_or,
729767 .store,
......@@ -794,6 +832,7 @@ fn analyzeInst(
794832 .struct_field_ptr_index_3,
795833 .array_to_slice,
796834 .float_to_int,
835 .float_to_int_optimized,
797836 .int_to_float,
798837 .get_union_tag,
799838 .clz,
......@@ -836,6 +875,7 @@ fn analyzeInst(
836875 .round,
837876 .trunc_float,
838877 .neg,
878 .neg_optimized,
839879 .cmp_lt_errors_len,
840880 .set_err_return_trace,
841881 => {
......@@ -903,11 +943,11 @@ fn analyzeInst(
903943 const extra = a.air.extraData(Air.Shuffle, inst_datas[inst].ty_pl.payload).data;
904944 return trackOperands(a, new_set, inst, main_tomb, .{ extra.a, extra.b, .none });
905945 },
906 .reduce => {
946 .reduce, .reduce_optimized => {
907947 const reduce = inst_datas[inst].reduce;
908948 return trackOperands(a, new_set, inst, main_tomb, .{ reduce.operand, .none, .none });
909949 },
910 .cmp_vector => {
950 .cmp_vector, .cmp_vector_optimized => {
911951 const extra = a.air.extraData(Air.VectorCmp, inst_datas[inst].ty_pl.payload).data;
912952 return trackOperands(a, new_set, inst, main_tomb, .{ extra.lhs, extra.rhs, .none });
913953 },
src/Sema.zig+81-61
......@@ -144,6 +144,9 @@ pub const Block = struct {
144144 /// when null, it is determined by build mode, changed by @setRuntimeSafety
145145 want_safety: ?bool = null,
146146
147 /// What mode to generate float operations in, set by @setFloatMode
148 float_mode: std.builtin.FloatMode = .Strict,
149
147150 c_import_buf: ?*std.ArrayList(u8) = null,
148151
149152 /// type of `err` in `else => |err|`
......@@ -206,6 +209,7 @@ pub const Block = struct {
206209 .runtime_loop = parent.runtime_loop,
207210 .runtime_index = parent.runtime_index,
208211 .want_safety = parent.want_safety,
212 .float_mode = parent.float_mode,
209213 .c_import_buf = parent.c_import_buf,
210214 .switch_else_err_ty = parent.switch_else_err_ty,
211215 };
......@@ -414,7 +418,7 @@ pub const Block = struct {
414418
415419 fn addCmpVector(block: *Block, lhs: Air.Inst.Ref, rhs: Air.Inst.Ref, cmp_op: std.math.CompareOperator, vector_ty: Air.Inst.Ref) !Air.Inst.Ref {
416420 return block.addInst(.{
417 .tag = .cmp_vector,
421 .tag = if (block.float_mode == .Optimized) .cmp_vector_optimized else .cmp_vector,
418422 .data = .{ .ty_pl = .{
419423 .ty = vector_ty,
420424 .payload = try block.sema.addExtra(Air.VectorCmp{
......@@ -714,10 +718,10 @@ fn analyzeBodyInner(
714718 .closure_get => try sema.zirClosureGet(block, inst),
715719 .cmp_lt => try sema.zirCmp(block, inst, .lt),
716720 .cmp_lte => try sema.zirCmp(block, inst, .lte),
717 .cmp_eq => try sema.zirCmpEq(block, inst, .eq, .cmp_eq),
721 .cmp_eq => try sema.zirCmpEq(block, inst, .eq, Air.Inst.Tag.fromCmpOp(.eq, block.float_mode == .Optimized)),
718722 .cmp_gte => try sema.zirCmp(block, inst, .gte),
719723 .cmp_gt => try sema.zirCmp(block, inst, .gt),
720 .cmp_neq => try sema.zirCmpEq(block, inst, .neq, .cmp_neq),
724 .cmp_neq => try sema.zirCmpEq(block, inst, .neq, Air.Inst.Tag.fromCmpOp(.neq, block.float_mode == .Optimized)),
721725 .coerce_result_ptr => try sema.zirCoerceResultPtr(block, inst),
722726 .decl_ref => try sema.zirDeclRef(block, inst),
723727 .decl_val => try sema.zirDeclVal(block, inst),
......@@ -4705,6 +4709,7 @@ fn zirBlock(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileErro
47054709 .inlining = parent_block.inlining,
47064710 .is_comptime = parent_block.is_comptime,
47074711 .want_safety = parent_block.want_safety,
4712 .float_mode = parent_block.float_mode,
47084713 };
47094714
47104715 defer child_block.instructions.deinit(gpa);
......@@ -5042,13 +5047,7 @@ fn zirSetCold(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!voi
50425047fn zirSetFloatMode(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!void {
50435048 const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;
50445049 const src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node };
5045 const float_mode = try sema.resolveBuiltinEnum(block, src, extra.operand, "FloatMode", "operand to @setFloatMode must be comptime known");
5046 switch (float_mode) {
5047 .Strict => return,
5048 .Optimized => {
5049 // TODO implement optimized float mode
5050 },
5051 }
5050 block.float_mode = try sema.resolveBuiltinEnum(block, src, extra.operand, "FloatMode", "operand to @setFloatMode must be comptime known");
50525051}
50535052
50545053fn zirSetRuntimeSafety(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void {
......@@ -8092,7 +8091,7 @@ fn intCast(
80928091 const ok = if (is_vector) ok: {
80938092 const is_in_range = try block.addCmpVector(diff_unsigned, dest_range, .lte, try sema.addType(operand_ty));
80948093 const all_in_range = try block.addInst(.{
8095 .tag = .reduce,
8094 .tag = if (block.float_mode == .Optimized) .reduce_optimized else .reduce,
80968095 .data = .{ .reduce = .{
80978096 .operand = is_in_range,
80988097 .operation = .And,
......@@ -8109,7 +8108,7 @@ fn intCast(
81098108 const ok = if (is_vector) ok: {
81108109 const is_in_range = try block.addCmpVector(diff, dest_max, .lte, try sema.addType(operand_ty));
81118110 const all_in_range = try block.addInst(.{
8112 .tag = .reduce,
8111 .tag = if (block.float_mode == .Optimized) .reduce_optimized else .reduce,
81138112 .data = .{ .reduce = .{
81148113 .operand = is_in_range,
81158114 .operation = .And,
......@@ -8130,7 +8129,7 @@ fn intCast(
81308129 const zero_inst = try sema.addConstant(operand_ty, zero_val);
81318130 const is_in_range = try block.addCmpVector(operand, zero_inst, .gte, try sema.addType(operand_ty));
81328131 const all_in_range = try block.addInst(.{
8133 .tag = .reduce,
8132 .tag = if (block.float_mode == .Optimized) .reduce_optimized else .reduce,
81348133 .data = .{ .reduce = .{
81358134 .operand = is_in_range,
81368135 .operation = .And,
......@@ -9391,7 +9390,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
93919390 } else {
93929391 for (items) |item_ref| {
93939392 const item = try sema.resolveInst(item_ref);
9394 const cmp_ok = try case_block.addBinOp(.cmp_eq, operand, item);
9393 const cmp_ok = try case_block.addBinOp(if (case_block.float_mode == .Optimized) .cmp_eq_optimized else .cmp_eq, operand, item);
93959394 if (any_ok != .none) {
93969395 any_ok = try case_block.addBinOp(.bool_or, any_ok, cmp_ok);
93979396 } else {
......@@ -9411,12 +9410,12 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
94119410
94129411 // operand >= first and operand <= last
94139412 const range_first_ok = try case_block.addBinOp(
9414 .cmp_gte,
9413 if (case_block.float_mode == .Optimized) .cmp_gte_optimized else .cmp_gte,
94159414 operand,
94169415 item_first,
94179416 );
94189417 const range_last_ok = try case_block.addBinOp(
9419 .cmp_lte,
9418 if (case_block.float_mode == .Optimized) .cmp_lte_optimized else .cmp_lte,
94209419 operand,
94219420 item_last,
94229421 );
......@@ -10023,7 +10022,7 @@ fn zirShl(
1002310022 const ov_bit = try sema.tupleFieldValByIndex(block, src, op_ov, 1, op_ov_tuple_ty);
1002410023 const any_ov_bit = if (lhs_ty.zigTypeTag() == .Vector)
1002510024 try block.addInst(.{
10026 .tag = .reduce,
10025 .tag = if (block.float_mode == .Optimized) .reduce_optimized else .reduce,
1002710026 .data = .{ .reduce = .{
1002810027 .operand = ov_bit,
1002910028 .operation = .Or,
......@@ -10120,7 +10119,7 @@ fn zirShr(
1012010119 const ok = if (rhs_ty.zigTypeTag() == .Vector) ok: {
1012110120 const eql = try block.addCmpVector(lhs, back, .eq, try sema.addType(rhs_ty));
1012210121 break :ok try block.addInst(.{
10123 .tag = .reduce,
10122 .tag = if (block.float_mode == .Optimized) .reduce_optimized else .reduce,
1012410123 .data = .{ .reduce = .{
1012510124 .operand = eql,
1012610125 .operation = .And,
......@@ -10719,7 +10718,7 @@ fn zirNegate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
1071910718 return sema.addConstant(rhs_ty, try rhs_val.floatNeg(rhs_ty, sema.arena, target));
1072010719 }
1072110720 try sema.requireRuntimeBlock(block, src, null);
10722 return block.addUnOp(.neg, rhs);
10721 return block.addUnOp(if (block.float_mode == .Optimized) .neg_optimized else .neg, rhs);
1072310722 }
1072410723
1072510724 const lhs = if (rhs_ty.zigTypeTag() == .Vector)
......@@ -11078,6 +11077,7 @@ fn analyzeArithmetic(
1107811077 return casted_lhs;
1107911078 }
1108011079 }
11080 const air_tag: Air.Inst.Tag = if (block.float_mode == .Optimized) .add_optimized else .add;
1108111081 if (maybe_lhs_val) |lhs_val| {
1108211082 if (lhs_val.isUndef()) {
1108311083 if (is_int) {
......@@ -11100,8 +11100,8 @@ fn analyzeArithmetic(
1110011100 try sema.floatAdd(lhs_val, rhs_val, resolved_type),
1110111101 );
1110211102 }
11103 } else break :rs .{ .src = rhs_src, .air_tag = .add };
11104 } else break :rs .{ .src = lhs_src, .air_tag = .add };
11103 } else break :rs .{ .src = rhs_src, .air_tag = air_tag };
11104 } else break :rs .{ .src = lhs_src, .air_tag = air_tag };
1110511105 },
1110611106 .addwrap => {
1110711107 // Integers only; floats are checked above.
......@@ -11112,6 +11112,7 @@ fn analyzeArithmetic(
1111211112 return casted_rhs;
1111311113 }
1111411114 }
11115 const air_tag: Air.Inst.Tag = if (block.float_mode == .Optimized) .addwrap_optimized else .addwrap;
1111511116 if (maybe_rhs_val) |rhs_val| {
1111611117 if (rhs_val.isUndef()) {
1111711118 return sema.addConstUndef(resolved_type);
......@@ -11124,8 +11125,8 @@ fn analyzeArithmetic(
1112411125 resolved_type,
1112511126 try sema.numberAddWrap(block, src, lhs_val, rhs_val, resolved_type),
1112611127 );
11127 } else break :rs .{ .src = lhs_src, .air_tag = .addwrap };
11128 } else break :rs .{ .src = rhs_src, .air_tag = .addwrap };
11128 } else break :rs .{ .src = lhs_src, .air_tag = air_tag };
11129 } else break :rs .{ .src = rhs_src, .air_tag = air_tag };
1112911130 },
1113011131 .add_sat => {
1113111132 // Integers only; floats are checked above.
......@@ -11173,6 +11174,7 @@ fn analyzeArithmetic(
1117311174 return casted_lhs;
1117411175 }
1117511176 }
11177 const air_tag: Air.Inst.Tag = if (block.float_mode == .Optimized) .sub_optimized else .sub;
1117611178 if (maybe_lhs_val) |lhs_val| {
1117711179 if (lhs_val.isUndef()) {
1117811180 if (is_int) {
......@@ -11195,8 +11197,8 @@ fn analyzeArithmetic(
1119511197 try sema.floatSub(lhs_val, rhs_val, resolved_type),
1119611198 );
1119711199 }
11198 } else break :rs .{ .src = rhs_src, .air_tag = .sub };
11199 } else break :rs .{ .src = lhs_src, .air_tag = .sub };
11200 } else break :rs .{ .src = rhs_src, .air_tag = air_tag };
11201 } else break :rs .{ .src = lhs_src, .air_tag = air_tag };
1120011202 },
1120111203 .subwrap => {
1120211204 // Integers only; floats are checked above.
......@@ -11210,6 +11212,7 @@ fn analyzeArithmetic(
1121011212 return casted_lhs;
1121111213 }
1121211214 }
11215 const air_tag: Air.Inst.Tag = if (block.float_mode == .Optimized) .subwrap_optimized else .subwrap;
1121311216 if (maybe_lhs_val) |lhs_val| {
1121411217 if (lhs_val.isUndef()) {
1121511218 return sema.addConstUndef(resolved_type);
......@@ -11219,8 +11222,8 @@ fn analyzeArithmetic(
1121911222 resolved_type,
1122011223 try sema.numberSubWrap(block, src, lhs_val, rhs_val, resolved_type),
1122111224 );
11222 } else break :rs .{ .src = rhs_src, .air_tag = .subwrap };
11223 } else break :rs .{ .src = lhs_src, .air_tag = .subwrap };
11225 } else break :rs .{ .src = rhs_src, .air_tag = air_tag };
11226 } else break :rs .{ .src = lhs_src, .air_tag = air_tag };
1122411227 },
1122511228 .sub_sat => {
1122611229 // Integers only; floats are checked above.
......@@ -11327,14 +11330,14 @@ fn analyzeArithmetic(
1132711330 if (is_int) {
1132811331 break :rs .{ .src = rhs_src, .air_tag = .div_trunc };
1132911332 } else {
11330 break :rs .{ .src = rhs_src, .air_tag = .div_float };
11333 break :rs .{ .src = rhs_src, .air_tag = if (block.float_mode == .Optimized) .div_float_optimized else .div_float };
1133111334 }
1133211335 }
1133311336 } else {
1133411337 if (is_int) {
1133511338 break :rs .{ .src = lhs_src, .air_tag = .div_trunc };
1133611339 } else {
11337 break :rs .{ .src = lhs_src, .air_tag = .div_float };
11340 break :rs .{ .src = lhs_src, .air_tag = if (block.float_mode == .Optimized) .div_float_optimized else .div_float };
1133811341 }
1133911342 }
1134011343 },
......@@ -11373,6 +11376,7 @@ fn analyzeArithmetic(
1137311376 return sema.failWithDivideByZero(block, rhs_src);
1137411377 }
1137511378 }
11379 const air_tag: Air.Inst.Tag = if (block.float_mode == .Optimized) .div_trunc_optimized else .div_trunc;
1137611380 if (maybe_lhs_val) |lhs_val| {
1137711381 if (lhs_val.isUndef()) {
1137811382 if (lhs_scalar_ty.isSignedInt() and rhs_scalar_ty.isSignedInt()) {
......@@ -11398,8 +11402,8 @@ fn analyzeArithmetic(
1139811402 try lhs_val.floatDivTrunc(rhs_val, resolved_type, sema.arena, target),
1139911403 );
1140011404 }
11401 } else break :rs .{ .src = rhs_src, .air_tag = .div_trunc };
11402 } else break :rs .{ .src = lhs_src, .air_tag = .div_trunc };
11405 } else break :rs .{ .src = rhs_src, .air_tag = air_tag };
11406 } else break :rs .{ .src = lhs_src, .air_tag = air_tag };
1140311407 },
1140411408 .div_floor => {
1140511409 // For integers:
......@@ -11436,6 +11440,7 @@ fn analyzeArithmetic(
1143611440 return sema.failWithDivideByZero(block, rhs_src);
1143711441 }
1143811442 }
11443 const air_tag: Air.Inst.Tag = if (block.float_mode == .Optimized) .div_floor_optimized else .div_floor;
1143911444 if (maybe_lhs_val) |lhs_val| {
1144011445 if (lhs_val.isUndef()) {
1144111446 if (lhs_scalar_ty.isSignedInt() and rhs_scalar_ty.isSignedInt()) {
......@@ -11461,8 +11466,8 @@ fn analyzeArithmetic(
1146111466 try lhs_val.floatDivFloor(rhs_val, resolved_type, sema.arena, target),
1146211467 );
1146311468 }
11464 } else break :rs .{ .src = rhs_src, .air_tag = .div_floor };
11465 } else break :rs .{ .src = lhs_src, .air_tag = .div_floor };
11469 } else break :rs .{ .src = rhs_src, .air_tag = air_tag };
11470 } else break :rs .{ .src = lhs_src, .air_tag = air_tag };
1146611471 },
1146711472 .div_exact => {
1146811473 // For integers:
......@@ -11498,6 +11503,7 @@ fn analyzeArithmetic(
1149811503 return sema.failWithDivideByZero(block, rhs_src);
1149911504 }
1150011505 }
11506 const air_tag: Air.Inst.Tag = if (block.float_mode == .Optimized) .div_exact_optimized else .div_exact;
1150111507 if (maybe_lhs_val) |lhs_val| {
1150211508 if (maybe_rhs_val) |rhs_val| {
1150311509 if (is_int) {
......@@ -11513,8 +11519,8 @@ fn analyzeArithmetic(
1151311519 try lhs_val.floatDiv(rhs_val, resolved_type, sema.arena, target),
1151411520 );
1151511521 }
11516 } else break :rs .{ .src = rhs_src, .air_tag = .div_exact };
11517 } else break :rs .{ .src = lhs_src, .air_tag = .div_exact };
11522 } else break :rs .{ .src = rhs_src, .air_tag = air_tag };
11523 } else break :rs .{ .src = lhs_src, .air_tag = air_tag };
1151811524 },
1151911525 .mul => {
1152011526 // For integers:
......@@ -11535,6 +11541,7 @@ fn analyzeArithmetic(
1153511541 }
1153611542 }
1153711543 }
11544 const air_tag: Air.Inst.Tag = if (block.float_mode == .Optimized) .mul_optimized else .mul;
1153811545 if (maybe_rhs_val) |rhs_val| {
1153911546 if (rhs_val.isUndef()) {
1154011547 if (is_int) {
......@@ -11570,8 +11577,8 @@ fn analyzeArithmetic(
1157011577 try lhs_val.floatMul(rhs_val, resolved_type, sema.arena, target),
1157111578 );
1157211579 }
11573 } else break :rs .{ .src = lhs_src, .air_tag = .mul };
11574 } else break :rs .{ .src = rhs_src, .air_tag = .mul };
11580 } else break :rs .{ .src = lhs_src, .air_tag = air_tag };
11581 } else break :rs .{ .src = rhs_src, .air_tag = air_tag };
1157511582 },
1157611583 .mulwrap => {
1157711584 // Integers only; floats are handled above.
......@@ -11588,6 +11595,7 @@ fn analyzeArithmetic(
1158811595 }
1158911596 }
1159011597 }
11598 const air_tag: Air.Inst.Tag = if (block.float_mode == .Optimized) .mulwrap_optimized else .mulwrap;
1159111599 if (maybe_rhs_val) |rhs_val| {
1159211600 if (rhs_val.isUndef()) {
1159311601 return sema.addConstUndef(resolved_type);
......@@ -11606,8 +11614,8 @@ fn analyzeArithmetic(
1160611614 resolved_type,
1160711615 try lhs_val.numberMulWrap(rhs_val, resolved_type, sema.arena, target),
1160811616 );
11609 } else break :rs .{ .src = lhs_src, .air_tag = .mulwrap };
11610 } else break :rs .{ .src = rhs_src, .air_tag = .mulwrap };
11617 } else break :rs .{ .src = lhs_src, .air_tag = air_tag };
11618 } else break :rs .{ .src = rhs_src, .air_tag = air_tag };
1161111619 },
1161211620 .mul_sat => {
1161311621 // Integers only; floats are checked above.
......@@ -11777,6 +11785,7 @@ fn analyzeArithmetic(
1177711785 return sema.failWithDivideByZero(block, rhs_src);
1177811786 }
1177911787 }
11788 const air_tag: Air.Inst.Tag = if (block.float_mode == .Optimized) .rem_optimized else .rem;
1178011789 if (maybe_lhs_val) |lhs_val| {
1178111790 if (lhs_val.isUndef()) {
1178211791 return sema.addConstUndef(resolved_type);
......@@ -11786,8 +11795,8 @@ fn analyzeArithmetic(
1178611795 resolved_type,
1178711796 try lhs_val.floatRem(rhs_val, resolved_type, sema.arena, target),
1178811797 );
11789 } else break :rs .{ .src = rhs_src, .air_tag = .rem };
11790 } else break :rs .{ .src = lhs_src, .air_tag = .rem };
11798 } else break :rs .{ .src = rhs_src, .air_tag = air_tag };
11799 } else break :rs .{ .src = lhs_src, .air_tag = air_tag };
1179111800 },
1179211801 .mod => {
1179311802 // For integers:
......@@ -11834,6 +11843,7 @@ fn analyzeArithmetic(
1183411843 return sema.failWithDivideByZero(block, rhs_src);
1183511844 }
1183611845 }
11846 const air_tag: Air.Inst.Tag = if (block.float_mode == .Optimized) .mod_optimized else .mod;
1183711847 if (maybe_lhs_val) |lhs_val| {
1183811848 if (lhs_val.isUndef()) {
1183911849 return sema.addConstUndef(resolved_type);
......@@ -11843,8 +11853,8 @@ fn analyzeArithmetic(
1184311853 resolved_type,
1184411854 try lhs_val.floatMod(rhs_val, resolved_type, sema.arena, target),
1184511855 );
11846 } else break :rs .{ .src = rhs_src, .air_tag = .mod };
11847 } else break :rs .{ .src = lhs_src, .air_tag = .mod };
11856 } else break :rs .{ .src = rhs_src, .air_tag = air_tag };
11857 } else break :rs .{ .src = lhs_src, .air_tag = air_tag };
1184811858 },
1184911859 else => unreachable,
1185011860 }
......@@ -11874,7 +11884,7 @@ fn analyzeArithmetic(
1187411884 const ov_bit = try sema.tupleFieldValByIndex(block, src, op_ov, 1, op_ov_tuple_ty);
1187511885 const any_ov_bit = if (resolved_type.zigTypeTag() == .Vector)
1187611886 try block.addInst(.{
11877 .tag = .reduce,
11887 .tag = if (block.float_mode == .Optimized) .reduce_optimized else .reduce,
1187811888 .data = .{ .reduce = .{
1187911889 .operand = ov_bit,
1188011890 .operation = .Or,
......@@ -11890,13 +11900,17 @@ fn analyzeArithmetic(
1189011900 }
1189111901 }
1189211902 switch (rs.air_tag) {
11893 .div_float, .div_exact, .div_trunc, .div_floor => {
11903 // zig fmt: off
11904 .div_float, .div_exact, .div_trunc, .div_floor, .div_float_optimized,
11905 .div_exact_optimized, .div_trunc_optimized, .div_floor_optimized
11906 // zig fmt: on
11907 => if (scalar_tag == .Int or block.float_mode == .Optimized) {
1189411908 const ok = if (resolved_type.zigTypeTag() == .Vector) ok: {
1189511909 const zero_val = try Value.Tag.repeated.create(sema.arena, Value.zero);
1189611910 const zero = try sema.addConstant(sema.typeOf(casted_rhs), zero_val);
1189711911 const ok = try block.addCmpVector(casted_rhs, zero, .neq, try sema.addType(resolved_type));
1189811912 break :ok try block.addInst(.{
11899 .tag = .reduce,
11913 .tag = if (block.float_mode == .Optimized) .reduce_optimized else .reduce,
1190011914 .data = .{ .reduce = .{
1190111915 .operand = ok,
1190211916 .operation = .And,
......@@ -11904,17 +11918,17 @@ fn analyzeArithmetic(
1190411918 });
1190511919 } else ok: {
1190611920 const zero = try sema.addConstant(sema.typeOf(casted_rhs), Value.zero);
11907 break :ok try block.addBinOp(.cmp_neq, casted_rhs, zero);
11921 break :ok try block.addBinOp(if (block.float_mode == .Optimized) .cmp_neq_optimized else .cmp_neq, casted_rhs, zero);
1190811922 };
1190911923 try sema.addSafetyCheck(block, ok, .divide_by_zero);
1191011924 },
11911 .rem, .mod => {
11925 .rem, .mod, .rem_optimized, .mod_optimized => {
1191211926 const ok = if (resolved_type.zigTypeTag() == .Vector) ok: {
1191311927 const zero_val = try Value.Tag.repeated.create(sema.arena, Value.zero);
1191411928 const zero = try sema.addConstant(sema.typeOf(casted_rhs), zero_val);
1191511929 const ok = try block.addCmpVector(casted_rhs, zero, if (scalar_tag == .Int) .gt else .neq, try sema.addType(resolved_type));
1191611930 break :ok try block.addInst(.{
11917 .tag = .reduce,
11931 .tag = if (block.float_mode == .Optimized) .reduce_optimized else .reduce,
1191811932 .data = .{ .reduce = .{
1191911933 .operand = ok,
1192011934 .operation = .And,
......@@ -11922,13 +11936,19 @@ fn analyzeArithmetic(
1192211936 });
1192311937 } else ok: {
1192411938 const zero = try sema.addConstant(sema.typeOf(casted_rhs), Value.zero);
11925 break :ok try block.addBinOp(if (scalar_tag == .Int) .cmp_gt else .cmp_neq, casted_rhs, zero);
11939 const air_tag = if (scalar_tag == .Int)
11940 Air.Inst.Tag.cmp_gt
11941 else if (block.float_mode == .Optimized)
11942 Air.Inst.Tag.cmp_neq_optimized
11943 else
11944 Air.Inst.Tag.cmp_neq;
11945 break :ok try block.addBinOp(air_tag, casted_rhs, zero);
1192611946 };
1192711947 try sema.addSafetyCheck(block, ok, .remainder_division_zero_negative);
1192811948 },
1192911949 else => {},
1193011950 }
11931 if (rs.air_tag == .div_exact) {
11951 if (rs.air_tag == .div_exact or rs.air_tag == .div_exact_optimized) {
1193211952 const result = try block.addBinOp(.div_exact, casted_lhs, casted_rhs);
1193311953 const ok = if (scalar_tag == .Float) ok: {
1193411954 const floored = try block.addUnOp(.floor, result);
......@@ -11936,14 +11956,14 @@ fn analyzeArithmetic(
1193611956 if (resolved_type.zigTypeTag() == .Vector) {
1193711957 const eql = try block.addCmpVector(result, floored, .eq, try sema.addType(resolved_type));
1193811958 break :ok try block.addInst(.{
11939 .tag = .reduce,
11959 .tag = if (block.float_mode == .Optimized) .reduce_optimized else .reduce,
1194011960 .data = .{ .reduce = .{
1194111961 .operand = eql,
1194211962 .operation = .And,
1194311963 } },
1194411964 });
1194511965 } else {
11946 const is_in_range = try block.addBinOp(.cmp_eq, result, floored);
11966 const is_in_range = try block.addBinOp(if (block.float_mode == .Optimized) .cmp_eq_optimized else .cmp_eq, result, floored);
1194711967 break :ok is_in_range;
1194811968 }
1194911969 } else ok: {
......@@ -11962,7 +11982,7 @@ fn analyzeArithmetic(
1196211982 });
1196311983 } else {
1196411984 const zero = try sema.addConstant(sema.typeOf(casted_rhs), Value.zero);
11965 const is_in_range = try block.addBinOp(.cmp_eq, remainder, zero);
11985 const is_in_range = try block.addBinOp(if (block.float_mode == .Optimized) .cmp_eq_optimized else .cmp_eq, remainder, zero);
1196611986 break :ok is_in_range;
1196711987 }
1196811988 };
......@@ -12476,7 +12496,7 @@ fn cmpSelf(
1247612496 const result_ty_ref = try sema.addType(result_ty);
1247712497 return block.addCmpVector(casted_lhs, casted_rhs, op, result_ty_ref);
1247812498 }
12479 const tag = Air.Inst.Tag.fromCmpOp(op);
12499 const tag = Air.Inst.Tag.fromCmpOp(op, block.float_mode == .Optimized);
1248012500 return block.addBinOp(tag, casted_lhs, casted_rhs);
1248112501}
1248212502
......@@ -15954,12 +15974,12 @@ fn zirFloatToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
1595415974 }
1595515975
1595615976 try sema.requireRuntimeBlock(block, inst_data.src(), operand_src);
15957 const result = try block.addTyOp(.float_to_int, dest_ty, operand);
15977 const result = try block.addTyOp(if (block.float_mode == .Optimized) .float_to_int_optimized else .float_to_int, dest_ty, operand);
1595815978 if (block.wantSafety()) {
1595915979 const back = try block.addTyOp(.int_to_float, operand_ty, result);
1596015980 const diff = try block.addBinOp(.sub, operand, back);
15961 const ok_pos = try block.addBinOp(.cmp_lt, diff, try sema.addConstant(operand_ty, Value.one));
15962 const ok_neg = try block.addBinOp(.cmp_gt, diff, try sema.addConstant(operand_ty, Value.negative_one));
15981 const ok_pos = try block.addBinOp(if (block.float_mode == .Optimized) .cmp_lt_optimized else .cmp_lt, diff, try sema.addConstant(operand_ty, Value.one));
15982 const ok_neg = try block.addBinOp(if (block.float_mode == .Optimized) .cmp_gt_optimized else .cmp_gt, diff, try sema.addConstant(operand_ty, Value.negative_one));
1596315983 const ok = try block.addBinOp(.bool_and, ok_pos, ok_neg);
1596415984 try sema.addSafetyCheck(block, ok, .integer_part_out_of_bounds);
1596515985 }
......@@ -17194,7 +17214,7 @@ fn zirReduce(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
1719417214
1719517215 try sema.requireRuntimeBlock(block, inst_data.src(), operand_src);
1719617216 return block.addInst(.{
17197 .tag = .reduce,
17217 .tag = if (block.float_mode == .Optimized) .reduce_optimized else .reduce,
1719817218 .data = .{ .reduce = .{
1719917219 .operand = operand,
1720017220 .operation = operation,
......@@ -24489,7 +24509,7 @@ fn cmpNumeric(
2448924509 };
2449024510 const casted_lhs = try sema.coerce(block, dest_ty, lhs, lhs_src);
2449124511 const casted_rhs = try sema.coerce(block, dest_ty, rhs, rhs_src);
24492 return block.addBinOp(Air.Inst.Tag.fromCmpOp(op), casted_lhs, casted_rhs);
24512 return block.addBinOp(Air.Inst.Tag.fromCmpOp(op, block.float_mode == .Optimized), casted_lhs, casted_rhs);
2449324513 }
2449424514 // For mixed unsigned integer sizes, implicit cast both operands to the larger integer.
2449524515 // For mixed signed and unsigned integers, implicit cast both operands to a signed
......@@ -24610,7 +24630,7 @@ fn cmpNumeric(
2461024630 const casted_lhs = try sema.coerce(block, dest_ty, lhs, lhs_src);
2461124631 const casted_rhs = try sema.coerce(block, dest_ty, rhs, rhs_src);
2461224632
24613 return block.addBinOp(Air.Inst.Tag.fromCmpOp(op), casted_lhs, casted_rhs);
24633 return block.addBinOp(Air.Inst.Tag.fromCmpOp(op, block.float_mode == .Optimized), casted_lhs, casted_rhs);
2461424634}
2461524635
2461624636/// Asserts that lhs and rhs types are both vectors.
src/arch/aarch64/CodeGen.zig+24
......@@ -729,6 +729,30 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
729729 .wrap_errunion_payload => try self.airWrapErrUnionPayload(inst),
730730 .wrap_errunion_err => try self.airWrapErrUnionErr(inst),
731731
732 .add_optimized,
733 .addwrap_optimized,
734 .sub_optimized,
735 .subwrap_optimized,
736 .mul_optimized,
737 .mulwrap_optimized,
738 .div_float_optimized,
739 .div_trunc_optimized,
740 .div_floor_optimized,
741 .div_exact_optimized,
742 .rem_optimized,
743 .mod_optimized,
744 .neg_optimized,
745 .cmp_lt_optimized,
746 .cmp_lte_optimized,
747 .cmp_eq_optimized,
748 .cmp_gte_optimized,
749 .cmp_gt_optimized,
750 .cmp_neq_optimized,
751 .cmp_vector_optimized,
752 .reduce_optimized,
753 .float_to_int_optimized,
754 => return self.fail("TODO implement optimized float mode", .{}),
755
732756 .wasm_memory_size => unreachable,
733757 .wasm_memory_grow => unreachable,
734758 // zig fmt: on
src/arch/arm/CodeGen.zig+24
......@@ -744,6 +744,30 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
744744 .wrap_errunion_payload => try self.airWrapErrUnionPayload(inst),
745745 .wrap_errunion_err => try self.airWrapErrUnionErr(inst),
746746
747 .add_optimized,
748 .addwrap_optimized,
749 .sub_optimized,
750 .subwrap_optimized,
751 .mul_optimized,
752 .mulwrap_optimized,
753 .div_float_optimized,
754 .div_trunc_optimized,
755 .div_floor_optimized,
756 .div_exact_optimized,
757 .rem_optimized,
758 .mod_optimized,
759 .neg_optimized,
760 .cmp_lt_optimized,
761 .cmp_lte_optimized,
762 .cmp_eq_optimized,
763 .cmp_gte_optimized,
764 .cmp_gt_optimized,
765 .cmp_neq_optimized,
766 .cmp_vector_optimized,
767 .reduce_optimized,
768 .float_to_int_optimized,
769 => return self.fail("TODO implement optimized float mode", .{}),
770
747771 .wasm_memory_size => unreachable,
748772 .wasm_memory_grow => unreachable,
749773 // zig fmt: on
src/arch/riscv64/CodeGen.zig+24
......@@ -669,6 +669,30 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
669669 .wrap_errunion_payload => try self.airWrapErrUnionPayload(inst),
670670 .wrap_errunion_err => try self.airWrapErrUnionErr(inst),
671671
672 .add_optimized,
673 .addwrap_optimized,
674 .sub_optimized,
675 .subwrap_optimized,
676 .mul_optimized,
677 .mulwrap_optimized,
678 .div_float_optimized,
679 .div_trunc_optimized,
680 .div_floor_optimized,
681 .div_exact_optimized,
682 .rem_optimized,
683 .mod_optimized,
684 .neg_optimized,
685 .cmp_lt_optimized,
686 .cmp_lte_optimized,
687 .cmp_eq_optimized,
688 .cmp_gte_optimized,
689 .cmp_gt_optimized,
690 .cmp_neq_optimized,
691 .cmp_vector_optimized,
692 .reduce_optimized,
693 .float_to_int_optimized,
694 => return self.fail("TODO implement optimized float mode", .{}),
695
672696 .wasm_memory_size => unreachable,
673697 .wasm_memory_grow => unreachable,
674698 // zig fmt: on
src/arch/sparc64/CodeGen.zig+24
......@@ -681,6 +681,30 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
681681 .wrap_errunion_payload => @panic("TODO try self.airWrapErrUnionPayload(inst)"),
682682 .wrap_errunion_err => try self.airWrapErrUnionErr(inst),
683683
684 .add_optimized,
685 .addwrap_optimized,
686 .sub_optimized,
687 .subwrap_optimized,
688 .mul_optimized,
689 .mulwrap_optimized,
690 .div_float_optimized,
691 .div_trunc_optimized,
692 .div_floor_optimized,
693 .div_exact_optimized,
694 .rem_optimized,
695 .mod_optimized,
696 .neg_optimized,
697 .cmp_lt_optimized,
698 .cmp_lte_optimized,
699 .cmp_eq_optimized,
700 .cmp_gte_optimized,
701 .cmp_gt_optimized,
702 .cmp_neq_optimized,
703 .cmp_vector_optimized,
704 .reduce_optimized,
705 .float_to_int_optimized,
706 => @panic("TODO implement optimized float mode"),
707
684708 .wasm_memory_size => unreachable,
685709 .wasm_memory_grow => unreachable,
686710 // zig fmt: on
src/arch/wasm/CodeGen.zig+24
......@@ -1622,6 +1622,30 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue {
16221622 .err_return_trace,
16231623 .set_err_return_trace,
16241624 => |tag| return self.fail("TODO: Implement wasm inst: {s}", .{@tagName(tag)}),
1625
1626 .add_optimized,
1627 .addwrap_optimized,
1628 .sub_optimized,
1629 .subwrap_optimized,
1630 .mul_optimized,
1631 .mulwrap_optimized,
1632 .div_float_optimized,
1633 .div_trunc_optimized,
1634 .div_floor_optimized,
1635 .div_exact_optimized,
1636 .rem_optimized,
1637 .mod_optimized,
1638 .neg_optimized,
1639 .cmp_lt_optimized,
1640 .cmp_lte_optimized,
1641 .cmp_eq_optimized,
1642 .cmp_gte_optimized,
1643 .cmp_gt_optimized,
1644 .cmp_neq_optimized,
1645 .cmp_vector_optimized,
1646 .reduce_optimized,
1647 .float_to_int_optimized,
1648 => return self.fail("TODO implement optimized float mode", .{}),
16251649 };
16261650}
16271651
src/arch/x86_64/CodeGen.zig+24
......@@ -751,6 +751,30 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
751751 .wrap_errunion_payload => try self.airWrapErrUnionPayload(inst),
752752 .wrap_errunion_err => try self.airWrapErrUnionErr(inst),
753753
754 .add_optimized,
755 .addwrap_optimized,
756 .sub_optimized,
757 .subwrap_optimized,
758 .mul_optimized,
759 .mulwrap_optimized,
760 .div_float_optimized,
761 .div_trunc_optimized,
762 .div_floor_optimized,
763 .div_exact_optimized,
764 .rem_optimized,
765 .mod_optimized,
766 .neg_optimized,
767 .cmp_lt_optimized,
768 .cmp_lte_optimized,
769 .cmp_eq_optimized,
770 .cmp_gte_optimized,
771 .cmp_gt_optimized,
772 .cmp_neq_optimized,
773 .cmp_vector_optimized,
774 .reduce_optimized,
775 .float_to_int_optimized,
776 => return self.fail("TODO implement optimized float mode", .{}),
777
754778 .wasm_memory_size => unreachable,
755779 .wasm_memory_grow => unreachable,
756780 // zig fmt: on
src/codegen/c.zig+24
......@@ -1928,6 +1928,30 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
19281928
19291929 .wasm_memory_size => try airWasmMemorySize(f, inst),
19301930 .wasm_memory_grow => try airWasmMemoryGrow(f, inst),
1931
1932 .add_optimized,
1933 .addwrap_optimized,
1934 .sub_optimized,
1935 .subwrap_optimized,
1936 .mul_optimized,
1937 .mulwrap_optimized,
1938 .div_float_optimized,
1939 .div_trunc_optimized,
1940 .div_floor_optimized,
1941 .div_exact_optimized,
1942 .rem_optimized,
1943 .mod_optimized,
1944 .neg_optimized,
1945 .cmp_lt_optimized,
1946 .cmp_lte_optimized,
1947 .cmp_eq_optimized,
1948 .cmp_gte_optimized,
1949 .cmp_gt_optimized,
1950 .cmp_neq_optimized,
1951 .cmp_vector_optimized,
1952 .reduce_optimized,
1953 .float_to_int_optimized,
1954 => return f.fail("TODO implement optimized float mode", .{}),
19311955 // zig fmt: on
19321956 };
19331957 switch (result_value) {
src/codegen/llvm.zig+95-40
......@@ -3984,21 +3984,21 @@ pub const FuncGen = struct {
39843984 for (body) |inst, i| {
39853985 const opt_value: ?*const llvm.Value = switch (air_tags[inst]) {
39863986 // zig fmt: off
3987 .add => try self.airAdd(inst),
3988 .addwrap => try self.airAddWrap(inst),
3987 .add => try self.airAdd(inst, false),
3988 .addwrap => try self.airAddWrap(inst, false),
39893989 .add_sat => try self.airAddSat(inst),
3990 .sub => try self.airSub(inst),
3991 .subwrap => try self.airSubWrap(inst),
3990 .sub => try self.airSub(inst, false),
3991 .subwrap => try self.airSubWrap(inst, false),
39923992 .sub_sat => try self.airSubSat(inst),
3993 .mul => try self.airMul(inst),
3994 .mulwrap => try self.airMulWrap(inst),
3993 .mul => try self.airMul(inst, false),
3994 .mulwrap => try self.airMulWrap(inst, false),
39953995 .mul_sat => try self.airMulSat(inst),
3996 .div_float => try self.airDivFloat(inst),
3997 .div_trunc => try self.airDivTrunc(inst),
3998 .div_floor => try self.airDivFloor(inst),
3999 .div_exact => try self.airDivExact(inst),
4000 .rem => try self.airRem(inst),
4001 .mod => try self.airMod(inst),
3996 .div_float => try self.airDivFloat(inst, false),
3997 .div_trunc => try self.airDivTrunc(inst, false),
3998 .div_floor => try self.airDivFloor(inst, false),
3999 .div_exact => try self.airDivExact(inst, false),
4000 .rem => try self.airRem(inst, false),
4001 .mod => try self.airMod(inst, false),
40024002 .ptr_add => try self.airPtrAdd(inst),
40034003 .ptr_sub => try self.airPtrSub(inst),
40044004 .shl => try self.airShl(inst),
......@@ -4009,6 +4009,19 @@ pub const FuncGen = struct {
40094009 .slice => try self.airSlice(inst),
40104010 .mul_add => try self.airMulAdd(inst),
40114011
4012 .add_optimized => try self.airAdd(inst, true),
4013 .addwrap_optimized => try self.airAddWrap(inst, true),
4014 .sub_optimized => try self.airSub(inst, true),
4015 .subwrap_optimized => try self.airSubWrap(inst, true),
4016 .mul_optimized => try self.airMul(inst, true),
4017 .mulwrap_optimized => try self.airMulWrap(inst, true),
4018 .div_float_optimized => try self.airDivFloat(inst, true),
4019 .div_trunc_optimized => try self.airDivTrunc(inst, true),
4020 .div_floor_optimized => try self.airDivFloor(inst, true),
4021 .div_exact_optimized => try self.airDivExact(inst, true),
4022 .rem_optimized => try self.airRem(inst, true),
4023 .mod_optimized => try self.airMod(inst, true),
4024
40124025 .add_with_overflow => try self.airOverflow(inst, "llvm.sadd.with.overflow", "llvm.uadd.with.overflow"),
40134026 .sub_with_overflow => try self.airOverflow(inst, "llvm.ssub.with.overflow", "llvm.usub.with.overflow"),
40144027 .mul_with_overflow => try self.airOverflow(inst, "llvm.smul.with.overflow", "llvm.umul.with.overflow"),
......@@ -4034,17 +4047,27 @@ pub const FuncGen = struct {
40344047 .ceil => try self.airUnaryOp(inst, .ceil),
40354048 .round => try self.airUnaryOp(inst, .round),
40364049 .trunc_float => try self.airUnaryOp(inst, .trunc),
4037 .neg => try self.airUnaryOp(inst, .neg),
4038
4039 .cmp_eq => try self.airCmp(inst, .eq),
4040 .cmp_gt => try self.airCmp(inst, .gt),
4041 .cmp_gte => try self.airCmp(inst, .gte),
4042 .cmp_lt => try self.airCmp(inst, .lt),
4043 .cmp_lte => try self.airCmp(inst, .lte),
4044 .cmp_neq => try self.airCmp(inst, .neq),
40454050
4046 .cmp_vector => try self.airCmpVector(inst),
4047 .cmp_lt_errors_len => try self.airCmpLtErrorsLen(inst),
4051 .neg => try self.airNeg(inst, false),
4052 .neg_optimized => try self.airNeg(inst, true),
4053
4054 .cmp_eq => try self.airCmp(inst, .eq, false),
4055 .cmp_gt => try self.airCmp(inst, .gt, false),
4056 .cmp_gte => try self.airCmp(inst, .gte, false),
4057 .cmp_lt => try self.airCmp(inst, .lt, false),
4058 .cmp_lte => try self.airCmp(inst, .lte, false),
4059 .cmp_neq => try self.airCmp(inst, .neq, false),
4060
4061 .cmp_eq_optimized => try self.airCmp(inst, .eq, true),
4062 .cmp_gt_optimized => try self.airCmp(inst, .gt, true),
4063 .cmp_gte_optimized => try self.airCmp(inst, .gte, true),
4064 .cmp_lt_optimized => try self.airCmp(inst, .lt, true),
4065 .cmp_lte_optimized => try self.airCmp(inst, .lte, true),
4066 .cmp_neq_optimized => try self.airCmp(inst, .neq, true),
4067
4068 .cmp_vector => try self.airCmpVector(inst, false),
4069 .cmp_vector_optimized => try self.airCmpVector(inst, true),
4070 .cmp_lt_errors_len => try self.airCmpLtErrorsLen(inst),
40484071
40494072 .is_non_null => try self.airIsNonNull(inst, false, .NE),
40504073 .is_non_null_ptr => try self.airIsNonNull(inst, true , .NE),
......@@ -4093,8 +4116,10 @@ pub const FuncGen = struct {
40934116 .ptr_slice_ptr_ptr => try self.airPtrSliceFieldPtr(inst, 0),
40944117 .ptr_slice_len_ptr => try self.airPtrSliceFieldPtr(inst, 1),
40954118
4119 .float_to_int => try self.airFloatToInt(inst, false),
4120 .float_to_int_optimized => try self.airFloatToInt(inst, true),
4121
40964122 .array_to_slice => try self.airArrayToSlice(inst),
4097 .float_to_int => try self.airFloatToInt(inst),
40984123 .int_to_float => try self.airIntToFloat(inst),
40994124 .cmpxchg_weak => try self.airCmpxchg(inst, true),
41004125 .cmpxchg_strong => try self.airCmpxchg(inst, false),
......@@ -4115,11 +4140,13 @@ pub const FuncGen = struct {
41154140 .splat => try self.airSplat(inst),
41164141 .select => try self.airSelect(inst),
41174142 .shuffle => try self.airShuffle(inst),
4118 .reduce => try self.airReduce(inst),
41194143 .aggregate_init => try self.airAggregateInit(inst),
41204144 .union_init => try self.airUnionInit(inst),
41214145 .prefetch => try self.airPrefetch(inst),
41224146
4147 .reduce => try self.airReduce(inst, false),
4148 .reduce_optimized => try self.airReduce(inst, true),
4149
41234150 .atomic_store_unordered => try self.airAtomicStore(inst, .Unordered),
41244151 .atomic_store_monotonic => try self.airAtomicStore(inst, .Monotonic),
41254152 .atomic_store_release => try self.airAtomicStore(inst, .Release),
......@@ -4485,8 +4512,9 @@ pub const FuncGen = struct {
44854512 return null;
44864513 }
44874514
4488 fn airCmp(self: *FuncGen, inst: Air.Inst.Index, op: math.CompareOperator) !?*const llvm.Value {
4515 fn airCmp(self: *FuncGen, inst: Air.Inst.Index, op: math.CompareOperator, want_fast_math: bool) !?*const llvm.Value {
44894516 if (self.liveness.isUnused(inst)) return null;
4517 self.builder.setFastMath(want_fast_math);
44904518
44914519 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
44924520 const lhs = try self.resolveInst(bin_op.lhs);
......@@ -4496,8 +4524,9 @@ pub const FuncGen = struct {
44964524 return self.cmp(lhs, rhs, operand_ty, op);
44974525 }
44984526
4499 fn airCmpVector(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
4527 fn airCmpVector(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*const llvm.Value {
45004528 if (self.liveness.isUnused(inst)) return null;
4529 self.builder.setFastMath(want_fast_math);
45014530
45024531 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
45034532 const extra = self.air.extraData(Air.VectorCmp, ty_pl.payload).data;
......@@ -4943,10 +4972,12 @@ pub const FuncGen = struct {
49434972 return self.builder.buildCall(libc_fn, &params, params.len, .C, .Auto, "");
49444973 }
49454974
4946 fn airFloatToInt(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
4975 fn airFloatToInt(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*const llvm.Value {
49474976 if (self.liveness.isUnused(inst))
49484977 return null;
49494978
4979 self.builder.setFastMath(want_fast_math);
4980
49504981 const target = self.dg.module.getTarget();
49514982 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
49524983
......@@ -6095,8 +6126,9 @@ pub const FuncGen = struct {
60956126 return self.builder.buildInsertValue(partial, len, 1, "");
60966127 }
60976128
6098 fn airAdd(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
6129 fn airAdd(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*const llvm.Value {
60996130 if (self.liveness.isUnused(inst)) return null;
6131 self.builder.setFastMath(want_fast_math);
61006132
61016133 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
61026134 const lhs = try self.resolveInst(bin_op.lhs);
......@@ -6109,8 +6141,9 @@ pub const FuncGen = struct {
61096141 return self.builder.buildNUWAdd(lhs, rhs, "");
61106142 }
61116143
6112 fn airAddWrap(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
6144 fn airAddWrap(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*const llvm.Value {
61136145 if (self.liveness.isUnused(inst)) return null;
6146 self.builder.setFastMath(want_fast_math);
61146147
61156148 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
61166149 const lhs = try self.resolveInst(bin_op.lhs);
......@@ -6134,8 +6167,9 @@ pub const FuncGen = struct {
61346167 return self.builder.buildUAddSat(lhs, rhs, "");
61356168 }
61366169
6137 fn airSub(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
6170 fn airSub(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*const llvm.Value {
61386171 if (self.liveness.isUnused(inst)) return null;
6172 self.builder.setFastMath(want_fast_math);
61396173
61406174 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
61416175 const lhs = try self.resolveInst(bin_op.lhs);
......@@ -6148,8 +6182,9 @@ pub const FuncGen = struct {
61486182 return self.builder.buildNUWSub(lhs, rhs, "");
61496183 }
61506184
6151 fn airSubWrap(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
6185 fn airSubWrap(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*const llvm.Value {
61526186 if (self.liveness.isUnused(inst)) return null;
6187 self.builder.setFastMath(want_fast_math);
61536188
61546189 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
61556190 const lhs = try self.resolveInst(bin_op.lhs);
......@@ -6172,8 +6207,9 @@ pub const FuncGen = struct {
61726207 return self.builder.buildUSubSat(lhs, rhs, "");
61736208 }
61746209
6175 fn airMul(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
6210 fn airMul(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*const llvm.Value {
61766211 if (self.liveness.isUnused(inst)) return null;
6212 self.builder.setFastMath(want_fast_math);
61776213
61786214 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
61796215 const lhs = try self.resolveInst(bin_op.lhs);
......@@ -6186,8 +6222,9 @@ pub const FuncGen = struct {
61866222 return self.builder.buildNUWMul(lhs, rhs, "");
61876223 }
61886224
6189 fn airMulWrap(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
6225 fn airMulWrap(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*const llvm.Value {
61906226 if (self.liveness.isUnused(inst)) return null;
6227 self.builder.setFastMath(want_fast_math);
61916228
61926229 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
61936230 const lhs = try self.resolveInst(bin_op.lhs);
......@@ -6210,8 +6247,9 @@ pub const FuncGen = struct {
62106247 return self.builder.buildUMulFixSat(lhs, rhs, "");
62116248 }
62126249
6213 fn airDivFloat(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
6250 fn airDivFloat(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*const llvm.Value {
62146251 if (self.liveness.isUnused(inst)) return null;
6252 self.builder.setFastMath(want_fast_math);
62156253
62166254 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
62176255 const lhs = try self.resolveInst(bin_op.lhs);
......@@ -6221,8 +6259,9 @@ pub const FuncGen = struct {
62216259 return self.buildFloatOp(.div, inst_ty, 2, .{ lhs, rhs });
62226260 }
62236261
6224 fn airDivTrunc(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
6262 fn airDivTrunc(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*const llvm.Value {
62256263 if (self.liveness.isUnused(inst)) return null;
6264 self.builder.setFastMath(want_fast_math);
62266265
62276266 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
62286267 const lhs = try self.resolveInst(bin_op.lhs);
......@@ -6238,8 +6277,9 @@ pub const FuncGen = struct {
62386277 return self.builder.buildUDiv(lhs, rhs, "");
62396278 }
62406279
6241 fn airDivFloor(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
6280 fn airDivFloor(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*const llvm.Value {
62426281 if (self.liveness.isUnused(inst)) return null;
6282 self.builder.setFastMath(want_fast_math);
62436283
62446284 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
62456285 const lhs = try self.resolveInst(bin_op.lhs);
......@@ -6270,8 +6310,9 @@ pub const FuncGen = struct {
62706310 return self.builder.buildUDiv(lhs, rhs, "");
62716311 }
62726312
6273 fn airDivExact(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
6313 fn airDivExact(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*const llvm.Value {
62746314 if (self.liveness.isUnused(inst)) return null;
6315 self.builder.setFastMath(want_fast_math);
62756316
62766317 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
62776318 const lhs = try self.resolveInst(bin_op.lhs);
......@@ -6284,8 +6325,9 @@ pub const FuncGen = struct {
62846325 return self.builder.buildExactUDiv(lhs, rhs, "");
62856326 }
62866327
6287 fn airRem(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
6328 fn airRem(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*const llvm.Value {
62886329 if (self.liveness.isUnused(inst)) return null;
6330 self.builder.setFastMath(want_fast_math);
62896331
62906332 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
62916333 const lhs = try self.resolveInst(bin_op.lhs);
......@@ -6298,8 +6340,9 @@ pub const FuncGen = struct {
62986340 return self.builder.buildURem(lhs, rhs, "");
62996341 }
63006342
6301 fn airMod(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
6343 fn airMod(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*const llvm.Value {
63026344 if (self.liveness.isUnused(inst)) return null;
6345 self.builder.setFastMath(want_fast_math);
63036346
63046347 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
63056348 const lhs = try self.resolveInst(bin_op.lhs);
......@@ -7613,6 +7656,17 @@ pub const FuncGen = struct {
76137656 return self.buildFloatOp(op, operand_ty, 1, .{operand});
76147657 }
76157658
7659 fn airNeg(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*const llvm.Value {
7660 if (self.liveness.isUnused(inst)) return null;
7661 self.builder.setFastMath(want_fast_math);
7662
7663 const un_op = self.air.instructions.items(.data)[inst].un_op;
7664 const operand = try self.resolveInst(un_op);
7665 const operand_ty = self.air.typeOf(un_op);
7666
7667 return self.buildFloatOp(.neg, operand_ty, 1, .{operand});
7668 }
7669
76167670 fn airClzCtz(self: *FuncGen, inst: Air.Inst.Index, llvm_fn_name: []const u8) !?*const llvm.Value {
76177671 if (self.liveness.isUnused(inst)) return null;
76187672
......@@ -7927,8 +7981,9 @@ pub const FuncGen = struct {
79277981 return self.builder.buildShuffleVector(a, b, llvm_mask_value, "");
79287982 }
79297983
7930 fn airReduce(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
7984 fn airReduce(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*const llvm.Value {
79317985 if (self.liveness.isUnused(inst)) return null;
7986 self.builder.setFastMath(want_fast_math);
79327987
79337988 const reduce = self.air.instructions.items(.data)[inst].reduce;
79347989 const operand = try self.resolveInst(reduce.operand);
src/codegen/llvm/bindings.zig+3
......@@ -941,6 +941,9 @@ pub const Builder = opaque {
941941
942942 pub const buildFPMulReduce = ZigLLVMBuildFPMulReduce;
943943 extern fn ZigLLVMBuildFPMulReduce(B: *const Builder, Acc: *const Value, Val: *const Value) *const Value;
944
945 pub const setFastMath = ZigLLVMSetFastMath;
946 extern fn ZigLLVMSetFastMath(B: *const Builder, on_state: bool) void;
944947};
945948
946949pub const MDString = opaque {
src/print_air.zig+22-2
......@@ -138,6 +138,24 @@ const Writer = struct {
138138 .set_union_tag,
139139 .min,
140140 .max,
141 .add_optimized,
142 .addwrap_optimized,
143 .sub_optimized,
144 .subwrap_optimized,
145 .mul_optimized,
146 .mulwrap_optimized,
147 .div_float_optimized,
148 .div_trunc_optimized,
149 .div_floor_optimized,
150 .div_exact_optimized,
151 .rem_optimized,
152 .mod_optimized,
153 .cmp_lt_optimized,
154 .cmp_lte_optimized,
155 .cmp_eq_optimized,
156 .cmp_gte_optimized,
157 .cmp_gt_optimized,
158 .cmp_neq_optimized,
141159 => try w.writeBinOp(s, inst),
142160
143161 .is_null,
......@@ -169,6 +187,7 @@ const Writer = struct {
169187 .round,
170188 .trunc_float,
171189 .neg,
190 .neg_optimized,
172191 .cmp_lt_errors_len,
173192 .set_err_return_trace,
174193 => try w.writeUnOp(s, inst),
......@@ -216,6 +235,7 @@ const Writer = struct {
216235 .int_to_float,
217236 .splat,
218237 .float_to_int,
238 .float_to_int_optimized,
219239 .get_union_tag,
220240 .clz,
221241 .ctz,
......@@ -280,8 +300,8 @@ const Writer = struct {
280300 .mul_add => try w.writeMulAdd(s, inst),
281301 .select => try w.writeSelect(s, inst),
282302 .shuffle => try w.writeShuffle(s, inst),
283 .reduce => try w.writeReduce(s, inst),
284 .cmp_vector => try w.writeCmpVector(s, inst),
303 .reduce, .reduce_optimized => try w.writeReduce(s, inst),
304 .cmp_vector, .cmp_vector_optimized => try w.writeCmpVector(s, inst),
285305
286306 .dbg_block_begin, .dbg_block_end => {},
287307 }