authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-03-26 14:41:17-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-03-26 14:41:17-04:00
log310335580536777055d9bc2cb8b91b40203ae292
treec2fe3770c224c364310d20a4b9a9f1a5b97ec33c
parent5bc9feb5cb98fc13db62d01b2b9fec15677310a7

add comptime eval for some uint comparisons with 0

closes #55

2 files changed, 52 insertions(+), 0 deletions(-)

src/ir.cpp+33
...@@ -7349,6 +7349,39 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp...@@ -7349,6 +7349,39 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp
7349 return ira->codegen->builtin_types.entry_bool;7349 return ira->codegen->builtin_types.entry_bool;
7350 }7350 }
73517351
7352 // some comparisons with unsigned numbers can be evaluated
7353 if (resolved_type->id == TypeTableEntryIdInt && !resolved_type->data.integral.is_signed) {
7354 ConstExprValue *known_left_val;
7355 IrBinOp flipped_op_id;
7356 if (value_is_comptime(op1_val)) {
7357 known_left_val = op1_val;
7358 flipped_op_id = op_id;
7359 } else if (value_is_comptime(op2_val)) {
7360 known_left_val = op2_val;
7361 if (op_id == IrBinOpCmpLessThan) {
7362 flipped_op_id = IrBinOpCmpGreaterThan;
7363 } else if (op_id == IrBinOpCmpGreaterThan) {
7364 flipped_op_id = IrBinOpCmpLessThan;
7365 } else if (op_id == IrBinOpCmpLessOrEq) {
7366 flipped_op_id = IrBinOpCmpGreaterOrEq;
7367 } else if (op_id == IrBinOpCmpGreaterOrEq) {
7368 flipped_op_id = IrBinOpCmpLessOrEq;
7369 } else {
7370 flipped_op_id = op_id;
7371 }
7372 } else {
7373 known_left_val = nullptr;
7374 }
7375 if (known_left_val != nullptr && known_left_val->data.x_bignum.data.x_uint == 0 &&
7376 (flipped_op_id == IrBinOpCmpLessOrEq || flipped_op_id == IrBinOpCmpGreaterThan))
7377 {
7378 bool answer = (flipped_op_id == IrBinOpCmpLessOrEq);
7379 ConstExprValue *out_val = ir_build_const_from(ira, &bin_op_instruction->base);
7380 out_val->data.x_bool = answer;
7381 return ira->codegen->builtin_types.entry_bool;
7382 }
7383 }
7384
7352 ir_build_bin_op_from(&ira->new_irb, &bin_op_instruction->base, op_id,7385 ir_build_bin_op_from(&ira->new_irb, &bin_op_instruction->base, op_id,
7353 casted_op1, casted_op2, bin_op_instruction->safety_check_on);7386 casted_op1, casted_op2, bin_op_instruction->safety_check_on);
73547387
test/cases/eval.zig+19
...@@ -265,3 +265,22 @@ fn modifySomeBytes(bytes: []u8) {...@@ -265,3 +265,22 @@ fn modifySomeBytes(bytes: []u8) {
265 bytes[0] = 'a';265 bytes[0] = 'a';
266 bytes[9] = 'b';266 bytes[9] = 'b';
267}267}
268
269
270test "comparisons 0 <= uint and 0 > uint should be comptime" {
271 testCompTimeUIntComparisons(1234);
272}
273fn testCompTimeUIntComparisons(x: u32) {
274 if (!(0 <= x)) {
275 @compileError("this condition should be comptime known");
276 }
277 if (0 > x) {
278 @compileError("this condition should be comptime known");
279 }
280 if (!(x >= 0)) {
281 @compileError("this condition should be comptime known");
282 }
283 if (x < 0) {
284 @compileError("this condition should be comptime known");
285 }
286}