diff options
| author | kkHAIKE <kkhaike@gmail.com> | 2022-11-19 04:06:49 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-11-18 22:06:49 +0200 |
| commit | ea590ece4bcc26175d890dd82899ffc9ef64b6c3 (patch) | |
| tree | b5d77cc7bbe683e54c9bf2b7d29b4681dc057ba5 /src | |
| parent | 04f3067a7921a51bd55870f3138220fd66426e33 (diff) | |
| download | zig-ea590ece4bcc26175d890dd82899ffc9ef64b6c3.tar.gz zig-ea590ece4bcc26175d890dd82899ffc9ef64b6c3.zip | |
Sema: optimize compare comptime float with int
Diffstat (limited to 'src')
| -rw-r--r-- | src/Sema.zig | 56 | ||||
| -rw-r--r-- | src/value.zig | 30 |
2 files changed, 71 insertions, 15 deletions
diff --git a/src/Sema.zig b/src/Sema.zig index 3b362d83c4..a6811d37fd 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -13896,9 +13896,25 @@ fn analyzeArithmetic( // because there is a possible value for which the addition would // overflow (max_int), causing illegal behavior. // For floats: either operand being undef makes the result undef. + // If either of the operands are inf, and the other operand is zero, + // the result is nan. + // If either of the operands are nan, the result is nan. if (maybe_lhs_val) |lhs_val| { if (!lhs_val.isUndef()) { - if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema)) { + if (lhs_val.isNan()) { + return sema.addConstant(resolved_type, lhs_val); + } + if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema)) lz: { + if (maybe_rhs_val) |rhs_val| { + if (rhs_val.isNan()) { + return sema.addConstant(resolved_type, rhs_val); + } + if (rhs_val.isInf()) { + return sema.addConstant(resolved_type, try Value.Tag.float_32.create(sema.arena, std.math.nan_f32)); + } + } else if (resolved_type.isAnyFloat()) { + break :lz; + } const zero_val = if (is_vector) b: { break :b try Value.Tag.repeated.create(sema.arena, Value.zero); } else Value.zero; @@ -13918,7 +13934,17 @@ fn analyzeArithmetic( return sema.addConstUndef(resolved_type); } } - if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema)) { + if (rhs_val.isNan()) { + return sema.addConstant(resolved_type, rhs_val); + } + if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema)) rz: { + if (maybe_lhs_val) |lhs_val| { + if (lhs_val.isInf()) { + return sema.addConstant(resolved_type, try Value.Tag.float_32.create(sema.arena, std.math.nan_f32)); + } + } else if (resolved_type.isAnyFloat()) { + break :rz; + } const zero_val = if (is_vector) b: { break :b try Value.Tag.repeated.create(sema.arena, Value.zero); } else Value.zero; @@ -28175,8 +28201,10 @@ fn cmpNumeric( else => return Air.Inst.Ref.bool_false, }; if (lhs_val.isInf()) switch (op) { - .gt, .neq => return Air.Inst.Ref.bool_true, - .lt, .lte, .eq, .gte => return Air.Inst.Ref.bool_false, + .neq => return Air.Inst.Ref.bool_true, + .eq => return Air.Inst.Ref.bool_false, + .gt, .gte => return if (lhs_val.isNegativeInf()) Air.Inst.Ref.bool_false else Air.Inst.Ref.bool_true, + .lt, .lte => return if (lhs_val.isNegativeInf()) Air.Inst.Ref.bool_true else Air.Inst.Ref.bool_false, }; if (!rhs_is_signed) { switch (lhs_val.orderAgainstZero()) { @@ -28193,14 +28221,17 @@ fn cmpNumeric( } } if (lhs_is_float) { - var bigint = try float128IntPartToBigInt(sema.gpa, lhs_val.toFloat(f128)); - defer bigint.deinit(); if (lhs_val.floatHasFraction()) { switch (op) { .eq => return Air.Inst.Ref.bool_false, .neq => return Air.Inst.Ref.bool_true, else => {}, } + } + + var bigint = try float128IntPartToBigInt(sema.gpa, lhs_val.toFloat(f128)); + defer bigint.deinit(); + if (lhs_val.floatHasFraction()) { if (lhs_is_signed) { try bigint.addScalar(&bigint, -1); } else { @@ -28228,8 +28259,10 @@ fn cmpNumeric( else => return Air.Inst.Ref.bool_false, }; if (rhs_val.isInf()) switch (op) { - .lt, .neq => return Air.Inst.Ref.bool_true, - .gt, .lte, .eq, .gte => return Air.Inst.Ref.bool_false, + .neq => return Air.Inst.Ref.bool_true, + .eq => return Air.Inst.Ref.bool_false, + .gt, .gte => return if (rhs_val.isNegativeInf()) Air.Inst.Ref.bool_true else Air.Inst.Ref.bool_false, + .lt, .lte => return if (rhs_val.isNegativeInf()) Air.Inst.Ref.bool_false else Air.Inst.Ref.bool_true, }; if (!lhs_is_signed) { switch (rhs_val.orderAgainstZero()) { @@ -28246,14 +28279,17 @@ fn cmpNumeric( } } if (rhs_is_float) { - var bigint = try float128IntPartToBigInt(sema.gpa, rhs_val.toFloat(f128)); - defer bigint.deinit(); if (rhs_val.floatHasFraction()) { switch (op) { .eq => return Air.Inst.Ref.bool_false, .neq => return Air.Inst.Ref.bool_true, else => {}, } + } + + var bigint = try float128IntPartToBigInt(sema.gpa, rhs_val.toFloat(f128)); + defer bigint.deinit(); + if (rhs_val.floatHasFraction()) { if (rhs_is_signed) { try bigint.addScalar(&bigint, -1); } else { diff --git a/src/value.zig b/src/value.zig index 61d7840e04..042a960b25 100644 --- a/src/value.zig +++ b/src/value.zig @@ -2081,6 +2081,15 @@ pub const Value = extern union { op: std.math.CompareOperator, opt_sema: ?*Sema, ) Module.CompileError!bool { + if (lhs.isInf()) { + switch (op) { + .neq => return true, + .eq => return false, + .gt, .gte => return !lhs.isNegativeInf(), + .lt, .lte => return lhs.isNegativeInf(), + } + } + switch (lhs.tag()) { .repeated => return lhs.castTag(.repeated).?.data.compareAllWithZeroAdvanced(op, opt_sema), .aggregate => { @@ -2089,11 +2098,11 @@ pub const Value = extern union { } return true; }, - .float_16 => if (std.math.isNan(lhs.castTag(.float_16).?.data)) return op != .neq, - .float_32 => if (std.math.isNan(lhs.castTag(.float_32).?.data)) return op != .neq, - .float_64 => if (std.math.isNan(lhs.castTag(.float_64).?.data)) return op != .neq, - .float_80 => if (std.math.isNan(lhs.castTag(.float_80).?.data)) return op != .neq, - .float_128 => if (std.math.isNan(lhs.castTag(.float_128).?.data)) return op != .neq, + .float_16 => if (std.math.isNan(lhs.castTag(.float_16).?.data)) return op == .neq, + .float_32 => if (std.math.isNan(lhs.castTag(.float_32).?.data)) return op == .neq, + .float_64 => if (std.math.isNan(lhs.castTag(.float_64).?.data)) return op == .neq, + .float_80 => if (std.math.isNan(lhs.castTag(.float_80).?.data)) return op == .neq, + .float_128 => if (std.math.isNan(lhs.castTag(.float_128).?.data)) return op == .neq, else => {}, } return (try orderAgainstZeroAdvanced(lhs, opt_sema)).compare(op); @@ -3817,6 +3826,17 @@ pub const Value = extern union { }; } + pub fn isNegativeInf(val: Value) bool { + return switch (val.tag()) { + .float_16 => std.math.isNegativeInf(val.castTag(.float_16).?.data), + .float_32 => std.math.isNegativeInf(val.castTag(.float_32).?.data), + .float_64 => std.math.isNegativeInf(val.castTag(.float_64).?.data), + .float_80 => std.math.isNegativeInf(val.castTag(.float_80).?.data), + .float_128 => std.math.isNegativeInf(val.castTag(.float_128).?.data), + else => false, + }; + } + pub fn floatRem(lhs: Value, rhs: Value, float_type: Type, arena: Allocator, target: Target) !Value { if (float_type.zigTypeTag() == .Vector) { const result_data = try arena.alloc(Value, float_type.vectorLen()); |
