Commit 3103355805

Andrew Kelley <superjoe30@gmail.com>
2017-03-26 20:41:17
add comptime eval for some uint comparisons with 0
closes #55
1 parent 5bc9feb
Changed files (2)
src
test
cases
src/ir.cpp
@@ -7349,6 +7349,39 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp
         return ira->codegen->builtin_types.entry_bool;
     }
 
+    // some comparisons with unsigned numbers can be evaluated
+    if (resolved_type->id == TypeTableEntryIdInt && !resolved_type->data.integral.is_signed) {
+        ConstExprValue *known_left_val;
+        IrBinOp flipped_op_id;
+        if (value_is_comptime(op1_val)) {
+            known_left_val = op1_val;
+            flipped_op_id = op_id;
+        } else if (value_is_comptime(op2_val)) {
+            known_left_val = op2_val;
+            if (op_id == IrBinOpCmpLessThan) {
+                flipped_op_id = IrBinOpCmpGreaterThan;
+            } else if (op_id == IrBinOpCmpGreaterThan) {
+                flipped_op_id = IrBinOpCmpLessThan;
+            } else if (op_id == IrBinOpCmpLessOrEq) {
+                flipped_op_id = IrBinOpCmpGreaterOrEq;
+            } else if (op_id == IrBinOpCmpGreaterOrEq) {
+                flipped_op_id = IrBinOpCmpLessOrEq;
+            } else {
+                flipped_op_id = op_id;
+            }
+        } else {
+            known_left_val = nullptr;
+        }
+        if (known_left_val != nullptr && known_left_val->data.x_bignum.data.x_uint == 0 &&
+            (flipped_op_id == IrBinOpCmpLessOrEq || flipped_op_id == IrBinOpCmpGreaterThan))
+        {
+            bool answer = (flipped_op_id == IrBinOpCmpLessOrEq);
+            ConstExprValue *out_val = ir_build_const_from(ira, &bin_op_instruction->base);
+            out_val->data.x_bool = answer;
+            return ira->codegen->builtin_types.entry_bool;
+        }
+    }
+
     ir_build_bin_op_from(&ira->new_irb, &bin_op_instruction->base, op_id,
             casted_op1, casted_op2, bin_op_instruction->safety_check_on);
 
test/cases/eval.zig
@@ -265,3 +265,22 @@ fn modifySomeBytes(bytes: []u8) {
     bytes[0] = 'a';
     bytes[9] = 'b';
 }
+
+
+test "comparisons 0 <= uint and 0 > uint should be comptime" {
+    testCompTimeUIntComparisons(1234);
+}
+fn testCompTimeUIntComparisons(x: u32) {
+    if (!(0 <= x)) {
+        @compileError("this condition should be comptime known");
+    }
+    if (0 > x) {
+        @compileError("this condition should be comptime known");
+    }
+    if (!(x >= 0)) {
+        @compileError("this condition should be comptime known");
+    }
+    if (x < 0) {
+        @compileError("this condition should be comptime known");
+    }
+}