aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorkkHAIKE <kkhaike@gmail.com>2022-11-19 04:06:49 +0800
committerGitHub <noreply@github.com>2022-11-18 22:06:49 +0200
commitea590ece4bcc26175d890dd82899ffc9ef64b6c3 (patch)
treeb5d77cc7bbe683e54c9bf2b7d29b4681dc057ba5 /src
parent04f3067a7921a51bd55870f3138220fd66426e33 (diff)
downloadzig-ea590ece4bcc26175d890dd82899ffc9ef64b6c3.tar.gz
zig-ea590ece4bcc26175d890dd82899ffc9ef64b6c3.zip
Sema: optimize compare comptime float with int
Diffstat (limited to 'src')
-rw-r--r--src/Sema.zig56
-rw-r--r--src/value.zig30
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());