Commit 12a7a0d76f

Andrew Kelley <andrew@ziglang.org>
2023-02-19 00:28:21
omit safety check when incrementing for loop counter
Since for loops are statically analyzed to have an upper bound, and the loop counter is a usize, it is impossible for it to overflow.
1 parent 8b05205
src/AstGen.zig
@@ -2400,6 +2400,7 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
             .add,
             .addwrap,
             .add_sat,
+            .add_unsafe,
             .param,
             .param_comptime,
             .param_anytype,
@@ -6440,7 +6441,7 @@ fn forExpr(
     try loop_scope.instructions.append(gpa, cond_block);
 
     // Increment the index variable.
-    const index_plus_one = try loop_scope.addPlNode(.add, node, Zir.Inst.Bin{
+    const index_plus_one = try loop_scope.addPlNode(.add_unsafe, node, Zir.Inst.Bin{
         .lhs = index,
         .rhs = .one_usize,
     });
src/print_zir.zig
@@ -296,6 +296,7 @@ const Writer = struct {
             .add,
             .addwrap,
             .add_sat,
+            .add_unsafe,
             .array_cat,
             .array_mul,
             .mul,
src/Sema.zig
@@ -1060,15 +1060,16 @@ fn analyzeBodyInner(
             .error_set_decl_anon => try sema.zirErrorSetDecl(block, inst, .anon),
             .error_set_decl_func => try sema.zirErrorSetDecl(block, inst, .func),
 
-            .add       => try sema.zirArithmetic(block, inst, .add),
-            .addwrap   => try sema.zirArithmetic(block, inst, .addwrap),
-            .add_sat   => try sema.zirArithmetic(block, inst, .add_sat),
-            .mul       => try sema.zirArithmetic(block, inst, .mul),
-            .mulwrap   => try sema.zirArithmetic(block, inst, .mulwrap),
-            .mul_sat   => try sema.zirArithmetic(block, inst, .mul_sat),
-            .sub       => try sema.zirArithmetic(block, inst, .sub),
-            .subwrap   => try sema.zirArithmetic(block, inst, .subwrap),
-            .sub_sat   => try sema.zirArithmetic(block, inst, .sub_sat),
+            .add       => try sema.zirArithmetic(block, inst, .add,        true),
+            .addwrap   => try sema.zirArithmetic(block, inst, .addwrap,    true),
+            .add_sat   => try sema.zirArithmetic(block, inst, .add_sat,    true),
+            .add_unsafe=> try sema.zirArithmetic(block, inst, .add_unsafe, false),
+            .mul       => try sema.zirArithmetic(block, inst, .mul,        true),
+            .mulwrap   => try sema.zirArithmetic(block, inst, .mulwrap,    true),
+            .mul_sat   => try sema.zirArithmetic(block, inst, .mul_sat,    true),
+            .sub       => try sema.zirArithmetic(block, inst, .sub,        true),
+            .subwrap   => try sema.zirArithmetic(block, inst, .subwrap,    true),
+            .sub_sat   => try sema.zirArithmetic(block, inst, .sub_sat,    true),
 
             .div       => try sema.zirDiv(block, inst),
             .div_exact => try sema.zirDivExact(block, inst),
@@ -12887,6 +12888,7 @@ fn zirArithmetic(
     block: *Block,
     inst: Zir.Inst.Index,
     zir_tag: Zir.Inst.Tag,
+    safety: bool,
 ) CompileError!Air.Inst.Ref {
     const tracy = trace(@src());
     defer tracy.end();
@@ -12899,7 +12901,7 @@ fn zirArithmetic(
     const lhs = try sema.resolveInst(extra.lhs);
     const rhs = try sema.resolveInst(extra.rhs);
 
-    return sema.analyzeArithmetic(block, zir_tag, lhs, rhs, sema.src, lhs_src, rhs_src, true);
+    return sema.analyzeArithmetic(block, zir_tag, lhs, rhs, sema.src, lhs_src, rhs_src, safety);
 }
 
 fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
@@ -14250,7 +14252,7 @@ fn analyzeArithmetic(
     const maybe_rhs_val = try sema.resolveMaybeUndefValIntable(casted_rhs);
     const rs: struct { src: LazySrcLoc, air_tag: Air.Inst.Tag } = rs: {
         switch (zir_tag) {
-            .add => {
+            .add, .add_unsafe => {
                 // For integers:intAddSat
                 // If either of the operands are zero, then the other operand is
                 // returned, even if it is undefined.
src/Zir.zig
@@ -137,6 +137,8 @@ pub const Inst = struct {
         /// Saturating addition.
         /// Uses the `pl_node` union field. Payload is `Bin`.
         add_sat,
+        /// The same as `add` except no safety check.
+        add_unsafe,
         /// Arithmetic subtraction. Asserts no integer overflow.
         /// Uses the `pl_node` union field. Payload is `Bin`.
         sub,
@@ -1023,6 +1025,7 @@ pub const Inst = struct {
                 .add,
                 .addwrap,
                 .add_sat,
+                .add_unsafe,
                 .alloc,
                 .alloc_mut,
                 .alloc_comptime_mut,
@@ -1338,6 +1341,7 @@ pub const Inst = struct {
                 .add,
                 .addwrap,
                 .add_sat,
+                .add_unsafe,
                 .alloc,
                 .alloc_mut,
                 .alloc_comptime_mut,
@@ -1570,6 +1574,7 @@ pub const Inst = struct {
                 .add = .pl_node,
                 .addwrap = .pl_node,
                 .add_sat = .pl_node,
+                .add_unsafe = .pl_node,
                 .sub = .pl_node,
                 .subwrap = .pl_node,
                 .sub_sat = .pl_node,