authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-12-08 02:09:26-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-12-08 02:09:26-05:00
logd4a93dbac5b38bda79dc26872fcb87980ab4d272
tree0810382264abd8a46af275f9fe4cd981be99bffd
parent7d0fb281fee16d9c99f61c5bce090018228ae6df

IR: omit debug safety checks in for loop codegen


4 files changed, 34 insertions(+), 24 deletions(-)

src/all_types.hpp+1
...@@ -1523,6 +1523,7 @@ struct IrInstructionBinOp {...@@ -1523,6 +1523,7 @@ struct IrInstructionBinOp {
1523 IrInstruction *op1;1523 IrInstruction *op1;
1524 IrBinOp op_id;1524 IrBinOp op_id;
1525 IrInstruction *op2;1525 IrInstruction *op2;
1526 bool safety_check_on;
1526};1527};
15271528
1528struct IrInstructionDeclVar {1529struct IrInstructionDeclVar {
src/codegen.cpp+8-6
...@@ -812,6 +812,9 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,...@@ -812,6 +812,9 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,
812812
813 assert(op1->type_entry == op2->type_entry);813 assert(op1->type_entry == op2->type_entry);
814814
815 bool want_debug_safety = bin_op_instruction->safety_check_on &&
816 ir_want_debug_safety(g, &bin_op_instruction->base);
817
815 LLVMValueRef op1_value = ir_llvm_value(g, op1);818 LLVMValueRef op1_value = ir_llvm_value(g, op1);
816 LLVMValueRef op2_value = ir_llvm_value(g, op2);819 LLVMValueRef op2_value = ir_llvm_value(g, op2);
817 switch (op_id) {820 switch (op_id) {
...@@ -859,7 +862,7 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,...@@ -859,7 +862,7 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,
859 bool is_wrapping = (op_id == IrBinOpAddWrap);862 bool is_wrapping = (op_id == IrBinOpAddWrap);
860 if (is_wrapping) {863 if (is_wrapping) {
861 return LLVMBuildAdd(g->builder, op1_value, op2_value, "");864 return LLVMBuildAdd(g->builder, op1_value, op2_value, "");
862 } else if (ir_want_debug_safety(g, &bin_op_instruction->base)) {865 } else if (want_debug_safety) {
863 return gen_overflow_op(g, op1->type_entry, AddSubMulAdd, op1_value, op2_value);866 return gen_overflow_op(g, op1->type_entry, AddSubMulAdd, op1_value, op2_value);
864 } else if (op1->type_entry->data.integral.is_signed) {867 } else if (op1->type_entry->data.integral.is_signed) {
865 return LLVMBuildNSWAdd(g->builder, op1_value, op2_value, "");868 return LLVMBuildNSWAdd(g->builder, op1_value, op2_value, "");
...@@ -882,7 +885,7 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,...@@ -882,7 +885,7 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,
882 bool is_wrapping = (op_id == IrBinOpBitShiftLeftWrap);885 bool is_wrapping = (op_id == IrBinOpBitShiftLeftWrap);
883 if (is_wrapping) {886 if (is_wrapping) {
884 return LLVMBuildShl(g->builder, op1_value, op2_value, "");887 return LLVMBuildShl(g->builder, op1_value, op2_value, "");
885 } else if (ir_want_debug_safety(g, &bin_op_instruction->base)) {888 } else if (want_debug_safety) {
886 return gen_overflow_shl_op(g, op1->type_entry, op1_value, op2_value);889 return gen_overflow_shl_op(g, op1->type_entry, op1_value, op2_value);
887 } else if (op1->type_entry->data.integral.is_signed) {890 } else if (op1->type_entry->data.integral.is_signed) {
888 return ZigLLVMBuildNSWShl(g->builder, op1_value, op2_value, "");891 return ZigLLVMBuildNSWShl(g->builder, op1_value, op2_value, "");
...@@ -905,7 +908,7 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,...@@ -905,7 +908,7 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,
905 bool is_wrapping = (op_id == IrBinOpSubWrap);908 bool is_wrapping = (op_id == IrBinOpSubWrap);
906 if (is_wrapping) {909 if (is_wrapping) {
907 return LLVMBuildSub(g->builder, op1_value, op2_value, "");910 return LLVMBuildSub(g->builder, op1_value, op2_value, "");
908 } else if (ir_want_debug_safety(g, &bin_op_instruction->base)) {911 } else if (want_debug_safety) {
909 return gen_overflow_op(g, op1->type_entry, AddSubMulSub, op1_value, op2_value);912 return gen_overflow_op(g, op1->type_entry, AddSubMulSub, op1_value, op2_value);
910 } else if (op1->type_entry->data.integral.is_signed) {913 } else if (op1->type_entry->data.integral.is_signed) {
911 return LLVMBuildNSWSub(g->builder, op1_value, op2_value, "");914 return LLVMBuildNSWSub(g->builder, op1_value, op2_value, "");
...@@ -923,7 +926,7 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,...@@ -923,7 +926,7 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,
923 bool is_wrapping = (op_id == IrBinOpMultWrap);926 bool is_wrapping = (op_id == IrBinOpMultWrap);
924 if (is_wrapping) {927 if (is_wrapping) {
925 return LLVMBuildMul(g->builder, op1_value, op2_value, "");928 return LLVMBuildMul(g->builder, op1_value, op2_value, "");
926 } else if (ir_want_debug_safety(g, &bin_op_instruction->base)) {929 } else if (want_debug_safety) {
927 return gen_overflow_op(g, op1->type_entry, AddSubMulMul, op1_value, op2_value);930 return gen_overflow_op(g, op1->type_entry, AddSubMulMul, op1_value, op2_value);
928 } else if (op1->type_entry->data.integral.is_signed) {931 } else if (op1->type_entry->data.integral.is_signed) {
929 return LLVMBuildNSWMul(g->builder, op1_value, op2_value, "");932 return LLVMBuildNSWMul(g->builder, op1_value, op2_value, "");
...@@ -934,8 +937,7 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,...@@ -934,8 +937,7 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,
934 zig_unreachable();937 zig_unreachable();
935 }938 }
936 case IrBinOpDiv:939 case IrBinOpDiv:
937 return gen_div(g, ir_want_debug_safety(g, &bin_op_instruction->base),940 return gen_div(g, want_debug_safety, op1_value, op2_value, op1->type_entry, false);
938 op1_value, op2_value, op1->type_entry, false);
939 case IrBinOpMod:941 case IrBinOpMod:
940 if (op1->type_entry->id == TypeTableEntryIdFloat) {942 if (op1->type_entry->id == TypeTableEntryIdFloat) {
941 return LLVMBuildFRem(g->builder, op1_value, op2_value, "");943 return LLVMBuildFRem(g->builder, op1_value, op2_value, "");
src/ir.cpp+22-18
...@@ -567,12 +567,13 @@ static IrInstruction *ir_build_const_c_str_lit(IrBuilder *irb, Scope *scope, Ast...@@ -567,12 +567,13 @@ static IrInstruction *ir_build_const_c_str_lit(IrBuilder *irb, Scope *scope, Ast
567}567}
568568
569static IrInstruction *ir_build_bin_op(IrBuilder *irb, Scope *scope, AstNode *source_node, IrBinOp op_id,569static IrInstruction *ir_build_bin_op(IrBuilder *irb, Scope *scope, AstNode *source_node, IrBinOp op_id,
570 IrInstruction *op1, IrInstruction *op2)570 IrInstruction *op1, IrInstruction *op2, bool safety_check_on)
571{571{
572 IrInstructionBinOp *bin_op_instruction = ir_build_instruction<IrInstructionBinOp>(irb, scope, source_node);572 IrInstructionBinOp *bin_op_instruction = ir_build_instruction<IrInstructionBinOp>(irb, scope, source_node);
573 bin_op_instruction->op_id = op_id;573 bin_op_instruction->op_id = op_id;
574 bin_op_instruction->op1 = op1;574 bin_op_instruction->op1 = op1;
575 bin_op_instruction->op2 = op2;575 bin_op_instruction->op2 = op2;
576 bin_op_instruction->safety_check_on = safety_check_on;
576577
577 ir_ref_instruction(op1);578 ir_ref_instruction(op1);
578 ir_ref_instruction(op2);579 ir_ref_instruction(op2);
...@@ -581,10 +582,10 @@ static IrInstruction *ir_build_bin_op(IrBuilder *irb, Scope *scope, AstNode *sou...@@ -581,10 +582,10 @@ static IrInstruction *ir_build_bin_op(IrBuilder *irb, Scope *scope, AstNode *sou
581}582}
582583
583static IrInstruction *ir_build_bin_op_from(IrBuilder *irb, IrInstruction *old_instruction, IrBinOp op_id,584static IrInstruction *ir_build_bin_op_from(IrBuilder *irb, IrInstruction *old_instruction, IrBinOp op_id,
584 IrInstruction *op1, IrInstruction *op2)585 IrInstruction *op1, IrInstruction *op2, bool safety_check_on)
585{586{
586 IrInstruction *new_instruction = ir_build_bin_op(irb, old_instruction->scope,587 IrInstruction *new_instruction = ir_build_bin_op(irb, old_instruction->scope,
587 old_instruction->source_node, op_id, op1, op2);588 old_instruction->source_node, op_id, op1, op2, safety_check_on);
588 ir_link_new_instruction(new_instruction, old_instruction);589 ir_link_new_instruction(new_instruction, old_instruction);
589 return new_instruction;590 return new_instruction;
590}591}
...@@ -1455,7 +1456,7 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode...@@ -1455,7 +1456,7 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode
1455static IrInstruction *ir_gen_bin_op_id(IrBuilder *irb, Scope *scope, AstNode *node, IrBinOp op_id) {1456static IrInstruction *ir_gen_bin_op_id(IrBuilder *irb, Scope *scope, AstNode *node, IrBinOp op_id) {
1456 IrInstruction *op1 = ir_gen_node(irb, node->data.bin_op_expr.op1, scope);1457 IrInstruction *op1 = ir_gen_node(irb, node->data.bin_op_expr.op1, scope);
1457 IrInstruction *op2 = ir_gen_node(irb, node->data.bin_op_expr.op2, scope);1458 IrInstruction *op2 = ir_gen_node(irb, node->data.bin_op_expr.op2, scope);
1458 return ir_build_bin_op(irb, scope, node, op_id, op1, op2);1459 return ir_build_bin_op(irb, scope, node, op_id, op1, op2, true);
1459}1460}
14601461
1461static IrInstruction *ir_gen_assign(IrBuilder *irb, Scope *scope, AstNode *node) {1462static IrInstruction *ir_gen_assign(IrBuilder *irb, Scope *scope, AstNode *node) {
...@@ -1479,7 +1480,7 @@ static IrInstruction *ir_gen_assign_op(IrBuilder *irb, Scope *scope, AstNode *no...@@ -1479,7 +1480,7 @@ static IrInstruction *ir_gen_assign_op(IrBuilder *irb, Scope *scope, AstNode *no
1479 IrInstruction *op2 = ir_gen_node(irb, node->data.bin_op_expr.op2, scope);1480 IrInstruction *op2 = ir_gen_node(irb, node->data.bin_op_expr.op2, scope);
1480 if (op2 == irb->codegen->invalid_instruction)1481 if (op2 == irb->codegen->invalid_instruction)
1481 return op2;1482 return op2;
1482 IrInstruction *result = ir_build_bin_op(irb, scope, node, op_id, op1, op2);1483 IrInstruction *result = ir_build_bin_op(irb, scope, node, op_id, op1, op2, true);
1483 ir_build_store_ptr(irb, scope, node, lvalue, result);1484 ir_build_store_ptr(irb, scope, node, lvalue, result);
1484 return ir_build_const_void(irb, scope, node);1485 return ir_build_const_void(irb, scope, node);
1485}1486}
...@@ -2322,11 +2323,11 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo...@@ -2322,11 +2323,11 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo
23222323
2323 ir_set_cursor_at_end(irb, cond_block);2324 ir_set_cursor_at_end(irb, cond_block);
2324 IrInstruction *index_val = ir_build_load_ptr(irb, child_scope, node, index_ptr);2325 IrInstruction *index_val = ir_build_load_ptr(irb, child_scope, node, index_ptr);
2325 IrInstruction *cond = ir_build_bin_op(irb, child_scope, node, IrBinOpCmpLessThan, index_val, len_val);2326 IrInstruction *cond = ir_build_bin_op(irb, child_scope, node, IrBinOpCmpLessThan, index_val, len_val, false);
2326 ir_build_cond_br(irb, child_scope, node, cond, body_block, end_block, is_inline);2327 ir_build_cond_br(irb, child_scope, node, cond, body_block, end_block, is_inline);
23272328
2328 ir_set_cursor_at_end(irb, body_block);2329 ir_set_cursor_at_end(irb, body_block);
2329 IrInstruction *elem_ptr = ir_build_elem_ptr(irb, child_scope, node, array_val_ptr, index_val, true);2330 IrInstruction *elem_ptr = ir_build_elem_ptr(irb, child_scope, node, array_val_ptr, index_val, false);
2330 IrInstruction *elem_val;2331 IrInstruction *elem_val;
2331 if (node->data.for_expr.elem_is_ptr) {2332 if (node->data.for_expr.elem_is_ptr) {
2332 elem_val = elem_ptr;2333 elem_val = elem_ptr;
...@@ -2345,7 +2346,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo...@@ -2345,7 +2346,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo
2345 ir_build_br(irb, child_scope, node, continue_block, is_inline);2346 ir_build_br(irb, child_scope, node, continue_block, is_inline);
23462347
2347 ir_set_cursor_at_end(irb, continue_block);2348 ir_set_cursor_at_end(irb, continue_block);
2348 IrInstruction *new_index_val = ir_build_bin_op(irb, child_scope, node, IrBinOpAdd, index_val, one);2349 IrInstruction *new_index_val = ir_build_bin_op(irb, child_scope, node, IrBinOpAdd, index_val, one, false);
2349 ir_build_store_ptr(irb, child_scope, node, index_ptr, new_index_val);2350 ir_build_store_ptr(irb, child_scope, node, index_ptr, new_index_val);
2350 ir_build_br(irb, child_scope, node, cond_block, is_inline);2351 ir_build_br(irb, child_scope, node, cond_block, is_inline);
23512352
...@@ -2654,13 +2655,13 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *...@@ -2654,13 +2655,13 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *
2654 IrInstruction *end_value_const = ir_build_static_eval(irb, scope, start_node, end_value);2655 IrInstruction *end_value_const = ir_build_static_eval(irb, scope, start_node, end_value);
26552656
2656 IrInstruction *lower_range_ok = ir_build_bin_op(irb, scope, item_node, IrBinOpCmpGreaterOrEq,2657 IrInstruction *lower_range_ok = ir_build_bin_op(irb, scope, item_node, IrBinOpCmpGreaterOrEq,
2657 target_value, start_value_const);2658 target_value, start_value_const, false);
2658 IrInstruction *upper_range_ok = ir_build_bin_op(irb, scope, item_node, IrBinOpCmpLessOrEq,2659 IrInstruction *upper_range_ok = ir_build_bin_op(irb, scope, item_node, IrBinOpCmpLessOrEq,
2659 target_value, end_value_const);2660 target_value, end_value_const, false);
2660 IrInstruction *both_ok = ir_build_bin_op(irb, scope, item_node, IrBinOpBoolAnd,2661 IrInstruction *both_ok = ir_build_bin_op(irb, scope, item_node, IrBinOpBoolAnd,
2661 lower_range_ok, upper_range_ok);2662 lower_range_ok, upper_range_ok, false);
2662 if (ok_bit) {2663 if (ok_bit) {
2663 ok_bit = ir_build_bin_op(irb, scope, item_node, IrBinOpBoolOr, both_ok, ok_bit);2664 ok_bit = ir_build_bin_op(irb, scope, item_node, IrBinOpBoolOr, both_ok, ok_bit, false);
2664 } else {2665 } else {
2665 ok_bit = both_ok;2666 ok_bit = both_ok;
2666 }2667 }
...@@ -2670,9 +2671,9 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *...@@ -2670,9 +2671,9 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *
2670 return irb->codegen->invalid_instruction;2671 return irb->codegen->invalid_instruction;
26712672
2672 IrInstruction *cmp_ok = ir_build_bin_op(irb, scope, item_node, IrBinOpCmpEq,2673 IrInstruction *cmp_ok = ir_build_bin_op(irb, scope, item_node, IrBinOpCmpEq,
2673 item_value, target_value);2674 item_value, target_value, false);
2674 if (ok_bit) {2675 if (ok_bit) {
2675 ok_bit = ir_build_bin_op(irb, scope, item_node, IrBinOpBoolOr, cmp_ok, ok_bit);2676 ok_bit = ir_build_bin_op(irb, scope, item_node, IrBinOpBoolOr, cmp_ok, ok_bit, false);
2676 } else {2677 } else {
2677 ok_bit = cmp_ok;2678 ok_bit = cmp_ok;
2678 }2679 }
...@@ -4027,7 +4028,8 @@ static TypeTableEntry *ir_analyze_bin_op_bool(IrAnalyze *ira, IrInstructionBinOp...@@ -4027,7 +4028,8 @@ static TypeTableEntry *ir_analyze_bin_op_bool(IrAnalyze *ira, IrInstructionBinOp
4027 return bool_type;4028 return bool_type;
4028 }4029 }
40294030
4030 ir_build_bin_op_from(&ira->new_irb, &bin_op_instruction->base, bin_op_instruction->op_id, casted_op1, casted_op2);4031 ir_build_bin_op_from(&ira->new_irb, &bin_op_instruction->base, bin_op_instruction->op_id,
4032 casted_op1, casted_op2, bin_op_instruction->safety_check_on);
4031 return bool_type;4033 return bool_type;
4032}4034}
40334035
...@@ -4145,7 +4147,8 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp...@@ -4145,7 +4147,8 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp
4145 return ira->codegen->builtin_types.entry_bool;4147 return ira->codegen->builtin_types.entry_bool;
4146 }4148 }
41474149
4148 ir_build_bin_op_from(&ira->new_irb, &bin_op_instruction->base, op_id, casted_op1, casted_op2);4150 ir_build_bin_op_from(&ira->new_irb, &bin_op_instruction->base, op_id,
4151 casted_op1, casted_op2, bin_op_instruction->safety_check_on);
41494152
4150 return ira->codegen->builtin_types.entry_bool;4153 return ira->codegen->builtin_types.entry_bool;
4151}4154}
...@@ -4311,7 +4314,8 @@ static TypeTableEntry *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp...@@ -4311,7 +4314,8 @@ static TypeTableEntry *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp
43114314
4312 }4315 }
43134316
4314 ir_build_bin_op_from(&ira->new_irb, &bin_op_instruction->base, op_id, casted_op1, casted_op2);4317 ir_build_bin_op_from(&ira->new_irb, &bin_op_instruction->base, op_id,
4318 casted_op1, casted_op2, bin_op_instruction->safety_check_on);
4315 return resolved_type;4319 return resolved_type;
4316}4320}
43174321
...@@ -5345,7 +5349,7 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc...@@ -5345,7 +5349,7 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc
5345 if (casted_elem_index == ira->codegen->invalid_instruction)5349 if (casted_elem_index == ira->codegen->invalid_instruction)
5346 return ira->codegen->builtin_types.entry_invalid;5350 return ira->codegen->builtin_types.entry_invalid;
53475351
5348 bool safety_check_on = true;5352 bool safety_check_on = elem_ptr_instruction->safety_check_on;
5349 if (casted_elem_index->static_value.special != ConstValSpecialRuntime) {5353 if (casted_elem_index->static_value.special != ConstValSpecialRuntime) {
5350 uint64_t index = casted_elem_index->static_value.data.x_bignum.data.x_uint;5354 uint64_t index = casted_elem_index->static_value.data.x_bignum.data.x_uint;
5351 if (array_type->id == TypeTableEntryIdArray) {5355 if (array_type->id == TypeTableEntryIdArray) {
src/ir_print.cpp+3
...@@ -314,6 +314,9 @@ static void ir_print_bin_op(IrPrint *irp, IrInstructionBinOp *bin_op_instruction...@@ -314,6 +314,9 @@ static void ir_print_bin_op(IrPrint *irp, IrInstructionBinOp *bin_op_instruction
314 ir_print_other_instruction(irp, bin_op_instruction->op1);314 ir_print_other_instruction(irp, bin_op_instruction->op1);
315 fprintf(irp->f, " %s ", ir_bin_op_id_str(bin_op_instruction->op_id));315 fprintf(irp->f, " %s ", ir_bin_op_id_str(bin_op_instruction->op_id));
316 ir_print_other_instruction(irp, bin_op_instruction->op2);316 ir_print_other_instruction(irp, bin_op_instruction->op2);
317 if (!bin_op_instruction->safety_check_on) {
318 fprintf(irp->f, " // no safety");
319 }
317}320}
318321
319static void ir_print_decl_var(IrPrint *irp, IrInstructionDeclVar *decl_var_instruction) {322static void ir_print_decl_var(IrPrint *irp, IrInstructionDeclVar *decl_var_instruction) {