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" {...@@ -813,6 +813,7 @@ test "conversion to f32" {
813test "conversion to f80" {813test "conversion to f80" {
814 if (builtin.zig_backend == .stage1 and builtin.cpu.arch != .x86_64)814 if (builtin.zig_backend == .stage1 and builtin.cpu.arch != .x86_64)
815 return error.SkipZigTest; // https://github.com/ziglang/zig/issues/11408815 return error.SkipZigTest; // https://github.com/ziglang/zig/issues/11408
816 if (std.debug.runtime_safety) return error.SkipZigTest;
816817
817 const intToFloat = @import("./int_to_float.zig").intToFloat;818 const intToFloat = @import("./int_to_float.zig").intToFloat;
818819
src/Air.zig+81-16
...@@ -38,11 +38,15 @@ pub const Inst = struct {...@@ -38,11 +38,15 @@ pub const Inst = struct {
38 /// is the same as both operands.38 /// is the same as both operands.
39 /// Uses the `bin_op` field.39 /// Uses the `bin_op` field.
40 add,40 add,
41 /// Same as `add` with optimized float mode.
42 add_optimized,
41 /// Integer addition. Wrapping is defined to be twos complement wrapping.43 /// Integer addition. Wrapping is defined to be twos complement wrapping.
42 /// Both operands are guaranteed to be the same type, and the result type44 /// Both operands are guaranteed to be the same type, and the result type
43 /// is the same as both operands.45 /// is the same as both operands.
44 /// Uses the `bin_op` field.46 /// Uses the `bin_op` field.
45 addwrap,47 addwrap,
48 /// Same as `addwrap` with optimized float mode.
49 addwrap_optimized,
46 /// Saturating integer addition.50 /// Saturating integer addition.
47 /// Both operands are guaranteed to be the same type, and the result type51 /// Both operands are guaranteed to be the same type, and the result type
48 /// is the same as both operands.52 /// is the same as both operands.
...@@ -53,11 +57,15 @@ pub const Inst = struct {...@@ -53,11 +57,15 @@ pub const Inst = struct {
53 /// is the same as both operands.57 /// is the same as both operands.
54 /// Uses the `bin_op` field.58 /// Uses the `bin_op` field.
55 sub,59 sub,
60 /// Same as `sub` with optimized float mode.
61 sub_optimized,
56 /// Integer subtraction. Wrapping is defined to be twos complement wrapping.62 /// Integer subtraction. Wrapping is defined to be twos complement wrapping.
57 /// Both operands are guaranteed to be the same type, and the result type63 /// Both operands are guaranteed to be the same type, and the result type
58 /// is the same as both operands.64 /// is the same as both operands.
59 /// Uses the `bin_op` field.65 /// Uses the `bin_op` field.
60 subwrap,66 subwrap,
67 /// Same as `sub` with optimized float mode.
68 subwrap_optimized,
61 /// Saturating integer subtraction.69 /// Saturating integer subtraction.
62 /// Both operands are guaranteed to be the same type, and the result type70 /// Both operands are guaranteed to be the same type, and the result type
63 /// is the same as both operands.71 /// is the same as both operands.
...@@ -68,11 +76,15 @@ pub const Inst = struct {...@@ -68,11 +76,15 @@ pub const Inst = struct {
68 /// is the same as both operands.76 /// is the same as both operands.
69 /// Uses the `bin_op` field.77 /// Uses the `bin_op` field.
70 mul,78 mul,
79 /// Same as `mul` with optimized float mode.
80 mul_optimized,
71 /// Integer multiplication. Wrapping is defined to be twos complement wrapping.81 /// Integer multiplication. Wrapping is defined to be twos complement wrapping.
72 /// Both operands are guaranteed to be the same type, and the result type82 /// Both operands are guaranteed to be the same type, and the result type
73 /// is the same as both operands.83 /// is the same as both operands.
74 /// Uses the `bin_op` field.84 /// Uses the `bin_op` field.
75 mulwrap,85 mulwrap,
86 /// Same as `mulwrap` with optimized float mode.
87 mulwrap_optimized,
76 /// Saturating integer multiplication.88 /// Saturating integer multiplication.
77 /// Both operands are guaranteed to be the same type, and the result type89 /// Both operands are guaranteed to be the same type, and the result type
78 /// is the same as both operands.90 /// is the same as both operands.
...@@ -83,32 +95,44 @@ pub const Inst = struct {...@@ -83,32 +95,44 @@ pub const Inst = struct {
83 /// is the same as both operands.95 /// is the same as both operands.
84 /// Uses the `bin_op` field.96 /// Uses the `bin_op` field.
85 div_float,97 div_float,
98 /// Same as `div_float` with optimized float mode.
99 div_float_optimized,
86 /// Truncating integer or float division. For integers, wrapping is undefined behavior.100 /// Truncating integer or float division. For integers, wrapping is undefined behavior.
87 /// Both operands are guaranteed to be the same type, and the result type101 /// Both operands are guaranteed to be the same type, and the result type
88 /// is the same as both operands.102 /// is the same as both operands.
89 /// Uses the `bin_op` field.103 /// Uses the `bin_op` field.
90 div_trunc,104 div_trunc,
105 /// Same as `div_trunc` with optimized float mode.
106 div_trunc_optimized,
91 /// Flooring integer or float division. For integers, wrapping is undefined behavior.107 /// Flooring integer or float division. For integers, wrapping is undefined behavior.
92 /// Both operands are guaranteed to be the same type, and the result type108 /// Both operands are guaranteed to be the same type, and the result type
93 /// is the same as both operands.109 /// is the same as both operands.
94 /// Uses the `bin_op` field.110 /// Uses the `bin_op` field.
95 div_floor,111 div_floor,
112 /// Same as `div_floor` with optimized float mode.
113 div_floor_optimized,
96 /// Integer or float division. Guaranteed no remainder.114 /// Integer or float division. Guaranteed no remainder.
97 /// For integers, wrapping is undefined behavior.115 /// For integers, wrapping is undefined behavior.
98 /// Both operands are guaranteed to be the same type, and the result type116 /// Both operands are guaranteed to be the same type, and the result type
99 /// is the same as both operands.117 /// is the same as both operands.
100 /// Uses the `bin_op` field.118 /// Uses the `bin_op` field.
101 div_exact,119 div_exact,
120 /// Same as `div_exact` with optimized float mode.
121 div_exact_optimized,
102 /// Integer or float remainder division.122 /// Integer or float remainder division.
103 /// Both operands are guaranteed to be the same type, and the result type123 /// Both operands are guaranteed to be the same type, and the result type
104 /// is the same as both operands.124 /// is the same as both operands.
105 /// Uses the `bin_op` field.125 /// Uses the `bin_op` field.
106 rem,126 rem,
127 /// Same as `rem` with optimized float mode.
128 rem_optimized,
107 /// Integer or float modulus division.129 /// Integer or float modulus division.
108 /// Both operands are guaranteed to be the same type, and the result type130 /// Both operands are guaranteed to be the same type, and the result type
109 /// is the same as both operands.131 /// is the same as both operands.
110 /// Uses the `bin_op` field.132 /// Uses the `bin_op` field.
111 mod,133 mod,
134 /// Same as `mod` with optimized float mode.
135 mod_optimized,
112 /// Add an offset to a pointer, returning a new pointer.136 /// Add an offset to a pointer, returning a new pointer.
113 /// The offset is in element type units, not bytes.137 /// The offset is in element type units, not bytes.
114 /// Wrapping is undefined behavior.138 /// Wrapping is undefined behavior.
...@@ -293,29 +317,45 @@ pub const Inst = struct {...@@ -293,29 +317,45 @@ pub const Inst = struct {
293 /// LHS of zero.317 /// LHS of zero.
294 /// Uses the `un_op` field.318 /// Uses the `un_op` field.
295 neg,319 neg,
320 /// Same as `neg` with optimized float mode.
321 neg_optimized,
296322
297 /// `<`. Result type is always bool.323 /// `<`. Result type is always bool.
298 /// Uses the `bin_op` field.324 /// Uses the `bin_op` field.
299 cmp_lt,325 cmp_lt,
326 /// Same as `cmp_lt` with optimized float mode.
327 cmp_lt_optimized,
300 /// `<=`. Result type is always bool.328 /// `<=`. Result type is always bool.
301 /// Uses the `bin_op` field.329 /// Uses the `bin_op` field.
302 cmp_lte,330 cmp_lte,
331 /// Same as `cmp_lte` with optimized float mode.
332 cmp_lte_optimized,
303 /// `==`. Result type is always bool.333 /// `==`. Result type is always bool.
304 /// Uses the `bin_op` field.334 /// Uses the `bin_op` field.
305 cmp_eq,335 cmp_eq,
336 /// Same as `cmp_eq` with optimized float mode.
337 cmp_eq_optimized,
306 /// `>=`. Result type is always bool.338 /// `>=`. Result type is always bool.
307 /// Uses the `bin_op` field.339 /// Uses the `bin_op` field.
308 cmp_gte,340 cmp_gte,
341 /// Same as `cmp_gte` with optimized float mode.
342 cmp_gte_optimized,
309 /// `>`. Result type is always bool.343 /// `>`. Result type is always bool.
310 /// Uses the `bin_op` field.344 /// Uses the `bin_op` field.
311 cmp_gt,345 cmp_gt,
346 /// Same as `cmp_gt` with optimized float mode.
347 cmp_gt_optimized,
312 /// `!=`. Result type is always bool.348 /// `!=`. Result type is always bool.
313 /// Uses the `bin_op` field.349 /// Uses the `bin_op` field.
314 cmp_neq,350 cmp_neq,
351 /// Same as `cmp_neq` with optimized float mode.
352 cmp_neq_optimized,
315 /// Conditional between two vectors.353 /// Conditional between two vectors.
316 /// Result type is always a vector of bools.354 /// Result type is always a vector of bools.
317 /// Uses the `ty_pl` field, payload is `VectorCmp`.355 /// Uses the `ty_pl` field, payload is `VectorCmp`.
318 cmp_vector,356 cmp_vector,
357 /// Same as `cmp_vector` with optimized float mode.
358 cmp_vector_optimized,
319359
320 /// Conditional branch.360 /// Conditional branch.
321 /// Result type is always noreturn; no instructions in a block follow this one.361 /// Result type is always noreturn; no instructions in a block follow this one.
...@@ -553,6 +593,8 @@ pub const Inst = struct {...@@ -553,6 +593,8 @@ pub const Inst = struct {
553 /// Given a float operand, return the integer with the closest mathematical meaning.593 /// Given a float operand, return the integer with the closest mathematical meaning.
554 /// Uses the `ty_op` field.594 /// Uses the `ty_op` field.
555 float_to_int,595 float_to_int,
596 /// Same as `float_to_int` with optimized float mode.
597 float_to_int_optimized,
556 /// Given an integer operand, return the float with the closest mathematical meaning.598 /// Given an integer operand, return the float with the closest mathematical meaning.
557 /// Uses the `ty_op` field.599 /// Uses the `ty_op` field.
558 int_to_float,600 int_to_float,
...@@ -564,6 +606,8 @@ pub const Inst = struct {...@@ -564,6 +606,8 @@ pub const Inst = struct {
564 /// * min, max, add, mul => integer or float606 /// * min, max, add, mul => integer or float
565 /// Uses the `reduce` field.607 /// Uses the `reduce` field.
566 reduce,608 reduce,
609 /// Same as `reduce` with optimized float mode.
610 reduce_optimized,
567 /// Given an integer, bool, float, or pointer operand, return a vector with all elements611 /// Given an integer, bool, float, or pointer operand, return a vector with all elements
568 /// equal to the scalar value.612 /// equal to the scalar value.
569 /// Uses the `ty_op` field.613 /// Uses the `ty_op` field.
...@@ -676,25 +720,25 @@ pub const Inst = struct {...@@ -676,25 +720,25 @@ pub const Inst = struct {
676 /// Sets the operand as the current error return trace,720 /// Sets the operand as the current error return trace,
677 set_err_return_trace,721 set_err_return_trace,
678722
679 pub fn fromCmpOp(op: std.math.CompareOperator) Tag {723 pub fn fromCmpOp(op: std.math.CompareOperator, optimized: bool) Tag {
680 return switch (op) {724 switch (op) {
681 .lt => .cmp_lt,725 .lt => return if (optimized) .cmp_lt_optimized else .cmp_lt,
682 .lte => .cmp_lte,726 .lte => return if (optimized) .cmp_lte_optimized else .cmp_lte,
683 .eq => .cmp_eq,727 .eq => return if (optimized) .cmp_eq_optimized else .cmp_eq,
684 .gte => .cmp_gte,728 .gte => return if (optimized) .cmp_gte_optimized else .cmp_gte,
685 .gt => .cmp_gt,729 .gt => return if (optimized) .cmp_gt_optimized else .cmp_gt,
686 .neq => .cmp_neq,730 .neq => return if (optimized) .cmp_neq_optimized else .cmp_neq,
687 };731 }
688 }732 }
689733
690 pub fn toCmpOp(tag: Tag) ?std.math.CompareOperator {734 pub fn toCmpOp(tag: Tag) ?std.math.CompareOperator {
691 return switch (tag) {735 return switch (tag) {
692 .cmp_lt => .lt,736 .cmp_lt, .cmp_lt_optimized => .lt,
693 .cmp_lte => .lte,737 .cmp_lte, .cmp_lte_optimized => .lte,
694 .cmp_eq => .eq,738 .cmp_eq, .cmp_eq_optimized => .eq,
695 .cmp_gte => .gte,739 .cmp_gte, .cmp_gte_optimized => .gte,
696 .cmp_gt => .gt,740 .cmp_gt, .cmp_gt_optimized => .gt,
697 .cmp_neq => .neq,741 .cmp_neq, .cmp_neq_optimized => .neq,
698 else => null,742 else => null,
699 };743 };
700 }744 }
...@@ -959,6 +1003,18 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {...@@ -959,6 +1003,18 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {
959 .max,1003 .max,
960 .bool_and,1004 .bool_and,
961 .bool_or,1005 .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,
962 => return air.typeOf(datas[inst].bin_op.lhs),1018 => return air.typeOf(datas[inst].bin_op.lhs),
9631019
964 .sqrt,1020 .sqrt,
...@@ -976,6 +1032,7 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {...@@ -976,6 +1032,7 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {
976 .round,1032 .round,
977 .trunc_float,1033 .trunc_float,
978 .neg,1034 .neg,
1035 .neg_optimized,
979 => return air.typeOf(datas[inst].un_op),1036 => return air.typeOf(datas[inst].un_op),
9801037
981 .cmp_lt,1038 .cmp_lt,
...@@ -984,6 +1041,12 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {...@@ -984,6 +1041,12 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {
984 .cmp_gte,1041 .cmp_gte,
985 .cmp_gt,1042 .cmp_gt,
986 .cmp_neq,1043 .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,
987 .cmp_lt_errors_len,1050 .cmp_lt_errors_len,
988 .is_null,1051 .is_null,
989 .is_non_null,1052 .is_non_null,
...@@ -1018,6 +1081,7 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {...@@ -1018,6 +1081,7 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {
1018 .union_init,1081 .union_init,
1019 .field_parent_ptr,1082 .field_parent_ptr,
1020 .cmp_vector,1083 .cmp_vector,
1084 .cmp_vector_optimized,
1021 .add_with_overflow,1085 .add_with_overflow,
1022 .sub_with_overflow,1086 .sub_with_overflow,
1023 .mul_with_overflow,1087 .mul_with_overflow,
...@@ -1054,6 +1118,7 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {...@@ -1054,6 +1118,7 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {
1054 .struct_field_ptr_index_3,1118 .struct_field_ptr_index_3,
1055 .array_to_slice,1119 .array_to_slice,
1056 .float_to_int,1120 .float_to_int,
1121 .float_to_int_optimized,
1057 .int_to_float,1122 .int_to_float,
1058 .splat,1123 .splat,
1059 .get_union_tag,1124 .get_union_tag,
...@@ -1129,7 +1194,7 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {...@@ -1129,7 +1194,7 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {
1129 return ptr_ty.elemType();1194 return ptr_ty.elemType();
1130 },1195 },
11311196
1132 .reduce => return air.typeOf(datas[inst].reduce.operand).childType(),1197 .reduce, .reduce_optimized => return air.typeOf(datas[inst].reduce.operand).childType(),
11331198
1134 .mul_add => return air.typeOf(datas[inst].pl_op.operand),1199 .mul_add => return air.typeOf(datas[inst].pl_op.operand),
1135 .select => {1200 .select => {
src/Liveness.zig+44-4
...@@ -173,6 +173,25 @@ pub fn categorizeOperand(...@@ -173,6 +173,25 @@ pub fn categorizeOperand(
173 .shr_exact,173 .shr_exact,
174 .min,174 .min,
175 .max,175 .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,
176 => {195 => {
177 const o = air_datas[inst].bin_op;196 const o = air_datas[inst].bin_op;
178 if (o.lhs == operand_ref) return matchOperandSmallIndex(l, inst, 0, .none);197 if (o.lhs == operand_ref) return matchOperandSmallIndex(l, inst, 0, .none);
...@@ -239,6 +258,7 @@ pub fn categorizeOperand(...@@ -239,6 +258,7 @@ pub fn categorizeOperand(
239 .struct_field_ptr_index_3,258 .struct_field_ptr_index_3,
240 .array_to_slice,259 .array_to_slice,
241 .float_to_int,260 .float_to_int,
261 .float_to_int_optimized,
242 .int_to_float,262 .int_to_float,
243 .get_union_tag,263 .get_union_tag,
244 .clz,264 .clz,
...@@ -381,12 +401,12 @@ pub fn categorizeOperand(...@@ -381,12 +401,12 @@ pub fn categorizeOperand(
381 if (extra.b == operand_ref) return matchOperandSmallIndex(l, inst, 1, .none);401 if (extra.b == operand_ref) return matchOperandSmallIndex(l, inst, 1, .none);
382 return .none;402 return .none;
383 },403 },
384 .reduce => {404 .reduce, .reduce_optimized => {
385 const reduce = air_datas[inst].reduce;405 const reduce = air_datas[inst].reduce;
386 if (reduce.operand == operand_ref) return matchOperandSmallIndex(l, inst, 0, .none);406 if (reduce.operand == operand_ref) return matchOperandSmallIndex(l, inst, 0, .none);
387 return .none;407 return .none;
388 },408 },
389 .cmp_vector => {409 .cmp_vector, .cmp_vector_optimized => {
390 const extra = air.extraData(Air.VectorCmp, air_datas[inst].ty_pl.payload).data;410 const extra = air.extraData(Air.VectorCmp, air_datas[inst].ty_pl.payload).data;
391 if (extra.lhs == operand_ref) return matchOperandSmallIndex(l, inst, 0, .none);411 if (extra.lhs == operand_ref) return matchOperandSmallIndex(l, inst, 0, .none);
392 if (extra.rhs == operand_ref) return matchOperandSmallIndex(l, inst, 1, .none);412 if (extra.rhs == operand_ref) return matchOperandSmallIndex(l, inst, 1, .none);
...@@ -701,29 +721,47 @@ fn analyzeInst(...@@ -701,29 +721,47 @@ fn analyzeInst(
701721
702 switch (inst_tags[inst]) {722 switch (inst_tags[inst]) {
703 .add,723 .add,
724 .add_optimized,
704 .addwrap,725 .addwrap,
726 .addwrap_optimized,
705 .add_sat,727 .add_sat,
706 .sub,728 .sub,
729 .sub_optimized,
707 .subwrap,730 .subwrap,
731 .subwrap_optimized,
708 .sub_sat,732 .sub_sat,
709 .mul,733 .mul,
734 .mul_optimized,
710 .mulwrap,735 .mulwrap,
736 .mulwrap_optimized,
711 .mul_sat,737 .mul_sat,
712 .div_float,738 .div_float,
739 .div_float_optimized,
713 .div_trunc,740 .div_trunc,
741 .div_trunc_optimized,
714 .div_floor,742 .div_floor,
743 .div_floor_optimized,
715 .div_exact,744 .div_exact,
745 .div_exact_optimized,
716 .rem,746 .rem,
747 .rem_optimized,
717 .mod,748 .mod,
749 .mod_optimized,
718 .bit_and,750 .bit_and,
719 .bit_or,751 .bit_or,
720 .xor,752 .xor,
721 .cmp_lt,753 .cmp_lt,
754 .cmp_lt_optimized,
722 .cmp_lte,755 .cmp_lte,
756 .cmp_lte_optimized,
723 .cmp_eq,757 .cmp_eq,
758 .cmp_eq_optimized,
724 .cmp_gte,759 .cmp_gte,
760 .cmp_gte_optimized,
725 .cmp_gt,761 .cmp_gt,
762 .cmp_gt_optimized,
726 .cmp_neq,763 .cmp_neq,
764 .cmp_neq_optimized,
727 .bool_and,765 .bool_and,
728 .bool_or,766 .bool_or,
729 .store,767 .store,
...@@ -794,6 +832,7 @@ fn analyzeInst(...@@ -794,6 +832,7 @@ fn analyzeInst(
794 .struct_field_ptr_index_3,832 .struct_field_ptr_index_3,
795 .array_to_slice,833 .array_to_slice,
796 .float_to_int,834 .float_to_int,
835 .float_to_int_optimized,
797 .int_to_float,836 .int_to_float,
798 .get_union_tag,837 .get_union_tag,
799 .clz,838 .clz,
...@@ -836,6 +875,7 @@ fn analyzeInst(...@@ -836,6 +875,7 @@ fn analyzeInst(
836 .round,875 .round,
837 .trunc_float,876 .trunc_float,
838 .neg,877 .neg,
878 .neg_optimized,
839 .cmp_lt_errors_len,879 .cmp_lt_errors_len,
840 .set_err_return_trace,880 .set_err_return_trace,
841 => {881 => {
...@@ -903,11 +943,11 @@ fn analyzeInst(...@@ -903,11 +943,11 @@ fn analyzeInst(
903 const extra = a.air.extraData(Air.Shuffle, inst_datas[inst].ty_pl.payload).data;943 const extra = a.air.extraData(Air.Shuffle, inst_datas[inst].ty_pl.payload).data;
904 return trackOperands(a, new_set, inst, main_tomb, .{ extra.a, extra.b, .none });944 return trackOperands(a, new_set, inst, main_tomb, .{ extra.a, extra.b, .none });
905 },945 },
906 .reduce => {946 .reduce, .reduce_optimized => {
907 const reduce = inst_datas[inst].reduce;947 const reduce = inst_datas[inst].reduce;
908 return trackOperands(a, new_set, inst, main_tomb, .{ reduce.operand, .none, .none });948 return trackOperands(a, new_set, inst, main_tomb, .{ reduce.operand, .none, .none });
909 },949 },
910 .cmp_vector => {950 .cmp_vector, .cmp_vector_optimized => {
911 const extra = a.air.extraData(Air.VectorCmp, inst_datas[inst].ty_pl.payload).data;951 const extra = a.air.extraData(Air.VectorCmp, inst_datas[inst].ty_pl.payload).data;
912 return trackOperands(a, new_set, inst, main_tomb, .{ extra.lhs, extra.rhs, .none });952 return trackOperands(a, new_set, inst, main_tomb, .{ extra.lhs, extra.rhs, .none });
913 },953 },
src/Sema.zig+81-61
...@@ -144,6 +144,9 @@ pub const Block = struct {...@@ -144,6 +144,9 @@ pub const Block = struct {
144 /// when null, it is determined by build mode, changed by @setRuntimeSafety144 /// when null, it is determined by build mode, changed by @setRuntimeSafety
145 want_safety: ?bool = null,145 want_safety: ?bool = null,
146146
147 /// What mode to generate float operations in, set by @setFloatMode
148 float_mode: std.builtin.FloatMode = .Strict,
149
147 c_import_buf: ?*std.ArrayList(u8) = null,150 c_import_buf: ?*std.ArrayList(u8) = null,
148151
149 /// type of `err` in `else => |err|`152 /// type of `err` in `else => |err|`
...@@ -206,6 +209,7 @@ pub const Block = struct {...@@ -206,6 +209,7 @@ pub const Block = struct {
206 .runtime_loop = parent.runtime_loop,209 .runtime_loop = parent.runtime_loop,
207 .runtime_index = parent.runtime_index,210 .runtime_index = parent.runtime_index,
208 .want_safety = parent.want_safety,211 .want_safety = parent.want_safety,
212 .float_mode = parent.float_mode,
209 .c_import_buf = parent.c_import_buf,213 .c_import_buf = parent.c_import_buf,
210 .switch_else_err_ty = parent.switch_else_err_ty,214 .switch_else_err_ty = parent.switch_else_err_ty,
211 };215 };
...@@ -414,7 +418,7 @@ pub const Block = struct {...@@ -414,7 +418,7 @@ pub const Block = struct {
414418
415 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 {419 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 {
416 return block.addInst(.{420 return block.addInst(.{
417 .tag = .cmp_vector,421 .tag = if (block.float_mode == .Optimized) .cmp_vector_optimized else .cmp_vector,
418 .data = .{ .ty_pl = .{422 .data = .{ .ty_pl = .{
419 .ty = vector_ty,423 .ty = vector_ty,
420 .payload = try block.sema.addExtra(Air.VectorCmp{424 .payload = try block.sema.addExtra(Air.VectorCmp{
...@@ -714,10 +718,10 @@ fn analyzeBodyInner(...@@ -714,10 +718,10 @@ fn analyzeBodyInner(
714 .closure_get => try sema.zirClosureGet(block, inst),718 .closure_get => try sema.zirClosureGet(block, inst),
715 .cmp_lt => try sema.zirCmp(block, inst, .lt),719 .cmp_lt => try sema.zirCmp(block, inst, .lt),
716 .cmp_lte => try sema.zirCmp(block, inst, .lte),720 .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)),
718 .cmp_gte => try sema.zirCmp(block, inst, .gte),722 .cmp_gte => try sema.zirCmp(block, inst, .gte),
719 .cmp_gt => try sema.zirCmp(block, inst, .gt),723 .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)),
721 .coerce_result_ptr => try sema.zirCoerceResultPtr(block, inst),725 .coerce_result_ptr => try sema.zirCoerceResultPtr(block, inst),
722 .decl_ref => try sema.zirDeclRef(block, inst),726 .decl_ref => try sema.zirDeclRef(block, inst),
723 .decl_val => try sema.zirDeclVal(block, inst),727 .decl_val => try sema.zirDeclVal(block, inst),
...@@ -4705,6 +4709,7 @@ fn zirBlock(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileErro...@@ -4705,6 +4709,7 @@ fn zirBlock(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileErro
4705 .inlining = parent_block.inlining,4709 .inlining = parent_block.inlining,
4706 .is_comptime = parent_block.is_comptime,4710 .is_comptime = parent_block.is_comptime,
4707 .want_safety = parent_block.want_safety,4711 .want_safety = parent_block.want_safety,
4712 .float_mode = parent_block.float_mode,
4708 };4713 };
47094714
4710 defer child_block.instructions.deinit(gpa);4715 defer child_block.instructions.deinit(gpa);
...@@ -5042,13 +5047,7 @@ fn zirSetCold(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!voi...@@ -5042,13 +5047,7 @@ fn zirSetCold(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!voi
5042fn zirSetFloatMode(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!void {5047fn zirSetFloatMode(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!void {
5043 const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;5048 const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;
5044 const src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node };5049 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");5050 block.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 }
5052}5051}
50535052
5054fn zirSetRuntimeSafety(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void {5053fn zirSetRuntimeSafety(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void {
...@@ -8092,7 +8091,7 @@ fn intCast(...@@ -8092,7 +8091,7 @@ fn intCast(
8092 const ok = if (is_vector) ok: {8091 const ok = if (is_vector) ok: {
8093 const is_in_range = try block.addCmpVector(diff_unsigned, dest_range, .lte, try sema.addType(operand_ty));8092 const is_in_range = try block.addCmpVector(diff_unsigned, dest_range, .lte, try sema.addType(operand_ty));
8094 const all_in_range = try block.addInst(.{8093 const all_in_range = try block.addInst(.{
8095 .tag = .reduce,8094 .tag = if (block.float_mode == .Optimized) .reduce_optimized else .reduce,
8096 .data = .{ .reduce = .{8095 .data = .{ .reduce = .{
8097 .operand = is_in_range,8096 .operand = is_in_range,
8098 .operation = .And,8097 .operation = .And,
...@@ -8109,7 +8108,7 @@ fn intCast(...@@ -8109,7 +8108,7 @@ fn intCast(
8109 const ok = if (is_vector) ok: {8108 const ok = if (is_vector) ok: {
8110 const is_in_range = try block.addCmpVector(diff, dest_max, .lte, try sema.addType(operand_ty));8109 const is_in_range = try block.addCmpVector(diff, dest_max, .lte, try sema.addType(operand_ty));
8111 const all_in_range = try block.addInst(.{8110 const all_in_range = try block.addInst(.{
8112 .tag = .reduce,8111 .tag = if (block.float_mode == .Optimized) .reduce_optimized else .reduce,
8113 .data = .{ .reduce = .{8112 .data = .{ .reduce = .{
8114 .operand = is_in_range,8113 .operand = is_in_range,
8115 .operation = .And,8114 .operation = .And,
...@@ -8130,7 +8129,7 @@ fn intCast(...@@ -8130,7 +8129,7 @@ fn intCast(
8130 const zero_inst = try sema.addConstant(operand_ty, zero_val);8129 const zero_inst = try sema.addConstant(operand_ty, zero_val);
8131 const is_in_range = try block.addCmpVector(operand, zero_inst, .gte, try sema.addType(operand_ty));8130 const is_in_range = try block.addCmpVector(operand, zero_inst, .gte, try sema.addType(operand_ty));
8132 const all_in_range = try block.addInst(.{8131 const all_in_range = try block.addInst(.{
8133 .tag = .reduce,8132 .tag = if (block.float_mode == .Optimized) .reduce_optimized else .reduce,
8134 .data = .{ .reduce = .{8133 .data = .{ .reduce = .{
8135 .operand = is_in_range,8134 .operand = is_in_range,
8136 .operation = .And,8135 .operation = .And,
...@@ -9391,7 +9390,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -9391,7 +9390,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
9391 } else {9390 } else {
9392 for (items) |item_ref| {9391 for (items) |item_ref| {
9393 const item = try sema.resolveInst(item_ref);9392 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);
9395 if (any_ok != .none) {9394 if (any_ok != .none) {
9396 any_ok = try case_block.addBinOp(.bool_or, any_ok, cmp_ok);9395 any_ok = try case_block.addBinOp(.bool_or, any_ok, cmp_ok);
9397 } else {9396 } else {
...@@ -9411,12 +9410,12 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -9411,12 +9410,12 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
94119410
9412 // operand >= first and operand <= last9411 // operand >= first and operand <= last
9413 const range_first_ok = try case_block.addBinOp(9412 const range_first_ok = try case_block.addBinOp(
9414 .cmp_gte,9413 if (case_block.float_mode == .Optimized) .cmp_gte_optimized else .cmp_gte,
9415 operand,9414 operand,
9416 item_first,9415 item_first,
9417 );9416 );
9418 const range_last_ok = try case_block.addBinOp(9417 const range_last_ok = try case_block.addBinOp(
9419 .cmp_lte,9418 if (case_block.float_mode == .Optimized) .cmp_lte_optimized else .cmp_lte,
9420 operand,9419 operand,
9421 item_last,9420 item_last,
9422 );9421 );
...@@ -10023,7 +10022,7 @@ fn zirShl(...@@ -10023,7 +10022,7 @@ fn zirShl(
10023 const ov_bit = try sema.tupleFieldValByIndex(block, src, op_ov, 1, op_ov_tuple_ty);10022 const ov_bit = try sema.tupleFieldValByIndex(block, src, op_ov, 1, op_ov_tuple_ty);
10024 const any_ov_bit = if (lhs_ty.zigTypeTag() == .Vector)10023 const any_ov_bit = if (lhs_ty.zigTypeTag() == .Vector)
10025 try block.addInst(.{10024 try block.addInst(.{
10026 .tag = .reduce,10025 .tag = if (block.float_mode == .Optimized) .reduce_optimized else .reduce,
10027 .data = .{ .reduce = .{10026 .data = .{ .reduce = .{
10028 .operand = ov_bit,10027 .operand = ov_bit,
10029 .operation = .Or,10028 .operation = .Or,
...@@ -10120,7 +10119,7 @@ fn zirShr(...@@ -10120,7 +10119,7 @@ fn zirShr(
10120 const ok = if (rhs_ty.zigTypeTag() == .Vector) ok: {10119 const ok = if (rhs_ty.zigTypeTag() == .Vector) ok: {
10121 const eql = try block.addCmpVector(lhs, back, .eq, try sema.addType(rhs_ty));10120 const eql = try block.addCmpVector(lhs, back, .eq, try sema.addType(rhs_ty));
10122 break :ok try block.addInst(.{10121 break :ok try block.addInst(.{
10123 .tag = .reduce,10122 .tag = if (block.float_mode == .Optimized) .reduce_optimized else .reduce,
10124 .data = .{ .reduce = .{10123 .data = .{ .reduce = .{
10125 .operand = eql,10124 .operand = eql,
10126 .operation = .And,10125 .operation = .And,
...@@ -10719,7 +10718,7 @@ fn zirNegate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air....@@ -10719,7 +10718,7 @@ fn zirNegate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
10719 return sema.addConstant(rhs_ty, try rhs_val.floatNeg(rhs_ty, sema.arena, target));10718 return sema.addConstant(rhs_ty, try rhs_val.floatNeg(rhs_ty, sema.arena, target));
10720 }10719 }
10721 try sema.requireRuntimeBlock(block, src, null);10720 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);
10723 }10722 }
1072410723
10725 const lhs = if (rhs_ty.zigTypeTag() == .Vector)10724 const lhs = if (rhs_ty.zigTypeTag() == .Vector)
...@@ -11078,6 +11077,7 @@ fn analyzeArithmetic(...@@ -11078,6 +11077,7 @@ fn analyzeArithmetic(
11078 return casted_lhs;11077 return casted_lhs;
11079 }11078 }
11080 }11079 }
11080 const air_tag: Air.Inst.Tag = if (block.float_mode == .Optimized) .add_optimized else .add;
11081 if (maybe_lhs_val) |lhs_val| {11081 if (maybe_lhs_val) |lhs_val| {
11082 if (lhs_val.isUndef()) {11082 if (lhs_val.isUndef()) {
11083 if (is_int) {11083 if (is_int) {
...@@ -11100,8 +11100,8 @@ fn analyzeArithmetic(...@@ -11100,8 +11100,8 @@ fn analyzeArithmetic(
11100 try sema.floatAdd(lhs_val, rhs_val, resolved_type),11100 try sema.floatAdd(lhs_val, rhs_val, resolved_type),
11101 );11101 );
11102 }11102 }
11103 } else break :rs .{ .src = rhs_src, .air_tag = .add };11103 } else break :rs .{ .src = rhs_src, .air_tag = air_tag };
11104 } else break :rs .{ .src = lhs_src, .air_tag = .add };11104 } else break :rs .{ .src = lhs_src, .air_tag = air_tag };
11105 },11105 },
11106 .addwrap => {11106 .addwrap => {
11107 // Integers only; floats are checked above.11107 // Integers only; floats are checked above.
...@@ -11112,6 +11112,7 @@ fn analyzeArithmetic(...@@ -11112,6 +11112,7 @@ fn analyzeArithmetic(
11112 return casted_rhs;11112 return casted_rhs;
11113 }11113 }
11114 }11114 }
11115 const air_tag: Air.Inst.Tag = if (block.float_mode == .Optimized) .addwrap_optimized else .addwrap;
11115 if (maybe_rhs_val) |rhs_val| {11116 if (maybe_rhs_val) |rhs_val| {
11116 if (rhs_val.isUndef()) {11117 if (rhs_val.isUndef()) {
11117 return sema.addConstUndef(resolved_type);11118 return sema.addConstUndef(resolved_type);
...@@ -11124,8 +11125,8 @@ fn analyzeArithmetic(...@@ -11124,8 +11125,8 @@ fn analyzeArithmetic(
11124 resolved_type,11125 resolved_type,
11125 try sema.numberAddWrap(block, src, lhs_val, rhs_val, resolved_type),11126 try sema.numberAddWrap(block, src, lhs_val, rhs_val, resolved_type),
11126 );11127 );
11127 } else break :rs .{ .src = lhs_src, .air_tag = .addwrap };11128 } else break :rs .{ .src = lhs_src, .air_tag = air_tag };
11128 } else break :rs .{ .src = rhs_src, .air_tag = .addwrap };11129 } else break :rs .{ .src = rhs_src, .air_tag = air_tag };
11129 },11130 },
11130 .add_sat => {11131 .add_sat => {
11131 // Integers only; floats are checked above.11132 // Integers only; floats are checked above.
...@@ -11173,6 +11174,7 @@ fn analyzeArithmetic(...@@ -11173,6 +11174,7 @@ fn analyzeArithmetic(
11173 return casted_lhs;11174 return casted_lhs;
11174 }11175 }
11175 }11176 }
11177 const air_tag: Air.Inst.Tag = if (block.float_mode == .Optimized) .sub_optimized else .sub;
11176 if (maybe_lhs_val) |lhs_val| {11178 if (maybe_lhs_val) |lhs_val| {
11177 if (lhs_val.isUndef()) {11179 if (lhs_val.isUndef()) {
11178 if (is_int) {11180 if (is_int) {
...@@ -11195,8 +11197,8 @@ fn analyzeArithmetic(...@@ -11195,8 +11197,8 @@ fn analyzeArithmetic(
11195 try sema.floatSub(lhs_val, rhs_val, resolved_type),11197 try sema.floatSub(lhs_val, rhs_val, resolved_type),
11196 );11198 );
11197 }11199 }
11198 } else break :rs .{ .src = rhs_src, .air_tag = .sub };11200 } else break :rs .{ .src = rhs_src, .air_tag = air_tag };
11199 } else break :rs .{ .src = lhs_src, .air_tag = .sub };11201 } else break :rs .{ .src = lhs_src, .air_tag = air_tag };
11200 },11202 },
11201 .subwrap => {11203 .subwrap => {
11202 // Integers only; floats are checked above.11204 // Integers only; floats are checked above.
...@@ -11210,6 +11212,7 @@ fn analyzeArithmetic(...@@ -11210,6 +11212,7 @@ fn analyzeArithmetic(
11210 return casted_lhs;11212 return casted_lhs;
11211 }11213 }
11212 }11214 }
11215 const air_tag: Air.Inst.Tag = if (block.float_mode == .Optimized) .subwrap_optimized else .subwrap;
11213 if (maybe_lhs_val) |lhs_val| {11216 if (maybe_lhs_val) |lhs_val| {
11214 if (lhs_val.isUndef()) {11217 if (lhs_val.isUndef()) {
11215 return sema.addConstUndef(resolved_type);11218 return sema.addConstUndef(resolved_type);
...@@ -11219,8 +11222,8 @@ fn analyzeArithmetic(...@@ -11219,8 +11222,8 @@ fn analyzeArithmetic(
11219 resolved_type,11222 resolved_type,
11220 try sema.numberSubWrap(block, src, lhs_val, rhs_val, resolved_type),11223 try sema.numberSubWrap(block, src, lhs_val, rhs_val, resolved_type),
11221 );11224 );
11222 } else break :rs .{ .src = rhs_src, .air_tag = .subwrap };11225 } else break :rs .{ .src = rhs_src, .air_tag = air_tag };
11223 } else break :rs .{ .src = lhs_src, .air_tag = .subwrap };11226 } else break :rs .{ .src = lhs_src, .air_tag = air_tag };
11224 },11227 },
11225 .sub_sat => {11228 .sub_sat => {
11226 // Integers only; floats are checked above.11229 // Integers only; floats are checked above.
...@@ -11327,14 +11330,14 @@ fn analyzeArithmetic(...@@ -11327,14 +11330,14 @@ fn analyzeArithmetic(
11327 if (is_int) {11330 if (is_int) {
11328 break :rs .{ .src = rhs_src, .air_tag = .div_trunc };11331 break :rs .{ .src = rhs_src, .air_tag = .div_trunc };
11329 } else {11332 } 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 };
11331 }11334 }
11332 }11335 }
11333 } else {11336 } else {
11334 if (is_int) {11337 if (is_int) {
11335 break :rs .{ .src = lhs_src, .air_tag = .div_trunc };11338 break :rs .{ .src = lhs_src, .air_tag = .div_trunc };
11336 } else {11339 } 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 };
11338 }11341 }
11339 }11342 }
11340 },11343 },
...@@ -11373,6 +11376,7 @@ fn analyzeArithmetic(...@@ -11373,6 +11376,7 @@ fn analyzeArithmetic(
11373 return sema.failWithDivideByZero(block, rhs_src);11376 return sema.failWithDivideByZero(block, rhs_src);
11374 }11377 }
11375 }11378 }
11379 const air_tag: Air.Inst.Tag = if (block.float_mode == .Optimized) .div_trunc_optimized else .div_trunc;
11376 if (maybe_lhs_val) |lhs_val| {11380 if (maybe_lhs_val) |lhs_val| {
11377 if (lhs_val.isUndef()) {11381 if (lhs_val.isUndef()) {
11378 if (lhs_scalar_ty.isSignedInt() and rhs_scalar_ty.isSignedInt()) {11382 if (lhs_scalar_ty.isSignedInt() and rhs_scalar_ty.isSignedInt()) {
...@@ -11398,8 +11402,8 @@ fn analyzeArithmetic(...@@ -11398,8 +11402,8 @@ fn analyzeArithmetic(
11398 try lhs_val.floatDivTrunc(rhs_val, resolved_type, sema.arena, target),11402 try lhs_val.floatDivTrunc(rhs_val, resolved_type, sema.arena, target),
11399 );11403 );
11400 }11404 }
11401 } else break :rs .{ .src = rhs_src, .air_tag = .div_trunc };11405 } else break :rs .{ .src = rhs_src, .air_tag = air_tag };
11402 } else break :rs .{ .src = lhs_src, .air_tag = .div_trunc };11406 } else break :rs .{ .src = lhs_src, .air_tag = air_tag };
11403 },11407 },
11404 .div_floor => {11408 .div_floor => {
11405 // For integers:11409 // For integers:
...@@ -11436,6 +11440,7 @@ fn analyzeArithmetic(...@@ -11436,6 +11440,7 @@ fn analyzeArithmetic(
11436 return sema.failWithDivideByZero(block, rhs_src);11440 return sema.failWithDivideByZero(block, rhs_src);
11437 }11441 }
11438 }11442 }
11443 const air_tag: Air.Inst.Tag = if (block.float_mode == .Optimized) .div_floor_optimized else .div_floor;
11439 if (maybe_lhs_val) |lhs_val| {11444 if (maybe_lhs_val) |lhs_val| {
11440 if (lhs_val.isUndef()) {11445 if (lhs_val.isUndef()) {
11441 if (lhs_scalar_ty.isSignedInt() and rhs_scalar_ty.isSignedInt()) {11446 if (lhs_scalar_ty.isSignedInt() and rhs_scalar_ty.isSignedInt()) {
...@@ -11461,8 +11466,8 @@ fn analyzeArithmetic(...@@ -11461,8 +11466,8 @@ fn analyzeArithmetic(
11461 try lhs_val.floatDivFloor(rhs_val, resolved_type, sema.arena, target),11466 try lhs_val.floatDivFloor(rhs_val, resolved_type, sema.arena, target),
11462 );11467 );
11463 }11468 }
11464 } else break :rs .{ .src = rhs_src, .air_tag = .div_floor };11469 } else break :rs .{ .src = rhs_src, .air_tag = air_tag };
11465 } else break :rs .{ .src = lhs_src, .air_tag = .div_floor };11470 } else break :rs .{ .src = lhs_src, .air_tag = air_tag };
11466 },11471 },
11467 .div_exact => {11472 .div_exact => {
11468 // For integers:11473 // For integers:
...@@ -11498,6 +11503,7 @@ fn analyzeArithmetic(...@@ -11498,6 +11503,7 @@ fn analyzeArithmetic(
11498 return sema.failWithDivideByZero(block, rhs_src);11503 return sema.failWithDivideByZero(block, rhs_src);
11499 }11504 }
11500 }11505 }
11506 const air_tag: Air.Inst.Tag = if (block.float_mode == .Optimized) .div_exact_optimized else .div_exact;
11501 if (maybe_lhs_val) |lhs_val| {11507 if (maybe_lhs_val) |lhs_val| {
11502 if (maybe_rhs_val) |rhs_val| {11508 if (maybe_rhs_val) |rhs_val| {
11503 if (is_int) {11509 if (is_int) {
...@@ -11513,8 +11519,8 @@ fn analyzeArithmetic(...@@ -11513,8 +11519,8 @@ fn analyzeArithmetic(
11513 try lhs_val.floatDiv(rhs_val, resolved_type, sema.arena, target),11519 try lhs_val.floatDiv(rhs_val, resolved_type, sema.arena, target),
11514 );11520 );
11515 }11521 }
11516 } else break :rs .{ .src = rhs_src, .air_tag = .div_exact };11522 } else break :rs .{ .src = rhs_src, .air_tag = air_tag };
11517 } else break :rs .{ .src = lhs_src, .air_tag = .div_exact };11523 } else break :rs .{ .src = lhs_src, .air_tag = air_tag };
11518 },11524 },
11519 .mul => {11525 .mul => {
11520 // For integers:11526 // For integers:
...@@ -11535,6 +11541,7 @@ fn analyzeArithmetic(...@@ -11535,6 +11541,7 @@ fn analyzeArithmetic(
11535 }11541 }
11536 }11542 }
11537 }11543 }
11544 const air_tag: Air.Inst.Tag = if (block.float_mode == .Optimized) .mul_optimized else .mul;
11538 if (maybe_rhs_val) |rhs_val| {11545 if (maybe_rhs_val) |rhs_val| {
11539 if (rhs_val.isUndef()) {11546 if (rhs_val.isUndef()) {
11540 if (is_int) {11547 if (is_int) {
...@@ -11570,8 +11577,8 @@ fn analyzeArithmetic(...@@ -11570,8 +11577,8 @@ fn analyzeArithmetic(
11570 try lhs_val.floatMul(rhs_val, resolved_type, sema.arena, target),11577 try lhs_val.floatMul(rhs_val, resolved_type, sema.arena, target),
11571 );11578 );
11572 }11579 }
11573 } else break :rs .{ .src = lhs_src, .air_tag = .mul };11580 } else break :rs .{ .src = lhs_src, .air_tag = air_tag };
11574 } else break :rs .{ .src = rhs_src, .air_tag = .mul };11581 } else break :rs .{ .src = rhs_src, .air_tag = air_tag };
11575 },11582 },
11576 .mulwrap => {11583 .mulwrap => {
11577 // Integers only; floats are handled above.11584 // Integers only; floats are handled above.
...@@ -11588,6 +11595,7 @@ fn analyzeArithmetic(...@@ -11588,6 +11595,7 @@ fn analyzeArithmetic(
11588 }11595 }
11589 }11596 }
11590 }11597 }
11598 const air_tag: Air.Inst.Tag = if (block.float_mode == .Optimized) .mulwrap_optimized else .mulwrap;
11591 if (maybe_rhs_val) |rhs_val| {11599 if (maybe_rhs_val) |rhs_val| {
11592 if (rhs_val.isUndef()) {11600 if (rhs_val.isUndef()) {
11593 return sema.addConstUndef(resolved_type);11601 return sema.addConstUndef(resolved_type);
...@@ -11606,8 +11614,8 @@ fn analyzeArithmetic(...@@ -11606,8 +11614,8 @@ fn analyzeArithmetic(
11606 resolved_type,11614 resolved_type,
11607 try lhs_val.numberMulWrap(rhs_val, resolved_type, sema.arena, target),11615 try lhs_val.numberMulWrap(rhs_val, resolved_type, sema.arena, target),
11608 );11616 );
11609 } else break :rs .{ .src = lhs_src, .air_tag = .mulwrap };11617 } else break :rs .{ .src = lhs_src, .air_tag = air_tag };
11610 } else break :rs .{ .src = rhs_src, .air_tag = .mulwrap };11618 } else break :rs .{ .src = rhs_src, .air_tag = air_tag };
11611 },11619 },
11612 .mul_sat => {11620 .mul_sat => {
11613 // Integers only; floats are checked above.11621 // Integers only; floats are checked above.
...@@ -11777,6 +11785,7 @@ fn analyzeArithmetic(...@@ -11777,6 +11785,7 @@ fn analyzeArithmetic(
11777 return sema.failWithDivideByZero(block, rhs_src);11785 return sema.failWithDivideByZero(block, rhs_src);
11778 }11786 }
11779 }11787 }
11788 const air_tag: Air.Inst.Tag = if (block.float_mode == .Optimized) .rem_optimized else .rem;
11780 if (maybe_lhs_val) |lhs_val| {11789 if (maybe_lhs_val) |lhs_val| {
11781 if (lhs_val.isUndef()) {11790 if (lhs_val.isUndef()) {
11782 return sema.addConstUndef(resolved_type);11791 return sema.addConstUndef(resolved_type);
...@@ -11786,8 +11795,8 @@ fn analyzeArithmetic(...@@ -11786,8 +11795,8 @@ fn analyzeArithmetic(
11786 resolved_type,11795 resolved_type,
11787 try lhs_val.floatRem(rhs_val, resolved_type, sema.arena, target),11796 try lhs_val.floatRem(rhs_val, resolved_type, sema.arena, target),
11788 );11797 );
11789 } else break :rs .{ .src = rhs_src, .air_tag = .rem };11798 } else break :rs .{ .src = rhs_src, .air_tag = air_tag };
11790 } else break :rs .{ .src = lhs_src, .air_tag = .rem };11799 } else break :rs .{ .src = lhs_src, .air_tag = air_tag };
11791 },11800 },
11792 .mod => {11801 .mod => {
11793 // For integers:11802 // For integers:
...@@ -11834,6 +11843,7 @@ fn analyzeArithmetic(...@@ -11834,6 +11843,7 @@ fn analyzeArithmetic(
11834 return sema.failWithDivideByZero(block, rhs_src);11843 return sema.failWithDivideByZero(block, rhs_src);
11835 }11844 }
11836 }11845 }
11846 const air_tag: Air.Inst.Tag = if (block.float_mode == .Optimized) .mod_optimized else .mod;
11837 if (maybe_lhs_val) |lhs_val| {11847 if (maybe_lhs_val) |lhs_val| {
11838 if (lhs_val.isUndef()) {11848 if (lhs_val.isUndef()) {
11839 return sema.addConstUndef(resolved_type);11849 return sema.addConstUndef(resolved_type);
...@@ -11843,8 +11853,8 @@ fn analyzeArithmetic(...@@ -11843,8 +11853,8 @@ fn analyzeArithmetic(
11843 resolved_type,11853 resolved_type,
11844 try lhs_val.floatMod(rhs_val, resolved_type, sema.arena, target),11854 try lhs_val.floatMod(rhs_val, resolved_type, sema.arena, target),
11845 );11855 );
11846 } else break :rs .{ .src = rhs_src, .air_tag = .mod };11856 } else break :rs .{ .src = rhs_src, .air_tag = air_tag };
11847 } else break :rs .{ .src = lhs_src, .air_tag = .mod };11857 } else break :rs .{ .src = lhs_src, .air_tag = air_tag };
11848 },11858 },
11849 else => unreachable,11859 else => unreachable,
11850 }11860 }
...@@ -11874,7 +11884,7 @@ fn analyzeArithmetic(...@@ -11874,7 +11884,7 @@ fn analyzeArithmetic(
11874 const ov_bit = try sema.tupleFieldValByIndex(block, src, op_ov, 1, op_ov_tuple_ty);11884 const ov_bit = try sema.tupleFieldValByIndex(block, src, op_ov, 1, op_ov_tuple_ty);
11875 const any_ov_bit = if (resolved_type.zigTypeTag() == .Vector)11885 const any_ov_bit = if (resolved_type.zigTypeTag() == .Vector)
11876 try block.addInst(.{11886 try block.addInst(.{
11877 .tag = .reduce,11887 .tag = if (block.float_mode == .Optimized) .reduce_optimized else .reduce,
11878 .data = .{ .reduce = .{11888 .data = .{ .reduce = .{
11879 .operand = ov_bit,11889 .operand = ov_bit,
11880 .operation = .Or,11890 .operation = .Or,
...@@ -11890,13 +11900,17 @@ fn analyzeArithmetic(...@@ -11890,13 +11900,17 @@ fn analyzeArithmetic(
11890 }11900 }
11891 }11901 }
11892 switch (rs.air_tag) {11902 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) {
11894 const ok = if (resolved_type.zigTypeTag() == .Vector) ok: {11908 const ok = if (resolved_type.zigTypeTag() == .Vector) ok: {
11895 const zero_val = try Value.Tag.repeated.create(sema.arena, Value.zero);11909 const zero_val = try Value.Tag.repeated.create(sema.arena, Value.zero);
11896 const zero = try sema.addConstant(sema.typeOf(casted_rhs), zero_val);11910 const zero = try sema.addConstant(sema.typeOf(casted_rhs), zero_val);
11897 const ok = try block.addCmpVector(casted_rhs, zero, .neq, try sema.addType(resolved_type));11911 const ok = try block.addCmpVector(casted_rhs, zero, .neq, try sema.addType(resolved_type));
11898 break :ok try block.addInst(.{11912 break :ok try block.addInst(.{
11899 .tag = .reduce,11913 .tag = if (block.float_mode == .Optimized) .reduce_optimized else .reduce,
11900 .data = .{ .reduce = .{11914 .data = .{ .reduce = .{
11901 .operand = ok,11915 .operand = ok,
11902 .operation = .And,11916 .operation = .And,
...@@ -11904,17 +11918,17 @@ fn analyzeArithmetic(...@@ -11904,17 +11918,17 @@ fn analyzeArithmetic(
11904 });11918 });
11905 } else ok: {11919 } else ok: {
11906 const zero = try sema.addConstant(sema.typeOf(casted_rhs), Value.zero);11920 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);
11908 };11922 };
11909 try sema.addSafetyCheck(block, ok, .divide_by_zero);11923 try sema.addSafetyCheck(block, ok, .divide_by_zero);
11910 },11924 },
11911 .rem, .mod => {11925 .rem, .mod, .rem_optimized, .mod_optimized => {
11912 const ok = if (resolved_type.zigTypeTag() == .Vector) ok: {11926 const ok = if (resolved_type.zigTypeTag() == .Vector) ok: {
11913 const zero_val = try Value.Tag.repeated.create(sema.arena, Value.zero);11927 const zero_val = try Value.Tag.repeated.create(sema.arena, Value.zero);
11914 const zero = try sema.addConstant(sema.typeOf(casted_rhs), zero_val);11928 const zero = try sema.addConstant(sema.typeOf(casted_rhs), zero_val);
11915 const ok = try block.addCmpVector(casted_rhs, zero, if (scalar_tag == .Int) .gt else .neq, try sema.addType(resolved_type));11929 const ok = try block.addCmpVector(casted_rhs, zero, if (scalar_tag == .Int) .gt else .neq, try sema.addType(resolved_type));
11916 break :ok try block.addInst(.{11930 break :ok try block.addInst(.{
11917 .tag = .reduce,11931 .tag = if (block.float_mode == .Optimized) .reduce_optimized else .reduce,
11918 .data = .{ .reduce = .{11932 .data = .{ .reduce = .{
11919 .operand = ok,11933 .operand = ok,
11920 .operation = .And,11934 .operation = .And,
...@@ -11922,13 +11936,19 @@ fn analyzeArithmetic(...@@ -11922,13 +11936,19 @@ fn analyzeArithmetic(
11922 });11936 });
11923 } else ok: {11937 } else ok: {
11924 const zero = try sema.addConstant(sema.typeOf(casted_rhs), Value.zero);11938 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);
11926 };11946 };
11927 try sema.addSafetyCheck(block, ok, .remainder_division_zero_negative);11947 try sema.addSafetyCheck(block, ok, .remainder_division_zero_negative);
11928 },11948 },
11929 else => {},11949 else => {},
11930 }11950 }
11931 if (rs.air_tag == .div_exact) {11951 if (rs.air_tag == .div_exact or rs.air_tag == .div_exact_optimized) {
11932 const result = try block.addBinOp(.div_exact, casted_lhs, casted_rhs);11952 const result = try block.addBinOp(.div_exact, casted_lhs, casted_rhs);
11933 const ok = if (scalar_tag == .Float) ok: {11953 const ok = if (scalar_tag == .Float) ok: {
11934 const floored = try block.addUnOp(.floor, result);11954 const floored = try block.addUnOp(.floor, result);
...@@ -11936,14 +11956,14 @@ fn analyzeArithmetic(...@@ -11936,14 +11956,14 @@ fn analyzeArithmetic(
11936 if (resolved_type.zigTypeTag() == .Vector) {11956 if (resolved_type.zigTypeTag() == .Vector) {
11937 const eql = try block.addCmpVector(result, floored, .eq, try sema.addType(resolved_type));11957 const eql = try block.addCmpVector(result, floored, .eq, try sema.addType(resolved_type));
11938 break :ok try block.addInst(.{11958 break :ok try block.addInst(.{
11939 .tag = .reduce,11959 .tag = if (block.float_mode == .Optimized) .reduce_optimized else .reduce,
11940 .data = .{ .reduce = .{11960 .data = .{ .reduce = .{
11941 .operand = eql,11961 .operand = eql,
11942 .operation = .And,11962 .operation = .And,
11943 } },11963 } },
11944 });11964 });
11945 } else {11965 } 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);
11947 break :ok is_in_range;11967 break :ok is_in_range;
11948 }11968 }
11949 } else ok: {11969 } else ok: {
...@@ -11962,7 +11982,7 @@ fn analyzeArithmetic(...@@ -11962,7 +11982,7 @@ fn analyzeArithmetic(
11962 });11982 });
11963 } else {11983 } else {
11964 const zero = try sema.addConstant(sema.typeOf(casted_rhs), Value.zero);11984 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);
11966 break :ok is_in_range;11986 break :ok is_in_range;
11967 }11987 }
11968 };11988 };
...@@ -12476,7 +12496,7 @@ fn cmpSelf(...@@ -12476,7 +12496,7 @@ fn cmpSelf(
12476 const result_ty_ref = try sema.addType(result_ty);12496 const result_ty_ref = try sema.addType(result_ty);
12477 return block.addCmpVector(casted_lhs, casted_rhs, op, result_ty_ref);12497 return block.addCmpVector(casted_lhs, casted_rhs, op, result_ty_ref);
12478 }12498 }
12479 const tag = Air.Inst.Tag.fromCmpOp(op);12499 const tag = Air.Inst.Tag.fromCmpOp(op, block.float_mode == .Optimized);
12480 return block.addBinOp(tag, casted_lhs, casted_rhs);12500 return block.addBinOp(tag, casted_lhs, casted_rhs);
12481}12501}
1248212502
...@@ -15954,12 +15974,12 @@ fn zirFloatToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!...@@ -15954,12 +15974,12 @@ fn zirFloatToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
15954 }15974 }
1595515975
15956 try sema.requireRuntimeBlock(block, inst_data.src(), operand_src);15976 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);
15958 if (block.wantSafety()) {15978 if (block.wantSafety()) {
15959 const back = try block.addTyOp(.int_to_float, operand_ty, result);15979 const back = try block.addTyOp(.int_to_float, operand_ty, result);
15960 const diff = try block.addBinOp(.sub, operand, back);15980 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));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));
15962 const ok_neg = try block.addBinOp(.cmp_gt, diff, try sema.addConstant(operand_ty, Value.negative_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));
15963 const ok = try block.addBinOp(.bool_and, ok_pos, ok_neg);15983 const ok = try block.addBinOp(.bool_and, ok_pos, ok_neg);
15964 try sema.addSafetyCheck(block, ok, .integer_part_out_of_bounds);15984 try sema.addSafetyCheck(block, ok, .integer_part_out_of_bounds);
15965 }15985 }
...@@ -17194,7 +17214,7 @@ fn zirReduce(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air....@@ -17194,7 +17214,7 @@ fn zirReduce(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
1719417214
17195 try sema.requireRuntimeBlock(block, inst_data.src(), operand_src);17215 try sema.requireRuntimeBlock(block, inst_data.src(), operand_src);
17196 return block.addInst(.{17216 return block.addInst(.{
17197 .tag = .reduce,17217 .tag = if (block.float_mode == .Optimized) .reduce_optimized else .reduce,
17198 .data = .{ .reduce = .{17218 .data = .{ .reduce = .{
17199 .operand = operand,17219 .operand = operand,
17200 .operation = operation,17220 .operation = operation,
...@@ -24489,7 +24509,7 @@ fn cmpNumeric(...@@ -24489,7 +24509,7 @@ fn cmpNumeric(
24489 };24509 };
24490 const casted_lhs = try sema.coerce(block, dest_ty, lhs, lhs_src);24510 const casted_lhs = try sema.coerce(block, dest_ty, lhs, lhs_src);
24491 const casted_rhs = try sema.coerce(block, dest_ty, rhs, rhs_src);24511 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);
24493 }24513 }
24494 // For mixed unsigned integer sizes, implicit cast both operands to the larger integer.24514 // For mixed unsigned integer sizes, implicit cast both operands to the larger integer.
24495 // For mixed signed and unsigned integers, implicit cast both operands to a signed24515 // For mixed signed and unsigned integers, implicit cast both operands to a signed
...@@ -24610,7 +24630,7 @@ fn cmpNumeric(...@@ -24610,7 +24630,7 @@ fn cmpNumeric(
24610 const casted_lhs = try sema.coerce(block, dest_ty, lhs, lhs_src);24630 const casted_lhs = try sema.coerce(block, dest_ty, lhs, lhs_src);
24611 const casted_rhs = try sema.coerce(block, dest_ty, rhs, rhs_src);24631 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);
24614}24634}
2461524635
24616/// Asserts that lhs and rhs types are both vectors.24636/// 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 {...@@ -729,6 +729,30 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
729 .wrap_errunion_payload => try self.airWrapErrUnionPayload(inst),729 .wrap_errunion_payload => try self.airWrapErrUnionPayload(inst),
730 .wrap_errunion_err => try self.airWrapErrUnionErr(inst),730 .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
732 .wasm_memory_size => unreachable,756 .wasm_memory_size => unreachable,
733 .wasm_memory_grow => unreachable,757 .wasm_memory_grow => unreachable,
734 // zig fmt: on758 // zig fmt: on
src/arch/arm/CodeGen.zig+24
...@@ -744,6 +744,30 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -744,6 +744,30 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
744 .wrap_errunion_payload => try self.airWrapErrUnionPayload(inst),744 .wrap_errunion_payload => try self.airWrapErrUnionPayload(inst),
745 .wrap_errunion_err => try self.airWrapErrUnionErr(inst),745 .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
747 .wasm_memory_size => unreachable,771 .wasm_memory_size => unreachable,
748 .wasm_memory_grow => unreachable,772 .wasm_memory_grow => unreachable,
749 // zig fmt: on773 // zig fmt: on
src/arch/riscv64/CodeGen.zig+24
...@@ -669,6 +669,30 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -669,6 +669,30 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
669 .wrap_errunion_payload => try self.airWrapErrUnionPayload(inst),669 .wrap_errunion_payload => try self.airWrapErrUnionPayload(inst),
670 .wrap_errunion_err => try self.airWrapErrUnionErr(inst),670 .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
672 .wasm_memory_size => unreachable,696 .wasm_memory_size => unreachable,
673 .wasm_memory_grow => unreachable,697 .wasm_memory_grow => unreachable,
674 // zig fmt: on698 // zig fmt: on
src/arch/sparc64/CodeGen.zig+24
...@@ -681,6 +681,30 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -681,6 +681,30 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
681 .wrap_errunion_payload => @panic("TODO try self.airWrapErrUnionPayload(inst)"),681 .wrap_errunion_payload => @panic("TODO try self.airWrapErrUnionPayload(inst)"),
682 .wrap_errunion_err => try self.airWrapErrUnionErr(inst),682 .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
684 .wasm_memory_size => unreachable,708 .wasm_memory_size => unreachable,
685 .wasm_memory_grow => unreachable,709 .wasm_memory_grow => unreachable,
686 // zig fmt: on710 // zig fmt: on
src/arch/wasm/CodeGen.zig+24
...@@ -1622,6 +1622,30 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue {...@@ -1622,6 +1622,30 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue {
1622 .err_return_trace,1622 .err_return_trace,
1623 .set_err_return_trace,1623 .set_err_return_trace,
1624 => |tag| return self.fail("TODO: Implement wasm inst: {s}", .{@tagName(tag)}),1624 => |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", .{}),
1625 };1649 };
1626}1650}
16271651
src/arch/x86_64/CodeGen.zig+24
...@@ -751,6 +751,30 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -751,6 +751,30 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
751 .wrap_errunion_payload => try self.airWrapErrUnionPayload(inst),751 .wrap_errunion_payload => try self.airWrapErrUnionPayload(inst),
752 .wrap_errunion_err => try self.airWrapErrUnionErr(inst),752 .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
754 .wasm_memory_size => unreachable,778 .wasm_memory_size => unreachable,
755 .wasm_memory_grow => unreachable,779 .wasm_memory_grow => unreachable,
756 // zig fmt: on780 // zig fmt: on
src/codegen/c.zig+24
...@@ -1928,6 +1928,30 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO...@@ -1928,6 +1928,30 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
19281928
1929 .wasm_memory_size => try airWasmMemorySize(f, inst),1929 .wasm_memory_size => try airWasmMemorySize(f, inst),
1930 .wasm_memory_grow => try airWasmMemoryGrow(f, inst),1930 .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", .{}),
1931 // zig fmt: on1955 // zig fmt: on
1932 };1956 };
1933 switch (result_value) {1957 switch (result_value) {
src/codegen/llvm.zig+95-40
...@@ -3984,21 +3984,21 @@ pub const FuncGen = struct {...@@ -3984,21 +3984,21 @@ pub const FuncGen = struct {
3984 for (body) |inst, i| {3984 for (body) |inst, i| {
3985 const opt_value: ?*const llvm.Value = switch (air_tags[inst]) {3985 const opt_value: ?*const llvm.Value = switch (air_tags[inst]) {
3986 // zig fmt: off3986 // zig fmt: off
3987 .add => try self.airAdd(inst),3987 .add => try self.airAdd(inst, false),
3988 .addwrap => try self.airAddWrap(inst),3988 .addwrap => try self.airAddWrap(inst, false),
3989 .add_sat => try self.airAddSat(inst),3989 .add_sat => try self.airAddSat(inst),
3990 .sub => try self.airSub(inst),3990 .sub => try self.airSub(inst, false),
3991 .subwrap => try self.airSubWrap(inst),3991 .subwrap => try self.airSubWrap(inst, false),
3992 .sub_sat => try self.airSubSat(inst),3992 .sub_sat => try self.airSubSat(inst),
3993 .mul => try self.airMul(inst),3993 .mul => try self.airMul(inst, false),
3994 .mulwrap => try self.airMulWrap(inst),3994 .mulwrap => try self.airMulWrap(inst, false),
3995 .mul_sat => try self.airMulSat(inst),3995 .mul_sat => try self.airMulSat(inst),
3996 .div_float => try self.airDivFloat(inst),3996 .div_float => try self.airDivFloat(inst, false),
3997 .div_trunc => try self.airDivTrunc(inst),3997 .div_trunc => try self.airDivTrunc(inst, false),
3998 .div_floor => try self.airDivFloor(inst),3998 .div_floor => try self.airDivFloor(inst, false),
3999 .div_exact => try self.airDivExact(inst),3999 .div_exact => try self.airDivExact(inst, false),
4000 .rem => try self.airRem(inst),4000 .rem => try self.airRem(inst, false),
4001 .mod => try self.airMod(inst),4001 .mod => try self.airMod(inst, false),
4002 .ptr_add => try self.airPtrAdd(inst),4002 .ptr_add => try self.airPtrAdd(inst),
4003 .ptr_sub => try self.airPtrSub(inst),4003 .ptr_sub => try self.airPtrSub(inst),
4004 .shl => try self.airShl(inst),4004 .shl => try self.airShl(inst),
...@@ -4009,6 +4009,19 @@ pub const FuncGen = struct {...@@ -4009,6 +4009,19 @@ pub const FuncGen = struct {
4009 .slice => try self.airSlice(inst),4009 .slice => try self.airSlice(inst),
4010 .mul_add => try self.airMulAdd(inst),4010 .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
4012 .add_with_overflow => try self.airOverflow(inst, "llvm.sadd.with.overflow", "llvm.uadd.with.overflow"),4025 .add_with_overflow => try self.airOverflow(inst, "llvm.sadd.with.overflow", "llvm.uadd.with.overflow"),
4013 .sub_with_overflow => try self.airOverflow(inst, "llvm.ssub.with.overflow", "llvm.usub.with.overflow"),4026 .sub_with_overflow => try self.airOverflow(inst, "llvm.ssub.with.overflow", "llvm.usub.with.overflow"),
4014 .mul_with_overflow => try self.airOverflow(inst, "llvm.smul.with.overflow", "llvm.umul.with.overflow"),4027 .mul_with_overflow => try self.airOverflow(inst, "llvm.smul.with.overflow", "llvm.umul.with.overflow"),
...@@ -4034,17 +4047,27 @@ pub const FuncGen = struct {...@@ -4034,17 +4047,27 @@ pub const FuncGen = struct {
4034 .ceil => try self.airUnaryOp(inst, .ceil),4047 .ceil => try self.airUnaryOp(inst, .ceil),
4035 .round => try self.airUnaryOp(inst, .round),4048 .round => try self.airUnaryOp(inst, .round),
4036 .trunc_float => try self.airUnaryOp(inst, .trunc),4049 .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),4051 .neg => try self.airNeg(inst, false),
4047 .cmp_lt_errors_len => try self.airCmpLtErrorsLen(inst),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
4049 .is_non_null => try self.airIsNonNull(inst, false, .NE),4072 .is_non_null => try self.airIsNonNull(inst, false, .NE),
4050 .is_non_null_ptr => try self.airIsNonNull(inst, true , .NE),4073 .is_non_null_ptr => try self.airIsNonNull(inst, true , .NE),
...@@ -4093,8 +4116,10 @@ pub const FuncGen = struct {...@@ -4093,8 +4116,10 @@ pub const FuncGen = struct {
4093 .ptr_slice_ptr_ptr => try self.airPtrSliceFieldPtr(inst, 0),4116 .ptr_slice_ptr_ptr => try self.airPtrSliceFieldPtr(inst, 0),
4094 .ptr_slice_len_ptr => try self.airPtrSliceFieldPtr(inst, 1),4117 .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
4096 .array_to_slice => try self.airArrayToSlice(inst),4122 .array_to_slice => try self.airArrayToSlice(inst),
4097 .float_to_int => try self.airFloatToInt(inst),
4098 .int_to_float => try self.airIntToFloat(inst),4123 .int_to_float => try self.airIntToFloat(inst),
4099 .cmpxchg_weak => try self.airCmpxchg(inst, true),4124 .cmpxchg_weak => try self.airCmpxchg(inst, true),
4100 .cmpxchg_strong => try self.airCmpxchg(inst, false),4125 .cmpxchg_strong => try self.airCmpxchg(inst, false),
...@@ -4115,11 +4140,13 @@ pub const FuncGen = struct {...@@ -4115,11 +4140,13 @@ pub const FuncGen = struct {
4115 .splat => try self.airSplat(inst),4140 .splat => try self.airSplat(inst),
4116 .select => try self.airSelect(inst),4141 .select => try self.airSelect(inst),
4117 .shuffle => try self.airShuffle(inst),4142 .shuffle => try self.airShuffle(inst),
4118 .reduce => try self.airReduce(inst),
4119 .aggregate_init => try self.airAggregateInit(inst),4143 .aggregate_init => try self.airAggregateInit(inst),
4120 .union_init => try self.airUnionInit(inst),4144 .union_init => try self.airUnionInit(inst),
4121 .prefetch => try self.airPrefetch(inst),4145 .prefetch => try self.airPrefetch(inst),
41224146
4147 .reduce => try self.airReduce(inst, false),
4148 .reduce_optimized => try self.airReduce(inst, true),
4149
4123 .atomic_store_unordered => try self.airAtomicStore(inst, .Unordered),4150 .atomic_store_unordered => try self.airAtomicStore(inst, .Unordered),
4124 .atomic_store_monotonic => try self.airAtomicStore(inst, .Monotonic),4151 .atomic_store_monotonic => try self.airAtomicStore(inst, .Monotonic),
4125 .atomic_store_release => try self.airAtomicStore(inst, .Release),4152 .atomic_store_release => try self.airAtomicStore(inst, .Release),
...@@ -4485,8 +4512,9 @@ pub const FuncGen = struct {...@@ -4485,8 +4512,9 @@ pub const FuncGen = struct {
4485 return null;4512 return null;
4486 }4513 }
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 {
4489 if (self.liveness.isUnused(inst)) return null;4516 if (self.liveness.isUnused(inst)) return null;
4517 self.builder.setFastMath(want_fast_math);
44904518
4491 const bin_op = self.air.instructions.items(.data)[inst].bin_op;4519 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
4492 const lhs = try self.resolveInst(bin_op.lhs);4520 const lhs = try self.resolveInst(bin_op.lhs);
...@@ -4496,8 +4524,9 @@ pub const FuncGen = struct {...@@ -4496,8 +4524,9 @@ pub const FuncGen = struct {
4496 return self.cmp(lhs, rhs, operand_ty, op);4524 return self.cmp(lhs, rhs, operand_ty, op);
4497 }4525 }
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 {
4500 if (self.liveness.isUnused(inst)) return null;4528 if (self.liveness.isUnused(inst)) return null;
4529 self.builder.setFastMath(want_fast_math);
45014530
4502 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;4531 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
4503 const extra = self.air.extraData(Air.VectorCmp, ty_pl.payload).data;4532 const extra = self.air.extraData(Air.VectorCmp, ty_pl.payload).data;
...@@ -4943,10 +4972,12 @@ pub const FuncGen = struct {...@@ -4943,10 +4972,12 @@ pub const FuncGen = struct {
4943 return self.builder.buildCall(libc_fn, &params, params.len, .C, .Auto, "");4972 return self.builder.buildCall(libc_fn, &params, params.len, .C, .Auto, "");
4944 }4973 }
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 {
4947 if (self.liveness.isUnused(inst))4976 if (self.liveness.isUnused(inst))
4948 return null;4977 return null;
49494978
4979 self.builder.setFastMath(want_fast_math);
4980
4950 const target = self.dg.module.getTarget();4981 const target = self.dg.module.getTarget();
4951 const ty_op = self.air.instructions.items(.data)[inst].ty_op;4982 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
49524983
...@@ -6095,8 +6126,9 @@ pub const FuncGen = struct {...@@ -6095,8 +6126,9 @@ pub const FuncGen = struct {
6095 return self.builder.buildInsertValue(partial, len, 1, "");6126 return self.builder.buildInsertValue(partial, len, 1, "");
6096 }6127 }
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 {
6099 if (self.liveness.isUnused(inst)) return null;6130 if (self.liveness.isUnused(inst)) return null;
6131 self.builder.setFastMath(want_fast_math);
61006132
6101 const bin_op = self.air.instructions.items(.data)[inst].bin_op;6133 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
6102 const lhs = try self.resolveInst(bin_op.lhs);6134 const lhs = try self.resolveInst(bin_op.lhs);
...@@ -6109,8 +6141,9 @@ pub const FuncGen = struct {...@@ -6109,8 +6141,9 @@ pub const FuncGen = struct {
6109 return self.builder.buildNUWAdd(lhs, rhs, "");6141 return self.builder.buildNUWAdd(lhs, rhs, "");
6110 }6142 }
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 {
6113 if (self.liveness.isUnused(inst)) return null;6145 if (self.liveness.isUnused(inst)) return null;
6146 self.builder.setFastMath(want_fast_math);
61146147
6115 const bin_op = self.air.instructions.items(.data)[inst].bin_op;6148 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
6116 const lhs = try self.resolveInst(bin_op.lhs);6149 const lhs = try self.resolveInst(bin_op.lhs);
...@@ -6134,8 +6167,9 @@ pub const FuncGen = struct {...@@ -6134,8 +6167,9 @@ pub const FuncGen = struct {
6134 return self.builder.buildUAddSat(lhs, rhs, "");6167 return self.builder.buildUAddSat(lhs, rhs, "");
6135 }6168 }
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 {
6138 if (self.liveness.isUnused(inst)) return null;6171 if (self.liveness.isUnused(inst)) return null;
6172 self.builder.setFastMath(want_fast_math);
61396173
6140 const bin_op = self.air.instructions.items(.data)[inst].bin_op;6174 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
6141 const lhs = try self.resolveInst(bin_op.lhs);6175 const lhs = try self.resolveInst(bin_op.lhs);
...@@ -6148,8 +6182,9 @@ pub const FuncGen = struct {...@@ -6148,8 +6182,9 @@ pub const FuncGen = struct {
6148 return self.builder.buildNUWSub(lhs, rhs, "");6182 return self.builder.buildNUWSub(lhs, rhs, "");
6149 }6183 }
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 {
6152 if (self.liveness.isUnused(inst)) return null;6186 if (self.liveness.isUnused(inst)) return null;
6187 self.builder.setFastMath(want_fast_math);
61536188
6154 const bin_op = self.air.instructions.items(.data)[inst].bin_op;6189 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
6155 const lhs = try self.resolveInst(bin_op.lhs);6190 const lhs = try self.resolveInst(bin_op.lhs);
...@@ -6172,8 +6207,9 @@ pub const FuncGen = struct {...@@ -6172,8 +6207,9 @@ pub const FuncGen = struct {
6172 return self.builder.buildUSubSat(lhs, rhs, "");6207 return self.builder.buildUSubSat(lhs, rhs, "");
6173 }6208 }
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 {
6176 if (self.liveness.isUnused(inst)) return null;6211 if (self.liveness.isUnused(inst)) return null;
6212 self.builder.setFastMath(want_fast_math);
61776213
6178 const bin_op = self.air.instructions.items(.data)[inst].bin_op;6214 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
6179 const lhs = try self.resolveInst(bin_op.lhs);6215 const lhs = try self.resolveInst(bin_op.lhs);
...@@ -6186,8 +6222,9 @@ pub const FuncGen = struct {...@@ -6186,8 +6222,9 @@ pub const FuncGen = struct {
6186 return self.builder.buildNUWMul(lhs, rhs, "");6222 return self.builder.buildNUWMul(lhs, rhs, "");
6187 }6223 }
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 {
6190 if (self.liveness.isUnused(inst)) return null;6226 if (self.liveness.isUnused(inst)) return null;
6227 self.builder.setFastMath(want_fast_math);
61916228
6192 const bin_op = self.air.instructions.items(.data)[inst].bin_op;6229 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
6193 const lhs = try self.resolveInst(bin_op.lhs);6230 const lhs = try self.resolveInst(bin_op.lhs);
...@@ -6210,8 +6247,9 @@ pub const FuncGen = struct {...@@ -6210,8 +6247,9 @@ pub const FuncGen = struct {
6210 return self.builder.buildUMulFixSat(lhs, rhs, "");6247 return self.builder.buildUMulFixSat(lhs, rhs, "");
6211 }6248 }
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 {
6214 if (self.liveness.isUnused(inst)) return null;6251 if (self.liveness.isUnused(inst)) return null;
6252 self.builder.setFastMath(want_fast_math);
62156253
6216 const bin_op = self.air.instructions.items(.data)[inst].bin_op;6254 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
6217 const lhs = try self.resolveInst(bin_op.lhs);6255 const lhs = try self.resolveInst(bin_op.lhs);
...@@ -6221,8 +6259,9 @@ pub const FuncGen = struct {...@@ -6221,8 +6259,9 @@ pub const FuncGen = struct {
6221 return self.buildFloatOp(.div, inst_ty, 2, .{ lhs, rhs });6259 return self.buildFloatOp(.div, inst_ty, 2, .{ lhs, rhs });
6222 }6260 }
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 {
6225 if (self.liveness.isUnused(inst)) return null;6263 if (self.liveness.isUnused(inst)) return null;
6264 self.builder.setFastMath(want_fast_math);
62266265
6227 const bin_op = self.air.instructions.items(.data)[inst].bin_op;6266 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
6228 const lhs = try self.resolveInst(bin_op.lhs);6267 const lhs = try self.resolveInst(bin_op.lhs);
...@@ -6238,8 +6277,9 @@ pub const FuncGen = struct {...@@ -6238,8 +6277,9 @@ pub const FuncGen = struct {
6238 return self.builder.buildUDiv(lhs, rhs, "");6277 return self.builder.buildUDiv(lhs, rhs, "");
6239 }6278 }
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 {
6242 if (self.liveness.isUnused(inst)) return null;6281 if (self.liveness.isUnused(inst)) return null;
6282 self.builder.setFastMath(want_fast_math);
62436283
6244 const bin_op = self.air.instructions.items(.data)[inst].bin_op;6284 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
6245 const lhs = try self.resolveInst(bin_op.lhs);6285 const lhs = try self.resolveInst(bin_op.lhs);
...@@ -6270,8 +6310,9 @@ pub const FuncGen = struct {...@@ -6270,8 +6310,9 @@ pub const FuncGen = struct {
6270 return self.builder.buildUDiv(lhs, rhs, "");6310 return self.builder.buildUDiv(lhs, rhs, "");
6271 }6311 }
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 {
6274 if (self.liveness.isUnused(inst)) return null;6314 if (self.liveness.isUnused(inst)) return null;
6315 self.builder.setFastMath(want_fast_math);
62756316
6276 const bin_op = self.air.instructions.items(.data)[inst].bin_op;6317 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
6277 const lhs = try self.resolveInst(bin_op.lhs);6318 const lhs = try self.resolveInst(bin_op.lhs);
...@@ -6284,8 +6325,9 @@ pub const FuncGen = struct {...@@ -6284,8 +6325,9 @@ pub const FuncGen = struct {
6284 return self.builder.buildExactUDiv(lhs, rhs, "");6325 return self.builder.buildExactUDiv(lhs, rhs, "");
6285 }6326 }
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 {
6288 if (self.liveness.isUnused(inst)) return null;6329 if (self.liveness.isUnused(inst)) return null;
6330 self.builder.setFastMath(want_fast_math);
62896331
6290 const bin_op = self.air.instructions.items(.data)[inst].bin_op;6332 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
6291 const lhs = try self.resolveInst(bin_op.lhs);6333 const lhs = try self.resolveInst(bin_op.lhs);
...@@ -6298,8 +6340,9 @@ pub const FuncGen = struct {...@@ -6298,8 +6340,9 @@ pub const FuncGen = struct {
6298 return self.builder.buildURem(lhs, rhs, "");6340 return self.builder.buildURem(lhs, rhs, "");
6299 }6341 }
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 {
6302 if (self.liveness.isUnused(inst)) return null;6344 if (self.liveness.isUnused(inst)) return null;
6345 self.builder.setFastMath(want_fast_math);
63036346
6304 const bin_op = self.air.instructions.items(.data)[inst].bin_op;6347 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
6305 const lhs = try self.resolveInst(bin_op.lhs);6348 const lhs = try self.resolveInst(bin_op.lhs);
...@@ -7613,6 +7656,17 @@ pub const FuncGen = struct {...@@ -7613,6 +7656,17 @@ pub const FuncGen = struct {
7613 return self.buildFloatOp(op, operand_ty, 1, .{operand});7656 return self.buildFloatOp(op, operand_ty, 1, .{operand});
7614 }7657 }
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
7616 fn airClzCtz(self: *FuncGen, inst: Air.Inst.Index, llvm_fn_name: []const u8) !?*const llvm.Value {7670 fn airClzCtz(self: *FuncGen, inst: Air.Inst.Index, llvm_fn_name: []const u8) !?*const llvm.Value {
7617 if (self.liveness.isUnused(inst)) return null;7671 if (self.liveness.isUnused(inst)) return null;
76187672
...@@ -7927,8 +7981,9 @@ pub const FuncGen = struct {...@@ -7927,8 +7981,9 @@ pub const FuncGen = struct {
7927 return self.builder.buildShuffleVector(a, b, llvm_mask_value, "");7981 return self.builder.buildShuffleVector(a, b, llvm_mask_value, "");
7928 }7982 }
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 {
7931 if (self.liveness.isUnused(inst)) return null;7985 if (self.liveness.isUnused(inst)) return null;
7986 self.builder.setFastMath(want_fast_math);
79327987
7933 const reduce = self.air.instructions.items(.data)[inst].reduce;7988 const reduce = self.air.instructions.items(.data)[inst].reduce;
7934 const operand = try self.resolveInst(reduce.operand);7989 const operand = try self.resolveInst(reduce.operand);
src/codegen/llvm/bindings.zig+3
...@@ -941,6 +941,9 @@ pub const Builder = opaque {...@@ -941,6 +941,9 @@ pub const Builder = opaque {
941941
942 pub const buildFPMulReduce = ZigLLVMBuildFPMulReduce;942 pub const buildFPMulReduce = ZigLLVMBuildFPMulReduce;
943 extern fn ZigLLVMBuildFPMulReduce(B: *const Builder, Acc: *const Value, Val: *const Value) *const Value;943 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;
944};947};
945948
946pub const MDString = opaque {949pub const MDString = opaque {
src/print_air.zig+22-2
...@@ -138,6 +138,24 @@ const Writer = struct {...@@ -138,6 +138,24 @@ const Writer = struct {
138 .set_union_tag,138 .set_union_tag,
139 .min,139 .min,
140 .max,140 .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,
141 => try w.writeBinOp(s, inst),159 => try w.writeBinOp(s, inst),
142160
143 .is_null,161 .is_null,
...@@ -169,6 +187,7 @@ const Writer = struct {...@@ -169,6 +187,7 @@ const Writer = struct {
169 .round,187 .round,
170 .trunc_float,188 .trunc_float,
171 .neg,189 .neg,
190 .neg_optimized,
172 .cmp_lt_errors_len,191 .cmp_lt_errors_len,
173 .set_err_return_trace,192 .set_err_return_trace,
174 => try w.writeUnOp(s, inst),193 => try w.writeUnOp(s, inst),
...@@ -216,6 +235,7 @@ const Writer = struct {...@@ -216,6 +235,7 @@ const Writer = struct {
216 .int_to_float,235 .int_to_float,
217 .splat,236 .splat,
218 .float_to_int,237 .float_to_int,
238 .float_to_int_optimized,
219 .get_union_tag,239 .get_union_tag,
220 .clz,240 .clz,
221 .ctz,241 .ctz,
...@@ -280,8 +300,8 @@ const Writer = struct {...@@ -280,8 +300,8 @@ const Writer = struct {
280 .mul_add => try w.writeMulAdd(s, inst),300 .mul_add => try w.writeMulAdd(s, inst),
281 .select => try w.writeSelect(s, inst),301 .select => try w.writeSelect(s, inst),
282 .shuffle => try w.writeShuffle(s, inst),302 .shuffle => try w.writeShuffle(s, inst),
283 .reduce => try w.writeReduce(s, inst),303 .reduce, .reduce_optimized => try w.writeReduce(s, inst),
284 .cmp_vector => try w.writeCmpVector(s, inst),304 .cmp_vector, .cmp_vector_optimized => try w.writeCmpVector(s, inst),
285305
286 .dbg_block_begin, .dbg_block_end => {},306 .dbg_block_begin, .dbg_block_end => {},
287 }307 }