authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-02-27 15:32:46-05:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-02-27 15:32:46-05:00
log104a8840dbc0a09ce5e0035470052354a98693f1
treeee8a81a21eeaaa6baffc3fafb85bce7063a5d406
parent0bdc3d8f4e065f87083b52700350ca96330463ad
parenta7a508fcd9a961ea9d903f9065556a02b4045b95
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #11002 from topolarity/comptime-int-comparison

stage2: Add comptime result for certain unsigned/comptime comparisons

2 files changed, 39 insertions(+), 18 deletions(-)

src/Sema.zig+39-16
...@@ -11842,6 +11842,7 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -11842,6 +11842,7 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
11842 const operand = sema.resolveInst(inst_data.operand);11842 const operand = sema.resolveInst(inst_data.operand);
11843 const operand_ty = sema.typeOf(operand);11843 const operand_ty = sema.typeOf(operand);
1184411844
11845 try sema.resolveTypeLayout(block, operand_src, operand_ty);
11845 const enum_ty = switch (operand_ty.zigTypeTag()) {11846 const enum_ty = switch (operand_ty.zigTypeTag()) {
11846 .EnumLiteral => {11847 .EnumLiteral => {
11847 const val = try sema.resolveConstValue(block, operand_src, operand);11848 const val = try sema.resolveConstValue(block, operand_src, operand);
...@@ -17113,30 +17114,41 @@ fn cmpNumeric(...@@ -17113,30 +17114,41 @@ fn cmpNumeric(
17113 if (try sema.resolveMaybeUndefVal(block, lhs_src, lhs)) |lhs_val| {17114 if (try sema.resolveMaybeUndefVal(block, lhs_src, lhs)) |lhs_val| {
17114 if (lhs_val.isUndef())17115 if (lhs_val.isUndef())
17115 return sema.addConstUndef(Type.bool);17116 return sema.addConstUndef(Type.bool);
17116 const is_unsigned = if (lhs_is_float) x: {17117 if (!rhs_is_signed) {
17118 switch (lhs_val.orderAgainstZero()) {
17119 .gt => {},
17120 .eq => switch (op) { // LHS = 0, RHS is unsigned
17121 .lte => return Air.Inst.Ref.bool_true,
17122 .gt => return Air.Inst.Ref.bool_false,
17123 else => {},
17124 },
17125 .lt => switch (op) { // LHS < 0, RHS is unsigned
17126 .neq, .lt, .lte => return Air.Inst.Ref.bool_true,
17127 .eq, .gt, .gte => return Air.Inst.Ref.bool_false,
17128 },
17129 }
17130 }
17131 if (lhs_is_float) {
17117 var bigint_space: Value.BigIntSpace = undefined;17132 var bigint_space: Value.BigIntSpace = undefined;
17118 var bigint = try lhs_val.toBigInt(&bigint_space).toManaged(sema.gpa);17133 var bigint = try lhs_val.toBigInt(&bigint_space).toManaged(sema.gpa);
17119 defer bigint.deinit();17134 defer bigint.deinit();
17120 const zcmp = lhs_val.orderAgainstZero();
17121 if (lhs_val.floatHasFraction()) {17135 if (lhs_val.floatHasFraction()) {
17122 switch (op) {17136 switch (op) {
17123 .eq => return Air.Inst.Ref.bool_false,17137 .eq => return Air.Inst.Ref.bool_false,
17124 .neq => return Air.Inst.Ref.bool_true,17138 .neq => return Air.Inst.Ref.bool_true,
17125 else => {},17139 else => {},
17126 }17140 }
17127 if (zcmp == .lt) {17141 if (lhs_is_signed) {
17128 try bigint.addScalar(bigint.toConst(), -1);17142 try bigint.addScalar(bigint.toConst(), -1);
17129 } else {17143 } else {
17130 try bigint.addScalar(bigint.toConst(), 1);17144 try bigint.addScalar(bigint.toConst(), 1);
17131 }17145 }
17132 }17146 }
17133 lhs_bits = bigint.toConst().bitCountTwosComp();17147 lhs_bits = bigint.toConst().bitCountTwosComp();
17134 break :x (zcmp != .lt);17148 } else {
17135 } else x: {
17136 lhs_bits = lhs_val.intBitCountTwosComp(target);17149 lhs_bits = lhs_val.intBitCountTwosComp(target);
17137 break :x (lhs_val.orderAgainstZero() != .lt);17150 }
17138 };17151 lhs_bits += @boolToInt(!lhs_is_signed and dest_int_is_signed);
17139 lhs_bits += @boolToInt(is_unsigned and dest_int_is_signed);
17140 } else if (lhs_is_float) {17152 } else if (lhs_is_float) {
17141 dest_float_type = lhs_ty;17153 dest_float_type = lhs_ty;
17142 } else {17154 } else {
...@@ -17148,30 +17160,41 @@ fn cmpNumeric(...@@ -17148,30 +17160,41 @@ fn cmpNumeric(
17148 if (try sema.resolveMaybeUndefVal(block, rhs_src, rhs)) |rhs_val| {17160 if (try sema.resolveMaybeUndefVal(block, rhs_src, rhs)) |rhs_val| {
17149 if (rhs_val.isUndef())17161 if (rhs_val.isUndef())
17150 return sema.addConstUndef(Type.bool);17162 return sema.addConstUndef(Type.bool);
17151 const is_unsigned = if (rhs_is_float) x: {17163 if (!lhs_is_signed) {
17164 switch (rhs_val.orderAgainstZero()) {
17165 .gt => {},
17166 .eq => switch (op) { // RHS = 0, LHS is unsigned
17167 .gte => return Air.Inst.Ref.bool_true,
17168 .lt => return Air.Inst.Ref.bool_false,
17169 else => {},
17170 },
17171 .lt => switch (op) { // RHS < 0, LHS is unsigned
17172 .neq, .gt, .gte => return Air.Inst.Ref.bool_true,
17173 .eq, .lt, .lte => return Air.Inst.Ref.bool_false,
17174 },
17175 }
17176 }
17177 if (rhs_is_float) {
17152 var bigint_space: Value.BigIntSpace = undefined;17178 var bigint_space: Value.BigIntSpace = undefined;
17153 var bigint = try rhs_val.toBigInt(&bigint_space).toManaged(sema.gpa);17179 var bigint = try rhs_val.toBigInt(&bigint_space).toManaged(sema.gpa);
17154 defer bigint.deinit();17180 defer bigint.deinit();
17155 const zcmp = rhs_val.orderAgainstZero();
17156 if (rhs_val.floatHasFraction()) {17181 if (rhs_val.floatHasFraction()) {
17157 switch (op) {17182 switch (op) {
17158 .eq => return Air.Inst.Ref.bool_false,17183 .eq => return Air.Inst.Ref.bool_false,
17159 .neq => return Air.Inst.Ref.bool_true,17184 .neq => return Air.Inst.Ref.bool_true,
17160 else => {},17185 else => {},
17161 }17186 }
17162 if (zcmp == .lt) {17187 if (rhs_is_signed) {
17163 try bigint.addScalar(bigint.toConst(), -1);17188 try bigint.addScalar(bigint.toConst(), -1);
17164 } else {17189 } else {
17165 try bigint.addScalar(bigint.toConst(), 1);17190 try bigint.addScalar(bigint.toConst(), 1);
17166 }17191 }
17167 }17192 }
17168 rhs_bits = bigint.toConst().bitCountTwosComp();17193 rhs_bits = bigint.toConst().bitCountTwosComp();
17169 break :x (zcmp != .lt);17194 } else {
17170 } else x: {
17171 rhs_bits = rhs_val.intBitCountTwosComp(target);17195 rhs_bits = rhs_val.intBitCountTwosComp(target);
17172 break :x (rhs_val.orderAgainstZero() != .lt);17196 }
17173 };17197 rhs_bits += @boolToInt(!rhs_is_signed and dest_int_is_signed);
17174 rhs_bits += @boolToInt(is_unsigned and dest_int_is_signed);
17175 } else if (rhs_is_float) {17198 } else if (rhs_is_float) {
17176 dest_float_type = rhs_ty;17199 dest_float_type = rhs_ty;
17177 } else {17200 } else {
test/behavior/eval.zig-2
...@@ -559,8 +559,6 @@ fn modifySomeBytes(bytes: []u8) void {...@@ -559,8 +559,6 @@ fn modifySomeBytes(bytes: []u8) void {
559}559}
560560
561test "comparisons 0 <= uint and 0 > uint should be comptime" {561test "comparisons 0 <= uint and 0 > uint should be comptime" {
562 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
563
564 testCompTimeUIntComparisons(1234);562 testCompTimeUIntComparisons(1234);
565}563}
566fn testCompTimeUIntComparisons(x: u32) void {564fn testCompTimeUIntComparisons(x: u32) void {