| author | |
| committer | |
| log | d75fa86d7084bd41f68d1cd03763bd7cf2a87052 |
| tree | b454c3e13d627220cdff9a9245849a6ffd57aaa5 |
| parent | 585c160c2022d71197a3ce1399818372371c23a4 |
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" { |
| 813 | test "conversion to f80" { | 813 | test "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/11408 | 815 | return error.SkipZigTest; // https://github.com/ziglang/zig/issues/11408 |
| 816 | if (std.debug.runtime_safety) return error.SkipZigTest; | ||
| 816 | 817 | ||
| 817 | const intToFloat = @import("./int_to_float.zig").intToFloat; | 818 | const intToFloat = @import("./int_to_float.zig").intToFloat; |
| 818 | 819 |
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 type | 44 | /// 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 type | 51 | /// 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 type | 63 | /// 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 type | 70 | /// 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 type | 82 | /// 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 type | 89 | /// 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 type | 101 | /// 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 type | 108 | /// 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 type | 116 | /// 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 type | 123 | /// 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 type | 130 | /// 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, | ||
| 296 | 322 | ||
| 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, | ||
| 319 | 359 | ||
| 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 float | 606 | /// * 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 elements | 611 | /// 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, |
| 678 | 722 | ||
| 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 | } |
| 689 | 733 | ||
| 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), |
| 963 | 1019 | ||
| 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), |
| 980 | 1037 | ||
| 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 | }, |
| 1131 | 1196 | ||
| 1132 | .reduce => return air.typeOf(datas[inst].reduce.operand).childType(), | 1197 | .reduce, .reduce_optimized => return air.typeOf(datas[inst].reduce.operand).childType(), |
| 1133 | 1198 | ||
| 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( |
| 701 | 721 | ||
| 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 @setRuntimeSafety | 144 | /// when null, it is determined by build mode, changed by @setRuntimeSafety |
| 145 | want_safety: ?bool = null, | 145 | want_safety: ?bool = null, |
| 146 | 146 | ||
| 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, |
| 148 | 151 | ||
| 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 { |
| 414 | 418 | ||
| 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 | }; |
| 4709 | 4714 | ||
| 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 |
| 5042 | fn zirSetFloatMode(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!void { | 5047 | fn 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 | } |
| 5053 | 5052 | ||
| 5054 | fn zirSetRuntimeSafety(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { | 5053 | fn 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 |
| 9411 | 9410 | ||
| 9412 | // operand >= first and operand <= last | 9411 | // 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 | } |
| 10724 | 10723 | ||
| 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 | } |
| 12482 | 12502 | ||
| ... | @@ -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 | } |
| 15955 | 15975 | ||
| 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. |
| 17194 | 17214 | ||
| 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 signed | 24515 | // 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); |
| 24612 | 24632 | ||
| 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 | } |
| 24615 | 24635 | ||
| 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), |
| 731 | 731 | ||
| 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: on | 758 | // 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), |
| 746 | 746 | ||
| 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: on | 773 | // 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), |
| 671 | 671 | ||
| 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: on | 698 | // 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), |
| 683 | 683 | ||
| 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: on | 710 | // 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 | } |
| 1627 | 1651 |
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), |
| 753 | 753 | ||
| 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: on | 780 | // 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 |
| 1928 | 1928 | ||
| 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: on | 1955 | // 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: off | 3986 | // 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), |
| 4011 | 4011 | ||
| 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), | ||
| 4045 | 4050 | ||
| 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), | ||
| 4048 | 4071 | ||
| 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), |
| 4095 | 4118 | ||
| 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), |
| 4122 | 4146 | ||
| 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 | } |
| 4487 | 4514 | ||
| 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); | ||
| 4490 | 4518 | ||
| 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 | } |
| 4498 | 4526 | ||
| 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); | ||
| 4501 | 4530 | ||
| 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 | } |
| 4945 | 4974 | ||
| 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; |
| 4949 | 4978 | ||
| 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; |
| 4952 | 4983 | ||
| ... | @@ -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 | } |
| 6097 | 6128 | ||
| 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); | ||
| 6100 | 6132 | ||
| 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 | } |
| 6111 | 6143 | ||
| 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); | ||
| 6114 | 6147 | ||
| 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 | } |
| 6136 | 6169 | ||
| 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); | ||
| 6139 | 6173 | ||
| 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 | } |
| 6150 | 6184 | ||
| 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); | ||
| 6153 | 6188 | ||
| 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 | } |
| 6174 | 6209 | ||
| 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); | ||
| 6177 | 6213 | ||
| 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 | } |
| 6188 | 6224 | ||
| 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); | ||
| 6191 | 6228 | ||
| 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 | } |
| 6212 | 6249 | ||
| 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); | ||
| 6215 | 6253 | ||
| 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 | } |
| 6223 | 6261 | ||
| 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); | ||
| 6226 | 6265 | ||
| 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 | } |
| 6240 | 6279 | ||
| 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); | ||
| 6243 | 6283 | ||
| 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 | } |
| 6272 | 6312 | ||
| 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); | ||
| 6275 | 6316 | ||
| 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 | } |
| 6286 | 6327 | ||
| 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); | ||
| 6289 | 6331 | ||
| 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 | } |
| 6300 | 6342 | ||
| 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); | ||
| 6303 | 6346 | ||
| 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 | } |
| 7615 | 7658 | ||
| 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; |
| 7618 | 7672 | ||
| ... | @@ -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 | } |
| 7929 | 7983 | ||
| 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); | ||
| 7932 | 7987 | ||
| 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 { |
| 941 | 941 | ||
| 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 | }; |
| 945 | 948 | ||
| 946 | pub const MDString = opaque { | 949 | pub 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), |
| 142 | 160 | ||
| 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), |
| 285 | 305 | ||
| 286 | .dbg_block_begin, .dbg_block_end => {}, | 306 | .dbg_block_begin, .dbg_block_end => {}, |
| 287 | } | 307 | } |